2014-08-31 13:13:46 -04:00
// MainFrameViewController . m
// Limelight - iOS
//
// Created by Diego Waxemberg on 1 / 17 / 14.
// Copyright ( c ) 2014 Diego Waxemberg . All rights reserved .
//
# import "MainFrameViewController.h"
2014-10-14 19:21:48 -04:00
# import "Computer.h"
2014-10-16 21:20:27 -04:00
# import "CryptoManager.h"
2014-10-18 21:13:48 -04:00
# import "HttpManager.h"
2014-10-20 11:31:40 -04:00
# import "Connection.h"
# import "VideoDecoderRenderer.h"
2014-10-20 13:35:42 -04:00
# import "StreamManager.h"
2014-10-20 20:54:03 -04:00
# import "Utils.h"
2014-10-24 16:02:10 -04:00
# import "UIComputerView.h"
# import "UIAppView.h"
# import "App.h"
2014-10-29 00:47:51 -04:00
# import "SettingsViewController.h"
# import "DataManager.h"
# import "Settings.h"
2014-08-31 13:13:46 -04:00
2014-10-20 11:31:40 -04:00
@ implementation MainFrameViewController {
NSOperationQueue * _opQueue ;
MDNSManager * _mDNSManager ;
Computer * _selectedHost ;
2014-10-26 02:15:53 -04:00
NSString * _uniqueId ;
NSData * _cert ;
2014-10-20 13:35:42 -04:00
UIAlertView * _pairAlert ;
2014-10-26 02:15:53 -04:00
UIScrollView * hostScrollView ;
2014-10-20 11:31:40 -04:00
}
2014-10-26 02:15:53 -04:00
static NSString * deviceName = @ "roth" ;
static NSMutableSet * hostList ;
2014-12-04 18:41:01 +09:00
static NSArray * appList ;
2014-10-20 20:54:03 -04:00
static StreamConfiguration * streamConfig ;
2014-08-31 13:13:46 -04:00
2014-10-20 20:54:03 -04:00
+ ( StreamConfiguration * ) getStreamConfiguration {
return streamConfig ;
2014-08-31 13:13:46 -04:00
}
2014-10-20 13:35:42 -04:00
- ( void ) showPIN : ( NSString * ) PIN {
dispatch_sync ( dispatch_get _main _queue ( ) , ^ {
_pairAlert = [ [ UIAlertView alloc ] initWithTitle : @ "Pairing" message : [ NSString stringWithFormat : @ "Enter the following PIN on the host machine: %@" , PIN ] delegate : self cancelButtonTitle : @ "Ok" otherButtonTitles : nil , nil ] ;
[ _pairAlert show ] ;
} ) ;
}
- ( void ) pairFailed : ( NSString * ) message {
dispatch_sync ( dispatch_get _main _queue ( ) , ^ {
[ _pairAlert dismissWithClickedButtonIndex : 0 animated : NO ] ;
_pairAlert = [ [ UIAlertView alloc ] initWithTitle : @ "Pairing Failed" message : message delegate : self cancelButtonTitle : @ "Ok" otherButtonTitles : nil , nil ] ;
[ _pairAlert show ] ;
} ) ;
}
- ( void ) pairSuccessful {
dispatch_sync ( dispatch_get _main _queue ( ) , ^ {
[ _pairAlert dismissWithClickedButtonIndex : 0 animated : NO ] ;
_pairAlert = [ [ UIAlertView alloc ] initWithTitle : @ "Pairing Succesful" message : @ "Successfully paired to host" delegate : self cancelButtonTitle : @ "Ok" otherButtonTitles : nil , nil ] ;
[ _pairAlert show ] ;
} ) ;
}
2014-10-26 02:15:53 -04:00
- ( 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 ] ] ;
2014-12-04 18:41:01 +09:00
appList = [ HttpManager getAppListFromXML : appListResp ] ;
2014-10-26 02:15:53 -04:00
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2014-12-04 18:41:01 +09:00
[ self updateApps ] ;
2014-10-26 02:15:53 -04:00
} ) ;
[ AppManager retrieveAppAssets : appList withManager : hMan andCallback : self ] ;
} ) ;
}
- ( void ) receivedAssetForApp : ( App * ) app {
2014-12-04 18:41:01 +09:00
[ self . collectionView reloadData ] ;
2014-10-26 02:15:53 -04:00
}
2014-10-21 14:31:03 -04:00
- ( void ) displayDnsFailedDialog {
UIAlertController * alert = [ UIAlertController alertControllerWithTitle : @ "Network Error"
message : @ "Failed to resolve host."
preferredStyle : UIAlertControllerStyleAlert ] ;
[ alert addAction : [ UIAlertAction actionWithTitle : @ "Ok" style : UIAlertActionStyleDestructive handler : nil ] ] ;
[ self presentViewController : alert animated : YES completion : nil ] ;
}
2014-10-26 02:15:53 -04:00
- ( void ) hostClicked : ( Computer * ) computer {
NSLog ( @ "Clicked host: %@" , computer . displayName ) ;
_selectedHost = computer ;
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
HttpManager * hMan = [ [ HttpManager alloc ] initWithHost : computer . hostName uniqueId : _uniqueId deviceName : deviceName cert : _cert ] ;
NSData * serverInfoResp = [ hMan executeRequestSynchronously : [ hMan newServerInfoRequest ] ] ;
if ( [ [ HttpManager getStringFromXML : serverInfoResp tag : @ "PairStatus" ] isEqualToString : @ "1" ] ) {
NSLog ( @ "Already Paired" ) ;
[ self alreadyPaired ] ;
} else {
NSLog ( @ "Trying to pair" ) ;
PairManager * pMan = [ [ PairManager alloc ] initWithManager : hMan andCert : _cert callback : self ] ;
[ _opQueue addOperation : pMan ] ;
}
} ) ;
}
- ( void ) addHostClicked {
NSLog ( @ "Clicked add host" ) ;
UIAlertController * alertController = [ UIAlertController alertControllerWithTitle : @ "Host Address" message : @ "Please enter a hostname or IP address" preferredStyle : UIAlertControllerStyleAlert ] ;
[ alertController addAction : [ UIAlertAction actionWithTitle : @ "Cancel" style : UIAlertActionStyleCancel handler : nil ] ] ;
[ alertController addAction : [ UIAlertAction actionWithTitle : @ "OK" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * action ) {
NSString * host = ( ( UITextField * ) [ [ alertController textFields ] objectAtIndex : 0 ] ) . text ;
Computer * newHost = [ [ Computer alloc ] initWithIp : host ] ;
[ hostList addObject : newHost ] ;
[ self updateHosts : [ hostList allObjects ] ] ;
2014-11-26 17:57:16 -05:00
DataManager * dataMan = [ [ DataManager alloc ] init ] ;
[ dataMan createHost : newHost . displayName hostname : newHost . hostName ] ;
[ dataMan saveHosts ] ;
2014-10-26 02:15:53 -04:00
// TODO : get pair state
} ] ] ;
[ alertController addTextFieldWithConfigurationHandler : nil ] ;
[ self presentViewController : alertController animated : YES completion : nil ] ;
}
- ( void ) appClicked : ( App * ) app {
NSLog ( @ "Clicked app: %@" , app . appName ) ;
2014-10-20 20:54:03 -04:00
streamConfig = [ [ StreamConfiguration alloc ] init ] ;
streamConfig . host = _selectedHost . hostName ;
streamConfig . hostAddr = [ Utils resolveHost : _selectedHost . hostName ] ;
2014-10-26 02:15:53 -04:00
streamConfig . appID = app . appId ;
2014-10-21 14:31:03 -04:00
if ( streamConfig . hostAddr = = 0 ) {
[ self displayDnsFailedDialog ] ;
return ;
}
2014-10-20 20:54:03 -04:00
2014-10-29 00:47:51 -04:00
DataManager * dataMan = [ [ DataManager alloc ] init ] ;
Settings * streamSettings = [ dataMan retrieveSettings ] ;
streamConfig . frameRate = [ streamSettings . framerate intValue ] ;
streamConfig . bitRate = [ streamSettings . bitrate intValue ] ;
streamConfig . height = [ streamSettings . height intValue ] ;
streamConfig . width = [ streamSettings . width intValue ] ;
[ self performSegueWithIdentifier : @ "createStreamFrame" sender : nil ] ;
}
- ( void ) revealController : ( SWRevealViewController * ) revealController didMoveToPosition : ( FrontViewPosition ) position {
// If we moved back to the center position , we should save the settings
if ( position = = FrontViewPositionLeft ) {
[ ( SettingsViewController * ) [ revealController rearViewController ] saveSettings ] ;
2014-10-20 20:54:03 -04:00
}
2014-08-31 13:13:46 -04:00
}
- ( void ) viewDidLoad
{
[ super viewDidLoad ] ;
2014-10-29 00:47:51 -04:00
// Set the side bar button action . When it ' s tapped , it ' ll show up the sidebar .
2014-12-04 18:41:01 +09:00
[ _limelightLogoButton addTarget : self . revealViewController action : @ selector ( revealToggle : ) forControlEvents : UIControlEventTouchDown ] ;
2014-10-29 00:47:51 -04:00
// Set the gesture
[ self . view addGestureRecognizer : self . revealViewController . panGestureRecognizer ] ;
[ self . revealViewController setDelegate : self ] ;
// NSArray * streamConfigVals = [ [ NSArray alloc ] initWithObjects : @ "1280x720 (30Hz)" , @ "1280x720 (60Hz)" , @ "1920x1080 (30Hz)" , @ "1920x1080 (60Hz)" , nil ] ;
2014-10-19 04:19:54 -04:00
2014-10-21 05:11:51 -04:00
_opQueue = [ [ NSOperationQueue alloc ] init ] ;
2014-10-26 02:15:53 -04:00
[ CryptoManager generateKeyPairUsingSSl ] ;
_uniqueId = [ CryptoManager getUniqueID ] ;
_cert = [ CryptoManager readCertFromFile ] ;
2014-10-21 13:39:14 -04:00
2014-10-29 00:47:51 -04:00
// Only initialize the host picker list once
2014-10-26 02:15:53 -04:00
if ( hostList = = nil ) {
hostList = [ [ NSMutableSet alloc ] init ] ;
}
2014-10-24 16:02:10 -04:00
2014-10-29 00:47:51 -04:00
[ self setAutomaticallyAdjustsScrollViewInsets : NO ] ;
2014-10-26 02:15:53 -04:00
hostScrollView = [ [ UIScrollView alloc ] init ] ;
2014-10-29 00:47:51 -04:00
hostScrollView . frame = CGRectMake ( 0 , self . navigationController . navigationBar . frame . origin . y + self . navigationController . navigationBar . frame . size . height , self . view . frame . size . width , self . view . frame . size . height / 2 ) ;
2014-10-24 16:02:10 -04:00
[ hostScrollView setShowsHorizontalScrollIndicator : NO ] ;
2014-10-29 00:47:51 -04:00
2014-11-26 17:57:16 -05:00
[ self retrieveSavedHosts ] ;
2014-10-26 02:15:53 -04:00
[ self updateHosts : [ hostList allObjects ] ] ;
2014-10-24 16:02:10 -04:00
[ self . view addSubview : hostScrollView ] ;
2014-10-21 05:11:51 -04:00
}
- ( void ) viewDidAppear : ( BOOL ) animated
{
2014-11-26 17:57:16 -05:00
[ super viewDidAppear : animated ] ;
2014-10-29 00:47:51 -04:00
[ self . navigationController setNavigationBarHidden : NO animated : YES ] ;
2014-12-04 18:41:01 +09:00
// Hide 1 px border line
UIImage * fakeImage = [ [ UIImage alloc ] init ] ;
[ self . navigationController . navigationBar setShadowImage : fakeImage ] ;
[ self . navigationController . navigationBar setBackgroundImage : fakeImage forBarPosition : UIBarPositionAny barMetrics : UIBarMetricsDefault ] ;
2014-10-26 02:15:53 -04:00
_mDNSManager = [ [ MDNSManager alloc ] initWithCallback : self ] ;
[ _mDNSManager searchForHosts ] ;
2014-10-21 05:11:51 -04:00
}
- ( void ) viewDidDisappear : ( BOOL ) animated
{
2014-11-26 17:57:16 -05:00
[ super viewDidDisappear : animated ] ;
2014-10-26 02:15:53 -04:00
[ _mDNSManager stopSearching ] ;
2014-10-14 19:21:48 -04:00
}
2014-11-26 17:57:16 -05:00
- ( void ) retrieveSavedHosts {
// TODO : Get rid of Computer and only use Host
DataManager * dataMan = [ [ DataManager alloc ] init ] ;
NSArray * hosts = [ dataMan retrieveHosts ] ;
for ( Host * host in hosts ) {
Computer * comp = [ [ Computer alloc ] initWithIp : host . address ] ;
comp . displayName = host . name ;
[ hostList addObject : comp ] ;
}
}
2014-10-14 19:21:48 -04:00
- ( void ) updateHosts : ( NSArray * ) hosts {
2014-10-26 02:15:53 -04:00
[ hostList addObjectsFromArray : hosts ] ;
[ [ hostScrollView subviews ] makeObjectsPerformSelector : @ selector ( removeFromSuperview ) ] ;
UIComputerView * addComp = [ [ UIComputerView alloc ] initForAddWithCallback : self ] ;
UIComputerView * compView ;
float prevEdge = -1 ;
for ( Computer * comp in hostList ) {
compView = [ [ UIComputerView alloc ] initWithComputer : comp andCallback : self ] ;
compView . center = CGPointMake ( [ self getCompViewX : compView addComp : addComp prevEdge : prevEdge ] , hostScrollView . frame . size . height / 2 ) ;
prevEdge = compView . frame . origin . x + compView . frame . size . width ;
[ hostScrollView addSubview : compView ] ;
}
prevEdge = [ self getCompViewX : addComp addComp : addComp prevEdge : prevEdge ] ;
addComp . center = CGPointMake ( prevEdge , hostScrollView . frame . size . height / 2 ) ;
2014-10-21 13:39:14 -04:00
2014-10-26 02:15:53 -04:00
[ hostScrollView addSubview : addComp ] ;
[ hostScrollView setContentSize : CGSizeMake ( prevEdge + addComp . frame . size . width , hostScrollView . frame . size . height ) ] ;
}
- ( float ) getCompViewX : ( UIComputerView * ) comp addComp : ( UIComputerView * ) addComp prevEdge : ( float ) prevEdge {
if ( prevEdge = = -1 ) {
return hostScrollView . frame . origin . x + comp . frame . size . width / 2 + addComp . frame . size . width / 2 ;
} else {
return prevEdge + addComp . frame . size . width / 2 + comp . frame . size . width / 2 ;
}
}
2014-12-04 18:41:01 +09:00
- ( void ) updateApps {
[ hostScrollView removeFromSuperview ] ;
[ self . collectionView reloadData ] ;
2014-10-26 02:15:53 -04:00
}
2014-12-04 18:41:01 +09:00
- ( UICollectionViewCell * ) collectionView : ( UICollectionView * ) collectionView cellForItemAtIndexPath : ( NSIndexPath * ) indexPath {
UICollectionViewCell * cell = [ collectionView dequeueReusableCellWithReuseIdentifier : @ "AppCell" forIndexPath : indexPath ] ;
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 ) ;
2014-10-21 13:39:14 -04:00
}
2014-12-04 18:41:01 +09:00
[ cell . subviews . firstObject removeFromSuperview ] ; // Remove a view that was previously added
[ cell addSubview : appView ] ;
return cell ;
}
- ( NSInteger ) numberOfSectionsInCollectionView : ( UICollectionView * ) collectionView {
return 1 ; // App collection only
}
- ( NSInteger ) collectionView : ( UICollectionView * ) collectionView numberOfItemsInSection : ( NSInteger ) section {
return appList . count ;
2014-08-31 13:13:46 -04:00
}
2014-10-21 13:46:05 -04:00
- ( BOOL ) validatePcSelected {
if ( _selectedHost = = NULL ) {
UIAlertController * alert = [ UIAlertController alertControllerWithTitle : @ "No PC Selected"
message : @ "You must select a PC to continue."
preferredStyle : UIAlertControllerStyleAlert ] ;
[ alert addAction : [ UIAlertAction actionWithTitle : @ "Ok" style : UIAlertActionStyleDestructive handler : nil ] ] ;
[ self presentViewController : alert animated : YES completion : nil ] ;
return FALSE ;
}
return TRUE ;
}
2014-08-31 13:13:46 -04:00
- ( void ) didReceiveMemoryWarning
{
[ super didReceiveMemoryWarning ] ;
// Dispose of any resources that can be recreated .
}
2014-10-20 21:39:40 -04:00
2014-10-20 21:45:37 -04:00
- ( void ) touchesBegan : ( NSSet * ) touches withEvent : ( UIEvent * ) event {
[ self . view endEditing : YES ] ;
}
- ( BOOL ) textFieldShouldReturn : ( UITextField * ) textField {
[ textField resignFirstResponder ] ;
return YES ;
}
2014-10-20 21:39:40 -04:00
- ( BOOL ) shouldAutorotate {
return YES ;
}
2014-08-31 13:13:46 -04:00
@ end