App lists are now persisted in the database

This commit is contained in:
Diego Waxemberg
2015-07-10 21:22:57 -07:00
parent 5dee29a21c
commit 642085ca32
19 changed files with 267 additions and 149 deletions

View File

@@ -1,18 +0,0 @@
//
// App.h
// Moonlight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface App : NSObject
@property NSString* appId;
@property NSString* appName;
@property UIImage* appImage;
@property BOOL isRunning;
@end

View File

@@ -1,15 +0,0 @@
//
// App.m
// Moonlight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "App.h"
#import "HttpManager.h"
@implementation App
@synthesize appId, appName, appImage, isRunning;
@end

View File

@@ -0,0 +1,25 @@
//
// App+CoreDataProperties.h
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
// Delete this file and regenerate it using "Create NSManagedObject Subclass…"
// to keep your implementation up to date with your model.
//
#import "App.h"
NS_ASSUME_NONNULL_BEGIN
@interface App (CoreDataProperties)
@property (nullable, nonatomic, retain) NSString *id;
@property (nullable, nonatomic, retain) NSData *image;
@property (nullable, nonatomic, retain) NSString *name;
@property (nullable, nonatomic, retain) Host *host;
@end
NS_ASSUME_NONNULL_END

24
Limelight/Database/App.h Normal file
View File

@@ -0,0 +1,24 @@
//
// App.h
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@class Host;
NS_ASSUME_NONNULL_BEGIN
@interface App : NSManagedObject
@property BOOL isRunning;
@end
NS_ASSUME_NONNULL_END
#import "App+CoreDataProperties.h"

16
Limelight/Database/App.m Normal file
View File

@@ -0,0 +1,16 @@
//
// App.m
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import "App.h"
#import "Host.h"
@implementation App
@synthesize isRunning;
@end

View File

@@ -10,6 +10,7 @@
#import "Settings.h"
#import "AppDelegate.h"
#import "Host.h"
#import "App.h"
@interface DataManager : NSObject
@@ -21,5 +22,6 @@
- (void) saveHosts;
- (Host*) createHost;
- (void) removeHost:(Host*)host;
- (App*) createApp;
@end

View File

@@ -48,8 +48,7 @@
- (Host*) createHost {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]];
Host* host = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
return host;
return [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
}
- (void) removeHost:(Host*)host {
@@ -69,6 +68,11 @@
return [self fetchRecords:@"Host"];
}
- (App*) createApp {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:[self.appDelegate managedObjectContext]];
return [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
}
- (NSArray*) fetchRecords:(NSString*)entityName {
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[self.appDelegate managedObjectContext]];

View File

@@ -0,0 +1,38 @@
//
// Host+CoreDataProperties.h
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
// Delete this file and regenerate it using "Create NSManagedObject Subclass…"
// to keep your implementation up to date with your model.
//
#import "Host.h"
NS_ASSUME_NONNULL_BEGIN
@interface Host (CoreDataProperties)
@property (nullable, nonatomic, retain) NSString *address;
@property (nullable, nonatomic, retain) NSString *externalAddress;
@property (nullable, nonatomic, retain) NSString *localAddress;
@property (nullable, nonatomic, retain) NSString *mac;
@property (nullable, nonatomic, retain) NSString *name;
@property (nullable, nonatomic, retain) NSNumber *pairState;
@property (nullable, nonatomic, retain) NSString *uuid;
@property (nullable, nonatomic, retain) NSSet<NSManagedObject *> *appList;
@end
@interface Host (CoreDataGeneratedAccessors)
- (void)addAppListObject:(NSManagedObject *)value;
- (void)removeAppListObject:(NSManagedObject *)value;
- (void)addAppList:(NSSet<NSManagedObject *> *)values;
- (void)removeAppList:(NSSet<NSManagedObject *> *)values;
@end
NS_ASSUME_NONNULL_END

View File

@@ -2,24 +2,24 @@
// Host.h
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "Utils.h"
NS_ASSUME_NONNULL_BEGIN
@interface Host : NSManagedObject
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSString * localAddress;
@property (nonatomic, retain) NSString * externalAddress;
@property (nonatomic, retain) NSString * uuid;
@property (nonatomic, retain) NSString * mac;
@property (nonatomic) BOOL online;
@property (nonatomic) PairState pairState;
@property (nonatomic) NSString * activeAddress;
@end
NS_ASSUME_NONNULL_END
#import "Host+CoreDataProperties.h"

View File

@@ -2,21 +2,14 @@
// Host.m
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import "Host.h"
@implementation Host
@dynamic name;
@dynamic address;
@dynamic localAddress;
@dynamic externalAddress;
@dynamic uuid;
@dynamic mac;
@dynamic pairState;
@synthesize online;
@synthesize activeAddress;

View File

@@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>Limelight 0.3.1.xcdatamodel</string>
<string>Moonlight v1.0.xcdatamodel</string>
</dict>
</plist>

View File

@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="8118.17" systemVersion="15A204h" minimumToolsVersion="Automatic">
<entity name="App" representedClassName="App" syncable="YES">
<attribute name="id" attributeType="String" syncable="YES"/>
<attribute name="image" attributeType="Binary" allowsExternalBinaryDataStorage="YES" syncable="YES"/>
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
<relationship name="host" maxCount="1" deletionRule="Nullify" destinationEntity="Host" inverseName="appList" inverseEntity="Host" syncable="YES"/>
</entity>
<entity name="Host" representedClassName="Host" syncable="YES">
<attribute name="address" attributeType="String" syncable="YES"/>
<attribute name="externalAddress" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="localAddress" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="mac" optional="YES" attributeType="String" syncable="YES"/>
<attribute name="name" attributeType="String" syncable="YES"/>
<attribute name="pairState" optional="YES" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
<attribute name="uuid" optional="YES" attributeType="String" syncable="YES"/>
<relationship name="appList" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="App" inverseName="host" inverseEntity="App" syncable="YES"/>
</entity>
<entity name="Settings" representedClassName="Settings" syncable="YES">
<attribute name="bitrate" attributeType="Integer 32" defaultValueString="10000" syncable="YES"/>
<attribute name="framerate" attributeType="Integer 32" defaultValueString="60" syncable="YES"/>
<attribute name="height" attributeType="Integer 32" defaultValueString="720" syncable="YES"/>
<attribute name="onscreenControls" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
<attribute name="width" attributeType="Integer 32" defaultValueString="1280" syncable="YES"/>
</entity>
<elements>
<element name="App" positionX="0" positionY="54" width="128" height="103"/>
<element name="Host" positionX="0" positionY="0" width="128" height="163"/>
<element name="Settings" positionX="0" positionY="0" width="128" height="120"/>
</elements>
</model>

View File

@@ -15,8 +15,6 @@
@implementation AppAssetManager {
NSOperationQueue* _opQueue;
id<AppAssetCallback> _callback;
Host* _host;
NSMutableDictionary* _imageCache;
}
static const int MAX_REQUEST_COUNT = 4;
@@ -24,29 +22,22 @@ static const int MAX_REQUEST_COUNT = 4;
- (id) initWithCallback:(id<AppAssetCallback>)callback {
self = [super init];
_callback = callback;
_imageCache = [[NSMutableDictionary alloc] init];
_opQueue = [[NSOperationQueue alloc] init];
[_opQueue setMaxConcurrentOperationCount:MAX_REQUEST_COUNT];
return self;
}
- (void) retrieveAssets:(NSArray*)appList fromHost:(Host*)host {
Host* oldHost = _host;
_host = host;
BOOL useCache = [oldHost.uuid isEqualToString:_host.uuid];
Log(LOG_I, @"Using cached app images: %d", useCache);
if (!useCache) {
[_imageCache removeAllObjects];
}
for (App* app in appList) {
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
retriever.app = app;
retriever.host = _host;
retriever.callback = _callback;
retriever.cache = _imageCache;
retriever.useCache = useCache;
[_opQueue addOperation:retriever];
if (app.image == nil) {
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
retriever.app = app;
retriever.host = host;
retriever.callback = _callback;
[_opQueue addOperation:retriever];
}
}
}

View File

@@ -15,8 +15,6 @@
@property (nonatomic) Host* host;
@property (nonatomic) App* app;
@property (nonatomic) NSMutableDictionary* cache;
@property (nonatomic) id<AppAssetCallback> callback;
@property (nonatomic) BOOL useCache;
@end

View File

@@ -16,34 +16,18 @@
static const double RETRY_DELAY = 2; // seconds
static const int MAX_ATTEMPTS = 5;
- (void) main {
UIImage* appImage = nil;
int attempts = 0;
while (![self isCancelled] && appImage == nil && attempts++ < MAX_ATTEMPTS) {
if (self.useCache) {
@synchronized(self.cache) {
UIImage* cachedImage = [self.cache objectForKey:self.app.appId];
if (cachedImage != nil) {
appImage = cachedImage;
self.app.appImage = appImage;
}
}
}
if (appImage == nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[CryptoManager getUniqueID] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.appId]]];
appImage = [UIImage imageWithData:appAssetResp.data];
self.app.appImage = appImage;
if (appImage != nil) {
@synchronized(self.cache) {
[self.cache setObject:appImage forKey:self.app.appId];
}
}
}
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[CryptoManager getUniqueID] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.id]]];
appImage = [UIImage imageWithData:appAssetResp.data];
self.app.image = UIImagePNGRepresentation(appImage);
[NSThread sleepForTimeInterval:RETRY_DELAY];
}
[self performSelectorOnMainThread:@selector(sendCallbackForApp:) withObject:self.app waitUntilDone:NO];

View File

@@ -8,6 +8,7 @@
#import "AppListResponse.h"
#import "App.h"
#import "DataManager.h"
#import <libxml2/libxml/xmlreader.h>
@implementation AppListResponse {
@@ -59,6 +60,7 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
self.statusMessage = statusMsg;
node = node->children;
DataManager* dataMan = [[DataManager alloc] init];
while (node != NULL) {
//Log(LOG_D, @"node: %s", node->name);
@@ -93,11 +95,11 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
}
appInfoNode = appInfoNode->next;
}
App* app = [[App alloc] init];
app.appName = appName;
app.appId = appId;
App* app = [dataMan createApp];
app.name = appName;
app.id = appId;
app.isRunning = appIsRunning;
if (app.appId != nil) {
if (app.id != nil) {
[_appList addObject:app];
}
}

View File

@@ -24,7 +24,7 @@
_appButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage* noImage = [UIImage imageNamed:@"NoAppImage"];
[_appButton setBackgroundImage:noImage forState:UIControlStateNormal];
[_appButton setContentEdgeInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
[_appButton setContentEdgeInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
[_appButton sizeToFit];
[_appButton addTarget:self action:@selector(appClicked) forControlEvents:UIControlEventTouchUpInside];
@@ -54,18 +54,28 @@
- (void) updateAppImage {
[_appOverlay setHidden:!_app.isRunning];
if (_app.appImage != nil && !(_app.appImage.size.width == 130.f && _app.appImage.size.height == 180.f)) {
_appButton.frame = CGRectMake(0, 0, _app.appImage.size.width / 2, _app.appImage.size.height / 2);
self.frame = CGRectMake(0, 0, _app.appImage.size.width / 2, _app.appImage.size.height / 2);
_appOverlay.frame = CGRectMake(0, 0, self.frame.size.width / 2.f, self.frame.size.height / 4.f);
_appOverlay.layer.shadowRadius = 4.0;
[_appOverlay setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/6)];
[_appButton setBackgroundImage:_app.appImage forState:UIControlStateNormal];
[self setNeedsDisplay];
}
// TODO: Improve no-app image detection
if (_app.appImage == nil || (_app.appImage.size.width == 130.f && _app.appImage.size.height == 180.f)) { // This size of image might be blank image received from GameStream.
BOOL noAppImage = false;
if (_app.image != nil) {
UIImage* appImage = [UIImage imageWithData:_app.image];
// This size of image might be blank image received from GameStream.
if (!(appImage.size.width == 130.f && appImage.size.height == 180.f)) {
_appButton.frame = CGRectMake(0, 0, appImage.size.width / 2, appImage.size.height / 2);
self.frame = CGRectMake(0, 0, appImage.size.width / 2, appImage.size.height / 2);
_appOverlay.frame = CGRectMake(0, 0, self.frame.size.width / 2.f, self.frame.size.height / 4.f);
_appOverlay.layer.shadowRadius = 4.0;
[_appOverlay setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/6)];
[_appButton setBackgroundImage:appImage forState:UIControlStateNormal];
[self setNeedsDisplay];
} else {
noAppImage = true;
}
} else {
noAppImage = true;
}
if (noAppImage) {
_appLabel = [[UILabel alloc] init];
CGFloat padding = 4.f;
[_appLabel setFrame: CGRectMake(padding, padding, _appButton.frame.size.width - 2 * padding, _appButton.frame.size.height - 2 * padding)];
@@ -75,18 +85,10 @@
[_appLabel setTextAlignment:NSTextAlignmentCenter];
[_appLabel setLineBreakMode:NSLineBreakByWordWrapping];
[_appLabel setNumberOfLines:0];
[_appLabel setText:_app.appName];
[_appLabel setText:_app.name];
[_appButton addSubview:_appLabel];
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end

View File

@@ -71,12 +71,24 @@ static NSArray* appList;
}
- (void)alreadyPaired {
BOOL usingCachedAppList = false;
if (_selectedHost.appList != nil) {
usingCachedAppList = true;
dispatch_async(dispatch_get_main_queue(), ^{
appList = [_selectedHost.appList allObjects];
_computerNameButton.title = _selectedHost.name;
[self.navigationController.navigationBar setNeedsLayout];
[self updateApps];
[self hideLoadingFrame];
});
}
Log(LOG_I, @"Using cached app list: %d", usingCachedAppList);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.activeAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
AppListResponse* appListResp = [[AppListResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appListResp withUrlRequest:[hMan newAppListRequest]]];
if (appListResp == nil || ![appListResp isStatusOk] || (appList = [appListResp getAppList]) == nil) {
if (appListResp == nil || ![appListResp isStatusOk] || [appListResp getAppList] == nil) {
Log(LOG_W, @"Failed to get applist: %@", appListResp.statusMessage);
[self hideLoadingFrame];
dispatch_async(dispatch_get_main_queue(), ^{
@@ -89,6 +101,12 @@ static NSArray* appList;
[self showHostSelectionView];
});
} else {
if (!usingCachedAppList) {
appList = [[NSArray alloc] init];
[_selectedHost addAppList:[NSSet setWithArray:appList]];
}
[self mergeAppLists:[appListResp getAppList]];
dispatch_async(dispatch_get_main_queue(), ^{
_computerNameButton.title = _selectedHost.name;
[self.navigationController.navigationBar setNeedsLayout];
@@ -103,6 +121,23 @@ static NSArray* appList;
});
}
- (void) mergeAppLists:(NSArray*) newList {
NSMutableArray* mergedList = [NSMutableArray arrayWithArray:appList];
for (App* app in newList) {
BOOL appAlreadyInList = NO;
for (App* savedApp in mergedList) {
if (app.id == savedApp.id) {
appAlreadyInList = YES;
}
}
if (!appAlreadyInList) {
[mergedList addObject:app];
[_selectedHost addAppListObject:app];
}
}
appList = mergedList;
}
- (void)showHostSelectionView {
appList = [[NSArray alloc] init];
[_appManager stopRetrieving];
@@ -250,10 +285,10 @@ static NSArray* appList;
}
- (void) appClicked:(App *)app {
Log(LOG_D, @"Clicked app: %@", app.appName);
Log(LOG_D, @"Clicked app: %@", app.name);
_streamConfig = [[StreamConfiguration alloc] init];
_streamConfig.host = _selectedHost.activeAddress;
_streamConfig.appID = app.appId;
_streamConfig.appID = app.id;
DataManager* dataMan = [[DataManager alloc] init];
Settings* streamSettings = [dataMan retrieveSettings];
@@ -272,16 +307,16 @@ static NSArray* appList;
App* currentApp = [self findRunningApp];
if (currentApp != nil) {
UIAlertController* alertController = [UIAlertController
alertControllerWithTitle: app.appName
message: [app.appId isEqualToString:currentApp.appId] ? @"" : [NSString stringWithFormat:@"%@ is currently running", currentApp.appName]preferredStyle:UIAlertControllerStyleAlert];
alertControllerWithTitle: app.name
message: [app.id isEqualToString:currentApp.id] ? @"" : [NSString stringWithFormat:@"%@ is currently running", currentApp.name]preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction
actionWithTitle:[app.appId isEqualToString:currentApp.appId] ? @"Resume App" : @"Resume Running App" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
Log(LOG_I, @"Resuming application: %@", currentApp.appName);
actionWithTitle:[app.id isEqualToString:currentApp.id] ? @"Resume App" : @"Resume Running App" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
Log(LOG_I, @"Resuming application: %@", currentApp.name);
[self performSegueWithIdentifier:@"createStreamFrame" sender:nil];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:
[app.appId isEqualToString:currentApp.appId] ? @"Quit App" : @"Quit Running App and Start" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
Log(LOG_I, @"Quitting application: %@", currentApp.appName);
[app.id isEqualToString:currentApp.id] ? @"Quit App" : @"Quit Running App and Start" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
Log(LOG_I, @"Quitting application: %@", currentApp.name);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.activeAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
HttpResponse* quitResponse = [[HttpResponse alloc] init];
@@ -298,7 +333,7 @@ static NSArray* appList;
preferredStyle:UIAlertControllerStyleAlert];
}
// If it succeeds and we're to start streaming, segue to the stream and return
else if (![app.appId isEqualToString:currentApp.appId]) {
else if (![app.id isEqualToString:currentApp.id]) {
currentApp.isRunning = NO;
dispatch_async(dispatch_get_main_queue(), ^{

View File

@@ -65,12 +65,12 @@
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494219FC9C04002D2A60 /* AppAssetManager.m */; };
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494F19FF2174002D2A60 /* SettingsViewController.m */; };
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3495219FF36FB002D2A60 /* SWRevealViewController.m */; };
FBD3495B1A004411002D2A60 /* Host.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3495A1A004411002D2A60 /* Host.m */; };
FBD3495E1A004412002D2A60 /* Settings.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3495D1A004412002D2A60 /* Settings.m */; };
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD349611A0089F6002D2A60 /* DataManager.m */; };
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */ = {isa = PBXBuildFile; fileRef = FBDE86DF19F7A837001C18A8 /* UIComputerView.m */; };
FBDE86E619F82297001C18A8 /* UIAppView.m in Sources */ = {isa = PBXBuildFile; fileRef = FBDE86E519F82297001C18A8 /* UIAppView.m */; };
FBDE86E919F82315001C18A8 /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FBDE86E819F82315001C18A8 /* App.m */; };
FBFCB3311B50B29400089F8A /* Host.m in Sources */ = {isa = PBXBuildFile; fileRef = FBFCB3301B50B29400089F8A /* Host.m */; };
FBFCB3351B50B29400089F8A /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FBFCB3341B50B29400089F8A /* App.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
@@ -257,6 +257,7 @@
FB9AFD3F1A7E127D00872C98 /* AppListResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppListResponse.m; sourceTree = "<group>"; };
FB9AFD411A7F0C6900872C98 /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
FB9AFD421A7F0C6900872C98 /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.0.xcdatamodel"; sourceTree = "<group>"; };
FBD1C8E01A8AD69E00C6703C /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logger.h; sourceTree = "<group>"; };
FBD1C8E11A8AD71400C6703C /* Logger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Logger.m; sourceTree = "<group>"; };
FBD3494119FC9C04002D2A60 /* AppAssetManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppAssetManager.h; sourceTree = "<group>"; };
@@ -266,8 +267,6 @@
FBD3495119FF36FB002D2A60 /* SWRevealViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWRevealViewController.h; sourceTree = "<group>"; };
FBD3495219FF36FB002D2A60 /* SWRevealViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWRevealViewController.m; sourceTree = "<group>"; };
FBD349571A003F05002D2A60 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
FBD349591A004411002D2A60 /* Host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Host.h; path = Database/Host.h; sourceTree = "<group>"; };
FBD3495A1A004411002D2A60 /* Host.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Host.m; path = Database/Host.m; sourceTree = "<group>"; };
FBD3495C1A004412002D2A60 /* Settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Settings.h; path = Database/Settings.h; sourceTree = "<group>"; };
FBD3495D1A004412002D2A60 /* Settings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Settings.m; path = Database/Settings.m; sourceTree = "<group>"; };
FBD349601A0089F6002D2A60 /* DataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataManager.h; path = Database/DataManager.h; sourceTree = "<group>"; };
@@ -276,8 +275,12 @@
FBDE86DF19F7A837001C18A8 /* UIComputerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIComputerView.m; sourceTree = "<group>"; };
FBDE86E419F82297001C18A8 /* UIAppView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAppView.h; sourceTree = "<group>"; };
FBDE86E519F82297001C18A8 /* UIAppView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIAppView.m; sourceTree = "<group>"; };
FBDE86E719F82315001C18A8 /* App.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = App.h; path = ../App.h; sourceTree = "<group>"; };
FBDE86E819F82315001C18A8 /* App.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = App.m; path = ../App.m; sourceTree = "<group>"; };
FBFCB32E1B50B29400089F8A /* Host+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Host+CoreDataProperties.h"; path = "Database/Host+CoreDataProperties.h"; sourceTree = "<group>"; };
FBFCB32F1B50B29400089F8A /* Host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Host.h; path = Database/Host.h; sourceTree = "<group>"; };
FBFCB3301B50B29400089F8A /* Host.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Host.m; path = Database/Host.m; sourceTree = "<group>"; };
FBFCB3321B50B29400089F8A /* App+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "App+CoreDataProperties.h"; path = "Database/App+CoreDataProperties.h"; sourceTree = "<group>"; };
FBFCB3331B50B29400089F8A /* App.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = App.h; path = Database/App.h; sourceTree = "<group>"; };
FBFCB3341B50B29400089F8A /* App.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = App.m; path = Database/App.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -440,7 +443,7 @@
children = (
FB9AFD2F1A7C979700872C98 /* Http */,
FB9AFD341A7D877B00872C98 /* Discovery */,
FB9AFD331A7D876F00872C98 /* AppAsset */,
FB9AFD331A7D876F00872C98 /* AppList */,
FB89461319F646E200339C8A /* PairManager.h */,
FB89461419F646E200339C8A /* PairManager.m */,
FB4678FD1A565DAC00377732 /* WakeOnLanManager.h */,
@@ -467,8 +470,6 @@
FB89461E19F646E200339C8A /* Utility */ = {
isa = PBXGroup;
children = (
FBDE86E719F82315001C18A8 /* App.h */,
FBDE86E819F82315001C18A8 /* App.m */,
FB89462119F646E200339C8A /* Utils.h */,
FB89462219F646E200339C8A /* Utils.m */,
FBD1C8E01A8AD69E00C6703C /* Logger.h */,
@@ -674,7 +675,7 @@
name = Http;
sourceTree = "<group>";
};
FB9AFD331A7D876F00872C98 /* AppAsset */ = {
FB9AFD331A7D876F00872C98 /* AppList */ = {
isa = PBXGroup;
children = (
FBD3494119FC9C04002D2A60 /* AppAssetManager.h */,
@@ -682,7 +683,7 @@
FB9AFD301A7D867C00872C98 /* AppAssetRetriever.h */,
FB9AFD311A7D867C00872C98 /* AppAssetRetriever.m */,
);
name = AppAsset;
name = AppList;
sourceTree = "<group>";
};
FB9AFD341A7D877B00872C98 /* Discovery */ = {
@@ -701,10 +702,14 @@
FBD3495F1A004453002D2A60 /* Database */ = {
isa = PBXGroup;
children = (
FBFCB3321B50B29400089F8A /* App+CoreDataProperties.h */,
FBFCB3331B50B29400089F8A /* App.h */,
FBFCB3341B50B29400089F8A /* App.m */,
FBFCB32E1B50B29400089F8A /* Host+CoreDataProperties.h */,
FBFCB32F1B50B29400089F8A /* Host.h */,
FBFCB3301B50B29400089F8A /* Host.m */,
FBD3495C1A004412002D2A60 /* Settings.h */,
FBD3495D1A004412002D2A60 /* Settings.m */,
FBD349591A004411002D2A60 /* Host.h */,
FBD3495A1A004411002D2A60 /* Host.m */,
FBD349601A0089F6002D2A60 /* DataManager.h */,
FBD349611A0089F6002D2A60 /* DataManager.m */,
);
@@ -819,15 +824,14 @@
FB89462919F646E200339C8A /* mkcert.c in Sources */,
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */,
FBDE86E919F82315001C18A8 /* App.m in Sources */,
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */,
FBFCB3311B50B29400089F8A /* Host.m in Sources */,
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */,
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */,
FB89462C19F646E200339C8A /* HttpManager.m in Sources */,
FB89462D19F646E200339C8A /* MDNSManager.m in Sources */,
FB89462B19F646E200339C8A /* StreamView.m in Sources */,
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
FBD3495B1A004411002D2A60 /* Host.m in Sources */,
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
FBD1C8E21A8AD71400C6703C /* Logger.m in Sources */,
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */,
@@ -842,6 +846,7 @@
FB89462A19F646E200339C8A /* ControllerSupport.m in Sources */,
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */,
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */,
FBFCB3351B50B29400089F8A /* App.m in Sources */,
FB4A23B81A9D3637004D2EF2 /* LoadingFrameViewController.m in Sources */,
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */,
FB89463119F646E200339C8A /* StreamManager.m in Sources */,
@@ -1033,11 +1038,12 @@
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */,
FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */,
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */,
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */,
);
currentVersion = FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */;
currentVersion = FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */;
path = Limelight.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;