mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-10-15 13:04:15 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7c141c1fd2 | ||
|
|
42c4e7ca58 | ||
|
|
6a6ea4a79a | ||
|
|
5d0ca8451d | ||
|
|
4641f68eb8 | ||
|
|
dd33f57b9a | ||
|
|
f6b225ca9c | ||
|
|
4ac3f11ff8 | ||
|
|
62aaf27293 | ||
|
|
eac2d985e2 | ||
|
|
61ea7f3f1c | ||
|
|
40f7faa1b1 | ||
|
|
9e18b8021b | ||
|
|
ce95f2c153 | ||
|
|
fd50b71b16 | ||
|
|
39ab472cf6 | ||
|
|
48ba7eb2dc | ||
|
|
42edaa1bad | ||
|
|
955fb59156 | ||
|
|
2fbc67ef00 | ||
|
|
23564a3028 | ||
|
|
9a07d5a33a | ||
|
|
84c037f235 | ||
|
|
c13df82f5b | ||
|
|
b15d61a5bf | ||
|
|
5aff719984 | ||
|
|
b0c2978405 | ||
|
|
91dcb505de | ||
|
|
d1f35d938b | ||
|
|
359b822951 | ||
|
|
39580e4352 | ||
|
|
7b3d099449 | ||
|
|
b17c45e9ca | ||
|
|
4c7a2cecdd | ||
|
|
175074ece8 | ||
|
|
8a5ec513bf | ||
|
|
7cfb7f73a2 | ||
|
|
c608685737 | ||
|
|
3beca2fc72 | ||
|
|
c59aafb4bb | ||
|
|
256e40acdc | ||
|
|
39b1b65e16 | ||
|
|
1783abec13 | ||
|
|
983c65d399 | ||
|
|
4caa9672c9 | ||
|
|
15be6a3f75 | ||
|
|
d38eb0a3ba | ||
|
|
e8ea942ad2 | ||
|
|
cb68b10475 | ||
|
|
11c854ce44 | ||
|
|
9636f4742b | ||
|
|
5867317526 | ||
|
|
8a8f7b6903 | ||
|
|
61b6e25a91 | ||
|
|
50cff820de | ||
|
|
4e586a28c8 | ||
|
|
0702b4ed57 | ||
|
|
4a2132a682 | ||
|
|
ba81d1d6a9 | ||
|
|
402ce4b3ec | ||
|
|
fc713453ad | ||
|
|
b222ccffbb | ||
|
|
56ce7329d2 | ||
|
|
99ab6db557 | ||
|
|
d7adf96f3a | ||
|
|
0ae58c61a9 | ||
|
|
2ec7d1d2f1 | ||
|
|
ad1b9059ee | ||
|
|
4439c7cce6 | ||
|
|
b8a4093c75 | ||
|
|
ec3748b26e | ||
|
|
1c1f22e047 | ||
|
|
9aa9b0fc5a | ||
|
|
f8e2ca8500 | ||
|
|
3076e29335 | ||
|
|
fe616d86c5 | ||
|
|
bfa4856bbe | ||
|
|
5ea92a7b48 | ||
|
|
4ba71db7b2 | ||
|
|
c1e6aeb43c | ||
|
|
e3ffb66ef0 | ||
|
|
5daa82b0ba | ||
|
|
a8bcc6afba | ||
|
|
e6aa16ad01 | ||
|
|
ad0705d126 | ||
|
|
2f31f93bf8 | ||
|
|
ea3be613c5 | ||
|
|
b495246f34 | ||
|
|
814470f4bf | ||
|
|
82293a08b6 | ||
|
|
20d66336a7 | ||
|
|
c8441ec9fa | ||
|
|
f72135c227 | ||
|
|
100e6e4ce8 | ||
|
|
ec8be20d62 |
@@ -1,3 +1,4 @@
|
||||
**/xcuserdata/
|
||||
**/Moonlight.xcscmblueprint
|
||||
Build
|
||||
DerivedData
|
||||
|
||||
+3
-3
@@ -1,3 +1,3 @@
|
||||
[submodule "limelight-common-c"]
|
||||
path = limelight-common-c
|
||||
url = git@github.com:limelight-stream/limelight-common-c.git
|
||||
[submodule "moonlight-common/moonlight-common-c"]
|
||||
path = moonlight-common/moonlight-common-c
|
||||
url = https://github.com/moonlight-stream/moonlight-common-c.git
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
+ (NSData*) getSignatureFromCert:(NSData*)cert;
|
||||
+ (NSData*) nullTerminateString:(NSData*)data;
|
||||
|
||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN;
|
||||
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN;
|
||||
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN;
|
||||
- (NSData*) SHA1HashData:(NSData*)data;
|
||||
- (NSData*) SHA256HashData:(NSData*)data;
|
||||
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
|
||||
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
|
||||
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
|
||||
|
||||
@@ -16,19 +16,31 @@
|
||||
#include <openssl/evp.h>
|
||||
|
||||
@implementation CryptoManager
|
||||
static const int SHA1_DIGEST_LENGTH = 20;
|
||||
static const int SHA1_HASH_LENGTH = 20;
|
||||
static const int SHA256_HASH_LENGTH = 32;
|
||||
static NSData* key = nil;
|
||||
static NSData* cert = nil;
|
||||
static NSData* p12 = nil;
|
||||
|
||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN {
|
||||
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN {
|
||||
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||
}
|
||||
|
||||
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN {
|
||||
return [[self SHA256HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||
}
|
||||
|
||||
- (NSData*) SHA1HashData:(NSData*)data {
|
||||
unsigned char sha1[SHA1_DIGEST_LENGTH];
|
||||
unsigned char sha1[SHA1_HASH_LENGTH];
|
||||
SHA1([data bytes], [data length], sha1);
|
||||
NSData* bytes = [NSData dataWithBytes:sha1 length:20];
|
||||
NSData* bytes = [NSData dataWithBytes:sha1 length:sizeof(sha1)];
|
||||
return bytes;
|
||||
}
|
||||
|
||||
- (NSData*) SHA256HashData:(NSData*)data {
|
||||
unsigned char sha256[SHA256_HASH_LENGTH];
|
||||
SHA256([data bytes], [data length], sha256);
|
||||
NSData* bytes = [NSData dataWithBytes:sha256 length:sizeof(sha256)];
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,15 +13,14 @@
|
||||
|
||||
+ (NSString*) getUniqueId {
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
Settings* prefs = [dataMan retrieveSettings];
|
||||
|
||||
NSString* uniqueId = prefs.uniqueId;
|
||||
|
||||
NSString* uniqueId = [dataMan getUniqueId];
|
||||
if (uniqueId == nil) {
|
||||
uniqueId = [IdManager generateUniqueId];
|
||||
prefs.uniqueId = uniqueId;
|
||||
[dataMan saveData];
|
||||
[dataMan updateUniqueId:uniqueId];
|
||||
Log(LOG_I, @"No UUID found. Generated new UUID: %@", uniqueId);
|
||||
}
|
||||
|
||||
return uniqueId;
|
||||
}
|
||||
|
||||
|
||||
@@ -11,16 +11,8 @@
|
||||
|
||||
@class Host;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface App : NSManagedObject
|
||||
|
||||
@property BOOL isRunning;
|
||||
|
||||
- (NSComparisonResult)compareName:(App *)other;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#import "App+CoreDataProperties.h"
|
||||
|
||||
@@ -7,14 +7,7 @@
|
||||
//
|
||||
|
||||
#import "App.h"
|
||||
#import "Host.h"
|
||||
|
||||
@implementation App
|
||||
|
||||
@synthesize isRunning;
|
||||
|
||||
- (NSComparisonResult)compareName:(App *)other {
|
||||
return [self.name caseInsensitiveCompare:other.name];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,23 +7,25 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Settings.h"
|
||||
#import "AppDelegate.h"
|
||||
#import "Host.h"
|
||||
#import "App.h"
|
||||
#import "TemporaryHost.h"
|
||||
#import "TemporaryApp.h"
|
||||
#import "TemporarySettings.h"
|
||||
|
||||
@interface DataManager : NSObject
|
||||
|
||||
@property (strong, nonatomic) AppDelegate* appDelegate;
|
||||
|
||||
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls;
|
||||
- (Settings*) retrieveSettings;
|
||||
- (NSArray*) retrieveHosts;
|
||||
- (void) saveData;
|
||||
- (Host*) createHost;
|
||||
- (void) removeHost:(Host*)host;
|
||||
- (App*) addAppFromTemporaryApp:(TemporaryApp*)tempApp;
|
||||
- (void) removeAppFromHost:(App*)app;
|
||||
|
||||
- (NSArray*) getHosts;
|
||||
- (void) updateHost:(TemporaryHost*)host;
|
||||
- (void) updateAppsForExistingHost:(TemporaryHost *)host;
|
||||
- (void) updateIconForExistingApp:(TemporaryApp*)app;
|
||||
- (void) removeHost:(TemporaryHost*)host;
|
||||
- (void) removeApp:(TemporaryApp*)app;
|
||||
|
||||
- (TemporarySettings*) getSettings;
|
||||
|
||||
- (void) updateUniqueId:(NSString*)uniqueId;
|
||||
- (NSString*) getUniqueId;
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,45 +8,131 @@
|
||||
|
||||
#import "DataManager.h"
|
||||
#import "TemporaryApp.h"
|
||||
#import "TemporarySettings.h"
|
||||
#import "Settings.h"
|
||||
|
||||
@implementation DataManager
|
||||
|
||||
+ (NSObject *)databaseLock {
|
||||
static NSObject *lock = nil;
|
||||
if (lock == nil) {
|
||||
lock = [[NSObject alloc] init];
|
||||
}
|
||||
return lock;
|
||||
@implementation DataManager {
|
||||
NSManagedObjectContext *_managedObjectContext;
|
||||
AppDelegate *_appDelegate;
|
||||
}
|
||||
|
||||
- (id) init {
|
||||
self = [super init];
|
||||
self.appDelegate = [[UIApplication sharedApplication] delegate];
|
||||
|
||||
_appDelegate = [[UIApplication sharedApplication] delegate];
|
||||
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
|
||||
[_managedObjectContext setPersistentStoreCoordinator:_appDelegate.persistentStoreCoordinator];
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
|
||||
Settings* settingsToSave = [self retrieveSettings];
|
||||
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
|
||||
// Bitrate is persisted in kbps
|
||||
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
|
||||
settingsToSave.height = [NSNumber numberWithInteger:height];
|
||||
settingsToSave.width = [NSNumber numberWithInteger:width];
|
||||
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
|
||||
- (void) updateUniqueId:(NSString*)uniqueId {
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
[self retrieveSettings].uniqueId = uniqueId;
|
||||
[self saveData];
|
||||
}];
|
||||
}
|
||||
|
||||
NSError* error;
|
||||
if (![[self.appDelegate managedObjectContext] save:&error]) {
|
||||
Log(LOG_E, @"Unable to save settings to database: %@", error);
|
||||
}
|
||||
[self.appDelegate saveContext];
|
||||
- (NSString*) getUniqueId {
|
||||
__block NSString *uid;
|
||||
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
uid = [self retrieveSettings].uniqueId;
|
||||
}];
|
||||
|
||||
return uid;
|
||||
}
|
||||
|
||||
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
|
||||
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
Settings* settingsToSave = [self retrieveSettings];
|
||||
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
|
||||
// Bitrate is persisted in kbps
|
||||
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
|
||||
settingsToSave.height = [NSNumber numberWithInteger:height];
|
||||
settingsToSave.width = [NSNumber numberWithInteger:width];
|
||||
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
|
||||
|
||||
[self saveData];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) updateHost:(TemporaryHost *)host {
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
// Add a new persistent managed object if one doesn't exist
|
||||
Host* parent = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
|
||||
if (parent == nil) {
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:_managedObjectContext];
|
||||
parent = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
|
||||
}
|
||||
|
||||
// Push changes from the temp host to the persistent one
|
||||
[host propagateChangesToParent:parent];
|
||||
|
||||
[self saveData];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) updateAppsForExistingHost:(TemporaryHost *)host {
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
Host* parent = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
|
||||
if (parent == nil) {
|
||||
// The host must exist to be updated
|
||||
return;
|
||||
}
|
||||
|
||||
NSMutableSet *applist = [[NSMutableSet alloc] init];
|
||||
NSArray *appRecords = [self fetchRecords:@"App"];
|
||||
for (TemporaryApp* app in host.appList) {
|
||||
// Add a new persistent managed object if one doesn't exist
|
||||
App* parentApp = [self getAppForTemporaryApp:app withAppRecords:appRecords];
|
||||
if (parentApp == nil) {
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:_managedObjectContext];
|
||||
parentApp = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
|
||||
}
|
||||
|
||||
[app propagateChangesToParent:parentApp withHost:parent];
|
||||
|
||||
[applist addObject:parentApp];
|
||||
}
|
||||
|
||||
parent.appList = applist;
|
||||
|
||||
[self saveData];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) updateIconForExistingApp:(TemporaryApp*)app {
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
App* parentApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
|
||||
if (parentApp == nil) {
|
||||
// The app must exist to be updated
|
||||
return;
|
||||
}
|
||||
|
||||
parentApp.image = app.image;
|
||||
|
||||
[self saveData];
|
||||
}];
|
||||
}
|
||||
|
||||
- (TemporarySettings*) getSettings {
|
||||
__block TemporarySettings *tempSettings;
|
||||
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
tempSettings = [[TemporarySettings alloc] initFromSettings:[self retrieveSettings]];
|
||||
}];
|
||||
|
||||
return tempSettings;
|
||||
}
|
||||
|
||||
- (Settings*) retrieveSettings {
|
||||
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
|
||||
if (fetchedRecords.count == 0) {
|
||||
// create a new settings object with the default values
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
||||
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:_managedObjectContext];
|
||||
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
|
||||
|
||||
return settings;
|
||||
} else {
|
||||
@@ -55,74 +141,82 @@
|
||||
}
|
||||
}
|
||||
|
||||
- (Host*) createHost {
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
||||
return [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
||||
- (void) removeApp:(TemporaryApp*)app {
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
App* managedApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
|
||||
if (managedApp != nil) {
|
||||
[_managedObjectContext deleteObject:managedApp];
|
||||
[self saveData];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) removeHost:(Host*)host {
|
||||
[[self.appDelegate managedObjectContext] deleteObject:host];
|
||||
[self saveData];
|
||||
- (void) removeHost:(TemporaryHost*)host {
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
Host* managedHost = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
|
||||
if (managedHost != nil) {
|
||||
[_managedObjectContext deleteObject:managedHost];
|
||||
[self saveData];
|
||||
}
|
||||
}];
|
||||
}
|
||||
|
||||
- (void) saveData {
|
||||
@synchronized([DataManager databaseLock]) {
|
||||
NSError* error;
|
||||
if (![[self.appDelegate managedObjectContext] save:&error]) {
|
||||
Log(LOG_E, @"Unable to save hosts to database: %@", error);
|
||||
NSError* error;
|
||||
if (![_managedObjectContext save:&error]) {
|
||||
Log(LOG_E, @"Unable to save hosts to database: %@", error);
|
||||
}
|
||||
|
||||
[_appDelegate saveContext];
|
||||
}
|
||||
|
||||
- (NSArray*) getHosts {
|
||||
__block NSMutableArray *tempHosts = [[NSMutableArray alloc] init];
|
||||
|
||||
[_managedObjectContext performBlockAndWait:^{
|
||||
NSArray *hosts = [self fetchRecords:@"Host"];
|
||||
|
||||
for (Host* host in hosts) {
|
||||
[tempHosts addObject:[[TemporaryHost alloc] initFromHost:host]];
|
||||
}
|
||||
[self.appDelegate saveContext];
|
||||
}
|
||||
}];
|
||||
|
||||
return tempHosts;
|
||||
}
|
||||
|
||||
- (NSArray*) retrieveHosts {
|
||||
return [self fetchRecords:@"Host"];
|
||||
}
|
||||
|
||||
- (App*) addAppFromTemporaryApp:(TemporaryApp*)tempApp {
|
||||
|
||||
App* managedApp;
|
||||
|
||||
@synchronized([DataManager databaseLock]) {
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
||||
managedApp = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
||||
|
||||
assert(tempApp.host != nil);
|
||||
|
||||
managedApp.id = tempApp.id;
|
||||
managedApp.image = tempApp.image;
|
||||
managedApp.name = tempApp.name;
|
||||
managedApp.isRunning = tempApp.isRunning;
|
||||
managedApp.host = tempApp.host;
|
||||
|
||||
[managedApp.host addAppListObject:managedApp];
|
||||
// Only call from within performBlockAndWait!!!
|
||||
- (Host*) getHostForTemporaryHost:(TemporaryHost*)tempHost withHostRecords:(NSArray*)hosts {
|
||||
for (Host* host in hosts) {
|
||||
if ([tempHost.uuid isEqualToString:host.uuid]) {
|
||||
return host;
|
||||
}
|
||||
}
|
||||
|
||||
return managedApp;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (void) removeAppFromHost:(App*)app {
|
||||
@synchronized([DataManager databaseLock]) {
|
||||
assert(app.host != nil);
|
||||
|
||||
[app.host removeAppListObject:app];
|
||||
[[self.appDelegate managedObjectContext] deleteObject:app];
|
||||
// Only call from within performBlockAndWait!!!
|
||||
- (App*) getAppForTemporaryApp:(TemporaryApp*)tempApp withAppRecords:(NSArray*)apps {
|
||||
for (App* app in apps) {
|
||||
if ([app.id isEqualToString:tempApp.id] &&
|
||||
[app.host.uuid isEqualToString:app.host.uuid]) {
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSArray*) fetchRecords:(NSString*)entityName {
|
||||
NSArray* fetchedRecords;
|
||||
|
||||
@synchronized([DataManager databaseLock]) {
|
||||
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
||||
[fetchRequest setEntity:entity];
|
||||
[fetchRequest setAffectedStores:[NSArray arrayWithObjects:[[self.appDelegate persistentStoreCoordinator] persistentStoreForURL:[self.appDelegate getStoreURL]], nil]];
|
||||
|
||||
NSError* error;
|
||||
fetchedRecords = [[self.appDelegate managedObjectContext] executeFetchRequest:fetchRequest error:&error];
|
||||
//TODO: handle errors
|
||||
}
|
||||
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
|
||||
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];
|
||||
[fetchRequest setEntity:entity];
|
||||
|
||||
NSError* error;
|
||||
fetchedRecords = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
|
||||
//TODO: handle errors
|
||||
|
||||
return fetchedRecords;
|
||||
}
|
||||
|
||||
@@ -10,16 +10,8 @@
|
||||
#import <CoreData/CoreData.h>
|
||||
#import "Utils.h"
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface Host : NSManagedObject
|
||||
|
||||
@property (nonatomic) BOOL online;
|
||||
@property (nonatomic) PairState pairState;
|
||||
@property (nonatomic) NSString * activeAddress;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
#import "Host+CoreDataProperties.h"
|
||||
|
||||
@@ -10,8 +10,4 @@
|
||||
|
||||
@implementation Host
|
||||
|
||||
@dynamic pairState;
|
||||
@synthesize online;
|
||||
@synthesize activeAddress;
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,14 +7,24 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Host.h"
|
||||
#import "TemporaryHost.h"
|
||||
#import "App.h"
|
||||
|
||||
@interface TemporaryApp : NSObject
|
||||
|
||||
@property (nullable, nonatomic, retain) NSString *id;
|
||||
@property (nullable, nonatomic, retain) NSData *image;
|
||||
@property (nullable, nonatomic, retain) NSString *name;
|
||||
@property (nonatomic) BOOL isRunning;
|
||||
@property (nullable, nonatomic, retain) Host *host;
|
||||
@property (nullable, nonatomic, retain) TemporaryHost *host;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost;
|
||||
|
||||
- (NSComparisonResult)compareName:(TemporaryApp *)other;
|
||||
|
||||
- (void) propagateChangesToParent:(App*)parent withHost:(Host*)host;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@end
|
||||
|
||||
@@ -7,7 +7,46 @@
|
||||
//
|
||||
|
||||
#import "TemporaryApp.h"
|
||||
#import "App.h"
|
||||
|
||||
@implementation TemporaryApp
|
||||
|
||||
- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost {
|
||||
self = [self init];
|
||||
|
||||
self.id = app.id;
|
||||
self.image = app.image;
|
||||
self.name = app.name;
|
||||
self.host = tempHost;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) propagateChangesToParent:(App*)parent withHost:(Host*)host {
|
||||
parent.id = self.id;
|
||||
parent.name = self.name;
|
||||
parent.host = host;
|
||||
}
|
||||
|
||||
- (NSComparisonResult)compareName:(TemporaryApp *)other {
|
||||
return [self.name caseInsensitiveCompare:other.name];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [self.host.uuid hash] * 31 + [self.id intValue];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[App class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self.host.uuid isEqualToString:((App*)object).host.uuid] &&
|
||||
[self.id isEqualToString:((App*)object).id];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// TemporaryHost.h
|
||||
// Moonlight
|
||||
//
|
||||
// Created by Cameron Gutman on 12/1/15.
|
||||
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Utils.h"
|
||||
#import "Host.h"
|
||||
|
||||
@interface TemporaryHost : NSObject
|
||||
|
||||
@property (nonatomic) BOOL online;
|
||||
@property (nonatomic) PairState pairState;
|
||||
@property (nonatomic, nullable) NSString * activeAddress;
|
||||
@property (nonatomic, nullable) NSString * currentGame;
|
||||
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@property (nonatomic, retain) NSString *address;
|
||||
@property (nonatomic, retain) NSString *externalAddress;
|
||||
@property (nonatomic, retain) NSString *localAddress;
|
||||
@property (nonatomic, retain) NSString *mac;
|
||||
@property (nonatomic, retain) NSString *name;
|
||||
@property (nonatomic, retain) NSString *uuid;
|
||||
@property (nonatomic, retain) NSMutableSet *appList;
|
||||
|
||||
- (id) initFromHost:(Host*)host;
|
||||
|
||||
- (NSComparisonResult)compareName:(TemporaryHost *)other;
|
||||
|
||||
- (void) propagateChangesToParent:(Host*)host;
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,78 @@
|
||||
//
|
||||
// TemporaryHost.m
|
||||
// Moonlight
|
||||
//
|
||||
// Created by Cameron Gutman on 12/1/15.
|
||||
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import "DataManager.h"
|
||||
#import "TemporaryHost.h"
|
||||
#import "Host.h"
|
||||
#import "TemporaryApp.h"
|
||||
#import "App.h"
|
||||
|
||||
@implementation TemporaryHost
|
||||
|
||||
- (id) init {
|
||||
self = [super init];
|
||||
self.appList = [[NSMutableSet alloc] init];
|
||||
self.currentGame = @"0";
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initFromHost:(Host*)host {
|
||||
self = [self init];
|
||||
|
||||
self.address = host.address;
|
||||
self.externalAddress = host.externalAddress;
|
||||
self.localAddress = host.localAddress;
|
||||
self.mac = host.mac;
|
||||
self.name = host.name;
|
||||
self.uuid = host.uuid;
|
||||
self.pairState = [host.pairState intValue];
|
||||
|
||||
NSMutableSet *appList = [[NSMutableSet alloc] init];
|
||||
|
||||
for (App* app in host.appList) {
|
||||
TemporaryApp *tempApp = [[TemporaryApp alloc] initFromApp:app withTempHost:self];
|
||||
[appList addObject:tempApp];
|
||||
}
|
||||
|
||||
self.appList = appList;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) propagateChangesToParent:(Host*)parentHost {
|
||||
parentHost.address = self.address;
|
||||
parentHost.externalAddress = self.externalAddress;
|
||||
parentHost.localAddress = self.localAddress;
|
||||
parentHost.mac = self.mac;
|
||||
parentHost.name = self.name;
|
||||
parentHost.uuid = self.uuid;
|
||||
parentHost.pairState = [NSNumber numberWithInt:self.pairState];
|
||||
}
|
||||
|
||||
- (NSComparisonResult)compareName:(TemporaryHost *)other {
|
||||
return [self.name caseInsensitiveCompare:other.name];
|
||||
}
|
||||
|
||||
- (NSUInteger)hash {
|
||||
return [self.uuid hash];
|
||||
}
|
||||
|
||||
- (BOOL)isEqual:(id)object {
|
||||
if (self == object) {
|
||||
return YES;
|
||||
}
|
||||
|
||||
if (![object isKindOfClass:[Host class]]) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
return [self.uuid isEqualToString:((Host*)object).uuid];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,25 @@
|
||||
//
|
||||
// TemporarySettings.h
|
||||
// Moonlight
|
||||
//
|
||||
// Created by Cameron Gutman on 12/1/15.
|
||||
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Settings.h"
|
||||
|
||||
@interface TemporarySettings : NSObject
|
||||
|
||||
@property (nonatomic, retain) Settings * parent;
|
||||
|
||||
@property (nonatomic, retain) NSNumber * bitrate;
|
||||
@property (nonatomic, retain) NSNumber * framerate;
|
||||
@property (nonatomic, retain) NSNumber * height;
|
||||
@property (nonatomic, retain) NSNumber * width;
|
||||
@property (nonatomic, retain) NSNumber * onscreenControls;
|
||||
@property (nonatomic, retain) NSString * uniqueId;
|
||||
|
||||
- (id) initFromSettings:(Settings*)settings;
|
||||
|
||||
@end
|
||||
@@ -0,0 +1,28 @@
|
||||
//
|
||||
// TemporarySettings.m
|
||||
// Moonlight
|
||||
//
|
||||
// Created by Cameron Gutman on 12/1/15.
|
||||
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import "TemporarySettings.h"
|
||||
|
||||
@implementation TemporarySettings
|
||||
|
||||
- (id) initFromSettings:(Settings*)settings {
|
||||
self = [self init];
|
||||
|
||||
self.parent = settings;
|
||||
|
||||
self.bitrate = settings.bitrate;
|
||||
self.framerate = settings.framerate;
|
||||
self.height = settings.height;
|
||||
self.width = settings.width;
|
||||
self.onscreenControls = settings.onscreenControls;
|
||||
self.uniqueId = settings.uniqueId;
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -71,6 +71,12 @@
|
||||
"idiom" : "ipad",
|
||||
"filename" : "app_icon_152x152_@2x.png",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"size" : "83.5x83.5",
|
||||
"idiom" : "ipad",
|
||||
"filename" : "app_icon_167x167_@2x.png",
|
||||
"scale" : "2x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 59 KiB |
@@ -1,23 +0,0 @@
|
||||
//
|
||||
// Controller.h
|
||||
// Moonlight
|
||||
//
|
||||
// Created by Diego Waxemberg on 2/1/15.
|
||||
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface Controller : NSObject
|
||||
|
||||
@property (nonatomic) int playerIndex;
|
||||
@property (nonatomic) int lastButtonFlags;
|
||||
@property (nonatomic) int emulatingButtonFlags;
|
||||
@property (nonatomic) char lastLeftTrigger;
|
||||
@property (nonatomic) char lastRightTrigger;
|
||||
@property (nonatomic) short lastLeftStickX;
|
||||
@property (nonatomic) short lastLeftStickY;
|
||||
@property (nonatomic) short lastRightStickX;
|
||||
@property (nonatomic) short lastRightStickY;
|
||||
|
||||
@end
|
||||
@@ -1,15 +0,0 @@
|
||||
//
|
||||
// Controller.m
|
||||
// Moonlight
|
||||
//
|
||||
// Created by Diego Waxemberg on 2/1/15.
|
||||
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
#import "Controller.h"
|
||||
|
||||
@implementation Controller
|
||||
@synthesize playerIndex;
|
||||
@synthesize lastButtonFlags, emulatingButtonFlags, lastLeftTrigger, lastRightTrigger;
|
||||
@synthesize lastLeftStickX, lastLeftStickY, lastRightStickX, lastRightStickY;
|
||||
@end
|
||||
@@ -0,0 +1,26 @@
|
||||
//
|
||||
// Controller.swift
|
||||
// Moonlight
|
||||
//
|
||||
// Created by David Aghassi on 4/11/16.
|
||||
// Copyright © 2016 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
@objc
|
||||
/**
|
||||
Defines a controller layout
|
||||
*/
|
||||
class Controller: NSObject {
|
||||
// Swift requires initial properties
|
||||
var playerIndex: CInt = 0 // Controller number (e.g. 1, 2 ,3 etc)
|
||||
var lastButtonFlags: CInt = 0
|
||||
var emulatingButtonFlags: CInt = 0
|
||||
var lastLeftTrigger: CChar = 0 // Last left trigger pressed
|
||||
var lastRightTrigger: CChar = 0 // Last right trigger pressed
|
||||
var lastLeftStickX: CShort = 0 // Last X direction the left joystick went
|
||||
var lastLeftStickY: CShort = 0 // Last Y direction the left joystick went
|
||||
var lastRightStickX: CShort = 0 // Last X direction the right joystick went
|
||||
var lastRightStickY: CShort = 0 // Last Y direction the right joystick went
|
||||
}
|
||||
@@ -7,7 +7,10 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Controller.h"
|
||||
|
||||
// Swift
|
||||
#import "Moonlight-Swift.h"
|
||||
@class Controller;
|
||||
|
||||
@class OnScreenControls;
|
||||
|
||||
@@ -29,6 +32,7 @@
|
||||
-(void) clearButtonFlag:(Controller*)controller flags:(int)flags;
|
||||
|
||||
-(void) updateFinished:(Controller*)controller;
|
||||
-(Controller*) getOscController;
|
||||
|
||||
@property (nonatomic, strong) id connectObserver;
|
||||
@property (nonatomic, strong) id disconnectObserver;
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
|
||||
#import "ControllerSupport.h"
|
||||
#import "OnScreenControls.h"
|
||||
#import "Controller.h"
|
||||
#include "Limelight.h"
|
||||
|
||||
// Swift
|
||||
#import "Moonlight-Swift.h"
|
||||
@class Controller;
|
||||
|
||||
@import GameController;
|
||||
|
||||
@implementation ControllerSupport {
|
||||
@@ -19,6 +22,10 @@
|
||||
|
||||
OnScreenControls *_osc;
|
||||
|
||||
// This controller object is shared between on-screen controls
|
||||
// and player 0
|
||||
Controller *_player0osc;
|
||||
|
||||
char _controllerNumbers;
|
||||
|
||||
#define EMULATING_SELECT 0x1
|
||||
@@ -139,7 +146,8 @@
|
||||
{
|
||||
[_controllerStreamLock lock];
|
||||
@synchronized(controller) {
|
||||
LiSendMultiControllerEvent(controller.playerIndex, controller.lastButtonFlags, controller.lastLeftTrigger, controller.lastRightTrigger, controller.lastLeftStickX, controller.lastLeftStickY, controller.lastRightStickX, controller.lastRightStickY);
|
||||
// Player 1 is always present for OSC
|
||||
LiSendMultiControllerEvent(controller.playerIndex, _controllerNumbers | 1, controller.lastButtonFlags, controller.lastLeftTrigger, controller.lastRightTrigger, controller.lastLeftStickX, controller.lastLeftStickY, controller.lastRightStickX, controller.lastRightStickY);
|
||||
}
|
||||
[_controllerStreamLock unlock];
|
||||
}
|
||||
@@ -272,9 +280,17 @@
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!(_controllerNumbers & (1 << i))) {
|
||||
_controllerNumbers |= (1 << i);
|
||||
Controller* limeController = [[Controller alloc] init];
|
||||
controller.playerIndex = i;
|
||||
limeController.playerIndex = i;
|
||||
|
||||
Controller* limeController;
|
||||
if (i == 0) {
|
||||
// Player 0 shares a controller object with the on-screen controls
|
||||
limeController = _player0osc;
|
||||
} else {
|
||||
limeController = [[Controller alloc] init];
|
||||
limeController.playerIndex = i;
|
||||
}
|
||||
|
||||
[_controllers setObject:limeController forKey:[NSNumber numberWithInteger:controller.playerIndex]];
|
||||
|
||||
Log(LOG_I, @"Assigning controller index: %d", i);
|
||||
@@ -283,6 +299,10 @@
|
||||
}
|
||||
}
|
||||
|
||||
-(Controller*) getOscController {
|
||||
return _player0osc;
|
||||
}
|
||||
|
||||
-(id) init
|
||||
{
|
||||
self = [super init];
|
||||
@@ -290,6 +310,8 @@
|
||||
_controllerStreamLock = [[NSLock alloc] init];
|
||||
_controllers = [[NSMutableDictionary alloc] init];
|
||||
_controllerNumbers = 0;
|
||||
_player0osc = [[Controller alloc] init];
|
||||
_player0osc.playerIndex = 0;
|
||||
|
||||
Log(LOG_I, @"Number of controllers connected: %ld", (long)[[GCController controllers] count]);
|
||||
for (GCController* controller in [GCController controllers]) {
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
@@ -8,9 +8,12 @@
|
||||
|
||||
#import "OnScreenControls.h"
|
||||
#import "ControllerSupport.h"
|
||||
#import "Controller.h"
|
||||
//#import "Controller.h"
|
||||
#include "Limelight.h"
|
||||
|
||||
#import "Moonlight-Swift.h"
|
||||
@class Controller;
|
||||
|
||||
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
||||
(y) ? (buttonFlags | (x)) : (buttonFlags & ~(x)))
|
||||
|
||||
@@ -41,10 +44,7 @@
|
||||
UITouch* _bTouch;
|
||||
UITouch* _xTouch;
|
||||
UITouch* _yTouch;
|
||||
UITouch* _upTouch;
|
||||
UITouch* _downTouch;
|
||||
UITouch* _leftTouch;
|
||||
UITouch* _rightTouch;
|
||||
UITouch* _dpadTouch;
|
||||
UITouch* _lsTouch;
|
||||
UITouch* _rsTouch;
|
||||
UITouch* _startTouch;
|
||||
@@ -119,8 +119,7 @@ static float L3_Y;
|
||||
self = [self init];
|
||||
_view = view;
|
||||
_controllerSupport = controllerSupport;
|
||||
_controller = [[Controller alloc] init];
|
||||
_controller.playerIndex = 0;
|
||||
_controller = [controllerSupport getOscController];
|
||||
_edgeDelegate = swipeDelegate;
|
||||
_deadTouches = [[NSMutableArray alloc] init];
|
||||
|
||||
@@ -570,6 +569,26 @@ static float L3_Y;
|
||||
[_controllerSupport updateRightStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||
|
||||
updated = true;
|
||||
} else if (touch == _dpadTouch) {
|
||||
[_controllerSupport clearButtonFlag:_controller
|
||||
flags:UP_FLAG | DOWN_FLAG | LEFT_FLAG | RIGHT_FLAG];
|
||||
|
||||
// Allow the user to slide their finger to another d-pad button
|
||||
if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:UP_FLAG];
|
||||
updated = true;
|
||||
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:DOWN_FLAG];
|
||||
updated = true;
|
||||
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:LEFT_FLAG];
|
||||
updated = true;
|
||||
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:RIGHT_FLAG];
|
||||
updated = true;
|
||||
}
|
||||
|
||||
buttonTouch = true;
|
||||
} else if (touch == _aTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _bTouch) {
|
||||
@@ -578,14 +597,6 @@ static float L3_Y;
|
||||
buttonTouch = true;
|
||||
} else if (touch == _yTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _upTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _downTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _leftTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _rightTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _startTouch) {
|
||||
buttonTouch = true;
|
||||
} else if (touch == _selectTouch) {
|
||||
@@ -637,19 +648,19 @@ static float L3_Y;
|
||||
updated = true;
|
||||
} else if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:UP_FLAG];
|
||||
_upTouch = touch;
|
||||
_dpadTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:DOWN_FLAG];
|
||||
_downTouch = touch;
|
||||
_dpadTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:LEFT_FLAG];
|
||||
_leftTouch = touch;
|
||||
_dpadTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:RIGHT_FLAG];
|
||||
_rightTouch = touch;
|
||||
_dpadTouch = touch;
|
||||
updated = true;
|
||||
} else if ([_startButton.presentationLayer hitTest:touchLocation]) {
|
||||
[_controllerSupport setButtonFlag:_controller flags:PLAY_FLAG];
|
||||
@@ -755,21 +766,10 @@ static float L3_Y;
|
||||
[_controllerSupport clearButtonFlag:_controller flags:Y_FLAG];
|
||||
_yTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _upTouch) {
|
||||
[_controllerSupport clearButtonFlag:_controller flags:UP_FLAG];
|
||||
_upTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _downTouch) {
|
||||
[_controllerSupport clearButtonFlag:_controller flags:DOWN_FLAG];
|
||||
_downTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _leftTouch) {
|
||||
[_controllerSupport clearButtonFlag:_controller flags:LEFT_FLAG];
|
||||
_leftTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _rightTouch) {
|
||||
[_controllerSupport clearButtonFlag:_controller flags:RIGHT_FLAG];
|
||||
_rightTouch = nil;
|
||||
} else if (touch == _dpadTouch) {
|
||||
[_controllerSupport clearButtonFlag:_controller
|
||||
flags:UP_FLAG | DOWN_FLAG | LEFT_FLAG | RIGHT_FLAG];
|
||||
_dpadTouch = nil;
|
||||
updated = true;
|
||||
} else if (touch == _startTouch) {
|
||||
[_controllerSupport clearButtonFlag:_controller flags:PLAY_FLAG];
|
||||
|
||||
@@ -17,6 +17,9 @@
|
||||
BOOL touchMoved;
|
||||
OnScreenControls* onScreenControls;
|
||||
|
||||
BOOL isDragging;
|
||||
NSTimer* dragTimer;
|
||||
|
||||
float xDeltaFactor;
|
||||
float yDeltaFactor;
|
||||
float screenFactor;
|
||||
@@ -32,7 +35,7 @@
|
||||
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate {
|
||||
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate];
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan retrieveSettings].onscreenControls integerValue];
|
||||
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan getSettings].onscreenControls integerValue];
|
||||
|
||||
if (level == OnScreenControlsLevelAuto) {
|
||||
[controllerSupport initAutoOnScreenControlMode:onScreenControls];
|
||||
@@ -49,11 +52,27 @@
|
||||
UITouch *touch = [[event allTouches] anyObject];
|
||||
touchLocation = [touch locationInView:self];
|
||||
touchMoved = false;
|
||||
if ([[event allTouches] count] == 1 && !isDragging) {
|
||||
dragTimer = [NSTimer scheduledTimerWithTimeInterval:0.650
|
||||
target:self
|
||||
selector:@selector(onDragStart:)
|
||||
userInfo:nil
|
||||
repeats:NO];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)onDragStart:(NSTimer*)timer {
|
||||
if (!touchMoved && !isDragging){
|
||||
isDragging = true;
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
if (![onScreenControls handleTouchMovedEvent:touches]) {
|
||||
[dragTimer invalidate];
|
||||
dragTimer = nil;
|
||||
if ([[event allTouches] count] == 1) {
|
||||
UITouch *touch = [[event allTouches] anyObject];
|
||||
CGPoint currentLocation = [touch locationInView:self];
|
||||
@@ -91,6 +110,8 @@
|
||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||
Log(LOG_D, @"Touch up");
|
||||
if (![onScreenControls handleTouchUpEvent:touches]) {
|
||||
[dragTimer invalidate];
|
||||
dragTimer = nil;
|
||||
if (!touchMoved) {
|
||||
if ([[event allTouches] count] == 2) {
|
||||
Log(LOG_D, @"Sending right mouse button press");
|
||||
@@ -101,19 +122,23 @@
|
||||
usleep(100 * 1000);
|
||||
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
||||
|
||||
|
||||
} else {
|
||||
Log(LOG_D, @"Sending left mouse button press");
|
||||
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||
|
||||
// Wait 100 ms to simulate a real button press
|
||||
usleep(100 * 1000);
|
||||
|
||||
if (!isDragging){
|
||||
Log(LOG_D, @"Sending left mouse button press");
|
||||
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||
|
||||
// Wait 100 ms to simulate a real button press
|
||||
usleep(100 * 1000);
|
||||
}
|
||||
isDragging = false;
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||
}
|
||||
}
|
||||
else if (isDragging) {
|
||||
isDragging = false;
|
||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0.0</string>
|
||||
<string>1.2.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>3</string>
|
||||
<string>1</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
|
||||
@@ -7,20 +7,20 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "App.h"
|
||||
#import "TemporaryApp.h"
|
||||
#import "HttpManager.h"
|
||||
#import "Host.h"
|
||||
#import "TemporaryHost.h"
|
||||
|
||||
@protocol AppAssetCallback <NSObject>
|
||||
|
||||
- (void) receivedAssetForApp:(App*)app;
|
||||
- (void) receivedAssetForApp:(TemporaryApp*)app;
|
||||
|
||||
@end
|
||||
|
||||
@interface AppAssetManager : NSObject
|
||||
|
||||
- (id) initWithCallback:(id<AppAssetCallback>)callback;
|
||||
- (void) retrieveAssetsFromHost:(Host*)host;
|
||||
- (void) retrieveAssetsFromHost:(TemporaryHost*)host;
|
||||
- (void) stopRetrieving;
|
||||
|
||||
@end
|
||||
|
||||
@@ -28,8 +28,8 @@ static const int MAX_REQUEST_COUNT = 4;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) retrieveAssetsFromHost:(Host*)host {
|
||||
for (App* app in host.appList) {
|
||||
- (void) retrieveAssetsFromHost:(TemporaryHost*)host {
|
||||
for (TemporaryApp* app in host.appList) {
|
||||
if (app.image == nil) {
|
||||
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
|
||||
retriever.app = app;
|
||||
@@ -45,7 +45,7 @@ static const int MAX_REQUEST_COUNT = 4;
|
||||
[_opQueue cancelAllOperations];
|
||||
}
|
||||
|
||||
- (void) sendCallBackForApp:(App*)app {
|
||||
- (void) sendCallBackForApp:(TemporaryApp*)app {
|
||||
[_callback receivedAssetForApp:app];
|
||||
}
|
||||
|
||||
|
||||
@@ -7,14 +7,14 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Host.h"
|
||||
#import "App.h"
|
||||
#import "TemporaryHost.h"
|
||||
#import "TemporaryApp.h"
|
||||
#import "AppAssetManager.h"
|
||||
|
||||
@interface AppAssetRetriever : NSOperation
|
||||
|
||||
@property (nonatomic) Host* host;
|
||||
@property (nonatomic) App* app;
|
||||
@property (nonatomic) TemporaryHost* host;
|
||||
@property (nonatomic) TemporaryApp* app;
|
||||
@property (nonatomic) id<AppAssetCallback> callback;
|
||||
|
||||
@end
|
||||
|
||||
@@ -36,7 +36,7 @@ static const int MAX_ATTEMPTS = 5;
|
||||
[self performSelectorOnMainThread:@selector(sendCallbackForApp:) withObject:self.app waitUntilDone:NO];
|
||||
}
|
||||
|
||||
- (void) sendCallbackForApp:(App*)app {
|
||||
- (void) sendCallbackForApp:(TemporaryApp*)app {
|
||||
[self.callback receivedAssetForApp:app];
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
@interface AppListResponse : NSObject <Response>
|
||||
|
||||
- (void)populateWithData:(NSData *)data;
|
||||
- (NSArray*) getAppList;
|
||||
- (NSSet*) getAppList;
|
||||
- (BOOL) isStatusOk;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,18 +12,17 @@
|
||||
#import <libxml2/libxml/xmlreader.h>
|
||||
|
||||
@implementation AppListResponse {
|
||||
NSMutableArray* _appList;
|
||||
NSMutableSet* _appList;
|
||||
}
|
||||
@synthesize data, statusCode, statusMessage;
|
||||
|
||||
static const char* TAG_APP = "App";
|
||||
static const char* TAG_APP_TITLE = "AppTitle";
|
||||
static const char* TAG_APP_ID = "ID";
|
||||
static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
||||
|
||||
- (void)populateWithData:(NSData *)xml {
|
||||
self.data = xml;
|
||||
_appList = [[NSMutableArray alloc] init];
|
||||
_appList = [[NSMutableSet alloc] init];
|
||||
[self parseData];
|
||||
}
|
||||
|
||||
@@ -67,7 +66,6 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
||||
xmlNodePtr appInfoNode = node->xmlChildrenNode;
|
||||
NSString* appName = @"";
|
||||
NSString* appId = nil;
|
||||
BOOL appIsRunning = NO;
|
||||
while (appInfoNode != NULL) {
|
||||
if (!xmlStrcmp(appInfoNode->name, (xmlChar*)TAG_APP_TITLE)) {
|
||||
xmlChar* nodeVal = xmlNodeListGetString(docPtr, appInfoNode->xmlChildrenNode, 1);
|
||||
@@ -83,14 +81,6 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
||||
appId = [[NSString alloc] initWithCString:(const char*)nodeVal encoding:NSUTF8StringEncoding];
|
||||
xmlFree(nodeVal);
|
||||
}
|
||||
} else if (!xmlStrcmp(appInfoNode->name, (xmlChar*)TAG_APP_IS_RUNNING)) {
|
||||
xmlChar* nodeVal = xmlNodeListGetString(docPtr, appInfoNode->xmlChildrenNode, 1);
|
||||
if (nodeVal != NULL) {
|
||||
appIsRunning = [[[NSString alloc] initWithCString:(const char*)nodeVal encoding:NSUTF8StringEncoding] isEqualToString:@"1"];
|
||||
xmlFree(nodeVal);
|
||||
} else {
|
||||
appIsRunning = NO;
|
||||
}
|
||||
}
|
||||
appInfoNode = appInfoNode->next;
|
||||
}
|
||||
@@ -98,7 +88,6 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
||||
TemporaryApp* app = [[TemporaryApp alloc] init];
|
||||
app.name = appName;
|
||||
app.id = appId;
|
||||
app.isRunning = appIsRunning;
|
||||
[_appList addObject:app];
|
||||
}
|
||||
}
|
||||
@@ -108,7 +97,7 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
||||
xmlFreeDoc(docPtr);
|
||||
}
|
||||
|
||||
- (NSArray*) getAppList {
|
||||
- (NSSet*) getAppList {
|
||||
return _appList;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MDNSManager.h"
|
||||
#import "Host.h"
|
||||
#import "TemporaryHost.h"
|
||||
|
||||
@protocol DiscoveryCallback <NSObject>
|
||||
|
||||
@@ -22,8 +22,8 @@
|
||||
- (void) startDiscovery;
|
||||
- (void) stopDiscovery;
|
||||
- (void) stopDiscoveryBlocking;
|
||||
- (BOOL) addHostToDiscovery:(Host*)host;
|
||||
- (void) removeHostFromDiscovery:(Host*)host;
|
||||
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(Host*, NSString*))callback;
|
||||
- (BOOL) addHostToDiscovery:(TemporaryHost*)host;
|
||||
- (void) removeHostFromDiscovery:(TemporaryHost*)host;
|
||||
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(TemporaryHost*, NSString*))callback;
|
||||
|
||||
@end
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
@implementation DiscoveryManager {
|
||||
NSMutableArray* _hostQueue;
|
||||
NSMutableArray* _discoveredHosts;
|
||||
id<DiscoveryCallback> _callback;
|
||||
MDNSManager* _mdnsMan;
|
||||
NSOperationQueue* _opQueue;
|
||||
@@ -34,16 +33,10 @@
|
||||
_callback = callback;
|
||||
shouldDiscover = NO;
|
||||
_hostQueue = [NSMutableArray array];
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
for (Host* host in hosts)
|
||||
for (TemporaryHost* host in hosts)
|
||||
{
|
||||
if (![self addHostToDiscovery:host])
|
||||
{
|
||||
// Remove the duplicate host from the database
|
||||
[dataMan removeHost:host];
|
||||
}
|
||||
[self addHostToDiscovery:host];
|
||||
}
|
||||
[dataMan saveData];
|
||||
[_callback updateAllHosts:_hostQueue];
|
||||
|
||||
_opQueue = [[NSOperationQueue alloc] init];
|
||||
@@ -54,26 +47,24 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void) discoverHost:(NSString *)hostAddress withCallback:(void (^)(Host *, NSString*))callback {
|
||||
- (void) discoverHost:(NSString *)hostAddress withCallback:(void (^)(TemporaryHost *, NSString*))callback {
|
||||
HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
|
||||
ServerInfoResponse* serverInfoResponse = [[ServerInfoResponse alloc] init];
|
||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest] fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
|
||||
|
||||
Host* host = nil;
|
||||
TemporaryHost* host = nil;
|
||||
if ([serverInfoResponse isStatusOk]) {
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
host = [dataMan createHost];
|
||||
host = [[TemporaryHost alloc] init];
|
||||
host.activeAddress = host.address = hostAddress;
|
||||
host.online = YES;
|
||||
[serverInfoResponse populateHost:host];
|
||||
if (![self addHostToDiscovery:host]) {
|
||||
[dataMan removeHost:host];
|
||||
callback(nil, @"Host already added");
|
||||
} else {
|
||||
callback(host, nil);
|
||||
}
|
||||
} else {
|
||||
callback(nil, @"Could not connect to host");
|
||||
callback(nil, @"Could not connect to host. Ensure GameStream is enabled in GeForce Experience on your PC.");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -82,7 +73,7 @@
|
||||
Log(LOG_I, @"Starting discovery");
|
||||
shouldDiscover = YES;
|
||||
[_mdnsMan searchForHosts];
|
||||
for (Host* host in _hostQueue) {
|
||||
for (TemporaryHost* host in _hostQueue) {
|
||||
[_opQueue addOperation:[self createWorkerForHost:host]];
|
||||
}
|
||||
}
|
||||
@@ -103,18 +94,27 @@
|
||||
Log(LOG_I, @"All discovery workers stopped");
|
||||
}
|
||||
|
||||
- (BOOL) addHostToDiscovery:(Host *)host {
|
||||
if (host.uuid.length > 0 && ![self isHostInDiscovery:host]) {
|
||||
- (BOOL) addHostToDiscovery:(TemporaryHost *)host {
|
||||
if (host.uuid.length == 0) {
|
||||
return NO;
|
||||
}
|
||||
|
||||
TemporaryHost *existingHost = [self getHostInDiscovery:host.uuid];
|
||||
if (existingHost != nil) {
|
||||
// Update address of existing host
|
||||
existingHost.address = existingHost.activeAddress = host.address;
|
||||
return NO;
|
||||
}
|
||||
else {
|
||||
[_hostQueue addObject:host];
|
||||
if (shouldDiscover) {
|
||||
[_opQueue addOperation:[self createWorkerForHost:host]];
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (void) removeHostFromDiscovery:(Host *)host {
|
||||
- (void) removeHostFromDiscovery:(TemporaryHost *)host {
|
||||
for (DiscoveryWorker* worker in [_opQueue operations]) {
|
||||
if ([worker getHost] == host) {
|
||||
[worker cancel];
|
||||
@@ -126,9 +126,8 @@
|
||||
// Override from MDNSCallback
|
||||
- (void)updateHosts:(NSArray *)hosts {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
// Discover the hosts before adding to eliminate duplicates
|
||||
for (Host* host in hosts) {
|
||||
for (TemporaryHost* host in hosts) {
|
||||
Log(LOG_I, @"Found host through MDNS: %@:", host.name);
|
||||
// Since this is on a background thread, we do not need to use the opQueue
|
||||
DiscoveryWorker* worker = (DiscoveryWorker*)[self createWorkerForHost:host];
|
||||
@@ -138,24 +137,22 @@
|
||||
[_callback updateAllHosts:_hostQueue];
|
||||
} else {
|
||||
Log(LOG_I, @"Not adding host to discovery: %@", host.name);
|
||||
[dataMan removeHost:host];
|
||||
}
|
||||
}
|
||||
[dataMan saveData];
|
||||
});
|
||||
}
|
||||
|
||||
- (BOOL) isHostInDiscovery:(Host*)host {
|
||||
- (TemporaryHost*) getHostInDiscovery:(NSString*)uuidString {
|
||||
for (int i = 0; i < _hostQueue.count; i++) {
|
||||
Host* discoveredHost = [_hostQueue objectAtIndex:i];
|
||||
if (discoveredHost.uuid.length > 0 && [discoveredHost.uuid isEqualToString:host.uuid]) {
|
||||
return YES;
|
||||
TemporaryHost* discoveredHost = [_hostQueue objectAtIndex:i];
|
||||
if (discoveredHost.uuid.length > 0 && [discoveredHost.uuid isEqualToString:uuidString]) {
|
||||
return discoveredHost;
|
||||
}
|
||||
}
|
||||
return NO;
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (NSOperation*) createWorkerForHost:(Host*)host {
|
||||
- (NSOperation*) createWorkerForHost:(TemporaryHost*)host {
|
||||
DiscoveryWorker* worker = [[DiscoveryWorker alloc] initWithHost:host uniqueId:_uniqueId cert:_cert];
|
||||
return worker;
|
||||
}
|
||||
|
||||
@@ -7,12 +7,12 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Host.h"
|
||||
#import "TemporaryHost.h"
|
||||
|
||||
@interface DiscoveryWorker : NSOperation
|
||||
|
||||
- (id) initWithHost:(Host*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert;
|
||||
- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert;
|
||||
- (void) discoverHost;
|
||||
- (Host*) getHost;
|
||||
- (TemporaryHost*) getHost;
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,16 +11,17 @@
|
||||
#import "HttpManager.h"
|
||||
#import "ServerInfoResponse.h"
|
||||
#import "HttpRequest.h"
|
||||
#import "DataManager.h"
|
||||
|
||||
@implementation DiscoveryWorker {
|
||||
Host* _host;
|
||||
TemporaryHost* _host;
|
||||
NSString* _uniqueId;
|
||||
NSData* _cert;
|
||||
}
|
||||
|
||||
static const float POLL_RATE = 2.0f; // Poll every 2 seconds
|
||||
|
||||
- (id) initWithHost:(Host*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert {
|
||||
- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert {
|
||||
self = [super init];
|
||||
_host = host;
|
||||
_uniqueId = uniqueId;
|
||||
@@ -28,7 +29,7 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
|
||||
return self;
|
||||
}
|
||||
|
||||
- (Host*) getHost {
|
||||
- (TemporaryHost*) getHost {
|
||||
return _host;
|
||||
}
|
||||
|
||||
@@ -87,20 +88,37 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
|
||||
|
||||
Log(LOG_D, @"%@ has %d unique addresses", _host.name, [addresses count]);
|
||||
|
||||
for (NSString *address in addresses) {
|
||||
if (self.cancelled) {
|
||||
// Get out without updating the status because
|
||||
// it might not have finished checking the various
|
||||
// addresses
|
||||
return;
|
||||
// Give the PC 3 tries to respond before declaring it offline
|
||||
for (int i = 0; i < 3; i++) {
|
||||
for (NSString *address in addresses) {
|
||||
if (self.cancelled) {
|
||||
// Get out without updating the status because
|
||||
// it might not have finished checking the various
|
||||
// addresses
|
||||
return;
|
||||
}
|
||||
|
||||
ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:address];
|
||||
receivedResponse = [self checkResponse:serverInfoResp];
|
||||
if (receivedResponse) {
|
||||
[serverInfoResp populateHost:_host];
|
||||
_host.activeAddress = address;
|
||||
|
||||
// Update the database using the response
|
||||
DataManager *dataManager = [[DataManager alloc] init];
|
||||
[dataManager updateHost:_host];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:address];
|
||||
receivedResponse = [self checkResponse:serverInfoResp];
|
||||
if (receivedResponse) {
|
||||
_host.activeAddress = address;
|
||||
Log(LOG_I, @"Received serverinfo response on try %d", i);
|
||||
break;
|
||||
}
|
||||
else {
|
||||
// Wait for one second then retry
|
||||
[NSThread sleepForTimeInterval:1];
|
||||
}
|
||||
}
|
||||
|
||||
_host.online = receivedResponse;
|
||||
@@ -125,7 +143,6 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
|
||||
if ([response isStatusOk]) {
|
||||
// If the response is from a different host then do not update this host
|
||||
if ((_host.uuid == nil || [[response getStringTag:TAG_UNIQUE_ID] isEqualToString:_host.uuid])) {
|
||||
[response populateHost:_host];
|
||||
return YES;
|
||||
} else {
|
||||
Log(LOG_I, @"Received response from incorrect host: %@ expected: %@", [response getStringTag:TAG_UNIQUE_ID], _host.uuid);
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Host.h"
|
||||
#import "HttpResponse.h"
|
||||
#import "HttpRequest.h"
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#import "HttpManager.h"
|
||||
#import "HttpRequest.h"
|
||||
#import "CryptoManager.h"
|
||||
#import "App.h"
|
||||
#import "TemporaryApp.h"
|
||||
|
||||
#include <libxml2/libxml/xmlreader.h>
|
||||
#include <string.h>
|
||||
@@ -100,8 +100,8 @@ static const NSString* HTTPS_PORT = @"47984";
|
||||
NSURL* url = [[NSURL alloc] initWithString:urlString];
|
||||
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
|
||||
if (normalTimeout) {
|
||||
// Timeout the request after 5 seconds
|
||||
[request setTimeoutInterval:5];
|
||||
// Timeout the request after 7 seconds
|
||||
[request setTimeoutInterval:7];
|
||||
}
|
||||
else {
|
||||
// Timeout the request after 60 seconds
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Host.h"
|
||||
|
||||
static NSString* TAG_STATUS_CODE = @"status_code";
|
||||
static NSString* TAG_STATUS_MESSAGE = @"status_message";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import "HttpResponse.h"
|
||||
#import "App.h"
|
||||
#import "TemporaryApp.h"
|
||||
#import <libxml2/libxml/xmlreader.h>
|
||||
|
||||
@implementation HttpResponse {
|
||||
|
||||
@@ -7,8 +7,7 @@
|
||||
//
|
||||
|
||||
#import "MDNSManager.h"
|
||||
#import "Host.h"
|
||||
#import "DataManager.h"
|
||||
#import "TemporaryHost.h"
|
||||
|
||||
@implementation MDNSManager {
|
||||
NSNetServiceBrowser* mDNSBrowser;
|
||||
@@ -47,10 +46,9 @@ static NSString* NV_SERVICE_TYPE = @"_nvstream._tcp";
|
||||
|
||||
- (NSArray*) getFoundHosts {
|
||||
NSMutableArray* hosts = [[NSMutableArray alloc] init];
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
for (NSNetService* service in services) {
|
||||
if (service.hostName != nil) {
|
||||
Host* host = [dataMan createHost];
|
||||
TemporaryHost* host = [[TemporaryHost alloc] init];
|
||||
host.activeAddress = host.address = service.hostName;
|
||||
host.name = host.address;
|
||||
[hosts addObject:host];
|
||||
|
||||
@@ -22,6 +22,6 @@
|
||||
- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id<PairCallback>)callback;
|
||||
- (NSString*) generatePIN;
|
||||
- (NSData*) saltPIN:(NSString*)PIN;
|
||||
- (void) initiatePair;
|
||||
- (void) initiatePair:(int)serverMajorVersion;
|
||||
|
||||
@end
|
||||
|
||||
@@ -38,17 +38,24 @@
|
||||
return;
|
||||
}
|
||||
if ([serverInfoResp isStatusOk]) {
|
||||
if (![[serverInfoResp getStringTag:@"currentgame"] isEqual:@"0"]) {
|
||||
if (![[serverInfoResp getStringTag:@"state"] hasSuffix:@"_SERVER_AVAILABLE"]) {
|
||||
[_callback pairFailed:@"You must stop streaming before attempting to pair."];
|
||||
} else if (![[serverInfoResp getStringTag:@"PairStatus"] isEqual:@"1"]) {
|
||||
[self initiatePair];
|
||||
NSString* appversion = [serverInfoResp getStringTag:@"appversion"];
|
||||
if (appversion == nil) {
|
||||
[_callback pairFailed:@"Missing XML element"];
|
||||
return;
|
||||
}
|
||||
[self initiatePair: [[appversion substringToIndex:1] intValue]];
|
||||
} else {
|
||||
[_callback alreadyPaired];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void) initiatePair {
|
||||
- (void) initiatePair:(int)serverMajorVersion {
|
||||
Log(LOG_I, @"Pairing with generation %d server", serverMajorVersion);
|
||||
|
||||
NSString* PIN = [self generatePIN];
|
||||
NSData* salt = [self saltPIN:PIN];
|
||||
Log(LOG_I, @"PIN: %@, saltedPIN: %@", PIN, salt);
|
||||
@@ -61,15 +68,29 @@
|
||||
}
|
||||
NSInteger pairedStatus;
|
||||
if (![pairResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
|
||||
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
|
||||
[_callback pairFailed:@"Pairing was declined by the target."];
|
||||
return;
|
||||
}
|
||||
|
||||
NSString* plainCert = [pairResp getStringTag:@"plaincert"];
|
||||
if ([plainCert length] == 0) {
|
||||
[_callback pairFailed:@"Another pairing attempt is already in progress."];
|
||||
return;
|
||||
}
|
||||
|
||||
CryptoManager* cryptoMan = [[CryptoManager alloc] init];
|
||||
NSData* aesKey = [cryptoMan createAESKeyFromSalt:salt];
|
||||
NSData* aesKey;
|
||||
|
||||
// Gen 7 servers use SHA256 to get the key
|
||||
int hashLength;
|
||||
if (serverMajorVersion >= 7) {
|
||||
aesKey = [cryptoMan createAESKeyFromSaltSHA256:salt];
|
||||
hashLength = 32;
|
||||
}
|
||||
else {
|
||||
aesKey = [cryptoMan createAESKeyFromSaltSHA1:salt];
|
||||
hashLength = 20;
|
||||
}
|
||||
|
||||
NSData* randomChallenge = [Utils randomBytes:16];
|
||||
NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey];
|
||||
@@ -88,11 +109,18 @@
|
||||
NSData* encServerChallengeResp = [Utils hexToBytes:[challengeResp getStringTag:@"challengeresponse"]];
|
||||
NSData* decServerChallengeResp = [cryptoMan aesDecrypt:encServerChallengeResp withKey:aesKey];
|
||||
|
||||
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, 20)];
|
||||
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(20, 16)];
|
||||
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, hashLength)];
|
||||
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(hashLength, 16)];
|
||||
|
||||
NSData* clientSecret = [Utils randomBytes:16];
|
||||
NSData* challengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret]];
|
||||
NSData* challengeRespHashInput = [self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret];
|
||||
NSData* challengeRespHash;
|
||||
if (serverMajorVersion >= 7) {
|
||||
challengeRespHash = [cryptoMan SHA256HashData: challengeRespHashInput];
|
||||
}
|
||||
else {
|
||||
challengeRespHash = [cryptoMan SHA1HashData: challengeRespHashInput];
|
||||
}
|
||||
NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey];
|
||||
|
||||
HttpResponse* secretResp = [[HttpResponse alloc] init];
|
||||
@@ -116,7 +144,14 @@
|
||||
return;
|
||||
}
|
||||
|
||||
NSData* serverChallengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret]];
|
||||
NSData* serverChallengeRespHashInput = [self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret];
|
||||
NSData* serverChallengeRespHash;
|
||||
if (serverMajorVersion >= 7) {
|
||||
serverChallengeRespHash = [cryptoMan SHA256HashData: serverChallengeRespHashInput];
|
||||
}
|
||||
else {
|
||||
serverChallengeRespHash = [cryptoMan SHA1HashData: serverChallengeRespHashInput];
|
||||
}
|
||||
if (![serverChallengeRespHash isEqual:serverResponse]) {
|
||||
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
|
||||
[_callback pairFailed:@"Incorrect PIN"];
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
//
|
||||
|
||||
#import "HttpResponse.h"
|
||||
#import "TemporaryHost.h"
|
||||
|
||||
#define TAG_HOSTNAME @"hostname"
|
||||
#define TAG_EXTERNAL_IP @"ExternalIP"
|
||||
@@ -14,11 +15,13 @@
|
||||
#define TAG_UNIQUE_ID @"uniqueid"
|
||||
#define TAG_MAC_ADDRESS @"mac"
|
||||
#define TAG_PAIR_STATUS @"PairStatus"
|
||||
#define TAG_STATE @"state"
|
||||
#define TAG_CURRENT_GAME @"currentgame"
|
||||
|
||||
@interface ServerInfoResponse : HttpResponse <Response>
|
||||
|
||||
- (void) populateWithData:(NSData *)data;
|
||||
- (void) populateHost:(Host*)host;
|
||||
- (void) populateHost:(TemporaryHost*)host;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -17,12 +17,21 @@
|
||||
[super parseData];
|
||||
}
|
||||
|
||||
- (void) populateHost:(Host*)host {
|
||||
- (void) populateHost:(TemporaryHost*)host {
|
||||
host.name = [[self getStringTag:TAG_HOSTNAME] trim];
|
||||
host.externalAddress = [[self getStringTag:TAG_EXTERNAL_IP] trim];
|
||||
host.localAddress = [[self getStringTag:TAG_LOCAL_IP] trim];
|
||||
host.uuid = [[self getStringTag:TAG_UNIQUE_ID] trim];
|
||||
host.mac = [[self getStringTag:TAG_MAC_ADDRESS] trim];
|
||||
host.currentGame = [[self getStringTag:TAG_CURRENT_GAME] trim];
|
||||
|
||||
NSString *state = [[self getStringTag:TAG_STATE] trim];
|
||||
if ([state hasSuffix:@"_SERVER_AVAILABLE"]) {
|
||||
// GFE 2.8 started keeping currentgame set to the last game played. As a result, it no longer
|
||||
// has the semantics that its name would indicate. To contain the effects of this change as much
|
||||
// as possible, we'll force the current game to zero if the server isn't in a streaming session.
|
||||
host.currentGame = @"0";
|
||||
}
|
||||
|
||||
NSInteger pairStatus;
|
||||
if ([self getIntTag:TAG_PAIR_STATUS value:&pairStatus]) {
|
||||
|
||||
@@ -7,10 +7,10 @@
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "Host.h"
|
||||
#import "TemporaryHost.h"
|
||||
|
||||
@interface WakeOnLanManager : NSObject
|
||||
|
||||
+ (void) wakeHost:(Host*)host;
|
||||
+ (void) wakeHost:(TemporaryHost*)host;
|
||||
|
||||
@end
|
||||
|
||||
@@ -12,51 +12,86 @@
|
||||
#import <sys/socket.h>
|
||||
#import <netinet/in.h>
|
||||
#import <arpa/inet.h>
|
||||
#import <netdb.h>
|
||||
|
||||
@implementation WakeOnLanManager
|
||||
|
||||
static const int numPorts = 5;
|
||||
static const int ports[numPorts] = {7, 9, 47998, 47999, 48000};
|
||||
|
||||
+ (void) wakeHost:(Host*)host {
|
||||
NSData* wolPayload = [WakeOnLanManager createPayload:host];
|
||||
CFDataRef dataPayload = CFDataCreate(kCFAllocatorDefault, [wolPayload bytes], [wolPayload length]);
|
||||
CFSocketRef wolSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, NULL, NULL);
|
||||
if (!wolSocket) {
|
||||
CFRelease(dataPayload);
|
||||
Log(LOG_E, @"Failed to create WOL socket");
|
||||
return;
|
||||
+ (void) populateAddress:(struct sockaddr_storage*)addr withPort:(unsigned short)port {
|
||||
if (addr->ss_family == AF_INET) {
|
||||
struct sockaddr_in *sin = (struct sockaddr_in*)addr;
|
||||
sin->sin_port = htons(port);
|
||||
}
|
||||
Log(LOG_I, @"WOL socket created");
|
||||
|
||||
struct sockaddr_in addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
addr.sin_family = AF_INET;
|
||||
addr.sin_len = sizeof(addr);
|
||||
|
||||
|
||||
for (int i = 0; i < 2; i++) {
|
||||
// try all ip addresses
|
||||
if (i == 0) {
|
||||
inet_aton([host.localAddress UTF8String], &addr.sin_addr);
|
||||
} else {
|
||||
inet_aton([host.externalAddress UTF8String], &addr.sin_addr);
|
||||
}
|
||||
|
||||
CFDataRef dataAddress = CFDataCreate(kCFAllocatorDefault, (unsigned char*)&addr, sizeof(addr));
|
||||
|
||||
// try all ports
|
||||
for (int j = 0; j < numPorts; j++) {
|
||||
addr.sin_port = htons(ports[j]);
|
||||
Log(LOG_I, @"Sending WOL packet");
|
||||
CFSocketSendData(wolSocket, dataAddress, dataPayload, 0);
|
||||
}
|
||||
CFRelease(dataAddress);
|
||||
else if (addr->ss_family == AF_INET6) {
|
||||
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
|
||||
sin6->sin6_port = htons(port);
|
||||
}
|
||||
CFRelease(dataPayload);
|
||||
}
|
||||
|
||||
+ (NSData*) createPayload:(Host*)host {
|
||||
+ (void) wakeHost:(TemporaryHost*)host {
|
||||
NSData* wolPayload = [WakeOnLanManager createPayload:host];
|
||||
|
||||
for (int i = 0; i < 3; i++) {
|
||||
const char* address;
|
||||
struct addrinfo hints, *res, *curr;
|
||||
|
||||
// try all ip addresses
|
||||
if (i == 0 && host.localAddress != nil) {
|
||||
address = [host.localAddress UTF8String];
|
||||
} else if (i == 1 && host.externalAddress != nil) {
|
||||
address = [host.externalAddress UTF8String];
|
||||
} else if (i == 2 && host.address != nil) {
|
||||
address = [host.address UTF8String];
|
||||
} else {
|
||||
// Requested address wasn't present
|
||||
continue;
|
||||
}
|
||||
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC;
|
||||
hints.ai_flags = AI_ADDRCONFIG;
|
||||
if (getaddrinfo(address, NULL, &hints, &res) != 0 || res == NULL) {
|
||||
// Failed to resolve address
|
||||
Log(LOG_E, @"Failed to resolve WOL address");
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try all addresses that this DNS name resolves to. We have
|
||||
// to create a new socket each time because the addresses
|
||||
// may be different address families.
|
||||
for (curr = res; curr != NULL; curr = curr->ai_next) {
|
||||
int wolSocket;
|
||||
|
||||
wolSocket = socket(curr->ai_family, SOCK_DGRAM, IPPROTO_UDP);
|
||||
if (wolSocket < 0) {
|
||||
Log(LOG_E, @"Failed to create WOL socket");
|
||||
continue;
|
||||
}
|
||||
|
||||
struct sockaddr_storage addr;
|
||||
memset(&addr, 0, sizeof(addr));
|
||||
memcpy(&addr, curr->ai_addr, curr->ai_addrlen);
|
||||
|
||||
for (int j = 0; j < numPorts; j++) {
|
||||
[WakeOnLanManager populateAddress:&addr withPort:ports[j]];
|
||||
long err = sendto(wolSocket,
|
||||
[wolPayload bytes],
|
||||
[wolPayload length],
|
||||
0,
|
||||
(struct sockaddr*)&addr,
|
||||
curr->ai_addrlen);
|
||||
Log(LOG_I, @"Sending WOL packet returned: %ld", err);
|
||||
}
|
||||
|
||||
close(wolSocket);
|
||||
}
|
||||
freeaddrinfo(res);
|
||||
}
|
||||
}
|
||||
|
||||
+ (NSData*) createPayload:(TemporaryHost*)host {
|
||||
NSMutableData* payload = [[NSMutableData alloc] initWithCapacity:102];
|
||||
|
||||
// 6 bytes of FF
|
||||
|
||||
@@ -14,20 +14,19 @@
|
||||
|
||||
- (void) connectionStarted;
|
||||
- (void) connectionTerminated:(long)errorCode;
|
||||
- (void) stageStarting:(char*)stageName;
|
||||
- (void) stageComplete:(char*)stageName;
|
||||
- (void) stageFailed:(char*)stageName withError:(long)errorCode;
|
||||
- (void) stageStarting:(const char*)stageName;
|
||||
- (void) stageComplete:(const char*)stageName;
|
||||
- (void) stageFailed:(const char*)stageName withError:(long)errorCode;
|
||||
- (void) launchFailed:(NSString*)message;
|
||||
- (void) displayMessage:(char*)message;
|
||||
- (void) displayTransientMessage:(char*)message;
|
||||
- (void) displayMessage:(const char*)message;
|
||||
- (void) displayTransientMessage:(const char*)message;
|
||||
|
||||
@end
|
||||
|
||||
@interface Connection : NSOperation <NSStreamDelegate>
|
||||
|
||||
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion;
|
||||
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks;
|
||||
-(void) terminate;
|
||||
-(void) terminateInternal;
|
||||
-(void) main;
|
||||
|
||||
@end
|
||||
|
||||
@@ -15,14 +15,14 @@
|
||||
#include "opus.h"
|
||||
|
||||
@implementation Connection {
|
||||
const char* _host;
|
||||
SERVER_INFORMATION _serverInfo;
|
||||
STREAM_CONFIGURATION _streamConfig;
|
||||
CONNECTION_LISTENER_CALLBACKS _clCallbacks;
|
||||
DECODER_RENDERER_CALLBACKS _drCallbacks;
|
||||
AUDIO_RENDERER_CALLBACKS _arCallbacks;
|
||||
int _serverMajorVersion;
|
||||
}
|
||||
|
||||
static NSLock* initLock;
|
||||
static OpusDecoder *opusDecoder;
|
||||
static id<ConnectionCallbacks> _callbacks;
|
||||
|
||||
@@ -228,17 +228,17 @@ void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
|
||||
|
||||
void ClStageStarting(int stage)
|
||||
{
|
||||
[_callbacks stageStarting:(char*)LiGetStageName(stage)];
|
||||
[_callbacks stageStarting:LiGetStageName(stage)];
|
||||
}
|
||||
|
||||
void ClStageComplete(int stage)
|
||||
{
|
||||
[_callbacks stageComplete:(char*)LiGetStageName(stage)];
|
||||
[_callbacks stageComplete:LiGetStageName(stage)];
|
||||
}
|
||||
|
||||
void ClStageFailed(int stage, long errorCode)
|
||||
{
|
||||
[_callbacks stageFailed:(char*)LiGetStageName(stage) withError:errorCode];
|
||||
[_callbacks stageFailed:LiGetStageName(stage) withError:errorCode];
|
||||
}
|
||||
|
||||
void ClConnectionStarted(void)
|
||||
@@ -251,40 +251,47 @@ void ClConnectionTerminated(long errorCode)
|
||||
[_callbacks connectionTerminated: errorCode];
|
||||
}
|
||||
|
||||
void ClDisplayMessage(char* message)
|
||||
void ClDisplayMessage(const char* message)
|
||||
{
|
||||
[_callbacks displayMessage: message];
|
||||
}
|
||||
|
||||
void ClDisplayTransientMessage(char* message)
|
||||
void ClDisplayTransientMessage(const char* message)
|
||||
{
|
||||
[_callbacks displayTransientMessage: message];
|
||||
}
|
||||
|
||||
-(void) terminateInternal
|
||||
-(void) terminate
|
||||
{
|
||||
// We dispatch this async to get out because this can be invoked
|
||||
// on a thread inside common and we don't want to deadlock
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// This is safe to call even before LiStartConnection
|
||||
// on a thread inside common and we don't want to deadlock. It also avoids
|
||||
// blocking on the caller's thread waiting to acquire initLock.
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||
[initLock lock];
|
||||
LiStopConnection();
|
||||
[initLock unlock];
|
||||
});
|
||||
}
|
||||
|
||||
-(void) terminate
|
||||
{
|
||||
// We're guaranteed to not be on a moonlight-common thread
|
||||
// here so it's safe to call stop directly
|
||||
LiStopConnection();
|
||||
}
|
||||
|
||||
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion
|
||||
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks
|
||||
{
|
||||
self = [super init];
|
||||
_host = [config.host cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
|
||||
// Use a lock to ensure that only one thread is initializing
|
||||
// or deinitializing a connection at a time.
|
||||
if (initLock == nil) {
|
||||
initLock = [[NSLock alloc] init];
|
||||
}
|
||||
|
||||
LiInitializeServerInformation(&_serverInfo);
|
||||
_serverInfo.address = [config.host cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
_serverInfo.serverInfoAppVersion = [config.appVersion cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
if (config.gfeVersion != nil) {
|
||||
_serverInfo.serverInfoGfeVersion = [config.gfeVersion cStringUsingEncoding:NSUTF8StringEncoding];
|
||||
}
|
||||
|
||||
renderer = myRenderer;
|
||||
_callbacks = callbacks;
|
||||
_serverMajorVersion = serverMajorVersion;
|
||||
|
||||
LiInitializeStreamConfiguration(&_streamConfig);
|
||||
_streamConfig.width = config.width;
|
||||
@@ -302,6 +309,7 @@ void ClDisplayTransientMessage(char* message)
|
||||
|
||||
LiInitializeVideoCallbacks(&_drCallbacks);
|
||||
_drCallbacks.submitDecodeUnit = DrSubmitDecodeUnit;
|
||||
_drCallbacks.capabilities = CAPABILITY_REFERENCE_FRAME_INVALIDATION;
|
||||
|
||||
LiInitializeAudioCallbacks(&_arCallbacks);
|
||||
_arCallbacks.init = ArInit;
|
||||
@@ -403,12 +411,14 @@ static OSStatus playbackCallback(void *inRefCon,
|
||||
|
||||
-(void) main
|
||||
{
|
||||
LiStartConnection(_host,
|
||||
[initLock lock];
|
||||
LiStartConnection(&_serverInfo,
|
||||
&_streamConfig,
|
||||
&_clCallbacks,
|
||||
&_drCallbacks,
|
||||
&_arCallbacks,
|
||||
NULL, 0, _serverMajorVersion);
|
||||
NULL, 0);
|
||||
[initLock unlock];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
@interface StreamConfiguration : NSObject
|
||||
|
||||
@property NSString* host;
|
||||
@property NSString* appVersion;
|
||||
@property NSString* gfeVersion;
|
||||
@property NSString* appID;
|
||||
@property int width;
|
||||
@property int height;
|
||||
|
||||
@@ -14,6 +14,5 @@
|
||||
|
||||
- (id) initWithConfig:(StreamConfiguration*)config renderView:(UIView*)view connectionCallbacks:(id<ConnectionCallbacks>)callback;
|
||||
- (void) stopStream;
|
||||
- (void) stopStreamInternal;
|
||||
|
||||
@end
|
||||
|
||||
@@ -48,11 +48,11 @@
|
||||
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
|
||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
|
||||
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
|
||||
NSString* currentGame = [serverInfoResp getStringTag:@"currentgame"];
|
||||
NSString* pairStatus = [serverInfoResp getStringTag:@"PairStatus"];
|
||||
NSString* currentClient = [serverInfoResp getStringTag:@"CurrentClient"];
|
||||
NSString* appversion = [serverInfoResp getStringTag:@"appversion"];
|
||||
if (![serverInfoResp isStatusOk] || currentGame == NULL || pairStatus == NULL || appversion == NULL) {
|
||||
NSString* gfeVersion = [serverInfoResp getStringTag:@"GfeVersion"];
|
||||
NSString* serverState = [serverInfoResp getStringTag:@"state"];
|
||||
if (![serverInfoResp isStatusOk] || pairStatus == NULL || appversion == NULL || serverState == NULL) {
|
||||
[_callbacks launchFailed:@"Failed to connect to PC"];
|
||||
return;
|
||||
}
|
||||
@@ -64,12 +64,7 @@
|
||||
}
|
||||
|
||||
// resumeApp and launchApp handle calling launchFailed
|
||||
if (![currentGame isEqualToString:@"0"]) {
|
||||
if (![currentClient isEqualToString:@"1"]) {
|
||||
// The server is streaming to someone else
|
||||
[_callbacks launchFailed:@"There is another stream in progress"];
|
||||
return;
|
||||
}
|
||||
if ([serverState hasSuffix:@"_SERVER_BUSY"]) {
|
||||
// App already running, resume it
|
||||
if (![self resumeApp:hMan]) {
|
||||
return;
|
||||
@@ -88,29 +83,21 @@
|
||||
[((StreamView*)_renderView) setMouseDeltaFactors:_config.width / screenSize.width
|
||||
y:_config.height / screenSize.height];
|
||||
|
||||
int majorVersion = [[appversion substringToIndex:1] intValue];
|
||||
Log(LOG_I, @"Server is generation %d", majorVersion);
|
||||
// Populate the config's version fields from serverinfo
|
||||
_config.appVersion = appversion;
|
||||
_config.gfeVersion = gfeVersion;
|
||||
|
||||
VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc]initWithView:_renderView];
|
||||
_connection = [[Connection alloc] initWithConfig:_config renderer:renderer connectionCallbacks:_callbacks serverMajorVersion:majorVersion];
|
||||
_connection = [[Connection alloc] initWithConfig:_config renderer:renderer connectionCallbacks:_callbacks];
|
||||
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
|
||||
[opQueue addOperation:_connection];
|
||||
}
|
||||
|
||||
// This should NEVER be called from within a thread
|
||||
// owned by moonlight-common
|
||||
- (void) stopStream
|
||||
{
|
||||
[_connection terminate];
|
||||
}
|
||||
|
||||
// This should only be called from within a thread
|
||||
// owned by moonlight-common
|
||||
- (void) stopStreamInternal
|
||||
{
|
||||
[_connection terminateInternal];
|
||||
}
|
||||
|
||||
- (BOOL) launchApp:(HttpManager*)hMan {
|
||||
HttpResponse* launchResp = [[HttpResponse alloc] init];
|
||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest:
|
||||
|
||||
@@ -7,17 +7,17 @@
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "App.h"
|
||||
#import "TemporaryApp.h"
|
||||
|
||||
@protocol AppCallback <NSObject>
|
||||
|
||||
- (void) appClicked:(App*) app;
|
||||
- (void) appClicked:(TemporaryApp*) app;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIAppView : UIView
|
||||
|
||||
- (id) initWithApp:(App*)app andCallback:(id<AppCallback>)callback;
|
||||
- (id) initWithApp:(TemporaryApp*)app cache:(NSCache*)cache andCallback:(id<AppCallback>)callback;
|
||||
- (void) updateAppImage;
|
||||
|
||||
@end
|
||||
|
||||
+44
-16
@@ -9,40 +9,43 @@
|
||||
#import "UIAppView.h"
|
||||
|
||||
@implementation UIAppView {
|
||||
App* _app;
|
||||
TemporaryApp* _app;
|
||||
UIButton* _appButton;
|
||||
UILabel* _appLabel;
|
||||
UIImageView* _appOverlay;
|
||||
NSCache* _artCache;
|
||||
id<AppCallback> _callback;
|
||||
}
|
||||
|
||||
- (id) initWithApp:(App*)app andCallback:(id<AppCallback>)callback {
|
||||
static UIImage* noImage;
|
||||
|
||||
- (id) initWithApp:(TemporaryApp*)app cache:(NSCache*)cache andCallback:(id<AppCallback>)callback {
|
||||
self = [super init];
|
||||
_app = app;
|
||||
_callback = callback;
|
||||
_artCache = cache;
|
||||
|
||||
// Cache the NoAppImage ourselves to avoid
|
||||
// having to load it each time
|
||||
if (noImage == nil) {
|
||||
noImage = [UIImage imageNamed:@"NoAppImage"];
|
||||
}
|
||||
|
||||
_appButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||
UIImage* noImage = [UIImage imageNamed:@"NoAppImage"];
|
||||
[_appButton setBackgroundImage:noImage forState:UIControlStateNormal];
|
||||
[_appButton setContentEdgeInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
|
||||
[_appButton sizeToFit];
|
||||
[_appButton addTarget:self action:@selector(appClicked) forControlEvents:UIControlEventTouchUpInside];
|
||||
|
||||
_appOverlay = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Play"]];
|
||||
_appOverlay.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
_appOverlay.layer.shadowOffset = CGSizeMake(0, 0);
|
||||
_appOverlay.layer.shadowOpacity = 1;
|
||||
_appOverlay.layer.shadowRadius = 2.0;
|
||||
[_appOverlay setHidden: YES];
|
||||
|
||||
[self addSubview:_appButton];
|
||||
[self addSubview:_appOverlay];
|
||||
[self sizeToFit];
|
||||
|
||||
_appButton.frame = CGRectMake(0, 0, noImage.size.width, noImage.size.height);
|
||||
_appOverlay.frame = CGRectMake(0, 0, noImage.size.width / 2.f, noImage.size.height / 4.f);
|
||||
self.frame = CGRectMake(0, 0, noImage.size.width, noImage.size.height);
|
||||
[_appOverlay setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/6)];
|
||||
|
||||
// Rasterizing the cell layer increases rendering performance by quite a bit
|
||||
self.layer.shouldRasterize = YES;
|
||||
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
|
||||
|
||||
return self;
|
||||
}
|
||||
@@ -52,15 +55,40 @@
|
||||
}
|
||||
|
||||
- (void) updateAppImage {
|
||||
[_appOverlay setHidden:!_app.isRunning];
|
||||
if (_appOverlay != nil) {
|
||||
[_appOverlay removeFromSuperview];
|
||||
_appOverlay = nil;
|
||||
}
|
||||
|
||||
if ([_app.id isEqualToString:_app.host.currentGame]) {
|
||||
// Only create the app overlay if needed
|
||||
_appOverlay = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"Play"]];
|
||||
_appOverlay.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||
_appOverlay.layer.shadowOffset = CGSizeMake(0, 0);
|
||||
_appOverlay.layer.shadowOpacity = 1;
|
||||
_appOverlay.layer.shadowRadius = 2.0;
|
||||
|
||||
[self addSubview:_appOverlay];
|
||||
|
||||
_appOverlay.frame = CGRectMake(0, 0, noImage.size.width / 2.f, noImage.size.height / 4.f);
|
||||
[_appOverlay setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/6)];
|
||||
}
|
||||
|
||||
// TODO: Improve no-app image detection
|
||||
BOOL noAppImage = false;
|
||||
|
||||
if (_app.image != nil) {
|
||||
UIImage* appImage = [UIImage imageWithData:_app.image];
|
||||
// Load the decoded image from the cache
|
||||
UIImage* appImage = [_artCache objectForKey:_app];
|
||||
if (appImage == nil) {
|
||||
// Not cached; we have to decode this now
|
||||
appImage = [UIImage imageWithData:_app.image];
|
||||
[_artCache setObject:appImage forKey:_app];
|
||||
}
|
||||
|
||||
// This size of image might be blank image received from GameStream.
|
||||
if (!(appImage.size.width == 130.f && appImage.size.height == 180.f)) {
|
||||
if (!(appImage.size.width == 130.f && appImage.size.height == 180.f) && // GFE 2.0
|
||||
!(appImage.size.width == 628.f && appImage.size.height == 888.f)) { // GFE 3.0
|
||||
_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);
|
||||
|
||||
@@ -7,19 +7,19 @@
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "Host.h"
|
||||
#import "TemporaryHost.h"
|
||||
|
||||
@protocol HostCallback <NSObject>
|
||||
|
||||
- (void) hostClicked:(Host*)host view:(UIView*)view;
|
||||
- (void) hostLongClicked:(Host*)host view:(UIView*)view;
|
||||
- (void) hostClicked:(TemporaryHost*)host view:(UIView*)view;
|
||||
- (void) hostLongClicked:(TemporaryHost*)host view:(UIView*)view;
|
||||
- (void) addHostClicked;
|
||||
|
||||
@end
|
||||
|
||||
@interface UIComputerView : UIView
|
||||
|
||||
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback;
|
||||
- (id) initWithComputer:(TemporaryHost*)host andCallback:(id<HostCallback>)callback;
|
||||
- (id) initForAddWithCallback:(id<HostCallback>)callback;
|
||||
|
||||
@end
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
#import "UIComputerView.h"
|
||||
|
||||
@implementation UIComputerView {
|
||||
Host* _host;
|
||||
TemporaryHost* _host;
|
||||
UIButton* _hostButton;
|
||||
UILabel* _hostLabel;
|
||||
UILabel* _hostStatus;
|
||||
@@ -72,7 +72,7 @@ static const int LABEL_DY = 20;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback {
|
||||
- (id) initWithComputer:(TemporaryHost*)host andCallback:(id<HostCallback>)callback {
|
||||
self = [self init];
|
||||
_host = host;
|
||||
_callback = callback;
|
||||
@@ -123,7 +123,7 @@ static const int LABEL_DY = 20;
|
||||
self.frame = CGRectMake(x, y, width, height);
|
||||
}
|
||||
|
||||
- (void) updateContentsForHost:(Host*)host {
|
||||
- (void) updateContentsForHost:(TemporaryHost*)host {
|
||||
_hostLabel.text = _host.name;
|
||||
_hostLabel.textColor = [UIColor whiteColor];
|
||||
[_hostLabel sizeToFit];
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
@import ImageIO;
|
||||
|
||||
#import "MainFrameViewController.h"
|
||||
#import "CryptoManager.h"
|
||||
#import "HttpManager.h"
|
||||
@@ -13,10 +15,9 @@
|
||||
#import "Utils.h"
|
||||
#import "UIComputerView.h"
|
||||
#import "UIAppView.h"
|
||||
#import "App.h"
|
||||
#import "SettingsViewController.h"
|
||||
#import "DataManager.h"
|
||||
#import "Settings.h"
|
||||
#import "TemporarySettings.h"
|
||||
#import "WakeOnLanManager.h"
|
||||
#import "AppListResponse.h"
|
||||
#import "ServerInfoResponse.h"
|
||||
@@ -28,7 +29,7 @@
|
||||
|
||||
@implementation MainFrameViewController {
|
||||
NSOperationQueue* _opQueue;
|
||||
Host* _selectedHost;
|
||||
TemporaryHost* _selectedHost;
|
||||
NSString* _uniqueId;
|
||||
NSData* _cert;
|
||||
DiscoveryManager* _discMan;
|
||||
@@ -38,6 +39,7 @@
|
||||
UIScrollView* hostScrollView;
|
||||
int currentPosition;
|
||||
NSArray* _sortedAppList;
|
||||
NSCache* _boxArtCache;
|
||||
}
|
||||
static NSMutableSet* hostList;
|
||||
|
||||
@@ -46,27 +48,45 @@ static NSMutableSet* hostList;
|
||||
_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing"
|
||||
message:[NSString stringWithFormat:@"Enter the following PIN on the host machine: %@", PIN]
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[_pairAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action) {
|
||||
_pairAlert = nil;
|
||||
[_discMan startDiscovery];
|
||||
[self hideLoadingFrame];
|
||||
}]];
|
||||
[self presentViewController:_pairAlert animated:YES completion:nil];
|
||||
});
|
||||
}
|
||||
|
||||
- (void)displayFailureDialog:(NSString *)message {
|
||||
UIAlertController* failedDialog = [UIAlertController alertControllerWithTitle:@"Pairing Failed"
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[failedDialog addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
|
||||
[self presentViewController:failedDialog animated:YES completion:nil];
|
||||
|
||||
[_discMan startDiscovery];
|
||||
[self hideLoadingFrame];
|
||||
}
|
||||
|
||||
- (void)pairFailed:(NSString *)message {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_pairAlert dismissViewControllerAnimated:YES completion:nil];
|
||||
_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing Failed"
|
||||
message:message
|
||||
preferredStyle:UIAlertControllerStyleAlert];
|
||||
[_pairAlert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
|
||||
[self presentViewController:_pairAlert animated:YES completion:nil];
|
||||
|
||||
[_discMan startDiscovery];
|
||||
[self hideLoadingFrame];
|
||||
if (_pairAlert != nil) {
|
||||
[_pairAlert dismissViewControllerAnimated:YES completion:^{
|
||||
[self displayFailureDialog:message];
|
||||
}];
|
||||
_pairAlert = nil;
|
||||
}
|
||||
else {
|
||||
[self displayFailureDialog:message];
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
- (void)pairSuccessful {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[_pairAlert dismissViewControllerAnimated:YES completion:nil];
|
||||
_pairAlert = nil;
|
||||
|
||||
[_discMan startDiscovery];
|
||||
[self alreadyPaired];
|
||||
});
|
||||
@@ -77,7 +97,7 @@ static NSMutableSet* hostList;
|
||||
|
||||
// Capture the host here because it can change once we
|
||||
// leave the main thread
|
||||
Host* host = _selectedHost;
|
||||
TemporaryHost* host = _selectedHost;
|
||||
|
||||
if ([host.appList count] > 0) {
|
||||
usingCachedAppList = true;
|
||||
@@ -97,11 +117,26 @@ static NSMutableSet* hostList;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.activeAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
|
||||
|
||||
AppListResponse* appListResp = [[AppListResponse alloc] init];
|
||||
|
||||
// Exempt this host from discovery while handling the applist query
|
||||
[_discMan removeHostFromDiscovery:host];
|
||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appListResp withUrlRequest:[hMan newAppListRequest]]];
|
||||
|
||||
// Try up to 5 times to get the app list
|
||||
AppListResponse* appListResp;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
appListResp = [[AppListResponse alloc] init];
|
||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appListResp withUrlRequest:[hMan newAppListRequest]]];
|
||||
if (appListResp == nil || ![appListResp isStatusOk] || [appListResp getAppList] == nil) {
|
||||
Log(LOG_W, @"Failed to get applist on try %d: %@", i, appListResp.statusMessage);
|
||||
|
||||
// Wait for one second then retry
|
||||
[NSThread sleepForTimeInterval:1];
|
||||
}
|
||||
else {
|
||||
Log(LOG_I, @"App list successfully retreived - took %d tries", i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
[_discMan addHostToDiscovery:host];
|
||||
|
||||
if (appListResp == nil || ![appListResp isStatusOk] || [appListResp getAppList] == nil) {
|
||||
@@ -123,7 +158,7 @@ static NSMutableSet* hostList;
|
||||
});
|
||||
} else {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self mergeAppLists:[appListResp getAppList] forHost:host];
|
||||
[self updateApplist:[appListResp getAppList] forHost:host];
|
||||
|
||||
if (host != _selectedHost) {
|
||||
return;
|
||||
@@ -141,21 +176,21 @@ static NSMutableSet* hostList;
|
||||
});
|
||||
}
|
||||
|
||||
- (void) mergeAppLists:(NSArray*) newList forHost:(Host*)host {
|
||||
- (void) updateApplist:(NSSet*) newList forHost:(TemporaryHost*)host {
|
||||
DataManager* database = [[DataManager alloc] init];
|
||||
|
||||
for (TemporaryApp* app in newList) {
|
||||
BOOL appAlreadyInList = NO;
|
||||
for (App* savedApp in host.appList) {
|
||||
BOOL appAlreadyInList = NO;
|
||||
for (TemporaryApp* savedApp in host.appList) {
|
||||
if ([app.id isEqualToString:savedApp.id]) {
|
||||
savedApp.name = app.name;
|
||||
savedApp.isRunning = app.isRunning;
|
||||
appAlreadyInList = YES;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!appAlreadyInList) {
|
||||
app.host = host;
|
||||
[database addAppFromTemporaryApp:app];
|
||||
[host.appList addObject:app];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,9 +198,9 @@ static NSMutableSet* hostList;
|
||||
do {
|
||||
appWasRemoved = NO;
|
||||
|
||||
for (App* app in host.appList) {
|
||||
for (TemporaryApp* app in host.appList) {
|
||||
appWasRemoved = YES;
|
||||
for (App* mergedApp in newList) {
|
||||
for (TemporaryApp* mergedApp in newList) {
|
||||
if ([mergedApp.id isEqualToString:app.id]) {
|
||||
appWasRemoved = NO;
|
||||
break;
|
||||
@@ -174,7 +209,14 @@ static NSMutableSet* hostList;
|
||||
if (appWasRemoved) {
|
||||
// Removing the app mutates the list we're iterating (which isn't legal).
|
||||
// We need to jump out of this loop and restart enumeration.
|
||||
[database removeAppFromHost:app];
|
||||
|
||||
[host.appList removeObject:app];
|
||||
|
||||
// It's important to remove the app record from the database
|
||||
// since we'll have a constraint violation now that appList
|
||||
// doesn't have this app in it.
|
||||
[database removeApp:app];
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -182,19 +224,25 @@ static NSMutableSet* hostList;
|
||||
// Keep looping until the list is no longer being mutated
|
||||
} while (appWasRemoved);
|
||||
|
||||
[database saveData];
|
||||
[database updateAppsForExistingHost:host];
|
||||
}
|
||||
|
||||
- (void)showHostSelectionView {
|
||||
[_appManager stopRetrieving];
|
||||
[[[DataManager alloc] init] saveData];
|
||||
_selectedHost = nil;
|
||||
_computerNameButton.title = @"No Host Selected";
|
||||
[self.collectionView reloadData];
|
||||
[self.view addSubview:hostScrollView];
|
||||
}
|
||||
|
||||
- (void) receivedAssetForApp:(App*)app {
|
||||
- (void) receivedAssetForApp:(TemporaryApp*)app {
|
||||
// Update the box art cache now so we don't have to do it
|
||||
// on the main thread
|
||||
[self updateBoxArtCacheForApp:app];
|
||||
|
||||
DataManager* dataManager = [[DataManager alloc] init];
|
||||
[dataManager updateIconForExistingApp: app];
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self.collectionView reloadData];
|
||||
});
|
||||
@@ -208,7 +256,7 @@ static NSMutableSet* hostList;
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void) hostClicked:(Host *)host view:(UIView *)view {
|
||||
- (void) hostClicked:(TemporaryHost *)host view:(UIView *)view {
|
||||
// Treat clicks on offline hosts to be long clicks
|
||||
// This shows the context menu with wake, delete, etc. rather
|
||||
// than just hanging for a while and failing as we would in this
|
||||
@@ -224,8 +272,10 @@ static NSMutableSet* hostList;
|
||||
|
||||
// If we are online, paired, and have a cached app list, skip straight
|
||||
// to the app grid without a loading frame. This is the fast path that users
|
||||
// should hit most.
|
||||
if (host.online && host.pairState == PairStatePaired && host.appList.count > 0) {
|
||||
// should hit most. Check for a valid view because we don't want to hit the fast
|
||||
// path after coming back from streaming, since we need to fetch serverinfo too
|
||||
// so that our active game data is correct.
|
||||
if (host.online && host.pairState == PairStatePaired && host.appList.count > 0 && view != nil) {
|
||||
[self alreadyPaired];
|
||||
return;
|
||||
}
|
||||
@@ -274,7 +324,7 @@ static NSMutableSet* hostList;
|
||||
});
|
||||
}
|
||||
|
||||
- (void)hostLongClicked:(Host *)host view:(UIView *)view {
|
||||
- (void)hostLongClicked:(TemporaryHost *)host view:(UIView *)view {
|
||||
Log(LOG_D, @"Long clicked host: %@", host.name);
|
||||
UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
|
||||
if (!host.online) {
|
||||
@@ -300,8 +350,8 @@ static NSMutableSet* hostList;
|
||||
[dataMan removeHost:host];
|
||||
@synchronized(hostList) {
|
||||
[hostList removeObject:host];
|
||||
[self updateAllHosts:[hostList allObjects]];
|
||||
}
|
||||
[self updateAllHosts:[hostList allObjects]];
|
||||
|
||||
}]];
|
||||
[longClickAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
||||
@@ -323,10 +373,8 @@ static NSMutableSet* hostList;
|
||||
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
|
||||
NSString* hostAddress = ((UITextField*)[[alertController textFields] objectAtIndex:0]).text;
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||
[_discMan discoverHost:hostAddress withCallback:^(Host* host, NSString* error){
|
||||
[_discMan discoverHost:hostAddress withCallback:^(TemporaryHost* host, NSString* error){
|
||||
if (host != nil) {
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
[dataMan saveData];
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
@synchronized(hostList) {
|
||||
[hostList addObject:host];
|
||||
@@ -347,14 +395,14 @@ static NSMutableSet* hostList;
|
||||
[self presentViewController:alertController animated:YES completion:nil];
|
||||
}
|
||||
|
||||
- (void) appClicked:(App *)app {
|
||||
- (void) appClicked:(TemporaryApp *)app {
|
||||
Log(LOG_D, @"Clicked app: %@", app.name);
|
||||
_streamConfig = [[StreamConfiguration alloc] init];
|
||||
_streamConfig.host = app.host.activeAddress;
|
||||
_streamConfig.appID = app.id;
|
||||
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
Settings* streamSettings = [dataMan retrieveSettings];
|
||||
TemporarySettings* streamSettings = [dataMan getSettings];
|
||||
|
||||
_streamConfig.frameRate = [streamSettings.framerate intValue];
|
||||
_streamConfig.bitRate = [streamSettings.bitrate intValue];
|
||||
@@ -367,7 +415,7 @@ static NSMutableSet* hostList;
|
||||
[[self revealViewController] revealToggle:self];
|
||||
}
|
||||
|
||||
App* currentApp = [self findRunningApp:app.host];
|
||||
TemporaryApp* currentApp = [self findRunningApp:app.host];
|
||||
if (currentApp != nil) {
|
||||
UIAlertController* alertController = [UIAlertController
|
||||
alertControllerWithTitle: app.name
|
||||
@@ -388,6 +436,17 @@ static NSMutableSet* hostList;
|
||||
// Exempt this host from discovery while handling the quit operation
|
||||
[_discMan removeHostFromDiscovery:app.host];
|
||||
[hMan executeRequestSynchronously:quitRequest];
|
||||
if (quitResponse.statusCode == 200) {
|
||||
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
|
||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
|
||||
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
|
||||
if (![serverInfoResp isStatusOk] || ![[serverInfoResp getStringTag:@"state"] hasSuffix:@"_SERVER_AVAILABLE"]) {
|
||||
// On newer GFE versions, the quit request succeeds even though the app doesn't
|
||||
// really quit if another client tries to kill your app. We'll patch the response
|
||||
// to look like the old error in that case, so the UI behaves.
|
||||
quitResponse.statusCode = 599;
|
||||
}
|
||||
}
|
||||
[_discMan addHostToDiscovery:app.host];
|
||||
|
||||
UIAlertController* alert;
|
||||
@@ -401,7 +460,7 @@ static NSMutableSet* hostList;
|
||||
}
|
||||
// If it succeeds and we're to start streaming, segue to the stream and return
|
||||
else if (![app.id isEqualToString:currentApp.id]) {
|
||||
currentApp.isRunning = NO;
|
||||
app.host.currentGame = @"0";
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
[self updateAppsForHost:app.host];
|
||||
@@ -412,7 +471,7 @@ static NSMutableSet* hostList;
|
||||
}
|
||||
// Otherwise, display a dialog to notify the user that the app was quit
|
||||
else {
|
||||
currentApp.isRunning = NO;
|
||||
app.host.currentGame = @"0";
|
||||
|
||||
alert = [UIAlertController alertControllerWithTitle:@"Quitting App"
|
||||
message:@"The app was quit successfully."
|
||||
@@ -433,9 +492,9 @@ static NSMutableSet* hostList;
|
||||
}
|
||||
}
|
||||
|
||||
- (App*) findRunningApp:(Host*)host {
|
||||
for (App* app in host.appList) {
|
||||
if (app.isRunning) {
|
||||
- (TemporaryApp*) findRunningApp:(TemporaryHost*)host {
|
||||
for (TemporaryApp* app in host.appList) {
|
||||
if ([app.id isEqualToString:host.currentGame]) {
|
||||
return app;
|
||||
}
|
||||
}
|
||||
@@ -500,6 +559,8 @@ static NSMutableSet* hostList;
|
||||
hostList = [[NSMutableSet alloc] init];
|
||||
}
|
||||
|
||||
_boxArtCache = [[NSCache alloc] init];
|
||||
|
||||
[self setAutomaticallyAdjustsScrollViewInsets:NO];
|
||||
|
||||
hostScrollView = [[ComputerScrollView alloc] init];
|
||||
@@ -508,14 +569,13 @@ static NSMutableSet* hostList;
|
||||
hostScrollView.delaysContentTouches = NO;
|
||||
|
||||
UIButton* pullArrow = [[UIButton alloc] init];
|
||||
[pullArrow addTarget:self.revealViewController action:@selector(revealToggle:) forControlEvents:UIControlEventTouchDown];
|
||||
[pullArrow setImage:[UIImage imageNamed:@"PullArrow"] forState:UIControlStateNormal];
|
||||
[pullArrow sizeToFit];
|
||||
pullArrow.frame = CGRectMake(0,
|
||||
self.collectionView.frame.size.height / 2 - pullArrow.frame.size.height / 2 - self.navigationController.navigationBar.frame.size.height,
|
||||
self.collectionView.frame.size.height / 6 - pullArrow.frame.size.height / 2 - self.navigationController.navigationBar.frame.size.height,
|
||||
pullArrow.frame.size.width,
|
||||
pullArrow.frame.size.height);
|
||||
[self.view addSubview:pullArrow];
|
||||
|
||||
|
||||
self.collectionView.delaysContentTouches = NO;
|
||||
self.collectionView.allowsMultipleSelection = NO;
|
||||
@@ -524,8 +584,27 @@ static NSMutableSet* hostList;
|
||||
[self retrieveSavedHosts];
|
||||
_discMan = [[DiscoveryManager alloc] initWithHosts:[hostList allObjects] andCallback:self];
|
||||
|
||||
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||
selector: @selector(handleReturnToForeground)
|
||||
name: UIApplicationWillEnterForegroundNotification
|
||||
object: nil];
|
||||
|
||||
[self updateHosts];
|
||||
[self.view addSubview:hostScrollView];
|
||||
[self.view addSubview:pullArrow];
|
||||
}
|
||||
|
||||
-(void)dealloc
|
||||
{
|
||||
[[NSNotificationCenter defaultCenter] removeObserver:self];
|
||||
}
|
||||
|
||||
-(void)handleReturnToForeground
|
||||
{
|
||||
// This will refresh the applist when a paired host is selected
|
||||
if (_selectedHost != nil && _selectedHost.pairState == PairStatePaired) {
|
||||
[self hostClicked:_selectedHost view:nil];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
@@ -540,10 +619,7 @@ static NSMutableSet* hostList;
|
||||
|
||||
[_discMan startDiscovery];
|
||||
|
||||
// This will refresh the applist
|
||||
if (_selectedHost != nil) {
|
||||
[self hostClicked:_selectedHost view:nil];
|
||||
}
|
||||
[self handleReturnToForeground];
|
||||
}
|
||||
|
||||
- (void)viewDidDisappear:(BOOL)animated
|
||||
@@ -552,18 +628,18 @@ static NSMutableSet* hostList;
|
||||
// when discovery stops, we must create a new instance because you cannot restart an NSOperation when it is finished
|
||||
[_discMan stopDiscovery];
|
||||
|
||||
// In case the host objects were updated in the background
|
||||
[[[DataManager alloc] init] saveData];
|
||||
// Purge the box art cache
|
||||
[_boxArtCache removeAllObjects];
|
||||
}
|
||||
|
||||
- (void) retrieveSavedHosts {
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
NSArray* hosts = [dataMan retrieveHosts];
|
||||
NSArray* hosts = [dataMan getHosts];
|
||||
@synchronized(hostList) {
|
||||
[hostList addObjectsFromArray:hosts];
|
||||
|
||||
// Initialize the non-persistent host state
|
||||
for (Host* host in hostList) {
|
||||
for (TemporaryHost* host in hostList) {
|
||||
if (host.activeAddress == nil) {
|
||||
host.activeAddress = host.localAddress;
|
||||
}
|
||||
@@ -580,7 +656,7 @@ static NSMutableSet* hostList;
|
||||
- (void) updateAllHosts:(NSArray *)hosts {
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
Log(LOG_D, @"New host list:");
|
||||
for (Host* host in hosts) {
|
||||
for (TemporaryHost* host in hosts) {
|
||||
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\t activeAddress:%@ \n}", host.name, host.address, host.localAddress, host.externalAddress, host.uuid, host.mac, host.pairState, host.online, host.activeAddress);
|
||||
}
|
||||
@synchronized(hostList) {
|
||||
@@ -598,13 +674,16 @@ static NSMutableSet* hostList;
|
||||
UIComputerView* compView;
|
||||
float prevEdge = -1;
|
||||
@synchronized (hostList) {
|
||||
for (Host* comp in hostList) {
|
||||
// Sort the host list in alphabetical order
|
||||
NSArray* sortedHostList = [[hostList allObjects] sortedArrayUsingSelector:@selector(compareName:)];
|
||||
for (TemporaryHost* comp in sortedHostList) {
|
||||
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);
|
||||
|
||||
@@ -620,7 +699,31 @@ static NSMutableSet* hostList;
|
||||
}
|
||||
}
|
||||
|
||||
- (void) updateAppsForHost:(Host*)host {
|
||||
// This function forces immediate decoding of the UIImage, rather
|
||||
// than the default lazy decoding that results in janky scrolling.
|
||||
+ (UIImage*) loadBoxArtForCaching:(TemporaryApp*)app {
|
||||
|
||||
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)app.image, NULL);
|
||||
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)@{(id)kCGImageSourceShouldCacheImmediately: (id)kCFBooleanTrue});
|
||||
|
||||
UIImage *boxArt = [UIImage imageWithCGImage:cgImage];
|
||||
|
||||
CGImageRelease(cgImage);
|
||||
CFRelease(source);
|
||||
|
||||
return boxArt;
|
||||
}
|
||||
|
||||
- (void) updateBoxArtCacheForApp:(TemporaryApp*)app {
|
||||
if (app.image == nil) {
|
||||
[_boxArtCache removeObjectForKey:app];
|
||||
}
|
||||
else if ([_boxArtCache objectForKey:app] == nil) {
|
||||
[_boxArtCache setObject:[MainFrameViewController loadBoxArtForCaching:app] forKey:app];
|
||||
}
|
||||
}
|
||||
|
||||
- (void) updateAppsForHost:(TemporaryHost*)host {
|
||||
if (host != _selectedHost) {
|
||||
Log(LOG_W, @"Mismatched host during app update");
|
||||
return;
|
||||
@@ -629,6 +732,33 @@ static NSMutableSet* hostList;
|
||||
_sortedAppList = [host.appList allObjects];
|
||||
_sortedAppList = [_sortedAppList sortedArrayUsingSelector:@selector(compareName:)];
|
||||
|
||||
// Split the sorted array in half to allow 2 jobs to process app assets at once
|
||||
NSArray *firstHalf;
|
||||
NSArray *secondHalf;
|
||||
NSRange range;
|
||||
|
||||
range.location = 0;
|
||||
range.length = [_sortedAppList count] / 2;
|
||||
|
||||
firstHalf = [_sortedAppList subarrayWithRange:range];
|
||||
|
||||
range.location = range.length;
|
||||
range.length = [_sortedAppList count] - range.length;
|
||||
|
||||
secondHalf = [_sortedAppList subarrayWithRange:range];
|
||||
|
||||
// Start 2 jobs
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
for (TemporaryApp* app in firstHalf) {
|
||||
[self updateBoxArtCacheForApp:app];
|
||||
}
|
||||
});
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
for (TemporaryApp* app in secondHalf) {
|
||||
[self updateBoxArtCacheForApp:app];
|
||||
}
|
||||
});
|
||||
|
||||
[hostScrollView removeFromSuperview];
|
||||
[self.collectionView reloadData];
|
||||
}
|
||||
@@ -636,9 +766,8 @@ static NSMutableSet* hostList;
|
||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"AppCell" forIndexPath:indexPath];
|
||||
|
||||
|
||||
App* app = _sortedAppList[indexPath.row];
|
||||
UIAppView* appView = [[UIAppView alloc] initWithApp:app andCallback:self];
|
||||
TemporaryApp* app = _sortedAppList[indexPath.row];
|
||||
UIAppView* appView = [[UIAppView alloc] initWithApp:app cache:_boxArtCache andCallback:self];
|
||||
[appView updateAppImage];
|
||||
|
||||
if (appView.bounds.size.width > 10.0) {
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
//
|
||||
|
||||
#import "SettingsViewController.h"
|
||||
#import "Settings.h"
|
||||
#import "TemporarySettings.h"
|
||||
#import "DataManager.h"
|
||||
|
||||
#define BITRATE_INTERVAL 500 // in kbps
|
||||
@@ -22,7 +22,7 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
|
||||
[super viewDidLoad];
|
||||
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
Settings* currentSettings = [dataMan retrieveSettings];
|
||||
TemporarySettings* currentSettings = [dataMan getSettings];
|
||||
|
||||
// Bitrate is persisted in kbps
|
||||
_bitrate = [currentSettings.bitrate integerValue];
|
||||
@@ -38,13 +38,39 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
|
||||
NSInteger onscreenControls = [currentSettings.onscreenControls integerValue];
|
||||
|
||||
[self.resolutionSelector setSelectedSegmentIndex:resolution];
|
||||
[self.resolutionSelector addTarget:self action:@selector(newResolutionFpsChosen) forControlEvents:UIControlEventValueChanged];
|
||||
[self.framerateSelector setSelectedSegmentIndex:framerate];
|
||||
[self.framerateSelector addTarget:self action:@selector(newResolutionFpsChosen) forControlEvents:UIControlEventValueChanged];
|
||||
[self.onscreenControlSelector setSelectedSegmentIndex:onscreenControls];
|
||||
[self.bitrateSlider setValue:(_bitrate / BITRATE_INTERVAL) animated:YES];
|
||||
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
|
||||
[self updateBitrateText];
|
||||
}
|
||||
|
||||
- (void) newResolutionFpsChosen {
|
||||
NSInteger frameRate = [self getChosenFrameRate];
|
||||
NSInteger resHeight = [self getChosenStreamHeight];
|
||||
NSInteger defaultBitrate;
|
||||
|
||||
// 1080p60 is 20 Mbps
|
||||
if (frameRate == 60 && resHeight == 1080) {
|
||||
defaultBitrate = 20000;
|
||||
}
|
||||
// 720p60 and 1080p30 are 10 Mbps
|
||||
else if (frameRate == 60 || resHeight == 1080) {
|
||||
defaultBitrate = 10000;
|
||||
}
|
||||
// 720p30 is 5 Mbps
|
||||
else {
|
||||
defaultBitrate = 5000;
|
||||
}
|
||||
|
||||
_bitrate = defaultBitrate;
|
||||
[self.bitrateSlider setValue:defaultBitrate / BITRATE_INTERVAL animated:YES];
|
||||
|
||||
[self updateBitrateText];
|
||||
}
|
||||
|
||||
- (void) bitrateSliderMoved {
|
||||
_bitrate = BITRATE_INTERVAL * (int)self.bitrateSlider.value;
|
||||
[self updateBitrateText];
|
||||
@@ -55,11 +81,23 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
|
||||
[self.bitrateLabel setText:[NSString stringWithFormat:bitrateFormat, _bitrate / 1000.]];
|
||||
}
|
||||
|
||||
- (NSInteger) getChosenFrameRate {
|
||||
return [self.framerateSelector selectedSegmentIndex] == 0 ? 30 : 60;
|
||||
}
|
||||
|
||||
- (NSInteger) getChosenStreamHeight {
|
||||
return [self.resolutionSelector selectedSegmentIndex] == 0 ? 720 : 1080;
|
||||
}
|
||||
|
||||
- (NSInteger) getChosenStreamWidth {
|
||||
return [self getChosenStreamHeight] == 720 ? 1280 : 1920;
|
||||
}
|
||||
|
||||
- (void) saveSettings {
|
||||
DataManager* dataMan = [[DataManager alloc] init];
|
||||
NSInteger framerate = [self.framerateSelector selectedSegmentIndex] == 0 ? 30 : 60;
|
||||
NSInteger height = [self.resolutionSelector selectedSegmentIndex] == 0 ? 720 : 1080;
|
||||
NSInteger width = height == 720 ? 1280 : 1920;
|
||||
NSInteger framerate = [self getChosenFrameRate];
|
||||
NSInteger height = [self getChosenStreamHeight];
|
||||
NSInteger width = [self getChosenStreamWidth];
|
||||
NSInteger onscreenControls = [self.onscreenControlSelector selectedSegmentIndex];
|
||||
[dataMan saveSettingsWithBitrate:_bitrate framerate:framerate height:height width:width onscreenControls:onscreenControls];
|
||||
}
|
||||
|
||||
@@ -84,10 +84,10 @@
|
||||
[self presentViewController:conTermAlert animated:YES completion:nil];
|
||||
});
|
||||
|
||||
[_streamMan stopStreamInternal];
|
||||
[_streamMan stopStream];
|
||||
}
|
||||
|
||||
- (void) stageStarting:(char*)stageName {
|
||||
- (void) stageStarting:(const char*)stageName {
|
||||
Log(LOG_I, @"Starting %s", stageName);
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
NSString* lowerCase = [NSString stringWithFormat:@"%s in progress...", stageName];
|
||||
@@ -98,10 +98,10 @@
|
||||
});
|
||||
}
|
||||
|
||||
- (void) stageComplete:(char*)stageName {
|
||||
- (void) stageComplete:(const char*)stageName {
|
||||
}
|
||||
|
||||
- (void) stageFailed:(char*)stageName withError:(long)errorCode {
|
||||
- (void) stageFailed:(const char*)stageName withError:(long)errorCode {
|
||||
Log(LOG_I, @"Stage %s failed: %ld", stageName, errorCode);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
@@ -115,7 +115,7 @@
|
||||
[self presentViewController:alert animated:YES completion:nil];
|
||||
});
|
||||
|
||||
[_streamMan stopStreamInternal];
|
||||
[_streamMan stopStream];
|
||||
}
|
||||
|
||||
- (void) launchFailed:(NSString*)message {
|
||||
@@ -132,11 +132,11 @@
|
||||
});
|
||||
}
|
||||
|
||||
- (void) displayMessage:(char*)message {
|
||||
- (void) displayMessage:(const char*)message {
|
||||
Log(LOG_I, @"Display message: %s", message);
|
||||
}
|
||||
|
||||
- (void) displayTransientMessage:(char*)message {
|
||||
- (void) displayTransientMessage:(const char*)message {
|
||||
Log(LOG_I, @"Display transient message: %s", message);
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9832D1351BBCD5C50036EF48 /* TemporaryApp.m */; };
|
||||
987140041B04542F00AB57D5 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FB1E43101AE8B0F200AFF679 /* libmoonlight-common.a */; };
|
||||
98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98AB2E841CAD46840089BB98 /* libmoonlight-common.a */; };
|
||||
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */; };
|
||||
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */ = {isa = PBXBuildFile; fileRef = 98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */; };
|
||||
9E5D600B1A5A5A3900689918 /* Apache License.txt in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FF81A5A5A3900689918 /* Apache License.txt */; };
|
||||
9E5D600C1A5A5A3900689918 /* Roboto-Black.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FF91A5A5A3900689918 /* Roboto-Black.ttf */; };
|
||||
9E5D600E1A5A5A3900689918 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */; };
|
||||
@@ -16,6 +18,8 @@
|
||||
9E5D60131A5A5A3900689918 /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D60001A5A5A3900689918 /* Roboto-Medium.ttf */; };
|
||||
9E5D60151A5A5A3900689918 /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D60021A5A5A3900689918 /* Roboto-Regular.ttf */; };
|
||||
9E5D60161A5A5A3900689918 /* Roboto-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D60031A5A5A3900689918 /* Roboto-Thin.ttf */; };
|
||||
D46A73AD1CBC7D090039F1EE /* ControllerUnitTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D46A73AC1CBC7D090039F1EE /* ControllerUnitTests.swift */; };
|
||||
D4746EEC1CBC740C006FB401 /* Controller.swift in Sources */ = {isa = PBXBuildFile; fileRef = D4746EEB1CBC740C006FB401 /* Controller.swift */; };
|
||||
FB1D59971BBCCB6400F482CA /* ComputerScrollView.m in Sources */ = {isa = PBXBuildFile; fileRef = FB1D59961BBCCB6400F482CA /* ComputerScrollView.m */; };
|
||||
FB1D599A1BBCCD7E00F482CA /* AppCollectionView.m in Sources */ = {isa = PBXBuildFile; fileRef = FB1D59991BBCCD7E00F482CA /* AppCollectionView.m */; };
|
||||
FB290CF219B2C406004C83CF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF119B2C406004C83CF /* Foundation.framework */; };
|
||||
@@ -64,7 +68,6 @@
|
||||
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD391A7E05CE00872C98 /* ServerInfoResponse.m */; };
|
||||
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD3C1A7E111600872C98 /* AppAssetResponse.m */; };
|
||||
FB9AFD401A7E127D00872C98 /* AppListResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD3F1A7E127D00872C98 /* AppListResponse.m */; };
|
||||
FB9AFD431A7F0C6900872C98 /* Controller.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD421A7F0C6900872C98 /* Controller.m */; };
|
||||
FBD1C8E21A8AD71400C6703C /* Logger.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD1C8E11A8AD71400C6703C /* Logger.m */; };
|
||||
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494219FC9C04002D2A60 /* AppAssetManager.m */; };
|
||||
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494F19FF2174002D2A60 /* SettingsViewController.m */; };
|
||||
@@ -78,26 +81,37 @@
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
987140011B04541A00AB57D5 /* PBXContainerItemProxy */ = {
|
||||
98AB2E831CAD46840089BB98 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */;
|
||||
containerPortal = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = FB290E2E19B37A4E004C83CF;
|
||||
remoteInfo = "moonlight-common";
|
||||
};
|
||||
98AB2E851CAD468B0089BB98 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = FB290E2D19B37A4E004C83CF;
|
||||
remoteInfo = "moonlight-common";
|
||||
};
|
||||
FB1E430F1AE8B0F200AFF679 /* PBXContainerItemProxy */ = {
|
||||
D46A73A51CBC7CB60039F1EE /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */;
|
||||
proxyType = 2;
|
||||
remoteGlobalIDString = FB290E2E19B37A4E004C83CF;
|
||||
remoteInfo = "moonlight-common";
|
||||
containerPortal = FB290CE619B2C406004C83CF /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = FB290CED19B2C406004C83CF;
|
||||
remoteInfo = Moonlight;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryApp.h; path = Database/TemporaryApp.h; sourceTree = "<group>"; };
|
||||
9832D1351BBCD5C50036EF48 /* TemporaryApp.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporaryApp.m; path = Database/TemporaryApp.m; sourceTree = "<group>"; };
|
||||
98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "limelight-common-c/moonlight-common.xcodeproj"; sourceTree = "<group>"; };
|
||||
98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "moonlight-common/moonlight-common.xcodeproj"; sourceTree = "<group>"; };
|
||||
98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryHost.h; path = Database/TemporaryHost.h; sourceTree = "<group>"; };
|
||||
98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporaryHost.m; path = Database/TemporaryHost.m; sourceTree = "<group>"; };
|
||||
98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporarySettings.h; path = Database/TemporarySettings.h; sourceTree = "<group>"; };
|
||||
98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = TemporarySettings.m; path = Database/TemporarySettings.m; sourceTree = "<group>"; };
|
||||
9E5D5FF81A5A5A3900689918 /* Apache License.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = "Apache License.txt"; sourceTree = "<group>"; };
|
||||
9E5D5FF91A5A5A3900689918 /* Roboto-Black.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Black.ttf"; sourceTree = "<group>"; };
|
||||
9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
|
||||
@@ -105,6 +119,12 @@
|
||||
9E5D60001A5A5A3900689918 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Medium.ttf"; sourceTree = "<group>"; };
|
||||
9E5D60021A5A5A3900689918 /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
|
||||
9E5D60031A5A5A3900689918 /* Roboto-Thin.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Thin.ttf"; sourceTree = "<group>"; };
|
||||
D46A73A01CBC7CB60039F1EE /* MoonlightUnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = MoonlightUnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
D46A73A41CBC7CB60039F1EE /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
D46A73AB1CBC7D080039F1EE /* MoonlightUnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "MoonlightUnitTests-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
D46A73AC1CBC7D090039F1EE /* ControllerUnitTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ControllerUnitTests.swift; path = Input/ControllerUnitTests.swift; sourceTree = "<group>"; };
|
||||
D4746EEA1CBC740C006FB401 /* Moonlight-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = "Moonlight-Bridging-Header.h"; path = "Input/Moonlight-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
D4746EEB1CBC740C006FB401 /* Controller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Controller.swift; sourceTree = "<group>"; };
|
||||
FB1D59951BBCCB6400F482CA /* ComputerScrollView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ComputerScrollView.h; sourceTree = "<group>"; };
|
||||
FB1D59961BBCCB6400F482CA /* ComputerScrollView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ComputerScrollView.m; sourceTree = "<group>"; };
|
||||
FB1D59981BBCCD7E00F482CA /* AppCollectionView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppCollectionView.h; sourceTree = "<group>"; };
|
||||
@@ -268,8 +288,6 @@
|
||||
FB9AFD3C1A7E111600872C98 /* AppAssetResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppAssetResponse.m; sourceTree = "<group>"; };
|
||||
FB9AFD3E1A7E127D00872C98 /* AppListResponse.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppListResponse.h; sourceTree = "<group>"; };
|
||||
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>"; };
|
||||
@@ -297,11 +315,18 @@
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
D46A739D1CBC7CB60039F1EE /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
FB290CEB19B2C406004C83CF /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
987140041B04542F00AB57D5 /* libmoonlight-common.a in Frameworks */,
|
||||
98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */,
|
||||
FB8946ED19F6AFE800339C8A /* libopus.a in Frameworks */,
|
||||
FB8946EB19F6AFE100339C8A /* libcrypto.a in Frameworks */,
|
||||
FB8946EC19F6AFE400339C8A /* libssl.a in Frameworks */,
|
||||
@@ -320,6 +345,14 @@
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
98AB2E801CAD46830089BB98 /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
98AB2E841CAD46840089BB98 /* libmoonlight-common.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9E5D5FF61A5A5A3900689918 /* Font */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -342,19 +375,30 @@
|
||||
path = Roboto;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FB1E430C1AE8B0F200AFF679 /* Products */ = {
|
||||
D46A73A11CBC7CB60039F1EE /* MoonlightUnitTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FB1E43101AE8B0F200AFF679 /* libmoonlight-common.a */,
|
||||
D46A73AB1CBC7D080039F1EE /* MoonlightUnitTests-Bridging-Header.h */,
|
||||
D46A73AA1CBC7CEF0039F1EE /* Input */,
|
||||
D46A73A41CBC7CB60039F1EE /* Info.plist */,
|
||||
);
|
||||
name = Products;
|
||||
path = MoonlightUnitTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
D46A73AA1CBC7CEF0039F1EE /* Input */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D46A73AC1CBC7D090039F1EE /* ControllerUnitTests.swift */,
|
||||
);
|
||||
name = Input;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FB290CE519B2C406004C83CF = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */,
|
||||
FB290CF919B2C406004C83CF /* Limelight */,
|
||||
98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */,
|
||||
FB290CF919B2C406004C83CF /* Moonlight */,
|
||||
D46A73A11CBC7CB60039F1EE /* MoonlightUnitTests */,
|
||||
FB290CF019B2C406004C83CF /* Frameworks */,
|
||||
FB290CEF19B2C406004C83CF /* Products */,
|
||||
);
|
||||
@@ -364,6 +408,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FB290CEE19B2C406004C83CF /* Moonlight.app */,
|
||||
D46A73A01CBC7CB60039F1EE /* MoonlightUnitTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -387,9 +432,10 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FB290CF919B2C406004C83CF /* Limelight */ = {
|
||||
FB290CF919B2C406004C83CF /* Moonlight */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
D4746EEA1CBC740C006FB401 /* Moonlight-Bridging-Header.h */,
|
||||
9E5D5FF61A5A5A3900689918 /* Font */,
|
||||
FB89460419F646E200339C8A /* Crypto */,
|
||||
FB89460919F646E200339C8A /* Input */,
|
||||
@@ -415,6 +461,7 @@
|
||||
FB1D59981BBCCD7E00F482CA /* AppCollectionView.h */,
|
||||
FB1D59991BBCCD7E00F482CA /* AppCollectionView.m */,
|
||||
);
|
||||
name = Moonlight;
|
||||
path = Limelight;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
@@ -447,8 +494,7 @@
|
||||
children = (
|
||||
FB89460A19F646E200339C8A /* ControllerSupport.h */,
|
||||
FB89460B19F646E200339C8A /* ControllerSupport.m */,
|
||||
FB9AFD411A7F0C6900872C98 /* Controller.h */,
|
||||
FB9AFD421A7F0C6900872C98 /* Controller.m */,
|
||||
D4746EEB1CBC740C006FB401 /* Controller.swift */,
|
||||
FB89460C19F646E200339C8A /* StreamView.h */,
|
||||
FB89460D19F646E200339C8A /* StreamView.m */,
|
||||
FB4678EB1A50C40900377732 /* OnScreenControls.h */,
|
||||
@@ -733,6 +779,10 @@
|
||||
FBD349611A0089F6002D2A60 /* DataManager.m */,
|
||||
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */,
|
||||
9832D1351BBCD5C50036EF48 /* TemporaryApp.m */,
|
||||
98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */,
|
||||
98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */,
|
||||
98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */,
|
||||
98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */,
|
||||
);
|
||||
name = Database;
|
||||
sourceTree = "<group>";
|
||||
@@ -740,6 +790,24 @@
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
D46A739F1CBC7CB60039F1EE /* MoonlightUnitTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = D46A73A91CBC7CB60039F1EE /* Build configuration list for PBXNativeTarget "MoonlightUnitTests" */;
|
||||
buildPhases = (
|
||||
D46A739C1CBC7CB60039F1EE /* Sources */,
|
||||
D46A739D1CBC7CB60039F1EE /* Frameworks */,
|
||||
D46A739E1CBC7CB60039F1EE /* Resources */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
D46A73A61CBC7CB60039F1EE /* PBXTargetDependency */,
|
||||
);
|
||||
name = MoonlightUnitTests;
|
||||
productName = MoonlightUnitTests;
|
||||
productReference = D46A73A01CBC7CB60039F1EE /* MoonlightUnitTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
FB290CED19B2C406004C83CF /* Moonlight */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = FB290D2019B2C406004C83CF /* Build configuration list for PBXNativeTarget "Moonlight" */;
|
||||
@@ -751,7 +819,7 @@
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
987140021B04541A00AB57D5 /* PBXTargetDependency */,
|
||||
98AB2E861CAD468B0089BB98 /* PBXTargetDependency */,
|
||||
);
|
||||
name = Moonlight;
|
||||
productName = Limelight;
|
||||
@@ -764,11 +832,18 @@
|
||||
FB290CE619B2C406004C83CF /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0700;
|
||||
LastSwiftUpdateCheck = 0730;
|
||||
LastUpgradeCheck = 0800;
|
||||
ORGANIZATIONNAME = "Moonlight Stream";
|
||||
TargetAttributes = {
|
||||
D46A739F1CBC7CB60039F1EE = {
|
||||
CreatedOnToolsVersion = 7.3;
|
||||
LastSwiftMigration = 0800;
|
||||
TestTargetID = FB290CED19B2C406004C83CF;
|
||||
};
|
||||
FB290CED19B2C406004C83CF = {
|
||||
DevelopmentTeam = DM46QST4M7;
|
||||
LastSwiftMigration = 0800;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -784,28 +859,36 @@
|
||||
projectDirPath = "";
|
||||
projectReferences = (
|
||||
{
|
||||
ProductGroup = FB1E430C1AE8B0F200AFF679 /* Products */;
|
||||
ProjectRef = 98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */;
|
||||
ProductGroup = 98AB2E801CAD46830089BB98 /* Products */;
|
||||
ProjectRef = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
|
||||
},
|
||||
);
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
FB290CED19B2C406004C83CF /* Moonlight */,
|
||||
D46A739F1CBC7CB60039F1EE /* MoonlightUnitTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXReferenceProxy section */
|
||||
FB1E43101AE8B0F200AFF679 /* libmoonlight-common.a */ = {
|
||||
98AB2E841CAD46840089BB98 /* libmoonlight-common.a */ = {
|
||||
isa = PBXReferenceProxy;
|
||||
fileType = archive.ar;
|
||||
path = "libmoonlight-common.a";
|
||||
remoteRef = FB1E430F1AE8B0F200AFF679 /* PBXContainerItemProxy */;
|
||||
remoteRef = 98AB2E831CAD46840089BB98 /* PBXContainerItemProxy */;
|
||||
sourceTree = BUILT_PRODUCTS_DIR;
|
||||
};
|
||||
/* End PBXReferenceProxy section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
D46A739E1CBC7CB60039F1EE /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
FB290CEC19B2C406004C83CF /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -828,6 +911,14 @@
|
||||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
D46A739C1CBC7CB60039F1EE /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
D46A73AD1CBC7D090039F1EE /* ControllerUnitTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
FB290CEA19B2C406004C83CF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -855,22 +946,24 @@
|
||||
FB89462D19F646E200339C8A /* MDNSManager.m in Sources */,
|
||||
FB89462B19F646E200339C8A /* StreamView.m in Sources */,
|
||||
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
|
||||
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */,
|
||||
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
|
||||
FBD1C8E21A8AD71400C6703C /* Logger.m in Sources */,
|
||||
FB1D599A1BBCCD7E00F482CA /* AppCollectionView.m in Sources */,
|
||||
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */,
|
||||
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */,
|
||||
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */,
|
||||
FB89462819F646E200339C8A /* CryptoManager.m in Sources */,
|
||||
FB89462E19F646E200339C8A /* PairManager.m in Sources */,
|
||||
FB9AFD371A7E02DB00872C98 /* HttpRequest.m in Sources */,
|
||||
FB4678ED1A50C40900377732 /* OnScreenControls.m in Sources */,
|
||||
FB290D0019B2C406004C83CF /* main.m in Sources */,
|
||||
FB9AFD431A7F0C6900872C98 /* Controller.m in Sources */,
|
||||
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */,
|
||||
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */,
|
||||
FB89462A19F646E200339C8A /* ControllerSupport.m in Sources */,
|
||||
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */,
|
||||
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */,
|
||||
D4746EEC1CBC740C006FB401 /* Controller.swift in Sources */,
|
||||
FBFCB3351B50B29400089F8A /* App.m in Sources */,
|
||||
FB4A23B81A9D3637004D2EF2 /* LoadingFrameViewController.m in Sources */,
|
||||
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */,
|
||||
@@ -881,10 +974,15 @@
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
987140021B04541A00AB57D5 /* PBXTargetDependency */ = {
|
||||
98AB2E861CAD468B0089BB98 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
name = "moonlight-common";
|
||||
targetProxy = 987140011B04541A00AB57D5 /* PBXContainerItemProxy */;
|
||||
targetProxy = 98AB2E851CAD468B0089BB98 /* PBXContainerItemProxy */;
|
||||
};
|
||||
D46A73A61CBC7CB60039F1EE /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = FB290CED19B2C406004C83CF /* Moonlight */;
|
||||
targetProxy = D46A73A51CBC7CB60039F1EE /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
@@ -900,6 +998,54 @@
|
||||
/* End PBXVariantGroup section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
D46A73A71CBC7CB60039F1EE /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = MoonlightUnitTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.moonlight-stream.MoonlightUnitTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "MoonlightUnitTests/MoonlightUnitTests-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Moonlight.app/Moonlight";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
D46A73A81CBC7CB60039F1EE /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
INFOPLIST_FILE = MoonlightUnitTests/Info.plist;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 9.3;
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = "com.moonlight-stream.MoonlightUnitTests";
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "MoonlightUnitTests/MoonlightUnitTests-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 3.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Moonlight.app/Moonlight";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
FB290D1E19B2C406004C83CF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -913,15 +1059,20 @@
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
"DEBUG=1",
|
||||
@@ -954,14 +1105,19 @@
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
@@ -980,6 +1136,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -988,11 +1145,12 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(PROJECT_DIR)/limelight-common-c/limelight-common",
|
||||
"$(PROJECT_DIR)/moonlight-common/moonlight-common-c/src",
|
||||
"$(SDKROOT)/usr/include/libxml2/**",
|
||||
"$(PROJECT_DIR)/libs/**",
|
||||
);
|
||||
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/libs/opus/lib",
|
||||
@@ -1002,6 +1160,9 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
SKIP_INSTALL = NO;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Limelight/Input/Moonlight-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 3.0;
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Debug;
|
||||
@@ -1010,6 +1171,7 @@
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||
ENABLE_BITCODE = NO;
|
||||
@@ -1018,11 +1180,12 @@
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
||||
"$(PROJECT_DIR)/limelight-common-c/limelight-common",
|
||||
"$(PROJECT_DIR)/moonlight-common/moonlight-common-c/src",
|
||||
"$(SDKROOT)/usr/include/libxml2/**",
|
||||
"$(PROJECT_DIR)/libs/**",
|
||||
);
|
||||
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
|
||||
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||
LIBRARY_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"$(PROJECT_DIR)/libs/opus/lib",
|
||||
@@ -1032,6 +1195,9 @@
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE = "";
|
||||
SKIP_INSTALL = NO;
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Limelight/Input/Moonlight-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||
SWIFT_VERSION = 3.0;
|
||||
WRAPPER_EXTENSION = app;
|
||||
};
|
||||
name = Release;
|
||||
@@ -1039,6 +1205,15 @@
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
D46A73A91CBC7CB60039F1EE /* Build configuration list for PBXNativeTarget "MoonlightUnitTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
D46A73A71CBC7CB60039F1EE /* Debug */,
|
||||
D46A73A81CBC7CB60039F1EE /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Moonlight" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>BNDL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1</string>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -0,0 +1,192 @@
|
||||
//
|
||||
// ControllerUnitTests.swift
|
||||
// Moonlight
|
||||
//
|
||||
// Created by David Aghassi on 4/11/16.
|
||||
// Copyright © 2016 Moonlight Stream. All rights reserved.
|
||||
//
|
||||
|
||||
import XCTest
|
||||
@testable import Moonlight
|
||||
|
||||
/**
|
||||
Tests the `Controller.swift` class
|
||||
*/
|
||||
class ControllerUnitTests: XCTestCase {
|
||||
var controllerUnderTest: Controller!
|
||||
|
||||
override func setUp() {
|
||||
controllerUnderTest = Controller()
|
||||
XCTAssertNotNil(controllerUnderTest, "controllerUnderTest is nil, and should not be for this test. See line \(#line) \n")
|
||||
}
|
||||
|
||||
override func tearDown() {
|
||||
resetAllValues()
|
||||
}
|
||||
|
||||
|
||||
// MARK: Helper Methods
|
||||
/**
|
||||
Sets all the values of `controllerUnderTest` to `0`
|
||||
*/
|
||||
func resetAllValues() {
|
||||
controllerUnderTest.emulatingButtonFlags = CInt(0)
|
||||
controllerUnderTest.lastButtonFlags = CInt(0)
|
||||
|
||||
controllerUnderTest.lastLeftStickX = CShort(0)
|
||||
controllerUnderTest.lastLeftStickY = CShort(0)
|
||||
controllerUnderTest.lastRightStickX = CShort(0)
|
||||
controllerUnderTest.lastRightStickY = CShort(0)
|
||||
|
||||
controllerUnderTest.lastLeftTrigger = CChar(0)
|
||||
controllerUnderTest.lastRightTrigger = CChar(0)
|
||||
}
|
||||
|
||||
/**
|
||||
Displays "*name* failed to set CInt correctly." Shows expected and actual, as well as failure line.
|
||||
|
||||
- parameter name: The property being tested
|
||||
- parameter expected: The expected value for the property
|
||||
- parameter actual: The actual value for the property
|
||||
|
||||
- returns: A string with the failure in it. Formatted to state actual, expected, and the failure line.
|
||||
*/
|
||||
func displayCIntFailure(name: String, expected: CInt, actual: CInt) -> String {
|
||||
return "\(name) failed to set CInt correctly \n. Expected: \(expected)\n. Actual: \(actual) \n. See line \(#line) \n"
|
||||
}
|
||||
|
||||
/**
|
||||
Displays "*name* failed to set CShort correctly." Shows expected and actual, as well as failure line.
|
||||
|
||||
- parameter name: The property being tested
|
||||
- parameter expected: The expected value for the property
|
||||
- parameter actual: The actual value for the property
|
||||
|
||||
- returns: A string with the failure in it. Formatted to state actual, expected, and the failure line.
|
||||
*/
|
||||
func displayCShortFailure(name: String, expected: CShort, actual: CShort) -> String {
|
||||
return "\(name) failed to set CShort correctly \n. Expected: \(expected)\n. Actual: \(actual) \n. See line \(#line) \n"
|
||||
}
|
||||
|
||||
/**
|
||||
Displays "*name* failed to set CCHar correctly." Shows expected and actual, as well as the failure line.
|
||||
|
||||
- parameter name: The property being tested
|
||||
- parameter expected: The expected value for the property
|
||||
- parameter actual: The actual value for the property
|
||||
|
||||
- returns: A string with the failure in it. Formatted to state actual, expected, and the failure line.
|
||||
*/
|
||||
func displayCCharFailure(name: String, expected: CChar, actual: CChar) -> String {
|
||||
return "\(name) failed to set CChar correctly \n. Expected: \(expected)\n. Actual: \(actual) \n. See line \(#line) \n"
|
||||
}
|
||||
|
||||
|
||||
// MARK: Tests
|
||||
/**
|
||||
Asserts that the `emulatingButtonFlags` is of type `CInt` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_emulatingButtonFlags_Sets_To_CInt() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.emulatingButtonFlags.dynamicType == CInt.self, "Expected emulatingButtonFlags to be of type CInt. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CInt(1)
|
||||
controllerUnderTest.emulatingButtonFlags = expected
|
||||
XCTAssertTrue(controllerUnderTest.emulatingButtonFlags == expected, displayCIntFailure("emulatingButtonFlags", expected: expected, actual: controllerUnderTest.emulatingButtonFlags))
|
||||
}
|
||||
|
||||
/**
|
||||
Asserts that the `lastButtonFlags` is of type `CInt` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_lastButtonFlags_Sets_To_CInt() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.lastButtonFlags.dynamicType == CInt.self, "Expected lastButtonFlags to be of type CInt. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CInt(1)
|
||||
controllerUnderTest.lastButtonFlags = expected
|
||||
XCTAssertTrue(controllerUnderTest.lastButtonFlags == expected, displayCIntFailure("lastButtonFlags", expected: expected, actual: controllerUnderTest.lastButtonFlags))
|
||||
}
|
||||
|
||||
/**
|
||||
Asserts that the `lastLeftStickX` is of type `CShort` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_lastLeftStickX_Sets_To_CShort() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.lastLeftStickX.dynamicType == CShort.self, "Expected lastLeftStickX to be of type CShort. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CShort(1)
|
||||
controllerUnderTest.lastLeftStickX = expected
|
||||
XCTAssertTrue(controllerUnderTest.lastLeftStickX == expected, displayCShortFailure("lastLeftStickX", expected: expected, actual: controllerUnderTest.lastLeftStickX))
|
||||
}
|
||||
|
||||
/**
|
||||
Asserts that lastLeftStickY` is of type `CShort` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_lastLeftStickY_Sets_To_CShort() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.lastLeftStickY.dynamicType == CShort.self, "Expected lastLeftStickY to be of type CShort. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CShort(1)
|
||||
controllerUnderTest.lastLeftStickY = expected
|
||||
XCTAssertTrue(controllerUnderTest.lastLeftStickY == expected, displayCShortFailure("lastLeftStickY", expected: expected, actual: controllerUnderTest.lastLeftStickY))
|
||||
}
|
||||
|
||||
/**
|
||||
Asserts that the `lastRightStickX` is of type `CShort` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_lastRightStickX_SetsTo_CShort() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.lastRightStickX.dynamicType == CShort.self, "Expected lastRightStickX to be of type CShort. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CShort(1)
|
||||
controllerUnderTest.lastRightStickX = expected
|
||||
XCTAssertTrue(controllerUnderTest.lastRightStickX == expected, displayCShortFailure("lastRightStickX", expected: expected, actual: controllerUnderTest.lastRightStickX))
|
||||
}
|
||||
|
||||
/**
|
||||
Asserts that the `lastRightStickY` is of type `CShort` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_lastRightStickY_Sets_To_CShort() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.lastRightStickY.dynamicType == CShort.self, "Expected lastRightStickY to be of type CShort. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CShort(1)
|
||||
controllerUnderTest.lastRightStickY = expected
|
||||
XCTAssertTrue(controllerUnderTest.lastRightStickY == expected, displayCShortFailure("lastRightStickY", expected: expected, actual: controllerUnderTest.lastRightStickY))
|
||||
}
|
||||
|
||||
/**
|
||||
Asserts that the `lastLeftTrigger` is of type `CChar` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_lastLeftTrigger_Sets_To_CChar() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.lastLeftTrigger.dynamicType == CChar.self, "Expected lastLeftTrigger to be of type CChar. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CChar(1)
|
||||
controllerUnderTest.lastLeftTrigger = expected
|
||||
XCTAssertTrue(controllerUnderTest.lastLeftTrigger == expected, displayCCharFailure("lastLeftTrigger", expected: expected, actual: controllerUnderTest.lastLeftTrigger))
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
Asserts that the `lastRightTrigger` is of type `CChar` and can be set and gotten from properly
|
||||
*/
|
||||
func test_Assert_lastRightTrigger_Sets_To_CChar() {
|
||||
// Assert type hasn't changed
|
||||
XCTAssertTrue(controllerUnderTest.lastRightTrigger.dynamicType == CChar.self, "Expected lastRightTrigger to be of type CChar. See line \(#line) \n")
|
||||
|
||||
// Assert value is assigned properly.
|
||||
let expected = CChar(1)
|
||||
controllerUnderTest.lastRightTrigger = expected
|
||||
XCTAssertTrue(controllerUnderTest.lastRightTrigger == expected, displayCCharFailure("lastRightTrigger", expected: expected, actual: controllerUnderTest.lastRightTrigger))
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
//
|
||||
// Use this file to import your target's public headers that you would like to expose to Swift.
|
||||
//
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#Moonlight iOS
|
||||
|
||||
#### Update 7/16/15: We are not accepting more users into the beta program at this time. However, Moonlight iOS is getting ready to launch on the App Store. To be notified when this happens, [please sign up here](http://eepurl.com/btvkG9) to receive a one-time email notification when it's available to download onto your iOS device.
|
||||
#### Now available on the [App Store](https://itunes.apple.com/us/app/moonlight-game-streaming/id1000551566?mt=8)
|
||||
|
||||
[Moonlight](https://github.com/moonlight-stream) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built for iOS. Moonlight iOS allows you to stream your full collection of Steam games from
|
||||
[Moonlight](http://moonlight-stream.com) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built for iOS. Moonlight iOS allows you to stream your full collection of Steam games from
|
||||
your powerful desktop computer to your iOS Device.
|
||||
|
||||
This is actively being developed and will be available on the App Store soon - check back here or on [our website](http://moonlight-stream.com) for updates.
|
||||
There are also versions for [Android](https://github.com/moonlight-stream/moonlight-android) and [PC](https://github.com/moonlight-stream/moonlight-pc).
|
||||
|
||||
We understand that Moonlight users are eager for the opportunity to stream their Steam collection to their iOS devices. Moonlight for iOS is in the testing stage and preliminary versions are available for beta testers.
|
||||
##### Apple TV Note:
|
||||
We currently cannot port Moonlight to Apple TV due to a limitation in the tvOS SDK that prevents Moonlight from using the APIs that would be necessary for it to work. Thank you for your interest - you can track this issue [here](https://github.com/moonlight-stream/moonlight-ios/issues/184).
|
||||
|
||||
In the meantime, check out the existing versions for [Android](https://github.com/moonlight-stream/moonlight-android) and [PC](https://github.com/moonlight-stream/moonlight-pc). Also, a client for [Windows and Windows Phone](https://github.com/moonlight-stream/moonlight-windows) is in the works and actively being developed.
|
||||
|
||||
Please be patient as we work to bring Moonlight to more platforms.
|
||||
##### Questions?
|
||||
Check out our [wiki](https://github.com/moonlight-stream/moonlight-docs/wiki).
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="fv6-NS-qsK">
|
||||
<collectionViewCell clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="fv6-NS-qsK">
|
||||
<rect key="frame" x="20" y="40" width="150" height="200"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
|
||||
+1
-1
@@ -27,7 +27,7 @@
|
||||
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="Uqv-Di-fzX">
|
||||
<collectionViewCell clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="Uqv-Di-fzX">
|
||||
<rect key="frame" x="20" y="40" width="90" height="120"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||
|
||||
Submodule limelight-common-c deleted from 349d1baa53
Submodule
+1
Submodule moonlight-common/moonlight-common-c added at 20821e7eb6
@@ -0,0 +1,493 @@
|
||||
// !$*UTF8*$!
|
||||
{
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 47;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
9857AEEA1EBE85A20084F99E /* RtpFecQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 9857AEE91EBE85A20084F99E /* RtpFecQueue.c */; };
|
||||
9857AEF01EBE85E10084F99E /* rs.c in Sources */ = {isa = PBXBuildFile; fileRef = 9857AEEE1EBE85E10084F99E /* rs.c */; };
|
||||
98AB2E401CAD425A0089BB98 /* AudioStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E1A1CAD423B0089BB98 /* AudioStream.c */; };
|
||||
98AB2E411CAD425A0089BB98 /* ByteBuffer.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E1B1CAD423B0089BB98 /* ByteBuffer.c */; };
|
||||
98AB2E421CAD425A0089BB98 /* Connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E1D1CAD423B0089BB98 /* Connection.c */; };
|
||||
98AB2E431CAD425A0089BB98 /* ControlStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E1E1CAD423B0089BB98 /* ControlStream.c */; };
|
||||
98AB2E441CAD425A0089BB98 /* FakeCallbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E1F1CAD423B0089BB98 /* FakeCallbacks.c */; };
|
||||
98AB2E451CAD425A0089BB98 /* InputStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E211CAD423B0089BB98 /* InputStream.c */; };
|
||||
98AB2E461CAD425A0089BB98 /* LinkedBlockingQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E241CAD423B0089BB98 /* LinkedBlockingQueue.c */; };
|
||||
98AB2E471CAD425A0089BB98 /* Misc.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E261CAD423B0089BB98 /* Misc.c */; };
|
||||
98AB2E481CAD425A0089BB98 /* Platform.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E311CAD423B0089BB98 /* Platform.c */; };
|
||||
98AB2E491CAD425A0089BB98 /* PlatformSockets.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E331CAD423B0089BB98 /* PlatformSockets.c */; };
|
||||
98AB2E4A1CAD425A0089BB98 /* RtpReorderQueue.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E361CAD423B0089BB98 /* RtpReorderQueue.c */; };
|
||||
98AB2E4B1CAD425A0089BB98 /* RtspConnection.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E391CAD423B0089BB98 /* RtspConnection.c */; };
|
||||
98AB2E4C1CAD425A0089BB98 /* RtspParser.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E3A1CAD423B0089BB98 /* RtspParser.c */; };
|
||||
98AB2E4D1CAD425A0089BB98 /* SdpGenerator.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E3B1CAD423B0089BB98 /* SdpGenerator.c */; };
|
||||
98AB2E4E1CAD425A0089BB98 /* VideoDepacketizer.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E3D1CAD423B0089BB98 /* VideoDepacketizer.c */; };
|
||||
98AB2E4F1CAD425A0089BB98 /* VideoStream.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E3E1CAD423B0089BB98 /* VideoStream.c */; };
|
||||
98AB2E501CAD427A0089BB98 /* callbacks.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2DF01CAD422B0089BB98 /* callbacks.c */; };
|
||||
98AB2E511CAD427A0089BB98 /* compress.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2DF31CAD422B0089BB98 /* compress.c */; };
|
||||
98AB2E521CAD427A0089BB98 /* host.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E001CAD422B0089BB98 /* host.c */; };
|
||||
98AB2E531CAD427A0089BB98 /* list.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E0E1CAD422B0089BB98 /* list.c */; };
|
||||
98AB2E541CAD427A0089BB98 /* packet.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E121CAD422B0089BB98 /* packet.c */; };
|
||||
98AB2E551CAD427A0089BB98 /* peer.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E131CAD422B0089BB98 /* peer.c */; };
|
||||
98AB2E561CAD427A0089BB98 /* protocol.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E151CAD422B0089BB98 /* protocol.c */; };
|
||||
98AB2E571CAD427A0089BB98 /* unix.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E171CAD422B0089BB98 /* unix.c */; };
|
||||
98AB2E581CAD427A0089BB98 /* win32.c in Sources */ = {isa = PBXBuildFile; fileRef = 98AB2E181CAD422B0089BB98 /* win32.c */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
9857AEE91EBE85A20084F99E /* RtpFecQueue.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = RtpFecQueue.c; sourceTree = "<group>"; };
|
||||
9857AEEB1EBE85AB0084F99E /* RtpFecQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RtpFecQueue.h; sourceTree = "<group>"; };
|
||||
9857AEEE1EBE85E10084F99E /* rs.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = rs.c; path = "moonlight-common-c/reedsolomon/rs.c"; sourceTree = "<group>"; };
|
||||
9857AEEF1EBE85E10084F99E /* rs.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = rs.h; path = "moonlight-common-c/reedsolomon/rs.h"; sourceTree = "<group>"; };
|
||||
98AB2DF01CAD422B0089BB98 /* callbacks.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = callbacks.c; sourceTree = "<group>"; };
|
||||
98AB2DF11CAD422B0089BB98 /* ChangeLog */ = {isa = PBXFileReference; lastKnownFileType = text; path = ChangeLog; sourceTree = "<group>"; };
|
||||
98AB2DF21CAD422B0089BB98 /* CMakeLists.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = CMakeLists.txt; sourceTree = "<group>"; };
|
||||
98AB2DF31CAD422B0089BB98 /* compress.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = compress.c; sourceTree = "<group>"; };
|
||||
98AB2DF41CAD422B0089BB98 /* configure.ac */ = {isa = PBXFileReference; lastKnownFileType = text; path = configure.ac; sourceTree = "<group>"; };
|
||||
98AB2DF61CAD422B0089BB98 /* design.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = design.dox; sourceTree = "<group>"; };
|
||||
98AB2DF71CAD422B0089BB98 /* FAQ.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = FAQ.dox; sourceTree = "<group>"; };
|
||||
98AB2DF81CAD422B0089BB98 /* install.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = install.dox; sourceTree = "<group>"; };
|
||||
98AB2DF91CAD422B0089BB98 /* license.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = license.dox; sourceTree = "<group>"; };
|
||||
98AB2DFA1CAD422B0089BB98 /* mainpage.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = mainpage.dox; sourceTree = "<group>"; };
|
||||
98AB2DFB1CAD422B0089BB98 /* tutorial.dox */ = {isa = PBXFileReference; lastKnownFileType = text; path = tutorial.dox; sourceTree = "<group>"; };
|
||||
98AB2DFC1CAD422B0089BB98 /* Doxyfile */ = {isa = PBXFileReference; lastKnownFileType = text; path = Doxyfile; sourceTree = "<group>"; };
|
||||
98AB2DFD1CAD422B0089BB98 /* DoxygenLayout.xml */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = DoxygenLayout.xml; sourceTree = "<group>"; };
|
||||
98AB2DFE1CAD422B0089BB98 /* enet.dsp */ = {isa = PBXFileReference; lastKnownFileType = text; path = enet.dsp; sourceTree = "<group>"; };
|
||||
98AB2DFF1CAD422B0089BB98 /* enet_dll.cbp */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = enet_dll.cbp; sourceTree = "<group>"; };
|
||||
98AB2E001CAD422B0089BB98 /* host.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = host.c; sourceTree = "<group>"; };
|
||||
98AB2E031CAD422B0089BB98 /* callbacks.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = callbacks.h; sourceTree = "<group>"; };
|
||||
98AB2E041CAD422B0089BB98 /* enet.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = enet.h; sourceTree = "<group>"; };
|
||||
98AB2E051CAD422B0089BB98 /* list.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = list.h; sourceTree = "<group>"; };
|
||||
98AB2E061CAD422B0089BB98 /* protocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = protocol.h; sourceTree = "<group>"; };
|
||||
98AB2E071CAD422B0089BB98 /* time.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = time.h; sourceTree = "<group>"; };
|
||||
98AB2E081CAD422B0089BB98 /* types.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = types.h; sourceTree = "<group>"; };
|
||||
98AB2E091CAD422B0089BB98 /* unix.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = unix.h; sourceTree = "<group>"; };
|
||||
98AB2E0A1CAD422B0089BB98 /* utility.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = utility.h; sourceTree = "<group>"; };
|
||||
98AB2E0B1CAD422B0089BB98 /* win32.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = win32.h; sourceTree = "<group>"; };
|
||||
98AB2E0C1CAD422B0089BB98 /* libenet.pc.in */ = {isa = PBXFileReference; lastKnownFileType = text; path = libenet.pc.in; sourceTree = "<group>"; };
|
||||
98AB2E0D1CAD422B0089BB98 /* LICENSE */ = {isa = PBXFileReference; lastKnownFileType = text; path = LICENSE; sourceTree = "<group>"; };
|
||||
98AB2E0E1CAD422B0089BB98 /* list.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = list.c; sourceTree = "<group>"; };
|
||||
98AB2E101CAD422B0089BB98 /* .keep */ = {isa = PBXFileReference; lastKnownFileType = text; path = .keep; sourceTree = "<group>"; };
|
||||
98AB2E111CAD422B0089BB98 /* Makefile.am */ = {isa = PBXFileReference; lastKnownFileType = text; path = Makefile.am; sourceTree = "<group>"; };
|
||||
98AB2E121CAD422B0089BB98 /* packet.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = packet.c; sourceTree = "<group>"; };
|
||||
98AB2E131CAD422B0089BB98 /* peer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = peer.c; sourceTree = "<group>"; };
|
||||
98AB2E141CAD422B0089BB98 /* premake4.lua */ = {isa = PBXFileReference; lastKnownFileType = text; path = premake4.lua; sourceTree = "<group>"; };
|
||||
98AB2E151CAD422B0089BB98 /* protocol.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = protocol.c; sourceTree = "<group>"; };
|
||||
98AB2E161CAD422B0089BB98 /* README */ = {isa = PBXFileReference; lastKnownFileType = text; path = README; sourceTree = "<group>"; };
|
||||
98AB2E171CAD422B0089BB98 /* unix.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = unix.c; sourceTree = "<group>"; };
|
||||
98AB2E181CAD422B0089BB98 /* win32.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = win32.c; sourceTree = "<group>"; };
|
||||
98AB2E1A1CAD423B0089BB98 /* AudioStream.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = AudioStream.c; sourceTree = "<group>"; };
|
||||
98AB2E1B1CAD423B0089BB98 /* ByteBuffer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ByteBuffer.c; sourceTree = "<group>"; };
|
||||
98AB2E1C1CAD423B0089BB98 /* ByteBuffer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ByteBuffer.h; sourceTree = "<group>"; };
|
||||
98AB2E1D1CAD423B0089BB98 /* Connection.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Connection.c; sourceTree = "<group>"; };
|
||||
98AB2E1E1CAD423B0089BB98 /* ControlStream.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = ControlStream.c; sourceTree = "<group>"; };
|
||||
98AB2E1F1CAD423B0089BB98 /* FakeCallbacks.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = FakeCallbacks.c; sourceTree = "<group>"; };
|
||||
98AB2E201CAD423B0089BB98 /* Input.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Input.h; sourceTree = "<group>"; };
|
||||
98AB2E211CAD423B0089BB98 /* InputStream.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = InputStream.c; sourceTree = "<group>"; };
|
||||
98AB2E221CAD423B0089BB98 /* Limelight-internal.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Limelight-internal.h"; sourceTree = "<group>"; };
|
||||
98AB2E231CAD423B0089BB98 /* Limelight.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Limelight.h; sourceTree = "<group>"; };
|
||||
98AB2E241CAD423B0089BB98 /* LinkedBlockingQueue.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = LinkedBlockingQueue.c; sourceTree = "<group>"; };
|
||||
98AB2E251CAD423B0089BB98 /* LinkedBlockingQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = LinkedBlockingQueue.h; sourceTree = "<group>"; };
|
||||
98AB2E261CAD423B0089BB98 /* Misc.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Misc.c; sourceTree = "<group>"; };
|
||||
98AB2E311CAD423B0089BB98 /* Platform.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = Platform.c; sourceTree = "<group>"; };
|
||||
98AB2E321CAD423B0089BB98 /* Platform.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Platform.h; sourceTree = "<group>"; };
|
||||
98AB2E331CAD423B0089BB98 /* PlatformSockets.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = PlatformSockets.c; sourceTree = "<group>"; };
|
||||
98AB2E341CAD423B0089BB98 /* PlatformSockets.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformSockets.h; sourceTree = "<group>"; };
|
||||
98AB2E351CAD423B0089BB98 /* PlatformThreads.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PlatformThreads.h; sourceTree = "<group>"; };
|
||||
98AB2E361CAD423B0089BB98 /* RtpReorderQueue.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = RtpReorderQueue.c; sourceTree = "<group>"; };
|
||||
98AB2E371CAD423B0089BB98 /* RtpReorderQueue.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RtpReorderQueue.h; sourceTree = "<group>"; };
|
||||
98AB2E381CAD423B0089BB98 /* Rtsp.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Rtsp.h; sourceTree = "<group>"; };
|
||||
98AB2E391CAD423B0089BB98 /* RtspConnection.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = RtspConnection.c; sourceTree = "<group>"; };
|
||||
98AB2E3A1CAD423B0089BB98 /* RtspParser.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = RtspParser.c; sourceTree = "<group>"; };
|
||||
98AB2E3B1CAD423B0089BB98 /* SdpGenerator.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = SdpGenerator.c; sourceTree = "<group>"; };
|
||||
98AB2E3C1CAD423B0089BB98 /* Video.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Video.h; sourceTree = "<group>"; };
|
||||
98AB2E3D1CAD423B0089BB98 /* VideoDepacketizer.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = VideoDepacketizer.c; sourceTree = "<group>"; };
|
||||
98AB2E3E1CAD423B0089BB98 /* VideoStream.c */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.c; path = VideoStream.c; sourceTree = "<group>"; };
|
||||
FB290E2E19B37A4E004C83CF /* libmoonlight-common.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libmoonlight-common.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
FB290E2B19B37A4E004C83CF /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
9857AEED1EBE85D50084F99E /* reedsolomon */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9857AEEE1EBE85E10084F99E /* rs.c */,
|
||||
9857AEEF1EBE85E10084F99E /* rs.h */,
|
||||
);
|
||||
name = reedsolomon;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
98AB2DEF1CAD422B0089BB98 /* enet */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
98AB2DF01CAD422B0089BB98 /* callbacks.c */,
|
||||
98AB2DF11CAD422B0089BB98 /* ChangeLog */,
|
||||
98AB2DF21CAD422B0089BB98 /* CMakeLists.txt */,
|
||||
98AB2DF31CAD422B0089BB98 /* compress.c */,
|
||||
98AB2DF41CAD422B0089BB98 /* configure.ac */,
|
||||
98AB2DF51CAD422B0089BB98 /* docs */,
|
||||
98AB2DFC1CAD422B0089BB98 /* Doxyfile */,
|
||||
98AB2DFD1CAD422B0089BB98 /* DoxygenLayout.xml */,
|
||||
98AB2DFE1CAD422B0089BB98 /* enet.dsp */,
|
||||
98AB2DFF1CAD422B0089BB98 /* enet_dll.cbp */,
|
||||
98AB2E001CAD422B0089BB98 /* host.c */,
|
||||
98AB2E011CAD422B0089BB98 /* include */,
|
||||
98AB2E0C1CAD422B0089BB98 /* libenet.pc.in */,
|
||||
98AB2E0D1CAD422B0089BB98 /* LICENSE */,
|
||||
98AB2E0E1CAD422B0089BB98 /* list.c */,
|
||||
98AB2E0F1CAD422B0089BB98 /* m4 */,
|
||||
98AB2E111CAD422B0089BB98 /* Makefile.am */,
|
||||
98AB2E121CAD422B0089BB98 /* packet.c */,
|
||||
98AB2E131CAD422B0089BB98 /* peer.c */,
|
||||
98AB2E141CAD422B0089BB98 /* premake4.lua */,
|
||||
98AB2E151CAD422B0089BB98 /* protocol.c */,
|
||||
98AB2E161CAD422B0089BB98 /* README */,
|
||||
98AB2E171CAD422B0089BB98 /* unix.c */,
|
||||
98AB2E181CAD422B0089BB98 /* win32.c */,
|
||||
);
|
||||
name = enet;
|
||||
path = "moonlight-common-c/enet";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
98AB2DF51CAD422B0089BB98 /* docs */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
98AB2DF61CAD422B0089BB98 /* design.dox */,
|
||||
98AB2DF71CAD422B0089BB98 /* FAQ.dox */,
|
||||
98AB2DF81CAD422B0089BB98 /* install.dox */,
|
||||
98AB2DF91CAD422B0089BB98 /* license.dox */,
|
||||
98AB2DFA1CAD422B0089BB98 /* mainpage.dox */,
|
||||
98AB2DFB1CAD422B0089BB98 /* tutorial.dox */,
|
||||
);
|
||||
path = docs;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
98AB2E011CAD422B0089BB98 /* include */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
98AB2E021CAD422B0089BB98 /* enet */,
|
||||
);
|
||||
path = include;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
98AB2E021CAD422B0089BB98 /* enet */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
98AB2E031CAD422B0089BB98 /* callbacks.h */,
|
||||
98AB2E041CAD422B0089BB98 /* enet.h */,
|
||||
98AB2E051CAD422B0089BB98 /* list.h */,
|
||||
98AB2E061CAD422B0089BB98 /* protocol.h */,
|
||||
98AB2E071CAD422B0089BB98 /* time.h */,
|
||||
98AB2E081CAD422B0089BB98 /* types.h */,
|
||||
98AB2E091CAD422B0089BB98 /* unix.h */,
|
||||
98AB2E0A1CAD422B0089BB98 /* utility.h */,
|
||||
98AB2E0B1CAD422B0089BB98 /* win32.h */,
|
||||
);
|
||||
path = enet;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
98AB2E0F1CAD422B0089BB98 /* m4 */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
98AB2E101CAD422B0089BB98 /* .keep */,
|
||||
);
|
||||
path = m4;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
98AB2E191CAD423B0089BB98 /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9857AEEB1EBE85AB0084F99E /* RtpFecQueue.h */,
|
||||
9857AEE91EBE85A20084F99E /* RtpFecQueue.c */,
|
||||
98AB2E1A1CAD423B0089BB98 /* AudioStream.c */,
|
||||
98AB2E1B1CAD423B0089BB98 /* ByteBuffer.c */,
|
||||
98AB2E1C1CAD423B0089BB98 /* ByteBuffer.h */,
|
||||
98AB2E1D1CAD423B0089BB98 /* Connection.c */,
|
||||
98AB2E1E1CAD423B0089BB98 /* ControlStream.c */,
|
||||
98AB2E1F1CAD423B0089BB98 /* FakeCallbacks.c */,
|
||||
98AB2E201CAD423B0089BB98 /* Input.h */,
|
||||
98AB2E211CAD423B0089BB98 /* InputStream.c */,
|
||||
98AB2E221CAD423B0089BB98 /* Limelight-internal.h */,
|
||||
98AB2E231CAD423B0089BB98 /* Limelight.h */,
|
||||
98AB2E241CAD423B0089BB98 /* LinkedBlockingQueue.c */,
|
||||
98AB2E251CAD423B0089BB98 /* LinkedBlockingQueue.h */,
|
||||
98AB2E261CAD423B0089BB98 /* Misc.c */,
|
||||
98AB2E311CAD423B0089BB98 /* Platform.c */,
|
||||
98AB2E321CAD423B0089BB98 /* Platform.h */,
|
||||
98AB2E331CAD423B0089BB98 /* PlatformSockets.c */,
|
||||
98AB2E341CAD423B0089BB98 /* PlatformSockets.h */,
|
||||
98AB2E351CAD423B0089BB98 /* PlatformThreads.h */,
|
||||
98AB2E361CAD423B0089BB98 /* RtpReorderQueue.c */,
|
||||
98AB2E371CAD423B0089BB98 /* RtpReorderQueue.h */,
|
||||
98AB2E381CAD423B0089BB98 /* Rtsp.h */,
|
||||
98AB2E391CAD423B0089BB98 /* RtspConnection.c */,
|
||||
98AB2E3A1CAD423B0089BB98 /* RtspParser.c */,
|
||||
98AB2E3B1CAD423B0089BB98 /* SdpGenerator.c */,
|
||||
98AB2E3C1CAD423B0089BB98 /* Video.h */,
|
||||
98AB2E3D1CAD423B0089BB98 /* VideoDepacketizer.c */,
|
||||
98AB2E3E1CAD423B0089BB98 /* VideoStream.c */,
|
||||
);
|
||||
name = src;
|
||||
path = "moonlight-common-c/src";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FB290E2519B37A4E004C83CF = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9857AEED1EBE85D50084F99E /* reedsolomon */,
|
||||
98AB2E191CAD423B0089BB98 /* src */,
|
||||
98AB2DEF1CAD422B0089BB98 /* enet */,
|
||||
FB290E2F19B37A4E004C83CF /* Products */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
FB290E2F19B37A4E004C83CF /* Products */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
FB290E2E19B37A4E004C83CF /* libmoonlight-common.a */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
FB290E2D19B37A4E004C83CF /* moonlight-common */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = FB290E3219B37A4E004C83CF /* Build configuration list for PBXNativeTarget "moonlight-common" */;
|
||||
buildPhases = (
|
||||
FB290E2A19B37A4E004C83CF /* Sources */,
|
||||
FB290E2B19B37A4E004C83CF /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = "moonlight-common";
|
||||
productName = "limelight-common";
|
||||
productReference = FB290E2E19B37A4E004C83CF /* libmoonlight-common.a */;
|
||||
productType = "com.apple.product-type.library.static";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
FB290E2619B37A4E004C83CF /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastUpgradeCheck = 0810;
|
||||
ORGANIZATIONNAME = "Moonlight Stream";
|
||||
};
|
||||
buildConfigurationList = FB290E2919B37A4E004C83CF /* Build configuration list for PBXProject "moonlight-common" */;
|
||||
compatibilityVersion = "Xcode 6.3";
|
||||
developmentRegion = English;
|
||||
hasScannedForEncodings = 0;
|
||||
knownRegions = (
|
||||
en,
|
||||
);
|
||||
mainGroup = FB290E2519B37A4E004C83CF;
|
||||
productRefGroup = FB290E2F19B37A4E004C83CF /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
FB290E2D19B37A4E004C83CF /* moonlight-common */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
FB290E2A19B37A4E004C83CF /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
98AB2E401CAD425A0089BB98 /* AudioStream.c in Sources */,
|
||||
98AB2E411CAD425A0089BB98 /* ByteBuffer.c in Sources */,
|
||||
98AB2E421CAD425A0089BB98 /* Connection.c in Sources */,
|
||||
98AB2E431CAD425A0089BB98 /* ControlStream.c in Sources */,
|
||||
98AB2E441CAD425A0089BB98 /* FakeCallbacks.c in Sources */,
|
||||
98AB2E451CAD425A0089BB98 /* InputStream.c in Sources */,
|
||||
98AB2E461CAD425A0089BB98 /* LinkedBlockingQueue.c in Sources */,
|
||||
98AB2E471CAD425A0089BB98 /* Misc.c in Sources */,
|
||||
98AB2E481CAD425A0089BB98 /* Platform.c in Sources */,
|
||||
98AB2E491CAD425A0089BB98 /* PlatformSockets.c in Sources */,
|
||||
98AB2E4A1CAD425A0089BB98 /* RtpReorderQueue.c in Sources */,
|
||||
98AB2E4B1CAD425A0089BB98 /* RtspConnection.c in Sources */,
|
||||
98AB2E4C1CAD425A0089BB98 /* RtspParser.c in Sources */,
|
||||
98AB2E4D1CAD425A0089BB98 /* SdpGenerator.c in Sources */,
|
||||
98AB2E4E1CAD425A0089BB98 /* VideoDepacketizer.c in Sources */,
|
||||
9857AEEA1EBE85A20084F99E /* RtpFecQueue.c in Sources */,
|
||||
98AB2E4F1CAD425A0089BB98 /* VideoStream.c in Sources */,
|
||||
98AB2E501CAD427A0089BB98 /* callbacks.c in Sources */,
|
||||
98AB2E511CAD427A0089BB98 /* compress.c in Sources */,
|
||||
98AB2E521CAD427A0089BB98 /* host.c in Sources */,
|
||||
98AB2E531CAD427A0089BB98 /* list.c in Sources */,
|
||||
98AB2E541CAD427A0089BB98 /* packet.c in Sources */,
|
||||
98AB2E551CAD427A0089BB98 /* peer.c in Sources */,
|
||||
98AB2E561CAD427A0089BB98 /* protocol.c in Sources */,
|
||||
9857AEF01EBE85E10084F99E /* rs.c in Sources */,
|
||||
98AB2E571CAD427A0089BB98 /* unix.c in Sources */,
|
||||
98AB2E581CAD427A0089BB98 /* win32.c in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin XCBuildConfiguration section */
|
||||
FB290E3019B37A4E004C83CF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "Mac Developer";
|
||||
COPY_PHASE_STRIP = NO;
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_OPTIMIZATION_LEVEL = 0;
|
||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||
LC_DEBUG,
|
||||
"DEBUG=1",
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
FB290E3119B37A4E004C83CF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_BOOL_CONVERSION = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||
CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application";
|
||||
COPY_PHASE_STRIP = YES;
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
DEFINES_MODULE = YES;
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 10.10;
|
||||
PROVISIONING_PROFILE = "";
|
||||
SDKROOT = macosx;
|
||||
SKIP_INSTALL = YES;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
FB290E3319B37A4E004C83CF /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"moonlight-common-c/enet/include",
|
||||
"../libs/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
FB290E3419B37A4E004C83CF /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||
EXECUTABLE_PREFIX = lib;
|
||||
HEADER_SEARCH_PATHS = (
|
||||
"moonlight-common-c/enet/include",
|
||||
"../libs/**",
|
||||
);
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 8.0;
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
FB290E2919B37A4E004C83CF /* Build configuration list for PBXProject "moonlight-common" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
FB290E3019B37A4E004C83CF /* Debug */,
|
||||
FB290E3119B37A4E004C83CF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
FB290E3219B37A4E004C83CF /* Build configuration list for PBXNativeTarget "moonlight-common" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
FB290E3319B37A4E004C83CF /* Debug */,
|
||||
FB290E3419B37A4E004C83CF /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = FB290E2619B37A4E004C83CF /* Project object */;
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>IDESourceControlProjectFavoriteDictionaryKey</key>
|
||||
<false/>
|
||||
<key>IDESourceControlProjectIdentifier</key>
|
||||
<string>662F3EBE-A540-4F33-A434-3BBB22ECCB12</string>
|
||||
<key>IDESourceControlProjectName</key>
|
||||
<string>limelight-common</string>
|
||||
<key>IDESourceControlProjectOriginsDictionary</key>
|
||||
<dict>
|
||||
<key>151E8452-E928-4FE9-BF31-5F5C490B9DD4</key>
|
||||
<string>ssh://github.com/limelight-stream/limelight-common-c.git</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectPath</key>
|
||||
<string>limelight-common.xcodeproj/project.xcworkspace</string>
|
||||
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
|
||||
<dict>
|
||||
<key>151E8452-E928-4FE9-BF31-5F5C490B9DD4</key>
|
||||
<string>../..</string>
|
||||
</dict>
|
||||
<key>IDESourceControlProjectURL</key>
|
||||
<string>ssh://github.com/limelight-stream/limelight-common-c.git</string>
|
||||
<key>IDESourceControlProjectVersion</key>
|
||||
<integer>110</integer>
|
||||
<key>IDESourceControlProjectWCCIdentifier</key>
|
||||
<string>151E8452-E928-4FE9-BF31-5F5C490B9DD4</string>
|
||||
<key>IDESourceControlProjectWCConfigurations</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
|
||||
<string>public.vcs.git</string>
|
||||
<key>IDESourceControlWCCIdentifierKey</key>
|
||||
<string>151E8452-E928-4FE9-BF31-5F5C490B9DD4</string>
|
||||
<key>IDESourceControlWCCName</key>
|
||||
<string>limelight-common-c</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintPrimaryRemoteRepositoryKey" : "A4B0849259F9566B0CBA84A6D3D4A0F895C03123",
|
||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyRepositoryLocationsKey" : {
|
||||
|
||||
},
|
||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyStatesKey" : {
|
||||
"584110FE5ABD5BCB5065B76A98D3F8000D0644EC" : 0,
|
||||
"A4B0849259F9566B0CBA84A6D3D4A0F895C03123" : 0,
|
||||
"EB99D631D5149240E91F8D168F0F298D7A5BAA89" : 0
|
||||
},
|
||||
"DVTSourceControlWorkspaceBlueprintIdentifierKey" : "40250820-914C-4FB3-9CF1-3DB8A02E7012",
|
||||
"DVTSourceControlWorkspaceBlueprintWorkingCopyPathsKey" : {
|
||||
"584110FE5ABD5BCB5065B76A98D3F8000D0644EC" : "moonlight-ios\/moonlight-common\/moonlight-common-c\/enet\/",
|
||||
"A4B0849259F9566B0CBA84A6D3D4A0F895C03123" : "moonlight-ios\/",
|
||||
"EB99D631D5149240E91F8D168F0F298D7A5BAA89" : "moonlight-ios\/moonlight-common\/moonlight-common-c\/"
|
||||
},
|
||||
"DVTSourceControlWorkspaceBlueprintNameKey" : "moonlight-common",
|
||||
"DVTSourceControlWorkspaceBlueprintVersion" : 204,
|
||||
"DVTSourceControlWorkspaceBlueprintRelativePathToProjectKey" : "moonlight-common\/moonlight-common.xcodeproj",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoriesKey" : [
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/cgutman\/enet.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "584110FE5ABD5BCB5065B76A98D3F8000D0644EC"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "github.com:moonlight-stream\/moonlight-ios.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "A4B0849259F9566B0CBA84A6D3D4A0F895C03123"
|
||||
},
|
||||
{
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryURLKey" : "https:\/\/github.com\/moonlight-stream\/moonlight-common-c.git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositorySystemKey" : "com.apple.dt.Xcode.sourcecontrol.Git",
|
||||
"DVTSourceControlWorkspaceBlueprintRemoteRepositoryIdentifierKey" : "EB99D631D5149240E91F8D168F0F298D7A5BAA89"
|
||||
}
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user