2014-08-31 13:13:46 -04:00
// MainFrameViewController . m
2015-05-12 21:48:30 -04:00
// Moonlight
2014-08-31 13:13:46 -04:00
//
// Created by Diego Waxemberg on 1 / 17 / 14.
2015-05-12 21:48:30 -04:00
// Copyright ( c ) 2014 Moonlight Stream . All rights reserved .
2014-08-31 13:13:46 -04:00
//
# import "MainFrameViewController.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"
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"
2015-01-02 19:15:47 -05:00
# import "WakeOnLanManager.h"
2015-02-01 04:26:47 -05:00
# import "AppListResponse.h"
# import "ServerInfoResponse.h"
2015-02-01 19:46:28 -05:00
# import "StreamFrameViewController.h"
2015-02-24 22:13:33 -05:00
# import "LoadingFrameViewController.h"
2014-08-31 13:13:46 -04:00
2014-10-20 11:31:40 -04:00
@ implementation MainFrameViewController {
NSOperationQueue * _opQueue ;
2015-01-01 22:30:03 -05:00
Host * _selectedHost ;
2014-10-26 02:15:53 -04:00
NSString * _uniqueId ;
NSData * _cert ;
2015-01-01 16:50:10 -05:00
NSString * _currentGame ;
2015-01-01 22:30:03 -05:00
DiscoveryManager * _discMan ;
2015-01-31 20:10:14 -05:00
AppAssetManager * _appManager ;
2015-02-01 19:46:28 -05:00
StreamConfiguration * _streamConfig ;
2014-10-20 13:35:42 -04:00
UIAlertView * _pairAlert ;
2014-10-26 02:15:53 -04:00
UIScrollView * hostScrollView ;
2015-01-01 16:50:10 -05:00
int currentPosition ;
2014-10-20 11:31:40 -04:00
}
2014-10-26 02:15:53 -04:00
static NSMutableSet * hostList ;
2014-12-04 18:41:01 +09:00
static NSArray * appList ;
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 ] ;
2015-01-02 23:57:11 -05:00
[ _discMan startDiscovery ] ;
2015-02-24 22:33:14 -05:00
[ self hideLoadingFrame ] ;
2014-10-20 13:35:42 -04:00
} ) ;
}
- ( 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 ] ;
2015-01-02 23:57:11 -05:00
[ _discMan startDiscovery ] ;
2015-02-24 22:33:14 -05:00
[ self hideLoadingFrame ] ;
2014-10-20 13:35:42 -04:00
} ) ;
}
2014-10-26 02:15:53 -04:00
- ( void ) alreadyPaired {
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2015-01-01 22:30:03 -05:00
_computerNameButton . title = _selectedHost . name ;
2015-01-31 01:57:23 -05:00
[ self . navigationController . navigationBar setNeedsLayout ] ;
2014-10-26 02:15:53 -04:00
} ) ;
2015-01-01 22:30:03 -05:00
HttpManager * hMan = [ [ HttpManager alloc ] initWithHost : _selectedHost . address uniqueId : _uniqueId deviceName : deviceName cert : _cert ] ;
2015-02-01 04:26:47 -05:00
AppListResponse * appListResp = [ [ AppListResponse alloc ] init ] ;
[ hMan executeRequestSynchronously : [ HttpRequest requestForResponse : appListResp withUrlRequest : [ hMan newAppListRequest ] ] ] ;
2015-01-31 01:57:23 -05:00
if ( appListResp = = nil || ! [ appListResp isStatusOk ] ) {
2015-02-10 21:26:55 -05:00
Log ( LOG_W , @ "Failed to get applist: %@" , appListResp . statusMessage ) ;
2015-01-31 01:57:23 -05:00
} else {
appList = [ appListResp getAppList ] ;
if ( appList = = nil ) {
2015-02-10 21:26:55 -05:00
Log ( LOG_W , @ "Failed to parse applist" ) ;
2015-01-31 01:57:23 -05:00
} else {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self updateApps ] ;
} ) ;
[ _appManager stopRetrieving ] ;
[ _appManager retrieveAssets : appList fromHost : _selectedHost ] ;
}
}
2015-04-05 17:25:05 -07:00
[ self hideLoadingFrame ] ;
2014-10-26 02:15:53 -04:00
} ) ;
}
2014-12-04 19:54:21 +09:00
- ( void ) showHostSelectionView {
appList = [ [ NSArray alloc ] init ] ;
2015-02-10 18:40:22 -05:00
[ _appManager stopRetrieving ] ;
2015-01-01 23:30:18 -05:00
_computerNameButton . title = @ "No Host Selected" ;
2014-12-04 19:54:21 +09:00
[ self . collectionView reloadData ] ;
[ self . view addSubview : hostScrollView ] ;
}
2014-10-26 02:15:53 -04:00
- ( 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 ] ;
}
2015-01-01 22:30:03 -05:00
- ( void ) hostClicked : ( Host * ) host {
2015-02-10 21:26:55 -05:00
Log ( LOG_D , @ "Clicked host: %@" , host . name ) ;
2015-02-24 22:33:14 -05:00
[ self showLoadingFrame ] ;
2015-01-01 22:30:03 -05:00
_selectedHost = host ;
2014-10-26 02:15:53 -04:00
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
2015-01-01 22:30:03 -05:00
HttpManager * hMan = [ [ HttpManager alloc ] initWithHost : host . address uniqueId : _uniqueId deviceName : deviceName cert : _cert ] ;
2015-02-01 04:26:47 -05:00
ServerInfoResponse * serverInfoResp = [ [ ServerInfoResponse alloc ] init ] ;
[ hMan executeRequestSynchronously : [ HttpRequest requestForResponse : serverInfoResp withUrlRequest : [ hMan newServerInfoRequest ] ] ] ;
2015-01-31 01:57:23 -05:00
if ( serverInfoResp = = nil || ! [ serverInfoResp isStatusOk ] ) {
2015-02-10 21:26:55 -05:00
Log ( LOG_W , @ "Failed to get server info: %@" , serverInfoResp . statusMessage ) ;
2015-04-05 17:25:05 -07:00
[ self hideLoadingFrame ] ;
2014-10-26 02:15:53 -04:00
} else {
2015-02-10 21:26:55 -05:00
Log ( LOG_D , @ "server info pair status: %@" , [ serverInfoResp getStringTag : @ "PairStatus" ] ) ;
2015-02-01 04:26:47 -05:00
if ( [ [ serverInfoResp getStringTag : @ "PairStatus" ] isEqualToString : @ "1" ] ) {
2015-02-10 21:26:55 -05:00
Log ( LOG_I , @ "Already Paired" ) ;
2015-01-31 01:57:23 -05:00
[ self alreadyPaired ] ;
} else {
2015-02-10 21:26:55 -05:00
Log ( LOG_I , @ "Trying to pair" ) ;
2015-01-31 01:57:23 -05:00
// Polling the server while pairing causes the server to screw up
[ _discMan stopDiscoveryBlocking ] ;
PairManager * pMan = [ [ PairManager alloc ] initWithManager : hMan andCert : _cert callback : self ] ;
[ _opQueue addOperation : pMan ] ;
}
2014-10-26 02:15:53 -04:00
}
} ) ;
}
2015-01-08 19:37:51 -05:00
- ( void ) hostLongClicked : ( Host * ) host view : ( UIView * ) view {
2015-02-10 21:26:55 -05:00
Log ( LOG_D , @ "Long clicked host: %@" , host . name ) ;
2015-01-01 23:25:09 -05:00
UIAlertController * longClickAlert = [ UIAlertController alertControllerWithTitle : host . name message : @ "" preferredStyle : UIAlertControllerStyleActionSheet ] ;
2015-01-02 19:15:47 -05:00
if ( host . online ) {
[ longClickAlert addAction : [ UIAlertAction actionWithTitle : @ "Unpair" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * action ) {
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
HttpManager * hMan = [ [ HttpManager alloc ] initWithHost : host . address uniqueId : _uniqueId deviceName : deviceName cert : _cert ] ;
2015-02-01 04:26:47 -05:00
[ hMan executeRequest : [ HttpRequest requestWithUrlRequest : [ hMan newUnpairRequest ] ] ] ;
2015-01-02 19:15:47 -05:00
} ) ;
} ] ] ;
} else {
[ longClickAlert addAction : [ UIAlertAction actionWithTitle : @ "Wake" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * action ) {
UIAlertController * wolAlert = [ UIAlertController alertControllerWithTitle : @ "Wake On Lan" message : @ "" preferredStyle : UIAlertControllerStyleAlert ] ;
[ wolAlert addAction : [ UIAlertAction actionWithTitle : @ "OK" style : UIAlertActionStyleDefault handler : nil ] ] ;
if ( host . pairState ! = PairStatePaired ) {
wolAlert . message = @ "Cannot wake host because you are not paired" ;
} else if ( host . mac = = nil || [ host . mac isEqualToString : @ "00:00:00:00:00:00" ] ) {
wolAlert . message = @ "Host MAC unknown, unable to send WOL Packet" ;
} else {
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
[ WakeOnLanManager wakeHost : host ] ;
} ) ;
wolAlert . message = @ "Sent WOL Packet" ;
}
[ self presentViewController : wolAlert animated : YES completion : nil ] ;
} ] ] ;
}
2015-01-01 23:25:09 -05:00
[ longClickAlert addAction : [ UIAlertAction actionWithTitle : @ "Remove Host" style : UIAlertActionStyleDestructive handler : ^ ( UIAlertAction * action ) {
[ _discMan removeHostFromDiscovery : host ] ;
2015-01-01 23:40:52 -05:00
DataManager * dataMan = [ [ DataManager alloc ] init ] ;
[ dataMan removeHost : host ] ;
2015-01-08 19:37:51 -05:00
@ synchronized ( hostList ) {
[ hostList removeObject : host ] ;
}
[ self updateAllHosts : [ hostList allObjects ] ] ;
2015-01-01 23:25:09 -05:00
} ] ] ;
[ longClickAlert addAction : [ UIAlertAction actionWithTitle : @ "Cancel" style : UIAlertActionStyleCancel handler : nil ] ] ;
2015-01-08 19:37:51 -05:00
// these two lines are required for iPad support of UIAlertSheet
longClickAlert . popoverPresentationController . sourceView = view ;
2015-01-31 01:57:23 -05:00
2015-01-08 19:37:51 -05:00
longClickAlert . popoverPresentationController . sourceRect = CGRectMake ( view . bounds . size . width / 2.0 , view . bounds . size . height / 2.0 , 1.0 , 1.0 ) ; // center of the view
2015-01-01 23:25:09 -05:00
[ self presentViewController : longClickAlert animated : YES completion : ^ {
[ self updateHosts ] ;
} ] ;
}
2014-10-26 02:15:53 -04:00
- ( void ) addHostClicked {
2015-02-10 21:26:55 -05:00
Log ( LOG_D , @ "Clicked add host" ) ;
2015-02-24 22:33:14 -05:00
[ self showLoadingFrame ] ;
2014-10-26 02:15:53 -04:00
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 ) {
2015-01-01 22:30:03 -05:00
NSString * hostAddress = ( ( UITextField * ) [ [ alertController textFields ] objectAtIndex : 0 ] ) . text ;
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _HIGH , 0 ) , ^ {
2015-02-10 17:40:49 -05:00
[ _discMan discoverHost : hostAddress withCallback : ^ ( Host * host , NSString * error ) {
2015-01-01 22:30:03 -05:00
if ( host ! = nil ) {
DataManager * dataMan = [ [ DataManager alloc ] init ] ;
[ dataMan saveHosts ] ;
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2015-01-01 23:54:54 -05:00
@ synchronized ( hostList ) {
[ hostList addObject : host ] ;
}
2015-01-01 22:30:03 -05:00
[ self updateHosts ] ;
} ) ;
} else {
2015-02-10 17:40:49 -05:00
UIAlertController * hostNotFoundAlert = [ UIAlertController alertControllerWithTitle : @ "Add Host" message : error preferredStyle : UIAlertControllerStyleAlert ] ;
2015-01-01 22:30:03 -05:00
[ hostNotFoundAlert addAction : [ UIAlertAction actionWithTitle : @ "Ok" style : UIAlertActionStyleDestructive handler : nil ] ] ;
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
[ self presentViewController : hostNotFoundAlert animated : YES completion : nil ] ;
} ) ;
}
} ] ; } ) ;
2014-10-26 02:15:53 -04:00
} ] ] ;
[ alertController addTextFieldWithConfigurationHandler : nil ] ;
2015-02-24 22:33:14 -05:00
[ self hideLoadingFrame ] ;
2014-10-26 02:15:53 -04:00
[ self presentViewController : alertController animated : YES completion : nil ] ;
}
- ( void ) appClicked : ( App * ) app {
2015-02-10 21:26:55 -05:00
Log ( LOG_D , @ "Clicked app: %@" , app . appName ) ;
2015-02-01 19:46:28 -05:00
_streamConfig = [ [ StreamConfiguration alloc ] init ] ;
_streamConfig . host = _selectedHost . address ;
_streamConfig . appID = app . appId ;
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 ] ;
2015-02-01 19:46:28 -05:00
_streamConfig . frameRate = [ streamSettings . framerate intValue ] ;
_streamConfig . bitRate = [ streamSettings . bitrate intValue ] ;
_streamConfig . height = [ streamSettings . height intValue ] ;
_streamConfig . width = [ streamSettings . width intValue ] ;
2014-10-29 00:47:51 -04:00
2015-05-28 23:47:30 -07:00
[ _appManager stopRetrieving ] ;
2014-11-27 11:36:28 -05:00
if ( currentPosition ! = FrontViewPositionLeft ) {
[ [ self revealViewController ] revealToggle : self ] ;
}
2015-01-01 16:50:10 -05:00
App * currentApp = [ self findRunningApp ] ;
if ( currentApp ! = nil ) {
2015-01-09 17:25:18 -05:00
UIAlertController * alertController = [ UIAlertController
2015-01-31 01:57:23 -05:00
alertControllerWithTitle : app . appName
message : [ app . appId isEqualToString : currentApp . appId ] ? @ "" : [ NSString stringWithFormat : @ "%@ is currently running" , currentApp . appName ] preferredStyle : UIAlertControllerStyleAlert ] ;
2015-01-09 17:25:18 -05:00
[ alertController addAction : [ UIAlertAction
2015-01-31 01:57:23 -05:00
actionWithTitle : [ app . appId isEqualToString : currentApp . appId ] ? @ "Resume App" : @ "Resume Running App" style : UIAlertActionStyleDefault handler : ^ ( UIAlertAction * action ) {
2015-02-10 21:26:55 -05:00
Log ( LOG_I , @ "Resuming application: %@" , currentApp . appName ) ;
2015-01-31 01:57:23 -05:00
[ self performSegueWithIdentifier : @ "createStreamFrame" sender : nil ] ;
} ] ] ;
2015-01-09 17:25:18 -05:00
[ alertController addAction : [ UIAlertAction actionWithTitle :
2015-01-31 01:57:23 -05:00
[ app . appId isEqualToString : currentApp . appId ] ? @ "Quit App" : @ "Quit Running App and Start" style : UIAlertActionStyleDestructive handler : ^ ( UIAlertAction * action ) {
2015-02-10 21:26:55 -05:00
Log ( LOG_I , @ "Quitting application: %@" , currentApp . appName ) ;
2015-01-31 01:57:23 -05:00
dispatch_async ( dispatch_get _global _queue ( DISPATCH_QUEUE _PRIORITY _DEFAULT , 0 ) , ^ {
HttpManager * hMan = [ [ HttpManager alloc ] initWithHost : _selectedHost . address uniqueId : _uniqueId deviceName : deviceName cert : _cert ] ;
2015-02-01 04:26:47 -05:00
[ hMan executeRequestSynchronously : [ HttpRequest requestWithUrlRequest : [ hMan newQuitAppRequest ] ] ] ;
2015-01-31 01:57:23 -05:00
// 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 ] ;
} ) ;
}
} ) ;
} ] ] ;
2015-01-01 16:50:10 -05:00
[ 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 ;
}
2014-10-29 00:47:51 -04:00
- ( 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-11-27 11:36:28 -05:00
currentPosition = position ;
2014-08-31 13:13:46 -04:00
}
2015-02-01 19:46:28 -05:00
- ( void ) prepareForSegue : ( UIStoryboardSegue * ) segue sender : ( id ) sender {
if ( [ segue . destinationViewController isKindOfClass : [ StreamFrameViewController class ] ] ) {
StreamFrameViewController * streamFrame = segue . destinationViewController ;
streamFrame . streamConfig = _streamConfig ;
}
}
2015-02-24 22:13:33 -05:00
- ( void ) showLoadingFrame {
LoadingFrameViewController * loadingFrame = [ self . storyboard instantiateViewControllerWithIdentifier : @ "loadingFrame" ] ;
[ self . navigationController presentViewController : loadingFrame animated : YES completion : nil ] ;
}
- ( void ) hideLoadingFrame {
[ self dismissViewControllerAnimated : YES completion : nil ] ;
}
2014-08-31 13:13:46 -04:00
- ( void ) viewDidLoad
{
[ super viewDidLoad ] ;
2014-10-29 00:47:51 -04:00
2015-02-01 19:46:28 -05:00
// Set the side bar button action . When it ' s tapped , it ' ll show 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
2015-02-01 19:46:28 -05:00
// Set the host name button action . When it ' s tapped , it ' ll show the host selection view .
2014-12-04 19:54:21 +09:00
[ _computerNameButton setTarget : self ] ;
[ _computerNameButton setAction : @ selector ( showHostSelectionView ) ] ;
2014-10-29 00:47:51 -04:00
// Set the gesture
[ self . view addGestureRecognizer : self . revealViewController . panGestureRecognizer ] ;
2014-11-27 13:56:39 -05:00
// Get callbacks associated with the viewController
2014-10-29 00:47:51 -04:00
[ self . revealViewController setDelegate : self ] ;
2014-11-27 11:36:28 -05:00
// Set the current position to the center
currentPosition = FrontViewPositionLeft ;
2014-10-19 04:19:54 -04:00
2014-11-27 13:56:39 -05:00
// Set up crypto
2014-10-26 02:15:53 -04:00
[ CryptoManager generateKeyPairUsingSSl ] ;
_uniqueId = [ CryptoManager getUniqueID ] ;
_cert = [ CryptoManager readCertFromFile ] ;
2015-01-31 20:10:14 -05:00
_appManager = [ [ AppAssetManager alloc ] initWithCallback : self ] ;
2015-02-01 19:46:28 -05:00
_opQueue = [ [ NSOperationQueue alloc ] init ] ;
2015-01-08 22:18:26 -05: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 ] ;
2015-01-01 22:30:03 -05:00
_discMan = [ [ DiscoveryManager alloc ] initWithHosts : [ hostList allObjects ] andCallback : self ] ;
[ self updateHosts ] ;
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 ] ;
2015-01-01 22:30:03 -05:00
[ _discMan startDiscovery ] ;
2015-01-01 16:50:10 -05:00
// This will refresh the applist
if ( _selectedHost ! = nil ) {
[ self hostClicked : _selectedHost ] ;
}
2014-10-21 05:11:51 -04:00
}
- ( void ) viewDidDisappear : ( BOOL ) animated
{
2014-11-26 17:57:16 -05:00
[ super viewDidDisappear : animated ] ;
2015-01-01 22:30:03 -05:00
// when discovery stops , we must create a new instance because you cannot restart an NSOperation when it is finished
[ _discMan stopDiscovery ] ;
2015-01-31 01:57:23 -05:00
2015-01-01 22:30:03 -05:00
// In case the host objects were updated in the background
[ [ [ DataManager alloc ] init ] saveHosts ] ;
2014-10-14 19:21:48 -04:00
}
2014-11-26 17:57:16 -05:00
- ( void ) retrieveSavedHosts {
DataManager * dataMan = [ [ DataManager alloc ] init ] ;
NSArray * hosts = [ dataMan retrieveHosts ] ;
2015-01-01 23:54:54 -05:00
@ synchronized ( hostList ) {
[ hostList addObjectsFromArray : hosts ] ;
}
2014-11-26 17:57:16 -05:00
}
2015-01-01 22:30:03 -05:00
- ( void ) updateAllHosts : ( NSArray * ) hosts {
dispatch_async ( dispatch_get _main _queue ( ) , ^ {
2015-02-10 21:26:55 -05:00
Log ( LOG_D , @ "New host list:" ) ;
2015-01-01 22:30:03 -05:00
for ( Host * host in hosts ) {
2015-02-10 21:26:55 -05:00
Log ( LOG_D , @ "Host: \n{\n\t name:%@ \n\t address:%@ \n\t localAddress:%@ \n\t externalAddress:%@ \n\t uuid:%@ \n\t mac:%@ \n\t pairState:%d \n\t online:%d \n}" , host . name , host . address , host . localAddress , host . externalAddress , host . uuid , host . mac , host . pairState , host . online ) ;
2015-01-01 22:30:03 -05:00
}
2015-01-01 23:54:54 -05:00
@ synchronized ( hostList ) {
[ hostList removeAllObjects ] ;
[ hostList addObjectsFromArray : hosts ] ;
}
2015-01-01 22:30:03 -05:00
[ self updateHosts ] ;
} ) ;
}
- ( void ) updateHosts {
2015-02-10 21:26:55 -05:00
Log ( LOG_I , @ "Updating hosts..." ) ;
2014-10-26 02:15:53 -04:00
[ [ hostScrollView subviews ] makeObjectsPerformSelector : @ selector ( removeFromSuperview ) ] ;
UIComputerView * addComp = [ [ UIComputerView alloc ] initForAddWithCallback : self ] ;
UIComputerView * compView ;
float prevEdge = -1 ;
2015-01-01 23:54:54 -05:00
@ synchronized ( hostList ) {
for ( Host * 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 ] ;
}
2014-10-26 02:15:53 -04:00
}
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 ] ;
2015-01-01 16:50:10 -05:00
2014-12-04 18:41:01 +09:00
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
}
2015-01-01 16:50:10 -05:00
2014-12-04 18:41:01 +09:00
[ cell . subviews . firstObject removeFromSuperview ] ; // Remove a view that was previously added
[ cell addSubview : appView ] ;
2015-01-01 16:50:10 -05:00
2014-12-04 18:41:01 +09:00
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
}
- ( 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 ;
}
2015-02-01 19:46:28 -05:00
2014-08-31 13:13:46 -04:00
@ end