Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5584083809 | ||
|
|
9f9aec70b0 | ||
|
|
a8d1770871 | ||
|
|
d0d60b8ffc | ||
|
|
86f7112789 | ||
|
|
da1115e529 | ||
|
|
593da7ef3e | ||
|
|
de5377a95d | ||
|
|
7d7500b187 | ||
|
|
45dbd46da1 | ||
|
|
89d8bc6009 | ||
|
|
b99988836a | ||
|
|
3e94613eb3 | ||
|
|
832b9189f8 | ||
|
|
3464539bd3 | ||
|
|
815592117d | ||
|
|
b51341ef54 | ||
|
|
9ffbb5f155 | ||
|
|
9716867ade | ||
|
|
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 | ||
|
|
55d48101ef | ||
|
|
c36f4c5f84 | ||
|
|
06289ac4d2 | ||
|
|
e6a2d5d425 | ||
|
|
ea8db9c4ea | ||
|
|
3773e841d1 | ||
|
|
ad1ddd04f3 | ||
|
|
67a8b232b9 | ||
|
|
5293c07fc0 | ||
|
|
e3a42db007 | ||
|
|
3b1462af22 | ||
|
|
74a0c5b1cd | ||
|
|
05a5e4fa64 | ||
|
|
b6445295a7 | ||
|
|
391605ef36 | ||
|
|
695499dea9 | ||
|
|
9ba7f35444 | ||
|
|
37dc00735b | ||
|
|
920cbadc91 | ||
|
|
bc53b4dc32 | ||
|
|
6015c38d17 | ||
|
|
4ea8694a7d | ||
|
|
00f01196fb | ||
|
|
543639c93e | ||
|
|
1da877fed7 | ||
|
|
396b5fc156 | ||
|
|
297dfd4159 | ||
|
|
23e9d48b0d | ||
|
|
9ec650a84f | ||
|
|
90bdbc4ae0 | ||
|
|
dd5f06723b | ||
|
|
55b2871b83 |
@@ -1,2 +1,4 @@
|
|||||||
**/xcuserdata/
|
**/xcuserdata/
|
||||||
|
**/Moonlight.xcscmblueprint
|
||||||
Build
|
Build
|
||||||
|
DerivedData
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
[submodule "limelight-common-c"]
|
[submodule "moonlight-common/moonlight-common-c"]
|
||||||
path = limelight-common-c
|
path = moonlight-common/moonlight-common-c
|
||||||
url = git@github.com:limelight-stream/limelight-common-c.git
|
url = https://github.com/moonlight-stream/moonlight-common-c.git
|
||||||
|
|||||||
@@ -1,36 +1,51 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8121.17" systemVersion="15A204h" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="15A279b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8101.14"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
<navigationController id="vV9-32-ww6">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="y2P-aE-Haa">
|
||||||
<subviews>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2015 Moonlight Stream. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<rect key="frame" x="18" y="439.5" width="444" height="20.5"/>
|
<animations/>
|
||||||
<animations/>
|
<color key="barTintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
</navigationBar>
|
||||||
<color key="textColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<viewControllers>
|
||||||
<nil key="highlightedColor"/>
|
<viewController id="l6V-ue-5Om">
|
||||||
<variation key="widthClass=compact">
|
<layoutGuides>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<viewControllerLayoutGuide type="top" id="rEZ-vx-akr"/>
|
||||||
</variation>
|
<viewControllerLayoutGuide type="bottom" id="gBD-cy-cth"/>
|
||||||
</label>
|
</layoutGuides>
|
||||||
</subviews>
|
<view key="view" contentMode="scaleToFill" id="6lF-fc-kpK">
|
||||||
<animations/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<animations/>
|
||||||
<constraints>
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Gnz-uJ-CDw"/>
|
</view>
|
||||||
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
|
<navigationItem key="navigationItem" id="rW0-BH-s7l">
|
||||||
</constraints>
|
<barButtonItem key="leftBarButtonItem" enabled="NO" id="d9R-Zo-Uml">
|
||||||
<nil key="simulatedStatusBarMetrics"/>
|
<button key="customView" opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="9JC-B5-BAE">
|
||||||
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
|
<rect key="frame" x="20" y="-1" width="109" height="46"/>
|
||||||
<point key="canvasLocation" x="404" y="445"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
</view>
|
<animations/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
|
<state key="normal" title="Moonlight" image="Logo">
|
||||||
|
<color key="titleColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<color key="titleShadowColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
</state>
|
||||||
|
<variation key="widthClass=regular" preservesSuperviewLayoutMargins="NO"/>
|
||||||
|
</button>
|
||||||
|
</barButtonItem>
|
||||||
|
</navigationItem>
|
||||||
|
</viewController>
|
||||||
|
</viewControllers>
|
||||||
|
</navigationController>
|
||||||
</objects>
|
</objects>
|
||||||
|
<resources>
|
||||||
|
<image name="Logo" width="32" height="32"/>
|
||||||
|
</resources>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// AppCollectionView.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppCollectionView : UICollectionView
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// AppCollectionView.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppCollectionView.h"
|
||||||
|
|
||||||
|
@implementation AppCollectionView
|
||||||
|
|
||||||
|
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
|
||||||
|
if ([view isKindOfClass:[UIButton class]]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return [super touchesShouldCancelInContentView:view];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Only override drawRect: if you perform custom drawing.
|
||||||
|
// An empty implementation adversely affects performance during animation.
|
||||||
|
- (void)drawRect:(CGRect)rect {
|
||||||
|
// Drawing code
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -83,10 +83,7 @@ static NSOperationQueue* mainQueue;
|
|||||||
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
|
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
|
||||||
if (managedObjectContext != nil) {
|
if (managedObjectContext != nil) {
|
||||||
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
|
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
|
||||||
// Replace this implementation with code to handle the error appropriately.
|
Log(LOG_E, @"Critical database error: %@, %@", error, [error userInfo]);
|
||||||
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
|
||||||
Log(LOG_E, @"Unresolved error %@, %@", error, [error userInfo]);
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,32 +133,15 @@ static NSOperationQueue* mainQueue;
|
|||||||
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
||||||
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
|
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
|
||||||
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
|
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
|
||||||
/*
|
// Log the error
|
||||||
Replace this implementation with code to handle the error appropriately.
|
Log(LOG_E, @"Critical database error: %@, %@", error, [error userInfo]);
|
||||||
|
|
||||||
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
|
// Drop the database
|
||||||
|
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
|
||||||
Typical reasons for an error here include:
|
|
||||||
* The persistent store is not accessible;
|
// Try again
|
||||||
* The schema for the persistent store is incompatible with current managed object model.
|
return [self persistentStoreCoordinator];
|
||||||
Check the error message to determine what the actual problem was.
|
}
|
||||||
|
|
||||||
|
|
||||||
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
|
|
||||||
|
|
||||||
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
|
|
||||||
* Simply deleting the existing store:
|
|
||||||
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
|
|
||||||
|
|
||||||
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
|
|
||||||
@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
|
|
||||||
|
|
||||||
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
|
|
||||||
|
|
||||||
*/
|
|
||||||
Log(LOG_E, @"Unresolved error %@, %@", error, [error userInfo]);
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
|
|
||||||
return _persistentStoreCoordinator;
|
return _persistentStoreCoordinator;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// ComputerScrollView.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface ComputerScrollView : UIScrollView
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// ComputerScrollView.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ComputerScrollView.h"
|
||||||
|
|
||||||
|
@implementation ComputerScrollView
|
||||||
|
|
||||||
|
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
|
||||||
|
if ([view isKindOfClass:[UIButton class]]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return [super touchesShouldCancelInContentView:view];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Only override drawRect: if you perform custom drawing.
|
||||||
|
// An empty implementation adversely affects performance during animation.
|
||||||
|
- (void)drawRect:(CGRect)rect {
|
||||||
|
// Drawing code
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -11,15 +11,16 @@
|
|||||||
@interface CryptoManager : NSObject
|
@interface CryptoManager : NSObject
|
||||||
|
|
||||||
+ (void) generateKeyPairUsingSSl;
|
+ (void) generateKeyPairUsingSSl;
|
||||||
+ (NSString*) getUniqueID;
|
|
||||||
+ (NSData*) readCertFromFile;
|
+ (NSData*) readCertFromFile;
|
||||||
+ (NSData*) readKeyFromFile;
|
+ (NSData*) readKeyFromFile;
|
||||||
+ (NSData*) readP12FromFile;
|
+ (NSData*) readP12FromFile;
|
||||||
+ (NSData*) getSignatureFromCert:(NSData*)cert;
|
+ (NSData*) getSignatureFromCert:(NSData*)cert;
|
||||||
+ (NSData*) nullTerminateString:(NSData*)data;
|
+ (NSData*) nullTerminateString:(NSData*)data;
|
||||||
|
|
||||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN;
|
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN;
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN;
|
||||||
- (NSData*) SHA1HashData:(NSData*)data;
|
- (NSData*) SHA1HashData:(NSData*)data;
|
||||||
|
- (NSData*) SHA256HashData:(NSData*)data;
|
||||||
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
|
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
|
||||||
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
|
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
|
||||||
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
|
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
|
||||||
|
|||||||
@@ -8,7 +8,6 @@
|
|||||||
|
|
||||||
#import "CryptoManager.h"
|
#import "CryptoManager.h"
|
||||||
#import "mkcert.h"
|
#import "mkcert.h"
|
||||||
#import <AdSupport/ASIdentifierManager.h>
|
|
||||||
|
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
@@ -17,19 +16,31 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
@implementation CryptoManager
|
@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* key = nil;
|
||||||
static NSData* cert = nil;
|
static NSData* cert = nil;
|
||||||
static NSData* p12 = nil;
|
static NSData* p12 = nil;
|
||||||
|
|
||||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN {
|
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN {
|
||||||
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN {
|
||||||
|
return [[self SHA256HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSData*) SHA1HashData:(NSData*)data {
|
- (NSData*) SHA1HashData:(NSData*)data {
|
||||||
unsigned char sha1[SHA1_DIGEST_LENGTH];
|
unsigned char sha1[SHA1_HASH_LENGTH];
|
||||||
SHA1([data bytes], [data length], sha1);
|
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;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -229,18 +240,4 @@ static NSData* p12 = nil;
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString*) getUniqueID {
|
|
||||||
// generate a UUID
|
|
||||||
NSUUID* uuid = [ASIdentifierManager sharedManager].advertisingIdentifier;
|
|
||||||
NSString* idString = [NSString stringWithString:[uuid UUIDString]];
|
|
||||||
|
|
||||||
// we need a 16byte hex-string so we take the last 17 characters
|
|
||||||
// and remove the '-' to get a 16 character string
|
|
||||||
NSMutableString* uniqueId = [NSMutableString stringWithString:[idString substringFromIndex:19]];
|
|
||||||
[uniqueId deleteCharactersInRange:NSMakeRange(4, 1)];
|
|
||||||
|
|
||||||
//Log(LOG_D, @"Unique ID: %@", uniqueId);
|
|
||||||
return [NSString stringWithString:uniqueId];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// IdManager.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/31/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
@interface IdManager : NSObject
|
||||||
|
|
||||||
|
+ (NSString*) getUniqueId;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// IdManager.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/31/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "IdManager.h"
|
||||||
|
#import "DataManager.h"
|
||||||
|
|
||||||
|
@implementation IdManager
|
||||||
|
|
||||||
|
+ (NSString*) getUniqueId {
|
||||||
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
|
|
||||||
|
NSString* uniqueId = [dataMan getUniqueId];
|
||||||
|
if (uniqueId == nil) {
|
||||||
|
uniqueId = [IdManager generateUniqueId];
|
||||||
|
[dataMan updateUniqueId:uniqueId];
|
||||||
|
Log(LOG_I, @"No UUID found. Generated new UUID: %@", uniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString*) generateUniqueId {
|
||||||
|
UInt64 uuidLong = ((UInt64) arc4random() << 32) | arc4random();
|
||||||
|
return [NSString stringWithFormat:@"%016llx", uuidLong];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -85,7 +85,6 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
|||||||
|
|
||||||
if (*pkeyp == NULL) {
|
if (*pkeyp == NULL) {
|
||||||
if ((pk=EVP_PKEY_new()) == NULL) {
|
if ((pk=EVP_PKEY_new()) == NULL) {
|
||||||
abort();
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -102,7 +101,6 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
|||||||
|
|
||||||
rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
|
rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
|
||||||
if (!EVP_PKEY_assign_RSA(pk, rsa)) {
|
if (!EVP_PKEY_assign_RSA(pk, rsa)) {
|
||||||
abort();
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,16 +11,8 @@
|
|||||||
|
|
||||||
@class Host;
|
@class Host;
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
|
||||||
|
|
||||||
@interface App : NSManagedObject
|
@interface App : NSManagedObject
|
||||||
|
|
||||||
@property BOOL isRunning;
|
|
||||||
|
|
||||||
- (NSComparisonResult)compareName:(App *)other;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
|
||||||
|
|
||||||
#import "App+CoreDataProperties.h"
|
#import "App+CoreDataProperties.h"
|
||||||
|
|||||||
@@ -7,14 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "App.h"
|
#import "App.h"
|
||||||
#import "Host.h"
|
|
||||||
|
|
||||||
@implementation App
|
@implementation App
|
||||||
|
|
||||||
@synthesize isRunning;
|
|
||||||
|
|
||||||
- (NSComparisonResult)compareName:(App *)other {
|
|
||||||
return [self.name caseInsensitiveCompare:other.name];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,22 +7,25 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "Settings.h"
|
|
||||||
#import "AppDelegate.h"
|
#import "AppDelegate.h"
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
#import "App.h"
|
#import "TemporaryApp.h"
|
||||||
|
#import "TemporarySettings.h"
|
||||||
|
|
||||||
@interface DataManager : NSObject
|
@interface DataManager : NSObject
|
||||||
|
|
||||||
@property (strong, nonatomic) AppDelegate* appDelegate;
|
|
||||||
|
|
||||||
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls;
|
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls;
|
||||||
- (Settings*) retrieveSettings;
|
|
||||||
- (NSArray*) retrieveHosts;
|
- (NSArray*) getHosts;
|
||||||
- (void) saveData;
|
- (void) updateHost:(TemporaryHost*)host;
|
||||||
- (Host*) createHost;
|
- (void) updateAppsForExistingHost:(TemporaryHost *)host;
|
||||||
- (void) removeHost:(Host*)host;
|
- (void) updateIconForExistingApp:(TemporaryApp*)app;
|
||||||
- (App*) createApp;
|
- (void) removeHost:(TemporaryHost*)host;
|
||||||
- (void) removeApp:(App*)app;
|
- (void) removeApp:(TemporaryApp*)app;
|
||||||
|
|
||||||
|
- (TemporarySettings*) getSettings;
|
||||||
|
|
||||||
|
- (void) updateUniqueId:(NSString*)uniqueId;
|
||||||
|
- (NSString*) getUniqueId;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,37 +7,142 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
|
#import "TemporaryApp.h"
|
||||||
|
#import "TemporarySettings.h"
|
||||||
|
#import "Settings.h"
|
||||||
|
|
||||||
@implementation DataManager
|
@implementation DataManager {
|
||||||
|
NSManagedObjectContext *_managedObjectContext;
|
||||||
|
AppDelegate *_appDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
- (id) init {
|
- (id) init {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
self.appDelegate = [[UIApplication sharedApplication] delegate];
|
|
||||||
|
// HACK: Avoid calling [UIApplication delegate] off the UI thread to keep
|
||||||
|
// Main Thread Checker happy.
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
_appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||||
|
_appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
|
||||||
|
[_managedObjectContext setPersistentStoreCoordinator:_appDelegate.persistentStoreCoordinator];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
|
- (void) updateUniqueId:(NSString*)uniqueId {
|
||||||
Settings* settingsToSave = [self retrieveSettings];
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
|
[self retrieveSettings].uniqueId = uniqueId;
|
||||||
// Bitrate is persisted in kbps
|
[self saveData];
|
||||||
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
|
}];
|
||||||
settingsToSave.height = [NSNumber numberWithInteger:height];
|
}
|
||||||
settingsToSave.width = [NSNumber numberWithInteger:width];
|
|
||||||
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
|
|
||||||
|
|
||||||
NSError* error;
|
- (NSString*) getUniqueId {
|
||||||
if (![[self.appDelegate managedObjectContext] save:&error]) {
|
__block NSString *uid;
|
||||||
Log(LOG_E, @"Unable to save settings to database: %@", error);
|
|
||||||
}
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
[self.appDelegate saveContext];
|
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 {
|
- (Settings*) retrieveSettings {
|
||||||
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
|
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
|
||||||
if (fetchedRecords.count == 0) {
|
if (fetchedRecords.count == 0) {
|
||||||
// create a new settings object with the default values
|
// create a new settings object with the default values
|
||||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:_managedObjectContext];
|
||||||
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
} else {
|
} else {
|
||||||
@@ -46,49 +151,84 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (Host*) createHost {
|
- (void) removeApp:(TemporaryApp*)app {
|
||||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
return [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
App* managedApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
|
||||||
|
if (managedApp != nil) {
|
||||||
|
[_managedObjectContext deleteObject:managedApp];
|
||||||
|
[self saveData];
|
||||||
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeHost:(Host*)host {
|
- (void) removeHost:(TemporaryHost*)host {
|
||||||
[[self.appDelegate managedObjectContext] deleteObject:host];
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
[self saveData];
|
Host* managedHost = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
|
||||||
|
if (managedHost != nil) {
|
||||||
|
[_managedObjectContext deleteObject:managedHost];
|
||||||
|
[self saveData];
|
||||||
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) saveData {
|
- (void) saveData {
|
||||||
NSError* error;
|
NSError* error;
|
||||||
if (![[self.appDelegate managedObjectContext] save:&error]) {
|
if (![_managedObjectContext save:&error]) {
|
||||||
Log(LOG_E, @"Unable to save hosts to database: %@", error);
|
Log(LOG_E, @"Unable to save hosts to database: %@", error);
|
||||||
}
|
}
|
||||||
[self.appDelegate saveContext];
|
|
||||||
|
[_appDelegate saveContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray*) retrieveHosts {
|
- (NSArray*) getHosts {
|
||||||
return [self fetchRecords:@"Host"];
|
__block NSMutableArray *tempHosts = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
NSArray *hosts = [self fetchRecords:@"Host"];
|
||||||
|
|
||||||
|
for (Host* host in hosts) {
|
||||||
|
[tempHosts addObject:[[TemporaryHost alloc] initFromHost:host]];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
return tempHosts;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (App*) createApp {
|
// Only call from within performBlockAndWait!!!
|
||||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
- (Host*) getHostForTemporaryHost:(TemporaryHost*)tempHost withHostRecords:(NSArray*)hosts {
|
||||||
return [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
for (Host* host in hosts) {
|
||||||
|
if ([tempHost.uuid isEqualToString:host.uuid]) {
|
||||||
|
return host;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeApp:(App*)app {
|
// Only call from within performBlockAndWait!!!
|
||||||
[[self.appDelegate managedObjectContext] deleteObject:app];
|
- (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*) fetchRecords:(NSString*)entityName {
|
||||||
|
NSArray* fetchedRecords;
|
||||||
|
|
||||||
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
|
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
|
||||||
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];
|
||||||
[fetchRequest setEntity:entity];
|
[fetchRequest setEntity:entity];
|
||||||
[fetchRequest setAffectedStores:[NSArray arrayWithObjects:[[self.appDelegate persistentStoreCoordinator] persistentStoreForURL:[self.appDelegate getStoreURL]], nil]];
|
|
||||||
|
|
||||||
NSError* error;
|
NSError* error;
|
||||||
NSArray* fetchedRecords = [[self.appDelegate managedObjectContext] executeFetchRequest:fetchRequest error:&error];
|
fetchedRecords = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
|
||||||
//TODO: handle errors
|
//TODO: handle errors
|
||||||
|
|
||||||
return fetchedRecords;
|
return fetchedRecords;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,16 +10,8 @@
|
|||||||
#import <CoreData/CoreData.h>
|
#import <CoreData/CoreData.h>
|
||||||
#import "Utils.h"
|
#import "Utils.h"
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_BEGIN
|
|
||||||
|
|
||||||
@interface Host : NSManagedObject
|
@interface Host : NSManagedObject
|
||||||
|
|
||||||
@property (nonatomic) BOOL online;
|
|
||||||
@property (nonatomic) PairState pairState;
|
|
||||||
@property (nonatomic) NSString * activeAddress;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
NS_ASSUME_NONNULL_END
|
|
||||||
|
|
||||||
#import "Host+CoreDataProperties.h"
|
#import "Host+CoreDataProperties.h"
|
||||||
|
|||||||
@@ -10,8 +10,4 @@
|
|||||||
|
|
||||||
@implementation Host
|
@implementation Host
|
||||||
|
|
||||||
@dynamic pairState;
|
|
||||||
@synthesize online;
|
|
||||||
@synthesize activeAddress;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -17,5 +17,6 @@
|
|||||||
@property (nonatomic, retain) NSNumber * height;
|
@property (nonatomic, retain) NSNumber * height;
|
||||||
@property (nonatomic, retain) NSNumber * width;
|
@property (nonatomic, retain) NSNumber * width;
|
||||||
@property (nonatomic, retain) NSNumber * onscreenControls;
|
@property (nonatomic, retain) NSNumber * onscreenControls;
|
||||||
|
@property (nonatomic, retain) NSString * uniqueId;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -16,5 +16,6 @@
|
|||||||
@dynamic height;
|
@dynamic height;
|
||||||
@dynamic width;
|
@dynamic width;
|
||||||
@dynamic onscreenControls;
|
@dynamic onscreenControls;
|
||||||
|
@dynamic uniqueId;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// TemporaryApp.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.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 (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
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// TemporaryApp.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#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
|
||||||
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.2 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -1,76 +1,108 @@
|
|||||||
{
|
{
|
||||||
"images" : [
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "app_icon_settings_58x58_@2x-1.png",
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "app_icon_settings_87x87_@3x.png",
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "app_icon_spotlight_80x80_@2x-1.png",
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "app_icon_spotlight_120x120_@3x.png",
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "60x60",
|
"size" : "60x60",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "app_icon_120x120_@2x.png",
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "60x60",
|
"size" : "60x60",
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
"filename" : "app_icon_180x180_@3x.png",
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
"scale" : "3x"
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"filename" : "app_icon_settings_29x29_@1x.png",
|
"filename" : "Icon-App-[email protected]",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"filename" : "app_icon_settings_58x58_@2x.png",
|
"filename" : "Icon-App-29x29@2x-1.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"filename" : "app_icon_spotlight_40x40_@1x.png",
|
"filename" : "Icon-App-[email protected]",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"filename" : "app_icon_spotlight_80x80_@2x.png",
|
"filename" : "Icon-App-40x40@2x-1.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "76x76",
|
"size" : "76x76",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"filename" : "app_icon_76x76_@1x.png",
|
"filename" : "Icon-App-[email protected]",
|
||||||
"scale" : "1x"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"size" : "76x76",
|
"size" : "76x76",
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
"filename" : "app_icon_152x152_@2x.png",
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
"scale" : "2x"
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "83.5x83.5",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "[email protected]",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "1024x1024",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"filename" : "1024x icon.png",
|
||||||
|
"scale" : "1x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 41 KiB |
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.1 KiB |
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -6,8 +6,8 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "logo.png",
|
||||||
"filename" : "logo_universal.png"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
|
|||||||
|
After Width: | Height: | Size: 6.2 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 1.1 KiB |
|
Before Width: | Height: | Size: 3.1 KiB After Width: | Height: | Size: 1.4 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 1.6 KiB |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "[email protected]",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "[email protected]",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "[email protected]",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 901 B |
|
After Width: | Height: | Size: 812 B |
|
After Width: | Height: | Size: 1.5 KiB |
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.2 KiB |
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.3 KiB |
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "x[email protected]",
|
||||||
"filename" : "x[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "x[email protected]",
|
||||||
"filename" : "x[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.3 KiB |
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "[email protected]",
|
||||||
"filename" : "[email protected]"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "[email protected]"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 2.1 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 <Foundation/Foundation.h>
|
||||||
#import "Controller.h"
|
|
||||||
|
// Swift
|
||||||
|
#import "Moonlight-Swift.h"
|
||||||
|
@class Controller;
|
||||||
|
|
||||||
@class OnScreenControls;
|
@class OnScreenControls;
|
||||||
|
|
||||||
@@ -29,6 +32,7 @@
|
|||||||
-(void) clearButtonFlag:(Controller*)controller flags:(int)flags;
|
-(void) clearButtonFlag:(Controller*)controller flags:(int)flags;
|
||||||
|
|
||||||
-(void) updateFinished:(Controller*)controller;
|
-(void) updateFinished:(Controller*)controller;
|
||||||
|
-(Controller*) getOscController;
|
||||||
|
|
||||||
@property (nonatomic, strong) id connectObserver;
|
@property (nonatomic, strong) id connectObserver;
|
||||||
@property (nonatomic, strong) id disconnectObserver;
|
@property (nonatomic, strong) id disconnectObserver;
|
||||||
|
|||||||
@@ -8,9 +8,12 @@
|
|||||||
|
|
||||||
#import "ControllerSupport.h"
|
#import "ControllerSupport.h"
|
||||||
#import "OnScreenControls.h"
|
#import "OnScreenControls.h"
|
||||||
#import "Controller.h"
|
|
||||||
#include "Limelight.h"
|
#include "Limelight.h"
|
||||||
|
|
||||||
|
// Swift
|
||||||
|
#import "Moonlight-Swift.h"
|
||||||
|
@class Controller;
|
||||||
|
|
||||||
@import GameController;
|
@import GameController;
|
||||||
|
|
||||||
@implementation ControllerSupport {
|
@implementation ControllerSupport {
|
||||||
@@ -19,6 +22,10 @@
|
|||||||
|
|
||||||
OnScreenControls *_osc;
|
OnScreenControls *_osc;
|
||||||
|
|
||||||
|
// This controller object is shared between on-screen controls
|
||||||
|
// and player 0
|
||||||
|
Controller *_player0osc;
|
||||||
|
|
||||||
char _controllerNumbers;
|
char _controllerNumbers;
|
||||||
|
|
||||||
#define EMULATING_SELECT 0x1
|
#define EMULATING_SELECT 0x1
|
||||||
@@ -139,7 +146,8 @@
|
|||||||
{
|
{
|
||||||
[_controllerStreamLock lock];
|
[_controllerStreamLock lock];
|
||||||
@synchronized(controller) {
|
@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];
|
[_controllerStreamLock unlock];
|
||||||
}
|
}
|
||||||
@@ -272,9 +280,17 @@
|
|||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (!(_controllerNumbers & (1 << i))) {
|
if (!(_controllerNumbers & (1 << i))) {
|
||||||
_controllerNumbers |= (1 << i);
|
_controllerNumbers |= (1 << i);
|
||||||
Controller* limeController = [[Controller alloc] init];
|
|
||||||
controller.playerIndex = i;
|
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]];
|
[_controllers setObject:limeController forKey:[NSNumber numberWithInteger:controller.playerIndex]];
|
||||||
|
|
||||||
Log(LOG_I, @"Assigning controller index: %d", i);
|
Log(LOG_I, @"Assigning controller index: %d", i);
|
||||||
@@ -283,6 +299,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-(Controller*) getOscController {
|
||||||
|
return _player0osc;
|
||||||
|
}
|
||||||
|
|
||||||
-(id) init
|
-(id) init
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
@@ -290,6 +310,8 @@
|
|||||||
_controllerStreamLock = [[NSLock alloc] init];
|
_controllerStreamLock = [[NSLock alloc] init];
|
||||||
_controllers = [[NSMutableDictionary alloc] init];
|
_controllers = [[NSMutableDictionary alloc] init];
|
||||||
_controllerNumbers = 0;
|
_controllerNumbers = 0;
|
||||||
|
_player0osc = [[Controller alloc] init];
|
||||||
|
_player0osc.playerIndex = 0;
|
||||||
|
|
||||||
Log(LOG_I, @"Number of controllers connected: %ld", (long)[[GCController controllers] count]);
|
Log(LOG_I, @"Number of controllers connected: %ld", (long)[[GCController controllers] count]);
|
||||||
for (GCController* controller in [GCController controllers]) {
|
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 "OnScreenControls.h"
|
||||||
#import "ControllerSupport.h"
|
#import "ControllerSupport.h"
|
||||||
#import "Controller.h"
|
//#import "Controller.h"
|
||||||
#include "Limelight.h"
|
#include "Limelight.h"
|
||||||
|
|
||||||
|
#import "Moonlight-Swift.h"
|
||||||
|
@class Controller;
|
||||||
|
|
||||||
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
#define UPDATE_BUTTON(x, y) (buttonFlags = \
|
||||||
(y) ? (buttonFlags | (x)) : (buttonFlags & ~(x)))
|
(y) ? (buttonFlags | (x)) : (buttonFlags & ~(x)))
|
||||||
|
|
||||||
@@ -41,10 +44,7 @@
|
|||||||
UITouch* _bTouch;
|
UITouch* _bTouch;
|
||||||
UITouch* _xTouch;
|
UITouch* _xTouch;
|
||||||
UITouch* _yTouch;
|
UITouch* _yTouch;
|
||||||
UITouch* _upTouch;
|
UITouch* _dpadTouch;
|
||||||
UITouch* _downTouch;
|
|
||||||
UITouch* _leftTouch;
|
|
||||||
UITouch* _rightTouch;
|
|
||||||
UITouch* _lsTouch;
|
UITouch* _lsTouch;
|
||||||
UITouch* _rsTouch;
|
UITouch* _rsTouch;
|
||||||
UITouch* _startTouch;
|
UITouch* _startTouch;
|
||||||
@@ -63,25 +63,30 @@
|
|||||||
BOOL l3Set;
|
BOOL l3Set;
|
||||||
BOOL r3Set;
|
BOOL r3Set;
|
||||||
|
|
||||||
|
BOOL _iPad;
|
||||||
|
CGRect _controlArea;
|
||||||
UIView* _view;
|
UIView* _view;
|
||||||
OnScreenControlsLevel _level;
|
OnScreenControlsLevel _level;
|
||||||
|
|
||||||
ControllerSupport *_controllerSupport;
|
ControllerSupport *_controllerSupport;
|
||||||
Controller *_controller;
|
Controller *_controller;
|
||||||
id<EdgeDetectionDelegate> _edgeDelegate;
|
id<EdgeDetectionDelegate> _edgeDelegate;
|
||||||
|
NSMutableArray* _deadTouches;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const float EDGE_WIDTH = .1;
|
static const float EDGE_WIDTH = .05;
|
||||||
|
|
||||||
//static const float BUTTON_SIZE = 50;
|
//static const float BUTTON_SIZE = 50;
|
||||||
static const float BUTTON_DIST = 20;
|
static const float BUTTON_DIST = 20;
|
||||||
static float BUTTON_CENTER_X;
|
static float BUTTON_CENTER_X;
|
||||||
static float BUTTON_CENTER_Y;
|
static float BUTTON_CENTER_Y;
|
||||||
|
|
||||||
static const float D_PAD_DIST = 15;
|
static const float D_PAD_DIST = 10;
|
||||||
static float D_PAD_CENTER_X;
|
static float D_PAD_CENTER_X;
|
||||||
static float D_PAD_CENTER_Y;
|
static float D_PAD_CENTER_Y;
|
||||||
|
|
||||||
|
static const float DEAD_ZONE_PADDING = 15;
|
||||||
|
|
||||||
static const double STICK_CLICK_RATE = 100;
|
static const double STICK_CLICK_RATE = 100;
|
||||||
static const float STICK_DEAD_ZONE = .1;
|
static const float STICK_DEAD_ZONE = .1;
|
||||||
static float STICK_INNER_SIZE;
|
static float STICK_INNER_SIZE;
|
||||||
@@ -114,9 +119,23 @@ static float L3_Y;
|
|||||||
self = [self init];
|
self = [self init];
|
||||||
_view = view;
|
_view = view;
|
||||||
_controllerSupport = controllerSupport;
|
_controllerSupport = controllerSupport;
|
||||||
_controller = [[Controller alloc] init];
|
_controller = [controllerSupport getOscController];
|
||||||
_controller.playerIndex = 0;
|
|
||||||
_edgeDelegate = swipeDelegate;
|
_edgeDelegate = swipeDelegate;
|
||||||
|
_deadTouches = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
_iPad = (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad);
|
||||||
|
_controlArea = CGRectMake(0, 0, _view.frame.size.width, _view.frame.size.height);
|
||||||
|
if (_iPad)
|
||||||
|
{
|
||||||
|
// Cut down the control area on an iPad so the controls are more reachable
|
||||||
|
_controlArea.size.height = _view.frame.size.height / 2.0;
|
||||||
|
_controlArea.origin.y = _view.frame.size.height - _controlArea.size.height;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_controlArea.origin.x = _controlArea.size.width * EDGE_WIDTH;
|
||||||
|
_controlArea.size.width -= _controlArea.origin.x * 2;
|
||||||
|
}
|
||||||
|
|
||||||
_aButton = [CALayer layer];
|
_aButton = [CALayer layer];
|
||||||
_bButton = [CALayer layer];
|
_bButton = [CALayer layer];
|
||||||
@@ -139,7 +158,7 @@ static float L3_Y;
|
|||||||
_leftStick = [CALayer layer];
|
_leftStick = [CALayer layer];
|
||||||
_rightStick = [CALayer layer];
|
_rightStick = [CALayer layer];
|
||||||
_edge = [CALayer layer];
|
_edge = [CALayer layer];
|
||||||
|
|
||||||
[self setupEdgeDetection];
|
[self setupEdgeDetection];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
@@ -167,10 +186,10 @@ static float L3_Y;
|
|||||||
|
|
||||||
[self hideButtons];
|
[self hideButtons];
|
||||||
[self hideBumpers];
|
[self hideBumpers];
|
||||||
|
[self hideL3R3];
|
||||||
[self drawTriggers];
|
[self drawTriggers];
|
||||||
[self drawStartSelect];
|
[self drawStartSelect];
|
||||||
[self drawSticks];
|
[self drawSticks];
|
||||||
[self drawL3R3];
|
|
||||||
break;
|
break;
|
||||||
case OnScreenControlsLevelAutoGCExtendedGamepad:
|
case OnScreenControlsLevelAutoGCExtendedGamepad:
|
||||||
// GCExtendedGamepad is missing R3, L3, and select
|
// GCExtendedGamepad is missing R3, L3, and select
|
||||||
@@ -219,8 +238,8 @@ static float L3_Y;
|
|||||||
// Start with the default complex layout
|
// Start with the default complex layout
|
||||||
[self setupComplexControls];
|
[self setupComplexControls];
|
||||||
|
|
||||||
START_Y = _view.frame.size.height * .9;
|
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
SELECT_Y = _view.frame.size.height * .9;
|
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For GCGamepad controls we move triggers, start, and select
|
// For GCGamepad controls we move triggers, start, and select
|
||||||
@@ -229,7 +248,42 @@ static float L3_Y;
|
|||||||
// Start with the default complex layout
|
// Start with the default complex layout
|
||||||
[self setupComplexControls];
|
[self setupComplexControls];
|
||||||
|
|
||||||
// TODO
|
START_X = _controlArea.size.width * .6 + _controlArea.origin.x;
|
||||||
|
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
SELECT_X = _controlArea.size.width * .4 + _controlArea.origin.x;
|
||||||
|
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
L2_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
L2_X = _controlArea.size.width * .1 + _controlArea.origin.x;
|
||||||
|
|
||||||
|
R2_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
R2_X = _controlArea.size.width * .9 + _controlArea.origin.x;
|
||||||
|
|
||||||
|
if (_iPad) {
|
||||||
|
START_X = _controlArea.size.width * .75 + _controlArea.origin.x;
|
||||||
|
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
SELECT_X = _controlArea.size.width * .25 + _controlArea.origin.x;
|
||||||
|
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
// The analog sticks are kept closer to the sides on iPad
|
||||||
|
LS_CENTER_X = _controlArea.size.width * .18 + _controlArea.origin.x;
|
||||||
|
LS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
RS_CENTER_X = _controlArea.size.width * .82 + _controlArea.origin.x;
|
||||||
|
RS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
} else {
|
||||||
|
START_X = _controlArea.size.width * .6 + _controlArea.origin.x;
|
||||||
|
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
SELECT_X = _controlArea.size.width * .4 + _controlArea.origin.x;
|
||||||
|
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
LS_CENTER_X = _controlArea.size.width * .25 + _controlArea.origin.x;
|
||||||
|
LS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
RS_CENTER_X = _controlArea.size.width * .75 + _controlArea.origin.x;
|
||||||
|
RS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// For simple controls we move the triggers and buttons to the bottom
|
// For simple controls we move the triggers and buttons to the bottom
|
||||||
@@ -237,46 +291,59 @@ static float L3_Y;
|
|||||||
// Start with the default complex layout
|
// Start with the default complex layout
|
||||||
[self setupComplexControls];
|
[self setupComplexControls];
|
||||||
|
|
||||||
START_Y = _view.frame.size.height * .9;
|
START_X = _controlArea.size.width * .6 + _controlArea.origin.x;
|
||||||
SELECT_Y = _view.frame.size.height * .9;
|
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
SELECT_X = _controlArea.size.width * .4 + _controlArea.origin.x;
|
||||||
|
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
|
L2_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
L2_X = _controlArea.size.width * .1 + _controlArea.origin.x;
|
||||||
|
|
||||||
L1_Y = _view.frame.size.height * .7;
|
R2_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
L2_Y = _view.frame.size.height * .9;
|
R2_X = _controlArea.size.width * .9 + _controlArea.origin.x;
|
||||||
L2_X = _view.frame.size.width * .1;
|
|
||||||
R1_Y = _view.frame.size.height * .7;
|
|
||||||
R2_Y = _view.frame.size.height * .9;
|
|
||||||
R2_X = _view.frame.size.width * .9;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) setupComplexControls
|
- (void) setupComplexControls
|
||||||
{
|
{
|
||||||
D_PAD_CENTER_X = _view.frame.size.width * .15;
|
D_PAD_CENTER_X = _controlArea.size.width * .1 + _controlArea.origin.x;
|
||||||
D_PAD_CENTER_Y = _view.frame.size.height * .55;
|
D_PAD_CENTER_Y = _controlArea.size.height * .60 + _controlArea.origin.y;
|
||||||
BUTTON_CENTER_X = _view.frame.size.width * .85;
|
BUTTON_CENTER_X = _controlArea.size.width * .9 + _controlArea.origin.x;
|
||||||
BUTTON_CENTER_Y = _view.frame.size.height * .55;
|
BUTTON_CENTER_Y = _controlArea.size.height * .60 + _controlArea.origin.y;
|
||||||
|
|
||||||
LS_CENTER_X = _view.frame.size.width * .35;
|
if (_iPad)
|
||||||
LS_CENTER_Y = _view.frame.size.height * .75;
|
{
|
||||||
RS_CENTER_X = _view.frame.size.width * .65;
|
// The analog sticks are kept closer to the sides on iPad
|
||||||
RS_CENTER_Y = _view.frame.size.height * .75;
|
LS_CENTER_X = _controlArea.size.width * .22 + _controlArea.origin.x;
|
||||||
|
LS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
RS_CENTER_X = _controlArea.size.width * .77 + _controlArea.origin.x;
|
||||||
|
RS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LS_CENTER_X = _controlArea.size.width * .35 + _controlArea.origin.x;
|
||||||
|
LS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
RS_CENTER_X = _controlArea.size.width * .65 + _controlArea.origin.x;
|
||||||
|
RS_CENTER_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
|
}
|
||||||
|
|
||||||
START_X = _view.frame.size.width * .6;
|
START_X = _controlArea.size.width * .9 + _controlArea.origin.x;
|
||||||
START_Y = _view.frame.size.height * .1;
|
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
SELECT_X = _view.frame.size.width * .4;
|
SELECT_X = _controlArea.size.width * .1 + _controlArea.origin.x;
|
||||||
SELECT_Y = _view.frame.size.height * .1;
|
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
|
||||||
|
|
||||||
L1_X = _view.frame.size.width * .15;
|
L1_X = _controlArea.size.width * .1 + _controlArea.origin.x;
|
||||||
L1_Y = _view.frame.size.height * .27;
|
L1_Y = _controlArea.size.height * .27 + _controlArea.origin.y;
|
||||||
L2_X = _view.frame.size.width * .15;
|
L2_X = _controlArea.size.width * .1 + _controlArea.origin.x;
|
||||||
L2_Y = _view.frame.size.height * .1;
|
L2_Y = _controlArea.size.height * .1 + _controlArea.origin.y;
|
||||||
R1_X = _view.frame.size.width * .85;
|
R1_X = _controlArea.size.width * .9 + _controlArea.origin.x;
|
||||||
R1_Y = _view.frame.size.height * .27;
|
R1_Y = _controlArea.size.height * .27 + _controlArea.origin.y;
|
||||||
R2_X = _view.frame.size.width * .85;
|
R2_X = _controlArea.size.width * .9 + _controlArea.origin.x;
|
||||||
R2_Y = _view.frame.size.height * .1;
|
R2_Y = _controlArea.size.height * .1 + _controlArea.origin.y;
|
||||||
L3_X = _view.frame.size.width * .25;
|
L3_X = _controlArea.size.width * .25 + _controlArea.origin.x;
|
||||||
L3_Y = _view.frame.size.height * .75;
|
L3_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
R3_X = _view.frame.size.width * .75;
|
R3_X = _controlArea.size.width * .75 + _controlArea.origin.x;
|
||||||
R3_Y = _view.frame.size.height * .75;
|
R3_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) drawButtons {
|
- (void) drawButtons {
|
||||||
@@ -285,43 +352,43 @@ static float L3_Y;
|
|||||||
_aButton.contents = (id) aButtonImage.CGImage;
|
_aButton.contents = (id) aButtonImage.CGImage;
|
||||||
_aButton.frame = CGRectMake(BUTTON_CENTER_X - aButtonImage.size.width / 2, BUTTON_CENTER_Y + BUTTON_DIST, aButtonImage.size.width, aButtonImage.size.height);
|
_aButton.frame = CGRectMake(BUTTON_CENTER_X - aButtonImage.size.width / 2, BUTTON_CENTER_Y + BUTTON_DIST, aButtonImage.size.width, aButtonImage.size.height);
|
||||||
[_view.layer addSublayer:_aButton];
|
[_view.layer addSublayer:_aButton];
|
||||||
|
|
||||||
// create B button
|
// create B button
|
||||||
UIImage* bButtonImage = [UIImage imageNamed:@"BButton"];
|
UIImage* bButtonImage = [UIImage imageNamed:@"BButton"];
|
||||||
_bButton.frame = CGRectMake(BUTTON_CENTER_X + BUTTON_DIST, BUTTON_CENTER_Y - bButtonImage.size.height / 2, bButtonImage.size.width, bButtonImage.size.height);
|
_bButton.frame = CGRectMake(BUTTON_CENTER_X + BUTTON_DIST, BUTTON_CENTER_Y - bButtonImage.size.height / 2, bButtonImage.size.width, bButtonImage.size.height);
|
||||||
_bButton.contents = (id) bButtonImage.CGImage;
|
_bButton.contents = (id) bButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_bButton];
|
[_view.layer addSublayer:_bButton];
|
||||||
|
|
||||||
// create X Button
|
// create X Button
|
||||||
UIImage* xButtonImage = [UIImage imageNamed:@"XButton"];
|
UIImage* xButtonImage = [UIImage imageNamed:@"XButton"];
|
||||||
_xButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_DIST - xButtonImage.size.width, BUTTON_CENTER_Y - xButtonImage.size.height/ 2, xButtonImage.size.width, xButtonImage.size.height);
|
_xButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_DIST - xButtonImage.size.width, BUTTON_CENTER_Y - xButtonImage.size.height/ 2, xButtonImage.size.width, xButtonImage.size.height);
|
||||||
_xButton.contents = (id) xButtonImage.CGImage;
|
_xButton.contents = (id) xButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_xButton];
|
[_view.layer addSublayer:_xButton];
|
||||||
|
|
||||||
// create Y Button
|
// create Y Button
|
||||||
UIImage* yButtonImage = [UIImage imageNamed:@"YButton"];
|
UIImage* yButtonImage = [UIImage imageNamed:@"YButton"];
|
||||||
_yButton.frame = CGRectMake(BUTTON_CENTER_X - yButtonImage.size.width / 2, BUTTON_CENTER_Y - BUTTON_DIST - yButtonImage.size.height, yButtonImage.size.width, yButtonImage.size.height);
|
_yButton.frame = CGRectMake(BUTTON_CENTER_X - yButtonImage.size.width / 2, BUTTON_CENTER_Y - BUTTON_DIST - yButtonImage.size.height, yButtonImage.size.width, yButtonImage.size.height);
|
||||||
_yButton.contents = (id) yButtonImage.CGImage;
|
_yButton.contents = (id) yButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_yButton];
|
[_view.layer addSublayer:_yButton];
|
||||||
|
|
||||||
// create Down button
|
// create Down button
|
||||||
UIImage* downButtonImage = [UIImage imageNamed:@"DownButton"];
|
UIImage* downButtonImage = [UIImage imageNamed:@"DownButton"];
|
||||||
_downButton.frame = CGRectMake(D_PAD_CENTER_X - downButtonImage.size.width / 2, D_PAD_CENTER_Y + D_PAD_DIST, downButtonImage.size.width, downButtonImage.size.height);
|
_downButton.frame = CGRectMake(D_PAD_CENTER_X - downButtonImage.size.width / 2, D_PAD_CENTER_Y + D_PAD_DIST, downButtonImage.size.width, downButtonImage.size.height);
|
||||||
_downButton.contents = (id) downButtonImage.CGImage;
|
_downButton.contents = (id) downButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_downButton];
|
[_view.layer addSublayer:_downButton];
|
||||||
|
|
||||||
// create Right button
|
// create Right button
|
||||||
UIImage* rightButtonImage = [UIImage imageNamed:@"RightButton"];
|
UIImage* rightButtonImage = [UIImage imageNamed:@"RightButton"];
|
||||||
_rightButton.frame = CGRectMake(D_PAD_CENTER_X + D_PAD_DIST, D_PAD_CENTER_Y - rightButtonImage.size.height / 2, rightButtonImage.size.width, rightButtonImage.size.height);
|
_rightButton.frame = CGRectMake(D_PAD_CENTER_X + D_PAD_DIST, D_PAD_CENTER_Y - rightButtonImage.size.height / 2, rightButtonImage.size.width, rightButtonImage.size.height);
|
||||||
_rightButton.contents = (id) rightButtonImage.CGImage;
|
_rightButton.contents = (id) rightButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_rightButton];
|
[_view.layer addSublayer:_rightButton];
|
||||||
|
|
||||||
// create Up button
|
// create Up button
|
||||||
UIImage* upButtonImage = [UIImage imageNamed:@"UpButton"];
|
UIImage* upButtonImage = [UIImage imageNamed:@"UpButton"];
|
||||||
_upButton.frame = CGRectMake(D_PAD_CENTER_X - upButtonImage.size.width / 2, D_PAD_CENTER_Y - D_PAD_DIST - upButtonImage.size.height, upButtonImage.size.width, upButtonImage.size.height);
|
_upButton.frame = CGRectMake(D_PAD_CENTER_X - upButtonImage.size.width / 2, D_PAD_CENTER_Y - D_PAD_DIST - upButtonImage.size.height, upButtonImage.size.width, upButtonImage.size.height);
|
||||||
_upButton.contents = (id) upButtonImage.CGImage;
|
_upButton.contents = (id) upButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_upButton];
|
[_view.layer addSublayer:_upButton];
|
||||||
|
|
||||||
// create Left button
|
// create Left button
|
||||||
UIImage* leftButtonImage = [UIImage imageNamed:@"LeftButton"];
|
UIImage* leftButtonImage = [UIImage imageNamed:@"LeftButton"];
|
||||||
_leftButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_DIST - leftButtonImage.size.width, D_PAD_CENTER_Y - leftButtonImage.size.height / 2, leftButtonImage.size.width, leftButtonImage.size.height);
|
_leftButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_DIST - leftButtonImage.size.width, D_PAD_CENTER_Y - leftButtonImage.size.height / 2, leftButtonImage.size.width, leftButtonImage.size.height);
|
||||||
@@ -335,7 +402,7 @@ static float L3_Y;
|
|||||||
_startButton.frame = CGRectMake(START_X - startButtonImage.size.width / 2, START_Y - startButtonImage.size.height / 2, startButtonImage.size.width, startButtonImage.size.height);
|
_startButton.frame = CGRectMake(START_X - startButtonImage.size.width / 2, START_Y - startButtonImage.size.height / 2, startButtonImage.size.width, startButtonImage.size.height);
|
||||||
_startButton.contents = (id) startButtonImage.CGImage;
|
_startButton.contents = (id) startButtonImage.CGImage;
|
||||||
[_view.layer addSublayer:_startButton];
|
[_view.layer addSublayer:_startButton];
|
||||||
|
|
||||||
// create Select button
|
// create Select button
|
||||||
UIImage* selectButtonImage = [UIImage imageNamed:@"SelectButton"];
|
UIImage* selectButtonImage = [UIImage imageNamed:@"SelectButton"];
|
||||||
_selectButton.frame = CGRectMake(SELECT_X - selectButtonImage.size.width / 2, SELECT_Y - selectButtonImage.size.height / 2, selectButtonImage.size.width, selectButtonImage.size.height);
|
_selectButton.frame = CGRectMake(SELECT_X - selectButtonImage.size.width / 2, SELECT_Y - selectButtonImage.size.height / 2, selectButtonImage.size.width, selectButtonImage.size.height);
|
||||||
@@ -382,7 +449,7 @@ static float L3_Y;
|
|||||||
_leftStick.frame = CGRectMake(LS_CENTER_X - leftStickImage.size.width / 2, LS_CENTER_Y - leftStickImage.size.height / 2, leftStickImage.size.width, leftStickImage.size.height);
|
_leftStick.frame = CGRectMake(LS_CENTER_X - leftStickImage.size.width / 2, LS_CENTER_Y - leftStickImage.size.height / 2, leftStickImage.size.width, leftStickImage.size.height);
|
||||||
_leftStick.contents = (id) leftStickImage.CGImage;
|
_leftStick.contents = (id) leftStickImage.CGImage;
|
||||||
[_view.layer addSublayer:_leftStick];
|
[_view.layer addSublayer:_leftStick];
|
||||||
|
|
||||||
// create right analog stick
|
// create right analog stick
|
||||||
UIImage* rightStickBgImage = [UIImage imageNamed:@"StickOuter"];
|
UIImage* rightStickBgImage = [UIImage imageNamed:@"StickOuter"];
|
||||||
_rightStickBackground.frame = CGRectMake(RS_CENTER_X - rightStickBgImage.size.width / 2, RS_CENTER_Y - rightStickBgImage.size.height / 2, rightStickBgImage.size.width, rightStickBgImage.size.height);
|
_rightStickBackground.frame = CGRectMake(RS_CENTER_X - rightStickBgImage.size.width / 2, RS_CENTER_Y - rightStickBgImage.size.height / 2, rightStickBgImage.size.width, rightStickBgImage.size.height);
|
||||||
@@ -463,7 +530,7 @@ static float L3_Y;
|
|||||||
float lsMaxY = LS_CENTER_Y + STICK_OUTER_SIZE / 2;
|
float lsMaxY = LS_CENTER_Y + STICK_OUTER_SIZE / 2;
|
||||||
float lsMinX = LS_CENTER_X - STICK_OUTER_SIZE / 2;
|
float lsMinX = LS_CENTER_X - STICK_OUTER_SIZE / 2;
|
||||||
float lsMinY = LS_CENTER_Y - STICK_OUTER_SIZE / 2;
|
float lsMinY = LS_CENTER_Y - STICK_OUTER_SIZE / 2;
|
||||||
|
|
||||||
for (UITouch* touch in touches) {
|
for (UITouch* touch in touches) {
|
||||||
CGPoint touchLocation = [touch locationInView:_view];
|
CGPoint touchLocation = [touch locationInView:_view];
|
||||||
float xLoc = touchLocation.x;
|
float xLoc = touchLocation.x;
|
||||||
@@ -473,35 +540,55 @@ static float L3_Y;
|
|||||||
if (xLoc < lsMinX) xLoc = lsMinX;
|
if (xLoc < lsMinX) xLoc = lsMinX;
|
||||||
if (yLoc > lsMaxY) yLoc = lsMaxY;
|
if (yLoc > lsMaxY) yLoc = lsMaxY;
|
||||||
if (yLoc < lsMinY) yLoc = lsMinY;
|
if (yLoc < lsMinY) yLoc = lsMinY;
|
||||||
|
|
||||||
_leftStick.frame = CGRectMake(xLoc - STICK_INNER_SIZE / 2, yLoc - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
_leftStick.frame = CGRectMake(xLoc - STICK_INNER_SIZE / 2, yLoc - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
||||||
|
|
||||||
float xStickVal = (xLoc - LS_CENTER_X) / (lsMaxX - LS_CENTER_X);
|
float xStickVal = (xLoc - LS_CENTER_X) / (lsMaxX - LS_CENTER_X);
|
||||||
float yStickVal = (yLoc - LS_CENTER_Y) / (lsMaxY - LS_CENTER_Y);
|
float yStickVal = (yLoc - LS_CENTER_Y) / (lsMaxY - LS_CENTER_Y);
|
||||||
|
|
||||||
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
||||||
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
||||||
|
|
||||||
[_controllerSupport updateLeftStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
[_controllerSupport updateLeftStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||||
|
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if (touch == _rsTouch) {
|
} else if (touch == _rsTouch) {
|
||||||
if (xLoc > rsMaxX) xLoc = rsMaxX;
|
if (xLoc > rsMaxX) xLoc = rsMaxX;
|
||||||
if (xLoc < rsMinX) xLoc = rsMinX;
|
if (xLoc < rsMinX) xLoc = rsMinX;
|
||||||
if (yLoc > rsMaxY) yLoc = rsMaxY;
|
if (yLoc > rsMaxY) yLoc = rsMaxY;
|
||||||
if (yLoc < rsMinY) yLoc = rsMinY;
|
if (yLoc < rsMinY) yLoc = rsMinY;
|
||||||
|
|
||||||
_rightStick.frame = CGRectMake(xLoc - STICK_INNER_SIZE / 2, yLoc - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
_rightStick.frame = CGRectMake(xLoc - STICK_INNER_SIZE / 2, yLoc - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
|
||||||
|
|
||||||
float xStickVal = (xLoc - RS_CENTER_X) / (rsMaxX - RS_CENTER_X);
|
float xStickVal = (xLoc - RS_CENTER_X) / (rsMaxX - RS_CENTER_X);
|
||||||
float yStickVal = (yLoc - RS_CENTER_Y) / (rsMaxY - RS_CENTER_Y);
|
float yStickVal = (yLoc - RS_CENTER_Y) / (rsMaxY - RS_CENTER_Y);
|
||||||
|
|
||||||
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
|
||||||
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
|
||||||
|
|
||||||
[_controllerSupport updateRightStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
[_controllerSupport updateRightStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
|
||||||
|
|
||||||
updated = true;
|
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) {
|
} else if (touch == _aTouch) {
|
||||||
buttonTouch = true;
|
buttonTouch = true;
|
||||||
} else if (touch == _bTouch) {
|
} else if (touch == _bTouch) {
|
||||||
@@ -510,14 +597,6 @@ static float L3_Y;
|
|||||||
buttonTouch = true;
|
buttonTouch = true;
|
||||||
} else if (touch == _yTouch) {
|
} else if (touch == _yTouch) {
|
||||||
buttonTouch = true;
|
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) {
|
} else if (touch == _startTouch) {
|
||||||
buttonTouch = true;
|
buttonTouch = true;
|
||||||
} else if (touch == _selectTouch) {
|
} else if (touch == _selectTouch) {
|
||||||
@@ -535,11 +614,14 @@ static float L3_Y;
|
|||||||
} else if (touch == _r3Touch) {
|
} else if (touch == _r3Touch) {
|
||||||
buttonTouch = true;
|
buttonTouch = true;
|
||||||
}
|
}
|
||||||
|
if ([_deadTouches containsObject:touch]) {
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (updated) {
|
if (updated) {
|
||||||
[_controllerSupport updateFinished:_controller];
|
[_controllerSupport updateFinished:_controller];
|
||||||
}
|
}
|
||||||
return updated || buttonTouch;
|
return updated || buttonTouch;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)handleTouchDownEvent:touches {
|
- (BOOL)handleTouchDownEvent:touches {
|
||||||
@@ -566,19 +648,19 @@ static float L3_Y;
|
|||||||
updated = true;
|
updated = true;
|
||||||
} else if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
} else if ([_upButton.presentationLayer hitTest:touchLocation]) {
|
||||||
[_controllerSupport setButtonFlag:_controller flags:UP_FLAG];
|
[_controllerSupport setButtonFlag:_controller flags:UP_FLAG];
|
||||||
_upTouch = touch;
|
_dpadTouch = touch;
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
} else if ([_downButton.presentationLayer hitTest:touchLocation]) {
|
||||||
[_controllerSupport setButtonFlag:_controller flags:DOWN_FLAG];
|
[_controllerSupport setButtonFlag:_controller flags:DOWN_FLAG];
|
||||||
_downTouch = touch;
|
_dpadTouch = touch;
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
} else if ([_leftButton.presentationLayer hitTest:touchLocation]) {
|
||||||
[_controllerSupport setButtonFlag:_controller flags:LEFT_FLAG];
|
[_controllerSupport setButtonFlag:_controller flags:LEFT_FLAG];
|
||||||
_leftTouch = touch;
|
_dpadTouch = touch;
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
} else if ([_rightButton.presentationLayer hitTest:touchLocation]) {
|
||||||
[_controllerSupport setButtonFlag:_controller flags:RIGHT_FLAG];
|
[_controllerSupport setButtonFlag:_controller flags:RIGHT_FLAG];
|
||||||
_rightTouch = touch;
|
_dpadTouch = touch;
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if ([_startButton.presentationLayer hitTest:touchLocation]) {
|
} else if ([_startButton.presentationLayer hitTest:touchLocation]) {
|
||||||
[_controllerSupport setButtonFlag:_controller flags:PLAY_FLAG];
|
[_controllerSupport setButtonFlag:_controller flags:PLAY_FLAG];
|
||||||
@@ -653,6 +735,10 @@ static float L3_Y;
|
|||||||
} else if ([_edge.presentationLayer hitTest:touchLocation]) {
|
} else if ([_edge.presentationLayer hitTest:touchLocation]) {
|
||||||
_edgeTouch = touch;
|
_edgeTouch = touch;
|
||||||
}
|
}
|
||||||
|
if (!updated && !stickTouch && [self isInDeadZone:touch]) {
|
||||||
|
[_deadTouches addObject:touch];
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (updated) {
|
if (updated) {
|
||||||
[_controllerSupport updateFinished:_controller];
|
[_controllerSupport updateFinished:_controller];
|
||||||
@@ -680,21 +766,10 @@ static float L3_Y;
|
|||||||
[_controllerSupport clearButtonFlag:_controller flags:Y_FLAG];
|
[_controllerSupport clearButtonFlag:_controller flags:Y_FLAG];
|
||||||
_yTouch = nil;
|
_yTouch = nil;
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if (touch == _upTouch) {
|
} else if (touch == _dpadTouch) {
|
||||||
[_controllerSupport clearButtonFlag:_controller flags:UP_FLAG];
|
[_controllerSupport clearButtonFlag:_controller
|
||||||
_upTouch = nil;
|
flags:UP_FLAG | DOWN_FLAG | LEFT_FLAG | RIGHT_FLAG];
|
||||||
updated = true;
|
_dpadTouch = nil;
|
||||||
} 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;
|
|
||||||
updated = true;
|
updated = true;
|
||||||
} else if (touch == _startTouch) {
|
} else if (touch == _startTouch) {
|
||||||
[_controllerSupport clearButtonFlag:_controller flags:PLAY_FLAG];
|
[_controllerSupport clearButtonFlag:_controller flags:PLAY_FLAG];
|
||||||
@@ -744,15 +819,123 @@ static float L3_Y;
|
|||||||
touched = true;
|
touched = true;
|
||||||
} else if (touch == _edgeTouch) {
|
} else if (touch == _edgeTouch) {
|
||||||
_edgeTouch = nil;
|
_edgeTouch = nil;
|
||||||
if (![_edge.presentationLayer hitTest:[touch locationInView:_view]]) {
|
if ([touch locationInView:_view].x >= _view.frame.size.width / 4) {
|
||||||
[_edgeDelegate edgeSwiped];
|
[_edgeDelegate edgeSwiped];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ([_deadTouches containsObject:touch]) {
|
||||||
|
[_deadTouches removeObject:touch];
|
||||||
|
updated = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (updated) {
|
if (updated) {
|
||||||
[_controllerSupport updateFinished:_controller];
|
[_controllerSupport updateFinished:_controller];
|
||||||
}
|
}
|
||||||
|
|
||||||
return updated || touched;
|
return updated || touched;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL) isInDeadZone:(UITouch*) touch {
|
||||||
|
switch (_level) {
|
||||||
|
case OnScreenControlsLevelFull:
|
||||||
|
return [self isDpadDeadZone:touch]
|
||||||
|
|| [self isAbxyDeadZone:touch]
|
||||||
|
|| [self isTriggerDeadZone:touch]
|
||||||
|
|| [self isBumperDeadZone:touch]
|
||||||
|
|| [self isStartSelectDeadZone:touch];
|
||||||
|
case OnScreenControlsLevelSimple:
|
||||||
|
return [self isTriggerDeadZone:touch]
|
||||||
|
|| [self isStartSelectDeadZone:touch]
|
||||||
|
|| [self isL3R3DeadZone:touch];
|
||||||
|
case OnScreenControlsLevelAutoGCExtendedGamepad:
|
||||||
|
return [self isL3R3DeadZone:touch]
|
||||||
|
|| [self isStartSelectDeadZone:touch];
|
||||||
|
case OnScreenControlsLevelAutoGCGamepad:
|
||||||
|
return [self isTriggerDeadZone:touch]
|
||||||
|
|| [self isStartSelectDeadZone:touch];
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isDpadDeadZone:(UITouch*) touch {
|
||||||
|
return [self isDeadZone:touch
|
||||||
|
startX:_view.frame.origin.x
|
||||||
|
startY:_upButton.frame.origin.y
|
||||||
|
endX:_rightButton.frame.origin.x + _rightButton.frame.size.width
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isAbxyDeadZone:(UITouch*) touch {
|
||||||
|
return [self isDeadZone:touch
|
||||||
|
startX:_xButton.frame.origin.x
|
||||||
|
startY:_yButton.frame.origin.y
|
||||||
|
endX:_view.frame.origin.x + _view.frame.size.width
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isBumperDeadZone:(UITouch*) touch {
|
||||||
|
return [self isDeadZone:touch
|
||||||
|
startX:_view.frame.origin.x
|
||||||
|
startY:_l2Button.frame.origin.y + _l2Button.frame.size.height
|
||||||
|
endX:_l1Button.frame.origin.x + _l1Button.frame.size.width
|
||||||
|
endY:_upButton.frame.origin.y]
|
||||||
|
|| [self isDeadZone:touch
|
||||||
|
startX:_r2Button.frame.origin.x
|
||||||
|
startY:_r2Button.frame.origin.y + _r2Button.frame.size.height
|
||||||
|
endX:_view.frame.origin.x + _view.frame.size.width
|
||||||
|
endY:_yButton.frame.origin.y];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isTriggerDeadZone:(UITouch*) touch {
|
||||||
|
return [self isDeadZone:touch
|
||||||
|
startX:_view.frame.origin.x
|
||||||
|
startY:_l2Button.frame.origin.y
|
||||||
|
endX:_l2Button.frame.origin.x + _l2Button.frame.size.width
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height]
|
||||||
|
|| [self isDeadZone:touch
|
||||||
|
startX:_r2Button.frame.origin.x
|
||||||
|
startY:_r2Button.frame.origin.y
|
||||||
|
endX:_view.frame.origin.x + _view.frame.size.width
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isL3R3DeadZone:(UITouch*) touch {
|
||||||
|
return [self isDeadZone:touch
|
||||||
|
startX:_view.frame.origin.x
|
||||||
|
startY:_l3Button.frame.origin.y
|
||||||
|
endX:_view.frame.origin.x
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height]
|
||||||
|
|| [self isDeadZone:touch
|
||||||
|
startX:_r3Button.frame.origin.x
|
||||||
|
startY:_r3Button.frame.origin.y
|
||||||
|
endX:_view.frame.origin.x + _view.frame.size.width
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isStartSelectDeadZone:(UITouch*) touch {
|
||||||
|
return [self isDeadZone:touch
|
||||||
|
startX:_startButton.frame.origin.x
|
||||||
|
startY:_startButton.frame.origin.y
|
||||||
|
endX:_view.frame.origin.x + _view.frame.size.width
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height]
|
||||||
|
|| [self isDeadZone:touch
|
||||||
|
startX:_view.frame.origin.x
|
||||||
|
startY:_selectButton.frame.origin.y
|
||||||
|
endX:_selectButton.frame.origin.x + _selectButton.frame.size.width
|
||||||
|
endY:_view.frame.origin.y + _view.frame.size.height];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL) isDeadZone:(UITouch*) touch startX:(float)deadZoneStartX startY:(float)deadZoneStartY endX:(float)deadZoneEndX endY:(float)deadZoneEndY {
|
||||||
|
deadZoneStartX -= DEAD_ZONE_PADDING;
|
||||||
|
deadZoneStartY -= DEAD_ZONE_PADDING;
|
||||||
|
deadZoneEndX += DEAD_ZONE_PADDING;
|
||||||
|
deadZoneEndY += DEAD_ZONE_PADDING;
|
||||||
|
|
||||||
|
CGPoint touchLocation = [touch locationInView:_view];
|
||||||
|
return (touchLocation.x > deadZoneStartX && touchLocation.x < deadZoneEndX
|
||||||
|
&& touchLocation.y > deadZoneStartY && touchLocation.y < deadZoneEndY);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,10 +13,13 @@
|
|||||||
#import "ControllerSupport.h"
|
#import "ControllerSupport.h"
|
||||||
|
|
||||||
@implementation StreamView {
|
@implementation StreamView {
|
||||||
CGPoint touchLocation;
|
CGPoint touchLocation, originalLocation;
|
||||||
BOOL touchMoved;
|
BOOL touchMoved;
|
||||||
OnScreenControls* onScreenControls;
|
OnScreenControls* onScreenControls;
|
||||||
|
|
||||||
|
BOOL isDragging;
|
||||||
|
NSTimer* dragTimer;
|
||||||
|
|
||||||
float xDeltaFactor;
|
float xDeltaFactor;
|
||||||
float yDeltaFactor;
|
float yDeltaFactor;
|
||||||
float screenFactor;
|
float screenFactor;
|
||||||
@@ -32,7 +35,7 @@
|
|||||||
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate {
|
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate {
|
||||||
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate];
|
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate];
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan retrieveSettings].onscreenControls integerValue];
|
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan getSettings].onscreenControls integerValue];
|
||||||
|
|
||||||
if (level == OnScreenControlsLevelAuto) {
|
if (level == OnScreenControlsLevelAuto) {
|
||||||
[controllerSupport initAutoOnScreenControlMode:onScreenControls];
|
[controllerSupport initAutoOnScreenControlMode:onScreenControls];
|
||||||
@@ -43,17 +46,38 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (Boolean)isConfirmedMove:(CGPoint)currentPoint from:(CGPoint)originalPoint {
|
||||||
|
// Movements of greater than 20 pixels are considered confirmed
|
||||||
|
return hypotf(originalPoint.x - currentPoint.x, originalPoint.y - currentPoint.y) >= 20;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
Log(LOG_D, @"Touch down");
|
Log(LOG_D, @"Touch down");
|
||||||
if (![onScreenControls handleTouchDownEvent:touches]) {
|
if (![onScreenControls handleTouchDownEvent:touches]) {
|
||||||
UITouch *touch = [[event allTouches] anyObject];
|
UITouch *touch = [[event allTouches] anyObject];
|
||||||
touchLocation = [touch locationInView:self];
|
originalLocation = touchLocation = [touch locationInView:self];
|
||||||
touchMoved = false;
|
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 {
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
if (![onScreenControls handleTouchMovedEvent:touches]) {
|
if (![onScreenControls handleTouchMovedEvent:touches]) {
|
||||||
|
[dragTimer invalidate];
|
||||||
|
dragTimer = nil;
|
||||||
if ([[event allTouches] count] == 1) {
|
if ([[event allTouches] count] == 1) {
|
||||||
UITouch *touch = [[event allTouches] anyObject];
|
UITouch *touch = [[event allTouches] anyObject];
|
||||||
CGPoint currentLocation = [touch locationInView:self];
|
CGPoint currentLocation = [touch locationInView:self];
|
||||||
@@ -67,20 +91,32 @@
|
|||||||
deltaX *= xDeltaFactor * screenFactor;
|
deltaX *= xDeltaFactor * screenFactor;
|
||||||
deltaY *= yDeltaFactor * screenFactor;
|
deltaY *= yDeltaFactor * screenFactor;
|
||||||
|
|
||||||
LiSendMouseMoveEvent(deltaX, deltaY);
|
if (deltaX != 0 || deltaY != 0) {
|
||||||
|
LiSendMouseMoveEvent(deltaX, deltaY);
|
||||||
touchMoved = true;
|
touchLocation = currentLocation;
|
||||||
touchLocation = currentLocation;
|
|
||||||
|
// If we've moved far enough to confirm this wasn't just human/machine error,
|
||||||
|
// mark it as such.
|
||||||
|
if ([self isConfirmedMove:touchLocation from:originalLocation]) {
|
||||||
|
touchMoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if ([[event allTouches] count] == 2) {
|
} else if ([[event allTouches] count] == 2) {
|
||||||
CGPoint firstLocation = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:self];
|
CGPoint firstLocation = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:self];
|
||||||
CGPoint secondLocation = [[[[event allTouches] allObjects] objectAtIndex:1] locationInView:self];
|
CGPoint secondLocation = [[[[event allTouches] allObjects] objectAtIndex:1] locationInView:self];
|
||||||
|
|
||||||
CGPoint avgLocation = CGPointMake((firstLocation.x + secondLocation.x) / 2, (firstLocation.y + secondLocation.y) / 2);
|
CGPoint avgLocation = CGPointMake((firstLocation.x + secondLocation.x) / 2, (firstLocation.y + secondLocation.y) / 2);
|
||||||
if (touchLocation.y != avgLocation.y) {
|
if (touchLocation.y != avgLocation.y) {
|
||||||
LiSendScrollEvent(avgLocation.y - touchLocation.y);
|
LiSendScrollEvent(avgLocation.y - touchLocation.y);
|
||||||
}
|
}
|
||||||
touchMoved = true;
|
|
||||||
|
// If we've moved far enough to confirm this wasn't just human/machine error,
|
||||||
|
// mark it as such.
|
||||||
|
if ([self isConfirmedMove:firstLocation from:originalLocation]) {
|
||||||
|
touchMoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
touchLocation = avgLocation;
|
touchLocation = avgLocation;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,29 +126,49 @@
|
|||||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
Log(LOG_D, @"Touch up");
|
Log(LOG_D, @"Touch up");
|
||||||
if (![onScreenControls handleTouchUpEvent:touches]) {
|
if (![onScreenControls handleTouchUpEvent:touches]) {
|
||||||
|
[dragTimer invalidate];
|
||||||
|
dragTimer = nil;
|
||||||
if (!touchMoved) {
|
if (!touchMoved) {
|
||||||
if ([[event allTouches] count] == 2) {
|
if ([[event allTouches] count] == 2) {
|
||||||
Log(LOG_D, @"Sending right mouse button press");
|
Log(LOG_D, @"Sending right mouse button press");
|
||||||
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
||||||
|
|
||||||
// Wait 100 ms to simulate a real button press
|
// Wait 100 ms to simulate a real button press
|
||||||
usleep(100 * 1000);
|
usleep(100 * 1000);
|
||||||
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
||||||
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
Log(LOG_D, @"Sending left mouse button press");
|
if (!isDragging){
|
||||||
|
Log(LOG_D, @"Sending left mouse button press");
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||||
// Wait 100 ms to simulate a real button press
|
|
||||||
usleep(100 * 1000);
|
// Wait 100 ms to simulate a real button press
|
||||||
|
usleep(100 * 1000);
|
||||||
|
}
|
||||||
|
isDragging = false;
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (isDragging) {
|
||||||
|
isDragging = false;
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We we're moving from 2+ touches to 1. Synchronize the current position
|
||||||
|
// of the active finger so we don't jump unexpectedly on the next touchesMoved
|
||||||
|
// callback when finger 1 switches on us.
|
||||||
|
if ([[event allTouches] count] - [touches count] == 1) {
|
||||||
|
NSMutableSet *activeSet = [[NSMutableSet alloc] initWithCapacity:[[event allTouches] count]];
|
||||||
|
[activeSet unionSet:[event allTouches]];
|
||||||
|
[activeSet minusSet:touches];
|
||||||
|
touchLocation = [[activeSet anyObject] locationInView:self];
|
||||||
|
|
||||||
|
// Mark this touch as moved so we don't send a left mouse click if the user
|
||||||
|
// right clicks without moving their other finger.
|
||||||
|
touchMoved = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
<key>CFBundlePackageType</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>APPL</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>0.9.2</string>
|
<string>1.4.0</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>????</string>
|
<string>????</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
@@ -50,9 +50,9 @@
|
|||||||
<array>
|
<array>
|
||||||
<string>armv7</string>
|
<string>armv7</string>
|
||||||
</array>
|
</array>
|
||||||
<key>UIStatusBarHidden</key>
|
<key>UIRequiresFullScreen</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIStatusBarHidden~ipad</key>
|
<key>UIStatusBarHidden</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<array>
|
<array>
|
||||||
@@ -64,5 +64,7 @@
|
|||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
</array>
|
</array>
|
||||||
|
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||||||
|
<false/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -3,6 +3,6 @@
|
|||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>_XCCurrentVersionName</key>
|
<key>_XCCurrentVersionName</key>
|
||||||
<string>Moonlight v1.0.xcdatamodel</string>
|
<string>Moonlight v1.0-2.xcdatamodel</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
|
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="9057" systemVersion="15B42" minimumToolsVersion="Automatic">
|
||||||
|
<entity name="App" representedClassName="App" syncable="YES">
|
||||||
|
<attribute name="id" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="image" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES" syncable="YES"/>
|
||||||
|
<attribute name="name" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
|
<relationship name="host" maxCount="1" deletionRule="Nullify" destinationEntity="Host" inverseName="appList" inverseEntity="Host" syncable="YES"/>
|
||||||
|
</entity>
|
||||||
|
<entity name="Host" representedClassName="Host" syncable="YES">
|
||||||
|
<attribute name="address" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="externalAddress" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="localAddress" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="mac" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="name" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="pairState" optional="YES" attributeType="Integer 32" defaultValueString="0" syncable="YES"/>
|
||||||
|
<attribute name="uuid" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
|
<relationship name="appList" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="App" inverseName="host" inverseEntity="App" syncable="YES"/>
|
||||||
|
</entity>
|
||||||
|
<entity name="Settings" representedClassName="Settings" syncable="YES">
|
||||||
|
<attribute name="bitrate" attributeType="Integer 32" defaultValueString="10000" syncable="YES"/>
|
||||||
|
<attribute name="framerate" attributeType="Integer 32" defaultValueString="60" syncable="YES"/>
|
||||||
|
<attribute name="height" attributeType="Integer 32" defaultValueString="720" syncable="YES"/>
|
||||||
|
<attribute name="onscreenControls" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
|
||||||
|
<attribute name="uniqueId" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="width" attributeType="Integer 32" defaultValueString="1280" syncable="YES"/>
|
||||||
|
</entity>
|
||||||
|
<elements>
|
||||||
|
<element name="App" positionX="0" positionY="54" width="128" height="105"/>
|
||||||
|
<element name="Host" positionX="0" positionY="0" width="128" height="163"/>
|
||||||
|
<element name="Settings" positionX="0" positionY="0" width="128" height="135"/>
|
||||||
|
</elements>
|
||||||
|
</model>
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
|
||||||
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="8118.17" systemVersion="15A204h" minimumToolsVersion="Automatic">
|
<model userDefinedModelVersionIdentifier="" type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="9057" systemVersion="15B42" minimumToolsVersion="Automatic">
|
||||||
<entity name="App" representedClassName="App" syncable="YES">
|
<entity name="App" representedClassName="App" syncable="YES">
|
||||||
<attribute name="id" attributeType="String" syncable="YES"/>
|
<attribute name="id" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="image" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES" syncable="YES"/>
|
<attribute name="image" optional="YES" attributeType="Binary" allowsExternalBinaryDataStorage="YES" syncable="YES"/>
|
||||||
@@ -21,11 +21,12 @@
|
|||||||
<attribute name="framerate" attributeType="Integer 32" defaultValueString="60" syncable="YES"/>
|
<attribute name="framerate" attributeType="Integer 32" defaultValueString="60" syncable="YES"/>
|
||||||
<attribute name="height" attributeType="Integer 32" defaultValueString="720" syncable="YES"/>
|
<attribute name="height" attributeType="Integer 32" defaultValueString="720" syncable="YES"/>
|
||||||
<attribute name="onscreenControls" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
|
<attribute name="onscreenControls" attributeType="Integer 32" defaultValueString="1" syncable="YES"/>
|
||||||
|
<attribute name="uniqueId" optional="YES" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="width" attributeType="Integer 32" defaultValueString="1280" syncable="YES"/>
|
<attribute name="width" attributeType="Integer 32" defaultValueString="1280" syncable="YES"/>
|
||||||
</entity>
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="App" positionX="0" positionY="54" width="128" height="105"/>
|
<element name="App" positionX="0" positionY="54" width="128" height="105"/>
|
||||||
<element name="Host" positionX="0" positionY="0" width="128" height="163"/>
|
<element name="Host" positionX="0" positionY="0" width="128" height="163"/>
|
||||||
<element name="Settings" positionX="0" positionY="0" width="128" height="120"/>
|
<element name="Settings" positionX="0" positionY="0" width="128" height="135"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
||||||
@@ -7,20 +7,20 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "App.h"
|
#import "TemporaryApp.h"
|
||||||
#import "HttpManager.h"
|
#import "HttpManager.h"
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
|
|
||||||
@protocol AppAssetCallback <NSObject>
|
@protocol AppAssetCallback <NSObject>
|
||||||
|
|
||||||
- (void) receivedAssetForApp:(App*)app;
|
- (void) receivedAssetForApp:(TemporaryApp*)app;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface AppAssetManager : NSObject
|
@interface AppAssetManager : NSObject
|
||||||
|
|
||||||
- (id) initWithCallback:(id<AppAssetCallback>)callback;
|
- (id) initWithCallback:(id<AppAssetCallback>)callback;
|
||||||
- (void) retrieveAssetsFromHost:(Host*)host;
|
- (void) retrieveAssetsFromHost:(TemporaryHost*)host;
|
||||||
- (void) stopRetrieving;
|
- (void) stopRetrieving;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -28,8 +28,8 @@ static const int MAX_REQUEST_COUNT = 4;
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) retrieveAssetsFromHost:(Host*)host {
|
- (void) retrieveAssetsFromHost:(TemporaryHost*)host {
|
||||||
for (App* app in host.appList) {
|
for (TemporaryApp* app in host.appList) {
|
||||||
if (app.image == nil) {
|
if (app.image == nil) {
|
||||||
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
|
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
|
||||||
retriever.app = app;
|
retriever.app = app;
|
||||||
@@ -45,7 +45,7 @@ static const int MAX_REQUEST_COUNT = 4;
|
|||||||
[_opQueue cancelAllOperations];
|
[_opQueue cancelAllOperations];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) sendCallBackForApp:(App*)app {
|
- (void) sendCallBackForApp:(TemporaryApp*)app {
|
||||||
[_callback receivedAssetForApp:app];
|
[_callback receivedAssetForApp:app];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,14 +7,14 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
#import "App.h"
|
#import "TemporaryApp.h"
|
||||||
#import "AppAssetManager.h"
|
#import "AppAssetManager.h"
|
||||||
|
|
||||||
@interface AppAssetRetriever : NSOperation
|
@interface AppAssetRetriever : NSOperation
|
||||||
|
|
||||||
@property (nonatomic) Host* host;
|
@property (nonatomic) TemporaryHost* host;
|
||||||
@property (nonatomic) App* app;
|
@property (nonatomic) TemporaryApp* app;
|
||||||
@property (nonatomic) id<AppAssetCallback> callback;
|
@property (nonatomic) id<AppAssetCallback> callback;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#import "CryptoManager.h"
|
#import "CryptoManager.h"
|
||||||
#import "AppAssetResponse.h"
|
#import "AppAssetResponse.h"
|
||||||
#import "HttpRequest.h"
|
#import "HttpRequest.h"
|
||||||
|
#import "IdManager.h"
|
||||||
|
|
||||||
@implementation AppAssetRetriever
|
@implementation AppAssetRetriever
|
||||||
static const double RETRY_DELAY = 2; // seconds
|
static const double RETRY_DELAY = 2; // seconds
|
||||||
@@ -21,7 +22,7 @@ static const int MAX_ATTEMPTS = 5;
|
|||||||
int attempts = 0;
|
int attempts = 0;
|
||||||
while (![self isCancelled] && appImage == nil && attempts++ < MAX_ATTEMPTS) {
|
while (![self isCancelled] && appImage == nil && attempts++ < MAX_ATTEMPTS) {
|
||||||
|
|
||||||
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[CryptoManager getUniqueID] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
|
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[IdManager getUniqueId] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
|
||||||
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
|
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
|
||||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.id]]];
|
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.id]]];
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ static const int MAX_ATTEMPTS = 5;
|
|||||||
[self performSelectorOnMainThread:@selector(sendCallbackForApp:) withObject:self.app waitUntilDone:NO];
|
[self performSelectorOnMainThread:@selector(sendCallbackForApp:) withObject:self.app waitUntilDone:NO];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) sendCallbackForApp:(App*)app {
|
- (void) sendCallbackForApp:(TemporaryApp*)app {
|
||||||
[self.callback receivedAssetForApp:app];
|
[self.callback receivedAssetForApp:app];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
@interface AppListResponse : NSObject <Response>
|
@interface AppListResponse : NSObject <Response>
|
||||||
|
|
||||||
- (void)populateWithData:(NSData *)data;
|
- (void)populateWithData:(NSData *)data;
|
||||||
- (NSArray*) getAppList;
|
- (NSSet*) getAppList;
|
||||||
- (BOOL) isStatusOk;
|
- (BOOL) isStatusOk;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -7,23 +7,22 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "AppListResponse.h"
|
#import "AppListResponse.h"
|
||||||
#import "App.h"
|
#import "TemporaryApp.h"
|
||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
#import <libxml2/libxml/xmlreader.h>
|
#import <libxml2/libxml/xmlreader.h>
|
||||||
|
|
||||||
@implementation AppListResponse {
|
@implementation AppListResponse {
|
||||||
NSMutableArray* _appList;
|
NSMutableSet* _appList;
|
||||||
}
|
}
|
||||||
@synthesize data, statusCode, statusMessage;
|
@synthesize data, statusCode, statusMessage;
|
||||||
|
|
||||||
static const char* TAG_APP = "App";
|
static const char* TAG_APP = "App";
|
||||||
static const char* TAG_APP_TITLE = "AppTitle";
|
static const char* TAG_APP_TITLE = "AppTitle";
|
||||||
static const char* TAG_APP_ID = "ID";
|
static const char* TAG_APP_ID = "ID";
|
||||||
static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
|
||||||
|
|
||||||
- (void)populateWithData:(NSData *)xml {
|
- (void)populateWithData:(NSData *)xml {
|
||||||
self.data = xml;
|
self.data = xml;
|
||||||
_appList = [[NSMutableArray alloc] init];
|
_appList = [[NSMutableSet alloc] init];
|
||||||
[self parseData];
|
[self parseData];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,7 +59,6 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
|||||||
self.statusMessage = statusMsg;
|
self.statusMessage = statusMsg;
|
||||||
|
|
||||||
node = node->children;
|
node = node->children;
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
|
||||||
|
|
||||||
while (node != NULL) {
|
while (node != NULL) {
|
||||||
//Log(LOG_D, @"node: %s", node->name);
|
//Log(LOG_D, @"node: %s", node->name);
|
||||||
@@ -68,7 +66,6 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
|||||||
xmlNodePtr appInfoNode = node->xmlChildrenNode;
|
xmlNodePtr appInfoNode = node->xmlChildrenNode;
|
||||||
NSString* appName = @"";
|
NSString* appName = @"";
|
||||||
NSString* appId = nil;
|
NSString* appId = nil;
|
||||||
BOOL appIsRunning = NO;
|
|
||||||
while (appInfoNode != NULL) {
|
while (appInfoNode != NULL) {
|
||||||
if (!xmlStrcmp(appInfoNode->name, (xmlChar*)TAG_APP_TITLE)) {
|
if (!xmlStrcmp(appInfoNode->name, (xmlChar*)TAG_APP_TITLE)) {
|
||||||
xmlChar* nodeVal = xmlNodeListGetString(docPtr, appInfoNode->xmlChildrenNode, 1);
|
xmlChar* nodeVal = xmlNodeListGetString(docPtr, appInfoNode->xmlChildrenNode, 1);
|
||||||
@@ -84,22 +81,13 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
|||||||
appId = [[NSString alloc] initWithCString:(const char*)nodeVal encoding:NSUTF8StringEncoding];
|
appId = [[NSString alloc] initWithCString:(const char*)nodeVal encoding:NSUTF8StringEncoding];
|
||||||
xmlFree(nodeVal);
|
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;
|
appInfoNode = appInfoNode->next;
|
||||||
}
|
}
|
||||||
if (appId != nil) {
|
if (appId != nil) {
|
||||||
App* app = [dataMan createApp];
|
TemporaryApp* app = [[TemporaryApp alloc] init];
|
||||||
app.name = appName;
|
app.name = appName;
|
||||||
app.id = appId;
|
app.id = appId;
|
||||||
app.isRunning = appIsRunning;
|
|
||||||
[_appList addObject:app];
|
[_appList addObject:app];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,7 +97,7 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
|
|||||||
xmlFreeDoc(docPtr);
|
xmlFreeDoc(docPtr);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray*) getAppList {
|
- (NSSet*) getAppList {
|
||||||
return _appList;
|
return _appList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "MDNSManager.h"
|
#import "MDNSManager.h"
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
|
|
||||||
@protocol DiscoveryCallback <NSObject>
|
@protocol DiscoveryCallback <NSObject>
|
||||||
|
|
||||||
@@ -22,8 +22,8 @@
|
|||||||
- (void) startDiscovery;
|
- (void) startDiscovery;
|
||||||
- (void) stopDiscovery;
|
- (void) stopDiscovery;
|
||||||
- (void) stopDiscoveryBlocking;
|
- (void) stopDiscoveryBlocking;
|
||||||
- (BOOL) addHostToDiscovery:(Host*)host;
|
- (BOOL) addHostToDiscovery:(TemporaryHost*)host;
|
||||||
- (void) removeHostFromDiscovery:(Host*)host;
|
- (void) removeHostFromDiscovery:(TemporaryHost*)host;
|
||||||
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(Host*, NSString*))callback;
|
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(TemporaryHost*, NSString*))callback;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -13,10 +13,10 @@
|
|||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
#import "DiscoveryWorker.h"
|
#import "DiscoveryWorker.h"
|
||||||
#import "ServerInfoResponse.h"
|
#import "ServerInfoResponse.h"
|
||||||
|
#import "IdManager.h"
|
||||||
|
|
||||||
@implementation DiscoveryManager {
|
@implementation DiscoveryManager {
|
||||||
NSMutableArray* _hostQueue;
|
NSMutableArray* _hostQueue;
|
||||||
NSMutableArray* _discoveredHosts;
|
|
||||||
id<DiscoveryCallback> _callback;
|
id<DiscoveryCallback> _callback;
|
||||||
MDNSManager* _mdnsMan;
|
MDNSManager* _mdnsMan;
|
||||||
NSOperationQueue* _opQueue;
|
NSOperationQueue* _opQueue;
|
||||||
@@ -27,37 +27,44 @@
|
|||||||
|
|
||||||
- (id)initWithHosts:(NSArray *)hosts andCallback:(id<DiscoveryCallback>)callback {
|
- (id)initWithHosts:(NSArray *)hosts andCallback:(id<DiscoveryCallback>)callback {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
_hostQueue = [NSMutableArray arrayWithArray:hosts];
|
|
||||||
|
// Using addHostToDiscovery ensures no duplicates
|
||||||
|
// will make it into the list from the database
|
||||||
_callback = callback;
|
_callback = callback;
|
||||||
|
shouldDiscover = NO;
|
||||||
|
_hostQueue = [NSMutableArray array];
|
||||||
|
for (TemporaryHost* host in hosts)
|
||||||
|
{
|
||||||
|
[self addHostToDiscovery:host];
|
||||||
|
}
|
||||||
|
[_callback updateAllHosts:_hostQueue];
|
||||||
|
|
||||||
_opQueue = [[NSOperationQueue alloc] init];
|
_opQueue = [[NSOperationQueue alloc] init];
|
||||||
_mdnsMan = [[MDNSManager alloc] initWithCallback:self];
|
_mdnsMan = [[MDNSManager alloc] initWithCallback:self];
|
||||||
[CryptoManager generateKeyPairUsingSSl];
|
[CryptoManager generateKeyPairUsingSSl];
|
||||||
_uniqueId = [CryptoManager getUniqueID];
|
_uniqueId = [IdManager getUniqueId];
|
||||||
_cert = [CryptoManager readCertFromFile];
|
_cert = [CryptoManager readCertFromFile];
|
||||||
shouldDiscover = NO;
|
|
||||||
return self;
|
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];
|
HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
|
||||||
ServerInfoResponse* serverInfoResponse = [[ServerInfoResponse alloc] init];
|
ServerInfoResponse* serverInfoResponse = [[ServerInfoResponse alloc] init];
|
||||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest] fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
|
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest] fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
|
||||||
|
|
||||||
Host* host = nil;
|
TemporaryHost* host = nil;
|
||||||
if ([serverInfoResponse isStatusOk]) {
|
if ([serverInfoResponse isStatusOk]) {
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
host = [[TemporaryHost alloc] init];
|
||||||
host = [dataMan createHost];
|
|
||||||
host.activeAddress = host.address = hostAddress;
|
host.activeAddress = host.address = hostAddress;
|
||||||
host.online = YES;
|
host.online = YES;
|
||||||
[serverInfoResponse populateHost:host];
|
[serverInfoResponse populateHost:host];
|
||||||
if (![self addHostToDiscovery:host]) {
|
if (![self addHostToDiscovery:host]) {
|
||||||
[dataMan removeHost:host];
|
|
||||||
callback(nil, @"Host already added");
|
callback(nil, @"Host already added");
|
||||||
} else {
|
} else {
|
||||||
callback(host, nil);
|
callback(host, nil);
|
||||||
}
|
}
|
||||||
} else {
|
} 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.");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -66,7 +73,7 @@
|
|||||||
Log(LOG_I, @"Starting discovery");
|
Log(LOG_I, @"Starting discovery");
|
||||||
shouldDiscover = YES;
|
shouldDiscover = YES;
|
||||||
[_mdnsMan searchForHosts];
|
[_mdnsMan searchForHosts];
|
||||||
for (Host* host in _hostQueue) {
|
for (TemporaryHost* host in _hostQueue) {
|
||||||
[_opQueue addOperation:[self createWorkerForHost:host]];
|
[_opQueue addOperation:[self createWorkerForHost:host]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -87,18 +94,46 @@
|
|||||||
Log(LOG_I, @"All discovery workers stopped");
|
Log(LOG_I, @"All discovery workers stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL) addHostToDiscovery:(Host *)host {
|
- (BOOL) addHostToDiscovery:(TemporaryHost *)host {
|
||||||
if (host.uuid.length > 0 && ![self isHostInDiscovery:host]) {
|
if (host.uuid.length == 0) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
TemporaryHost *existingHost = [self getHostInDiscovery:host.uuid];
|
||||||
|
if (existingHost != nil) {
|
||||||
|
// Update address of existing host
|
||||||
|
if (host.address != nil) {
|
||||||
|
existingHost.address = host.address;
|
||||||
|
}
|
||||||
|
if (host.localAddress != nil) {
|
||||||
|
existingHost.localAddress = host.localAddress;
|
||||||
|
}
|
||||||
|
if (host.externalAddress != nil) {
|
||||||
|
existingHost.externalAddress = host.externalAddress;
|
||||||
|
}
|
||||||
|
existingHost.activeAddress = host.activeAddress;
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// If we were added without an explicit address,
|
||||||
|
// populate it from our other available addresses
|
||||||
|
if (host.address == nil) {
|
||||||
|
if (host.externalAddress != nil) {
|
||||||
|
host.address = host.externalAddress;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
host.address = host.localAddress;
|
||||||
|
}
|
||||||
|
}
|
||||||
[_hostQueue addObject:host];
|
[_hostQueue addObject:host];
|
||||||
if (shouldDiscover) {
|
if (shouldDiscover) {
|
||||||
[_opQueue addOperation:[self createWorkerForHost:host]];
|
[_opQueue addOperation:[self createWorkerForHost:host]];
|
||||||
}
|
}
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
return NO;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeHostFromDiscovery:(Host *)host {
|
- (void) removeHostFromDiscovery:(TemporaryHost *)host {
|
||||||
for (DiscoveryWorker* worker in [_opQueue operations]) {
|
for (DiscoveryWorker* worker in [_opQueue operations]) {
|
||||||
if ([worker getHost] == host) {
|
if ([worker getHost] == host) {
|
||||||
[worker cancel];
|
[worker cancel];
|
||||||
@@ -110,9 +145,8 @@
|
|||||||
// Override from MDNSCallback
|
// Override from MDNSCallback
|
||||||
- (void)updateHosts:(NSArray *)hosts {
|
- (void)updateHosts:(NSArray *)hosts {
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
|
||||||
// Discover the hosts before adding to eliminate duplicates
|
// 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);
|
Log(LOG_I, @"Found host through MDNS: %@:", host.name);
|
||||||
// Since this is on a background thread, we do not need to use the opQueue
|
// Since this is on a background thread, we do not need to use the opQueue
|
||||||
DiscoveryWorker* worker = (DiscoveryWorker*)[self createWorkerForHost:host];
|
DiscoveryWorker* worker = (DiscoveryWorker*)[self createWorkerForHost:host];
|
||||||
@@ -122,24 +156,22 @@
|
|||||||
[_callback updateAllHosts:_hostQueue];
|
[_callback updateAllHosts:_hostQueue];
|
||||||
} else {
|
} else {
|
||||||
Log(LOG_I, @"Not adding host to discovery: %@", host.name);
|
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++) {
|
for (int i = 0; i < _hostQueue.count; i++) {
|
||||||
Host* discoveredHost = [_hostQueue objectAtIndex:i];
|
TemporaryHost* discoveredHost = [_hostQueue objectAtIndex:i];
|
||||||
if (discoveredHost.uuid.length > 0 && [discoveredHost.uuid isEqualToString:host.uuid]) {
|
if (discoveredHost.uuid.length > 0 && [discoveredHost.uuid isEqualToString:uuidString]) {
|
||||||
return YES;
|
return discoveredHost;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return NO;
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSOperation*) createWorkerForHost:(Host*)host {
|
- (NSOperation*) createWorkerForHost:(TemporaryHost*)host {
|
||||||
DiscoveryWorker* worker = [[DiscoveryWorker alloc] initWithHost:host uniqueId:_uniqueId cert:_cert];
|
DiscoveryWorker* worker = [[DiscoveryWorker alloc] initWithHost:host uniqueId:_uniqueId cert:_cert];
|
||||||
return worker;
|
return worker;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,12 +7,12 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
|
|
||||||
@interface DiscoveryWorker : NSOperation
|
@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;
|
- (void) discoverHost;
|
||||||
- (Host*) getHost;
|
- (TemporaryHost*) getHost;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,16 +11,17 @@
|
|||||||
#import "HttpManager.h"
|
#import "HttpManager.h"
|
||||||
#import "ServerInfoResponse.h"
|
#import "ServerInfoResponse.h"
|
||||||
#import "HttpRequest.h"
|
#import "HttpRequest.h"
|
||||||
|
#import "DataManager.h"
|
||||||
|
|
||||||
@implementation DiscoveryWorker {
|
@implementation DiscoveryWorker {
|
||||||
Host* _host;
|
TemporaryHost* _host;
|
||||||
NSString* _uniqueId;
|
NSString* _uniqueId;
|
||||||
NSData* _cert;
|
NSData* _cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const float POLL_RATE = 2.0f; // Poll every 2 seconds
|
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];
|
self = [super init];
|
||||||
_host = host;
|
_host = host;
|
||||||
_uniqueId = uniqueId;
|
_uniqueId = uniqueId;
|
||||||
@@ -28,7 +29,7 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (Host*) getHost {
|
- (TemporaryHost*) getHost {
|
||||||
return _host;
|
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]);
|
Log(LOG_D, @"%@ has %d unique addresses", _host.name, [addresses count]);
|
||||||
|
|
||||||
for (NSString *address in addresses) {
|
// Give the PC 3 tries to respond before declaring it offline
|
||||||
if (self.cancelled) {
|
for (int i = 0; i < 3; i++) {
|
||||||
// Get out without updating the status because
|
for (NSString *address in addresses) {
|
||||||
// it might not have finished checking the various
|
if (self.cancelled) {
|
||||||
// addresses
|
// Get out without updating the status because
|
||||||
return;
|
// 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) {
|
if (receivedResponse) {
|
||||||
_host.activeAddress = address;
|
Log(LOG_I, @"Received serverinfo response on try %d", i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else {
|
||||||
|
// Wait for one second then retry
|
||||||
|
[NSThread sleepForTimeInterval:1];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
_host.online = receivedResponse;
|
_host.online = receivedResponse;
|
||||||
@@ -125,7 +143,6 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
|
|||||||
if ([response isStatusOk]) {
|
if ([response isStatusOk]) {
|
||||||
// If the response is from a different host then do not update this host
|
// 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])) {
|
if ((_host.uuid == nil || [[response getStringTag:TAG_UNIQUE_ID] isEqualToString:_host.uuid])) {
|
||||||
[response populateHost:_host];
|
|
||||||
return YES;
|
return YES;
|
||||||
} else {
|
} else {
|
||||||
Log(LOG_I, @"Received response from incorrect host: %@ expected: %@", [response getStringTag:TAG_UNIQUE_ID], _host.uuid);
|
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 <Foundation/Foundation.h>
|
||||||
#import "Host.h"
|
|
||||||
#import "HttpResponse.h"
|
#import "HttpResponse.h"
|
||||||
#import "HttpRequest.h"
|
#import "HttpRequest.h"
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#import "HttpManager.h"
|
#import "HttpManager.h"
|
||||||
#import "HttpRequest.h"
|
#import "HttpRequest.h"
|
||||||
#import "CryptoManager.h"
|
#import "CryptoManager.h"
|
||||||
#import "App.h"
|
#import "TemporaryApp.h"
|
||||||
|
|
||||||
#include <libxml2/libxml/xmlreader.h>
|
#include <libxml2/libxml/xmlreader.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -100,8 +100,8 @@ static const NSString* HTTPS_PORT = @"47984";
|
|||||||
NSURL* url = [[NSURL alloc] initWithString:urlString];
|
NSURL* url = [[NSURL alloc] initWithString:urlString];
|
||||||
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
|
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
|
||||||
if (normalTimeout) {
|
if (normalTimeout) {
|
||||||
// Timeout the request after 5 seconds
|
// Timeout the request after 7 seconds
|
||||||
[request setTimeoutInterval:5];
|
[request setTimeoutInterval:7];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Timeout the request after 60 seconds
|
// Timeout the request after 60 seconds
|
||||||
|
|||||||
@@ -7,7 +7,6 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "Host.h"
|
|
||||||
|
|
||||||
static NSString* TAG_STATUS_CODE = @"status_code";
|
static NSString* TAG_STATUS_CODE = @"status_code";
|
||||||
static NSString* TAG_STATUS_MESSAGE = @"status_message";
|
static NSString* TAG_STATUS_MESSAGE = @"status_message";
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "HttpResponse.h"
|
#import "HttpResponse.h"
|
||||||
#import "App.h"
|
#import "TemporaryApp.h"
|
||||||
#import <libxml2/libxml/xmlreader.h>
|
#import <libxml2/libxml/xmlreader.h>
|
||||||
|
|
||||||
@implementation HttpResponse {
|
@implementation HttpResponse {
|
||||||
|
|||||||
@@ -7,8 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "MDNSManager.h"
|
#import "MDNSManager.h"
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
#import "DataManager.h"
|
|
||||||
|
|
||||||
@implementation MDNSManager {
|
@implementation MDNSManager {
|
||||||
NSNetServiceBrowser* mDNSBrowser;
|
NSNetServiceBrowser* mDNSBrowser;
|
||||||
@@ -47,12 +46,11 @@ static NSString* NV_SERVICE_TYPE = @"_nvstream._tcp";
|
|||||||
|
|
||||||
- (NSArray*) getFoundHosts {
|
- (NSArray*) getFoundHosts {
|
||||||
NSMutableArray* hosts = [[NSMutableArray alloc] init];
|
NSMutableArray* hosts = [[NSMutableArray alloc] init];
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
|
||||||
for (NSNetService* service in services) {
|
for (NSNetService* service in services) {
|
||||||
if (service.hostName != nil) {
|
if (service.hostName != nil) {
|
||||||
Host* host = [dataMan createHost];
|
TemporaryHost* host = [[TemporaryHost alloc] init];
|
||||||
host.activeAddress = host.address = service.hostName;
|
host.activeAddress = host.localAddress = service.hostName;
|
||||||
host.name = host.address;
|
host.name = service.hostName;
|
||||||
[hosts addObject:host];
|
[hosts addObject:host];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,6 +22,6 @@
|
|||||||
- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id<PairCallback>)callback;
|
- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id<PairCallback>)callback;
|
||||||
- (NSString*) generatePIN;
|
- (NSString*) generatePIN;
|
||||||
- (NSData*) saltPIN:(NSString*)PIN;
|
- (NSData*) saltPIN:(NSString*)PIN;
|
||||||
- (void) initiatePair;
|
- (void) initiatePair:(int)serverMajorVersion;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -38,17 +38,24 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if ([serverInfoResp isStatusOk]) {
|
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."];
|
[_callback pairFailed:@"You must stop streaming before attempting to pair."];
|
||||||
} else if (![[serverInfoResp getStringTag:@"PairStatus"] isEqual:@"1"]) {
|
} 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 {
|
} else {
|
||||||
[_callback alreadyPaired];
|
[_callback alreadyPaired];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) initiatePair {
|
- (void) initiatePair:(int)serverMajorVersion {
|
||||||
|
Log(LOG_I, @"Pairing with generation %d server", serverMajorVersion);
|
||||||
|
|
||||||
NSString* PIN = [self generatePIN];
|
NSString* PIN = [self generatePIN];
|
||||||
NSData* salt = [self saltPIN:PIN];
|
NSData* salt = [self saltPIN:PIN];
|
||||||
Log(LOG_I, @"PIN: %@, saltedPIN: %@", PIN, salt);
|
Log(LOG_I, @"PIN: %@, saltedPIN: %@", PIN, salt);
|
||||||
@@ -61,15 +68,29 @@
|
|||||||
}
|
}
|
||||||
NSInteger pairedStatus;
|
NSInteger pairedStatus;
|
||||||
if (![pairResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
|
if (![pairResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
|
||||||
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
|
|
||||||
[_callback pairFailed:@"Pairing was declined by the target."];
|
[_callback pairFailed:@"Pairing was declined by the target."];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSString* plainCert = [pairResp getStringTag:@"plaincert"];
|
NSString* plainCert = [pairResp getStringTag:@"plaincert"];
|
||||||
|
if ([plainCert length] == 0) {
|
||||||
|
[_callback pairFailed:@"Another pairing attempt is already in progress."];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
CryptoManager* cryptoMan = [[CryptoManager alloc] init];
|
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* randomChallenge = [Utils randomBytes:16];
|
||||||
NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey];
|
NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey];
|
||||||
@@ -88,11 +109,18 @@
|
|||||||
NSData* encServerChallengeResp = [Utils hexToBytes:[challengeResp getStringTag:@"challengeresponse"]];
|
NSData* encServerChallengeResp = [Utils hexToBytes:[challengeResp getStringTag:@"challengeresponse"]];
|
||||||
NSData* decServerChallengeResp = [cryptoMan aesDecrypt:encServerChallengeResp withKey:aesKey];
|
NSData* decServerChallengeResp = [cryptoMan aesDecrypt:encServerChallengeResp withKey:aesKey];
|
||||||
|
|
||||||
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, 20)];
|
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, hashLength)];
|
||||||
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(20, 16)];
|
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(hashLength, 16)];
|
||||||
|
|
||||||
NSData* clientSecret = [Utils randomBytes: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];
|
NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey];
|
||||||
|
|
||||||
HttpResponse* secretResp = [[HttpResponse alloc] init];
|
HttpResponse* secretResp = [[HttpResponse alloc] init];
|
||||||
@@ -116,7 +144,14 @@
|
|||||||
return;
|
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]) {
|
if (![serverChallengeRespHash isEqual:serverResponse]) {
|
||||||
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
|
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
|
||||||
[_callback pairFailed:@"Incorrect PIN"];
|
[_callback pairFailed:@"Incorrect PIN"];
|
||||||
|
|||||||
@@ -7,6 +7,7 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "HttpResponse.h"
|
#import "HttpResponse.h"
|
||||||
|
#import "TemporaryHost.h"
|
||||||
|
|
||||||
#define TAG_HOSTNAME @"hostname"
|
#define TAG_HOSTNAME @"hostname"
|
||||||
#define TAG_EXTERNAL_IP @"ExternalIP"
|
#define TAG_EXTERNAL_IP @"ExternalIP"
|
||||||
@@ -14,11 +15,13 @@
|
|||||||
#define TAG_UNIQUE_ID @"uniqueid"
|
#define TAG_UNIQUE_ID @"uniqueid"
|
||||||
#define TAG_MAC_ADDRESS @"mac"
|
#define TAG_MAC_ADDRESS @"mac"
|
||||||
#define TAG_PAIR_STATUS @"PairStatus"
|
#define TAG_PAIR_STATUS @"PairStatus"
|
||||||
|
#define TAG_STATE @"state"
|
||||||
|
#define TAG_CURRENT_GAME @"currentgame"
|
||||||
|
|
||||||
@interface ServerInfoResponse : HttpResponse <Response>
|
@interface ServerInfoResponse : HttpResponse <Response>
|
||||||
|
|
||||||
- (void) populateWithData:(NSData *)data;
|
- (void) populateWithData:(NSData *)data;
|
||||||
- (void) populateHost:(Host*)host;
|
- (void) populateHost:(TemporaryHost*)host;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|||||||
@@ -17,12 +17,21 @@
|
|||||||
[super parseData];
|
[super parseData];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) populateHost:(Host*)host {
|
- (void) populateHost:(TemporaryHost*)host {
|
||||||
host.name = [[self getStringTag:TAG_HOSTNAME] trim];
|
host.name = [[self getStringTag:TAG_HOSTNAME] trim];
|
||||||
host.externalAddress = [[self getStringTag:TAG_EXTERNAL_IP] trim];
|
host.externalAddress = [[self getStringTag:TAG_EXTERNAL_IP] trim];
|
||||||
host.localAddress = [[self getStringTag:TAG_LOCAL_IP] trim];
|
host.localAddress = [[self getStringTag:TAG_LOCAL_IP] trim];
|
||||||
host.uuid = [[self getStringTag:TAG_UNIQUE_ID] trim];
|
host.uuid = [[self getStringTag:TAG_UNIQUE_ID] trim];
|
||||||
host.mac = [[self getStringTag:TAG_MAC_ADDRESS] 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;
|
NSInteger pairStatus;
|
||||||
if ([self getIntTag:TAG_PAIR_STATUS value:&pairStatus]) {
|
if ([self getIntTag:TAG_PAIR_STATUS value:&pairStatus]) {
|
||||||
|
|||||||
@@ -7,10 +7,10 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
|
|
||||||
@interface WakeOnLanManager : NSObject
|
@interface WakeOnLanManager : NSObject
|
||||||
|
|
||||||
+ (void) wakeHost:(Host*)host;
|
+ (void) wakeHost:(TemporaryHost*)host;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -12,51 +12,86 @@
|
|||||||
#import <sys/socket.h>
|
#import <sys/socket.h>
|
||||||
#import <netinet/in.h>
|
#import <netinet/in.h>
|
||||||
#import <arpa/inet.h>
|
#import <arpa/inet.h>
|
||||||
|
#import <netdb.h>
|
||||||
|
|
||||||
@implementation WakeOnLanManager
|
@implementation WakeOnLanManager
|
||||||
|
|
||||||
static const int numPorts = 5;
|
static const int numPorts = 5;
|
||||||
static const int ports[numPorts] = {7, 9, 47998, 47999, 48000};
|
static const int ports[numPorts] = {7, 9, 47998, 47999, 48000};
|
||||||
|
|
||||||
+ (void) wakeHost:(Host*)host {
|
+ (void) populateAddress:(struct sockaddr_storage*)addr withPort:(unsigned short)port {
|
||||||
NSData* wolPayload = [WakeOnLanManager createPayload:host];
|
if (addr->ss_family == AF_INET) {
|
||||||
CFDataRef dataPayload = CFDataCreate(kCFAllocatorDefault, [wolPayload bytes], [wolPayload length]);
|
struct sockaddr_in *sin = (struct sockaddr_in*)addr;
|
||||||
CFSocketRef wolSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, NULL, NULL);
|
sin->sin_port = htons(port);
|
||||||
if (!wolSocket) {
|
|
||||||
CFRelease(dataPayload);
|
|
||||||
Log(LOG_E, @"Failed to create WOL socket");
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
Log(LOG_I, @"WOL socket created");
|
else if (addr->ss_family == AF_INET6) {
|
||||||
|
struct sockaddr_in6 *sin6 = (struct sockaddr_in6*)addr;
|
||||||
struct sockaddr_in addr;
|
sin6->sin6_port = htons(port);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
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];
|
NSMutableData* payload = [[NSMutableData alloc] initWithCapacity:102];
|
||||||
|
|
||||||
// 6 bytes of FF
|
// 6 bytes of FF
|
||||||
|
|||||||
@@ -14,20 +14,19 @@
|
|||||||
|
|
||||||
- (void) connectionStarted;
|
- (void) connectionStarted;
|
||||||
- (void) connectionTerminated:(long)errorCode;
|
- (void) connectionTerminated:(long)errorCode;
|
||||||
- (void) stageStarting:(char*)stageName;
|
- (void) stageStarting:(const char*)stageName;
|
||||||
- (void) stageComplete:(char*)stageName;
|
- (void) stageComplete:(const char*)stageName;
|
||||||
- (void) stageFailed:(char*)stageName withError:(long)errorCode;
|
- (void) stageFailed:(const char*)stageName withError:(long)errorCode;
|
||||||
- (void) launchFailed:(NSString*)message;
|
- (void) launchFailed:(NSString*)message;
|
||||||
- (void) displayMessage:(char*)message;
|
- (void) displayMessage:(const char*)message;
|
||||||
- (void) displayTransientMessage:(char*)message;
|
- (void) displayTransientMessage:(const char*)message;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface Connection : NSOperation <NSStreamDelegate>
|
@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) terminate;
|
||||||
-(void) terminateInternal;
|
|
||||||
-(void) main;
|
-(void) main;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -10,19 +10,20 @@
|
|||||||
|
|
||||||
#import <AudioUnit/AudioUnit.h>
|
#import <AudioUnit/AudioUnit.h>
|
||||||
#import <AVFoundation/AVFoundation.h>
|
#import <AVFoundation/AVFoundation.h>
|
||||||
|
#import <VideoToolbox/VideoToolbox.h>
|
||||||
|
|
||||||
#include "Limelight.h"
|
#include "Limelight.h"
|
||||||
#include "opus.h"
|
#include "opus.h"
|
||||||
|
|
||||||
@implementation Connection {
|
@implementation Connection {
|
||||||
const char* _host;
|
SERVER_INFORMATION _serverInfo;
|
||||||
STREAM_CONFIGURATION _streamConfig;
|
STREAM_CONFIGURATION _streamConfig;
|
||||||
CONNECTION_LISTENER_CALLBACKS _clCallbacks;
|
CONNECTION_LISTENER_CALLBACKS _clCallbacks;
|
||||||
DECODER_RENDERER_CALLBACKS _drCallbacks;
|
DECODER_RENDERER_CALLBACKS _drCallbacks;
|
||||||
AUDIO_RENDERER_CALLBACKS _arCallbacks;
|
AUDIO_RENDERER_CALLBACKS _arCallbacks;
|
||||||
int _serverMajorVersion;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static NSLock* initLock;
|
||||||
static OpusDecoder *opusDecoder;
|
static OpusDecoder *opusDecoder;
|
||||||
static id<ConnectionCallbacks> _callbacks;
|
static id<ConnectionCallbacks> _callbacks;
|
||||||
|
|
||||||
@@ -45,6 +46,12 @@ static int audioBufferQueueLength;
|
|||||||
static AudioComponentInstance audioUnit;
|
static AudioComponentInstance audioUnit;
|
||||||
static VideoDecoderRenderer* renderer;
|
static VideoDecoderRenderer* renderer;
|
||||||
|
|
||||||
|
int DrDecoderSetup(int videoFormat, int width, int height, int redrawRate, void* context, int drFlags)
|
||||||
|
{
|
||||||
|
[renderer setupWithVideoFormat:videoFormat];
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit)
|
int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit)
|
||||||
{
|
{
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
@@ -65,11 +72,16 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit)
|
|||||||
return [renderer submitDecodeBuffer:data length:decodeUnit->fullLength];
|
return [renderer submitDecodeBuffer:data length:decodeUnit->fullLength];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArInit(void)
|
int ArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig, void* context, int flags)
|
||||||
{
|
{
|
||||||
int err;
|
int err;
|
||||||
|
|
||||||
opusDecoder = opus_decoder_create(48000, 2, &err);
|
// We only support stereo for now
|
||||||
|
assert(audioConfiguration == AUDIO_CONFIGURATION_STEREO);
|
||||||
|
|
||||||
|
opusDecoder = opus_decoder_create(opusConfig->sampleRate,
|
||||||
|
opusConfig->channelCount,
|
||||||
|
&err);
|
||||||
|
|
||||||
audioLock = [[NSLock alloc] init];
|
audioLock = [[NSLock alloc] init];
|
||||||
|
|
||||||
@@ -77,9 +89,9 @@ void ArInit(void)
|
|||||||
NSError *audioSessionError = nil;
|
NSError *audioSessionError = nil;
|
||||||
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
|
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
|
||||||
|
|
||||||
[audioSession setPreferredSampleRate:48000.0 error:&audioSessionError];
|
[audioSession setPreferredSampleRate:opusConfig->sampleRate error:&audioSessionError];
|
||||||
[audioSession setCategory: AVAudioSessionCategoryPlayback error: &audioSessionError];
|
[audioSession setCategory: AVAudioSessionCategoryPlayback error: &audioSessionError];
|
||||||
[audioSession setPreferredOutputNumberOfChannels:2 error:&audioSessionError];
|
[audioSession setPreferredOutputNumberOfChannels:opusConfig->channelCount error:&audioSessionError];
|
||||||
[audioSession setPreferredIOBufferDuration:0.005 error:&audioSessionError];
|
[audioSession setPreferredIOBufferDuration:0.005 error:&audioSessionError];
|
||||||
[audioSession setActive: YES error: &audioSessionError];
|
[audioSession setActive: YES error: &audioSessionError];
|
||||||
|
|
||||||
@@ -96,14 +108,15 @@ void ArInit(void)
|
|||||||
|
|
||||||
if (status) {
|
if (status) {
|
||||||
Log(LOG_E, @"Unable to instantiate new AudioComponent: %d", (int32_t)status);
|
Log(LOG_E, @"Unable to instantiate new AudioComponent: %d", (int32_t)status);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
AudioStreamBasicDescription audioFormat = {0};
|
AudioStreamBasicDescription audioFormat = {0};
|
||||||
audioFormat.mSampleRate = 48000;
|
audioFormat.mSampleRate = opusConfig->sampleRate;
|
||||||
audioFormat.mBitsPerChannel = 16;
|
audioFormat.mBitsPerChannel = 16;
|
||||||
audioFormat.mFormatID = kAudioFormatLinearPCM;
|
audioFormat.mFormatID = kAudioFormatLinearPCM;
|
||||||
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
|
||||||
audioFormat.mChannelsPerFrame = 2;
|
audioFormat.mChannelsPerFrame = opusConfig->channelCount;
|
||||||
audioFormat.mBytesPerFrame = audioFormat.mChannelsPerFrame * (audioFormat.mBitsPerChannel / 8);
|
audioFormat.mBytesPerFrame = audioFormat.mChannelsPerFrame * (audioFormat.mBitsPerChannel / 8);
|
||||||
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame;
|
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame;
|
||||||
audioFormat.mFramesPerPacket = audioFormat.mBytesPerPacket / audioFormat.mBytesPerFrame;
|
audioFormat.mFramesPerPacket = audioFormat.mBytesPerPacket / audioFormat.mBytesPerFrame;
|
||||||
@@ -117,6 +130,7 @@ void ArInit(void)
|
|||||||
sizeof(audioFormat));
|
sizeof(audioFormat));
|
||||||
if (status) {
|
if (status) {
|
||||||
Log(LOG_E, @"Unable to set audio unit to input: %d", (int32_t)status);
|
Log(LOG_E, @"Unable to set audio unit to input: %d", (int32_t)status);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
AURenderCallbackStruct callbackStruct = {0};
|
AURenderCallbackStruct callbackStruct = {0};
|
||||||
@@ -131,17 +145,22 @@ void ArInit(void)
|
|||||||
sizeof(callbackStruct));
|
sizeof(callbackStruct));
|
||||||
if (status) {
|
if (status) {
|
||||||
Log(LOG_E, @"Unable to set audio unit callback: %d", (int32_t)status);
|
Log(LOG_E, @"Unable to set audio unit callback: %d", (int32_t)status);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = AudioUnitInitialize(audioUnit);
|
status = AudioUnitInitialize(audioUnit);
|
||||||
if (status) {
|
if (status) {
|
||||||
Log(LOG_E, @"Unable to initialize audioUnit: %d", (int32_t)status);
|
Log(LOG_E, @"Unable to initialize audioUnit: %d", (int32_t)status);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
status = AudioOutputUnitStart(audioUnit);
|
status = AudioOutputUnitStart(audioUnit);
|
||||||
if (status) {
|
if (status) {
|
||||||
Log(LOG_E, @"Unable to start audioUnit: %d", (int32_t)status);
|
Log(LOG_E, @"Unable to start audioUnit: %d", (int32_t)status);
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArCleanup(void)
|
void ArCleanup(void)
|
||||||
@@ -223,17 +242,17 @@ void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
|
|||||||
|
|
||||||
void ClStageStarting(int stage)
|
void ClStageStarting(int stage)
|
||||||
{
|
{
|
||||||
[_callbacks stageStarting:(char*)LiGetStageName(stage)];
|
[_callbacks stageStarting:LiGetStageName(stage)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClStageComplete(int stage)
|
void ClStageComplete(int stage)
|
||||||
{
|
{
|
||||||
[_callbacks stageComplete:(char*)LiGetStageName(stage)];
|
[_callbacks stageComplete:LiGetStageName(stage)];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClStageFailed(int stage, long errorCode)
|
void ClStageFailed(int stage, long errorCode)
|
||||||
{
|
{
|
||||||
[_callbacks stageFailed:(char*)LiGetStageName(stage) withError:errorCode];
|
[_callbacks stageFailed:LiGetStageName(stage) withError:errorCode];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClConnectionStarted(void)
|
void ClConnectionStarted(void)
|
||||||
@@ -246,45 +265,68 @@ void ClConnectionTerminated(long errorCode)
|
|||||||
[_callbacks connectionTerminated: errorCode];
|
[_callbacks connectionTerminated: errorCode];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClDisplayMessage(char* message)
|
void ClDisplayMessage(const char* message)
|
||||||
{
|
{
|
||||||
[_callbacks displayMessage: message];
|
[_callbacks displayMessage: message];
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClDisplayTransientMessage(char* message)
|
void ClDisplayTransientMessage(const char* message)
|
||||||
{
|
{
|
||||||
[_callbacks displayTransientMessage: message];
|
[_callbacks displayTransientMessage: message];
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) terminateInternal
|
void ClLogMessage(const char* format, ...)
|
||||||
{
|
{
|
||||||
// We dispatch this async to get out because this can be invoked
|
va_list va;
|
||||||
// on a thread inside common and we don't want to deadlock
|
va_start(va, format);
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
vfprintf(stderr, format, va);
|
||||||
// This is safe to call even before LiStartConnection
|
va_end(va);
|
||||||
LiStopConnection();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
-(void) terminate
|
-(void) terminate
|
||||||
{
|
{
|
||||||
// We're guaranteed to not be on a moonlight-common thread
|
// We dispatch this async to get out because this can be invoked
|
||||||
// here so it's safe to call stop directly
|
// on a thread inside common and we don't want to deadlock. It also avoids
|
||||||
LiStopConnection();
|
// 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];
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
-(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];
|
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;
|
renderer = myRenderer;
|
||||||
_callbacks = callbacks;
|
_callbacks = callbacks;
|
||||||
_serverMajorVersion = serverMajorVersion;
|
|
||||||
|
LiInitializeStreamConfiguration(&_streamConfig);
|
||||||
_streamConfig.width = config.width;
|
_streamConfig.width = config.width;
|
||||||
_streamConfig.height = config.height;
|
_streamConfig.height = config.height;
|
||||||
_streamConfig.fps = config.frameRate;
|
_streamConfig.fps = config.frameRate;
|
||||||
_streamConfig.bitrate = config.bitRate;
|
_streamConfig.bitrate = config.bitRate;
|
||||||
|
|
||||||
|
// On iOS 11, we can use HEVC if the server supports encoding it
|
||||||
|
// and this device has hardware decode for it (A9 and later)
|
||||||
|
if (@available(iOS 11.0, *)) {
|
||||||
|
_streamConfig.supportsHevc = VTIsHardwareDecodeSupported(kCMVideoCodecType_HEVC);
|
||||||
|
}
|
||||||
|
|
||||||
// FIXME: We should use 1024 when streaming remotely
|
// FIXME: We should use 1024 when streaming remotely
|
||||||
_streamConfig.packetSize = 1292;
|
_streamConfig.packetSize = 1292;
|
||||||
|
|
||||||
@@ -293,13 +335,19 @@ void ClDisplayTransientMessage(char* message)
|
|||||||
int riKeyId = htonl(config.riKeyId);
|
int riKeyId = htonl(config.riKeyId);
|
||||||
memcpy(_streamConfig.remoteInputAesIv, &riKeyId, sizeof(riKeyId));
|
memcpy(_streamConfig.remoteInputAesIv, &riKeyId, sizeof(riKeyId));
|
||||||
|
|
||||||
memset(&_drCallbacks, 0, sizeof(_drCallbacks));
|
LiInitializeVideoCallbacks(&_drCallbacks);
|
||||||
|
_drCallbacks.setup = DrDecoderSetup;
|
||||||
_drCallbacks.submitDecodeUnit = DrSubmitDecodeUnit;
|
_drCallbacks.submitDecodeUnit = DrSubmitDecodeUnit;
|
||||||
|
|
||||||
|
// RFI doesn't work properly with HEVC on iOS 11 with an iPhone SE (at least)
|
||||||
|
_drCallbacks.capabilities = CAPABILITY_REFERENCE_FRAME_INVALIDATION_AVC;
|
||||||
|
|
||||||
|
LiInitializeAudioCallbacks(&_arCallbacks);
|
||||||
_arCallbacks.init = ArInit;
|
_arCallbacks.init = ArInit;
|
||||||
_arCallbacks.cleanup = ArCleanup;
|
_arCallbacks.cleanup = ArCleanup;
|
||||||
_arCallbacks.decodeAndPlaySample = ArDecodeAndPlaySample;
|
_arCallbacks.decodeAndPlaySample = ArDecodeAndPlaySample;
|
||||||
|
|
||||||
|
LiInitializeConnectionCallbacks(&_clCallbacks);
|
||||||
_clCallbacks.stageStarting = ClStageStarting;
|
_clCallbacks.stageStarting = ClStageStarting;
|
||||||
_clCallbacks.stageComplete = ClStageComplete;
|
_clCallbacks.stageComplete = ClStageComplete;
|
||||||
_clCallbacks.stageFailed = ClStageFailed;
|
_clCallbacks.stageFailed = ClStageFailed;
|
||||||
@@ -307,6 +355,7 @@ void ClDisplayTransientMessage(char* message)
|
|||||||
_clCallbacks.connectionTerminated = ClConnectionTerminated;
|
_clCallbacks.connectionTerminated = ClConnectionTerminated;
|
||||||
_clCallbacks.displayMessage = ClDisplayMessage;
|
_clCallbacks.displayMessage = ClDisplayMessage;
|
||||||
_clCallbacks.displayTransientMessage = ClDisplayTransientMessage;
|
_clCallbacks.displayTransientMessage = ClDisplayTransientMessage;
|
||||||
|
_clCallbacks.logMessage = ClLogMessage;
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -394,12 +443,15 @@ static OSStatus playbackCallback(void *inRefCon,
|
|||||||
|
|
||||||
-(void) main
|
-(void) main
|
||||||
{
|
{
|
||||||
LiStartConnection(_host,
|
[initLock lock];
|
||||||
|
LiStartConnection(&_serverInfo,
|
||||||
&_streamConfig,
|
&_streamConfig,
|
||||||
&_clCallbacks,
|
&_clCallbacks,
|
||||||
&_drCallbacks,
|
&_drCallbacks,
|
||||||
&_arCallbacks,
|
&_arCallbacks,
|
||||||
NULL, 0, _serverMajorVersion);
|
NULL, 0,
|
||||||
|
NULL, 0);
|
||||||
|
[initLock unlock];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
@interface StreamConfiguration : NSObject
|
@interface StreamConfiguration : NSObject
|
||||||
|
|
||||||
@property NSString* host;
|
@property NSString* host;
|
||||||
|
@property NSString* appVersion;
|
||||||
|
@property NSString* gfeVersion;
|
||||||
@property NSString* appID;
|
@property NSString* appID;
|
||||||
@property int width;
|
@property int width;
|
||||||
@property int height;
|
@property int height;
|
||||||
|
|||||||
@@ -14,6 +14,5 @@
|
|||||||
|
|
||||||
- (id) initWithConfig:(StreamConfiguration*)config renderView:(UIView*)view connectionCallbacks:(id<ConnectionCallbacks>)callback;
|
- (id) initWithConfig:(StreamConfiguration*)config renderView:(UIView*)view connectionCallbacks:(id<ConnectionCallbacks>)callback;
|
||||||
- (void) stopStream;
|
- (void) stopStream;
|
||||||
- (void) stopStreamInternal;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -15,6 +15,7 @@
|
|||||||
#import "ServerInfoResponse.h"
|
#import "ServerInfoResponse.h"
|
||||||
#import "HttpResponse.h"
|
#import "HttpResponse.h"
|
||||||
#import "HttpRequest.h"
|
#import "HttpRequest.h"
|
||||||
|
#import "IdManager.h"
|
||||||
|
|
||||||
@implementation StreamManager {
|
@implementation StreamManager {
|
||||||
StreamConfiguration* _config;
|
StreamConfiguration* _config;
|
||||||
@@ -36,7 +37,7 @@
|
|||||||
|
|
||||||
- (void)main {
|
- (void)main {
|
||||||
[CryptoManager generateKeyPairUsingSSl];
|
[CryptoManager generateKeyPairUsingSSl];
|
||||||
NSString* uniqueId = [CryptoManager getUniqueID];
|
NSString* uniqueId = [IdManager getUniqueId];
|
||||||
NSData* cert = [CryptoManager readCertFromFile];
|
NSData* cert = [CryptoManager readCertFromFile];
|
||||||
|
|
||||||
HttpManager* hMan = [[HttpManager alloc] initWithHost:_config.host
|
HttpManager* hMan = [[HttpManager alloc] initWithHost:_config.host
|
||||||
@@ -47,11 +48,11 @@
|
|||||||
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
|
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
|
||||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
|
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
|
||||||
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
|
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
|
||||||
NSString* currentGame = [serverInfoResp getStringTag:@"currentgame"];
|
|
||||||
NSString* pairStatus = [serverInfoResp getStringTag:@"PairStatus"];
|
NSString* pairStatus = [serverInfoResp getStringTag:@"PairStatus"];
|
||||||
NSString* currentClient = [serverInfoResp getStringTag:@"CurrentClient"];
|
|
||||||
NSString* appversion = [serverInfoResp getStringTag:@"appversion"];
|
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"];
|
[_callbacks launchFailed:@"Failed to connect to PC"];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -63,12 +64,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// resumeApp and launchApp handle calling launchFailed
|
// resumeApp and launchApp handle calling launchFailed
|
||||||
if (![currentGame isEqualToString:@"0"]) {
|
if ([serverState hasSuffix:@"_SERVER_BUSY"]) {
|
||||||
if (![currentClient isEqualToString:@"1"]) {
|
|
||||||
// The server is streaming to someone else
|
|
||||||
[_callbacks launchFailed:@"There is another stream in progress"];
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
// App already running, resume it
|
// App already running, resume it
|
||||||
if (![self resumeApp:hMan]) {
|
if (![self resumeApp:hMan]) {
|
||||||
return;
|
return;
|
||||||
@@ -87,29 +83,21 @@
|
|||||||
[((StreamView*)_renderView) setMouseDeltaFactors:_config.width / screenSize.width
|
[((StreamView*)_renderView) setMouseDeltaFactors:_config.width / screenSize.width
|
||||||
y:_config.height / screenSize.height];
|
y:_config.height / screenSize.height];
|
||||||
|
|
||||||
int majorVersion = [[appversion substringToIndex:1] intValue];
|
// Populate the config's version fields from serverinfo
|
||||||
Log(LOG_I, @"Server is generation %d", majorVersion);
|
_config.appVersion = appversion;
|
||||||
|
_config.gfeVersion = gfeVersion;
|
||||||
|
|
||||||
VideoDecoderRenderer* renderer = [[VideoDecoderRenderer alloc]initWithView:_renderView];
|
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];
|
NSOperationQueue* opQueue = [[NSOperationQueue alloc] init];
|
||||||
[opQueue addOperation:_connection];
|
[opQueue addOperation:_connection];
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should NEVER be called from within a thread
|
|
||||||
// owned by moonlight-common
|
|
||||||
- (void) stopStream
|
- (void) stopStream
|
||||||
{
|
{
|
||||||
[_connection terminate];
|
[_connection terminate];
|
||||||
}
|
}
|
||||||
|
|
||||||
// This should only be called from within a thread
|
|
||||||
// owned by moonlight-common
|
|
||||||
- (void) stopStreamInternal
|
|
||||||
{
|
|
||||||
[_connection terminateInternal];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (BOOL) launchApp:(HttpManager*)hMan {
|
- (BOOL) launchApp:(HttpManager*)hMan {
|
||||||
HttpResponse* launchResp = [[HttpResponse alloc] init];
|
HttpResponse* launchResp = [[HttpResponse alloc] init];
|
||||||
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest:
|
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:launchResp withUrlRequest:
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
- (id)initWithView:(UIView*)view;
|
- (id)initWithView:(UIView*)view;
|
||||||
|
|
||||||
|
- (void)setupWithVideoFormat:(int)videoFormat;
|
||||||
|
|
||||||
- (void)updateBufferForRange:(CMBlockBufferRef)existingBuffer data:(unsigned char *)data offset:(int)offset length:(int)nalLength;
|
- (void)updateBufferForRange:(CMBlockBufferRef)existingBuffer data:(unsigned char *)data offset:(int)offset length:(int)nalLength;
|
||||||
|
|
||||||
- (int)submitDecodeBuffer:(unsigned char *)data length:(int)length;
|
- (int)submitDecodeBuffer:(unsigned char *)data length:(int)length;
|
||||||
|
|||||||
@@ -14,9 +14,10 @@
|
|||||||
UIView *_view;
|
UIView *_view;
|
||||||
|
|
||||||
AVSampleBufferDisplayLayer* displayLayer;
|
AVSampleBufferDisplayLayer* displayLayer;
|
||||||
Boolean waitingForSps, waitingForPps;
|
Boolean waitingForSps, waitingForPps, waitingForVps;
|
||||||
|
int videoFormat;
|
||||||
|
|
||||||
NSData *spsData, *ppsData;
|
NSData *spsData, *ppsData, *vpsData;
|
||||||
CMVideoFormatDescriptionRef formatDesc;
|
CMVideoFormatDescriptionRef formatDesc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -43,6 +44,8 @@
|
|||||||
spsData = nil;
|
spsData = nil;
|
||||||
waitingForPps = true;
|
waitingForPps = true;
|
||||||
ppsData = nil;
|
ppsData = nil;
|
||||||
|
waitingForVps = true;
|
||||||
|
vpsData = nil;
|
||||||
|
|
||||||
if (formatDesc != nil) {
|
if (formatDesc != nil) {
|
||||||
CFRelease(formatDesc);
|
CFRelease(formatDesc);
|
||||||
@@ -61,11 +64,65 @@
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setupWithVideoFormat:(int)videoFormat
|
||||||
|
{
|
||||||
|
self->videoFormat = videoFormat;
|
||||||
|
}
|
||||||
|
|
||||||
#define FRAME_START_PREFIX_SIZE 4
|
#define FRAME_START_PREFIX_SIZE 4
|
||||||
#define NALU_START_PREFIX_SIZE 3
|
#define NALU_START_PREFIX_SIZE 3
|
||||||
#define NAL_LENGTH_PREFIX_SIZE 4
|
#define NAL_LENGTH_PREFIX_SIZE 4
|
||||||
#define NAL_TYPE_SPS 0x7
|
#define AVC_NAL_TYPE_SPS 0x67
|
||||||
#define NAL_TYPE_PPS 0x8
|
#define AVC_NAL_TYPE_PPS 0x68
|
||||||
|
#define HEVC_NAL_TYPE_VPS 0x40
|
||||||
|
#define HEVC_NAL_TYPE_SPS 0x42
|
||||||
|
#define HEVC_NAL_TYPE_PPS 0x44
|
||||||
|
|
||||||
|
#define IS_NAL_SPS(x) ((videoFormat == VIDEO_FORMAT_H264) ? ((x) == AVC_NAL_TYPE_SPS) : ((x) == HEVC_NAL_TYPE_SPS))
|
||||||
|
#define IS_NAL_PPS(x) ((videoFormat == VIDEO_FORMAT_H264) ? ((x) == AVC_NAL_TYPE_PPS) : ((x) == HEVC_NAL_TYPE_PPS))
|
||||||
|
#define IS_NAL_VPS(x) ((videoFormat == VIDEO_FORMAT_H265) && ((x) == HEVC_NAL_TYPE_VPS))
|
||||||
|
|
||||||
|
- (Boolean)readyForPictureData
|
||||||
|
{
|
||||||
|
if (videoFormat == VIDEO_FORMAT_H264) {
|
||||||
|
return !waitingForSps && !waitingForPps;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// H.265 requires VPS in addition to SPS and PPS
|
||||||
|
return !waitingForVps && !waitingForSps && !waitingForPps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (Boolean)isNalReferencePicture:(unsigned char)nalType
|
||||||
|
{
|
||||||
|
if (videoFormat == VIDEO_FORMAT_H264) {
|
||||||
|
return nalType == 0x65;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// HEVC has several types of reference NALU types
|
||||||
|
switch (nalType) {
|
||||||
|
case 0x20:
|
||||||
|
case 0x22:
|
||||||
|
case 0x24:
|
||||||
|
case 0x26:
|
||||||
|
case 0x28:
|
||||||
|
case 0x2A:
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (Boolean)isNalPictureData:(unsigned char)nalType
|
||||||
|
{
|
||||||
|
if (videoFormat == VIDEO_FORMAT_H264) {
|
||||||
|
return !(nalType == AVC_NAL_TYPE_SPS || nalType == AVC_NAL_TYPE_PPS);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return !(nalType == HEVC_NAL_TYPE_VPS || nalType == HEVC_NAL_TYPE_SPS || nalType == HEVC_NAL_TYPE_PPS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)updateBufferForRange:(CMBlockBufferRef)existingBuffer data:(unsigned char *)data offset:(int)offset length:(int)nalLength
|
- (void)updateBufferForRange:(CMBlockBufferRef)existingBuffer data:(unsigned char *)data offset:(int)offset length:(int)nalLength
|
||||||
{
|
{
|
||||||
@@ -136,7 +193,7 @@
|
|||||||
// This function must free data
|
// This function must free data
|
||||||
- (int)submitDecodeBuffer:(unsigned char *)data length:(int)length
|
- (int)submitDecodeBuffer:(unsigned char *)data length:(int)length
|
||||||
{
|
{
|
||||||
unsigned char nalType = data[FRAME_START_PREFIX_SIZE] & 0x1F;
|
unsigned char nalType = data[FRAME_START_PREFIX_SIZE];
|
||||||
OSStatus status;
|
OSStatus status;
|
||||||
|
|
||||||
// Check for previous decoder errors before doing anything
|
// Check for previous decoder errors before doing anything
|
||||||
@@ -150,35 +207,69 @@
|
|||||||
return DR_NEED_IDR;
|
return DR_NEED_IDR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nalType == NAL_TYPE_SPS || nalType == NAL_TYPE_PPS) {
|
if (![self isNalPictureData:nalType]) {
|
||||||
if (nalType == NAL_TYPE_SPS) {
|
if (IS_NAL_VPS(nalType)) {
|
||||||
|
Log(LOG_I, @"Got VPS");
|
||||||
|
vpsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE];
|
||||||
|
waitingForVps = false;
|
||||||
|
|
||||||
|
// We got a new VPS so wait for a new SPS to match it
|
||||||
|
waitingForSps = true;
|
||||||
|
}
|
||||||
|
else if (IS_NAL_SPS(nalType)) {
|
||||||
Log(LOG_I, @"Got SPS");
|
Log(LOG_I, @"Got SPS");
|
||||||
spsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE];
|
spsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE];
|
||||||
waitingForSps = false;
|
waitingForSps = false;
|
||||||
|
|
||||||
// We got a new SPS so wait for a new PPS to match it
|
// We got a new SPS so wait for a new PPS to match it
|
||||||
waitingForPps = true;
|
waitingForPps = true;
|
||||||
} else if (nalType == NAL_TYPE_PPS) {
|
} else if (IS_NAL_PPS(nalType)) {
|
||||||
Log(LOG_I, @"Got PPS");
|
Log(LOG_I, @"Got PPS");
|
||||||
ppsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE];
|
ppsData = [NSData dataWithBytes:&data[FRAME_START_PREFIX_SIZE] length:length - FRAME_START_PREFIX_SIZE];
|
||||||
waitingForPps = false;
|
waitingForPps = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// See if we've got all the parameter sets we need
|
// See if we've got all the parameter sets we need for our video format
|
||||||
if (!waitingForSps && !waitingForPps) {
|
if ([self readyForPictureData]) {
|
||||||
const uint8_t* const parameterSetPointers[] = { [spsData bytes], [ppsData bytes] };
|
if (videoFormat == VIDEO_FORMAT_H264) {
|
||||||
const size_t parameterSetSizes[] = { [spsData length], [ppsData length] };
|
const uint8_t* const parameterSetPointers[] = { [spsData bytes], [ppsData bytes] };
|
||||||
|
const size_t parameterSetSizes[] = { [spsData length], [ppsData length] };
|
||||||
Log(LOG_I, @"Constructing new format description");
|
|
||||||
status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,
|
Log(LOG_I, @"Constructing new H264 format description");
|
||||||
2, /* count of parameter sets */
|
status = CMVideoFormatDescriptionCreateFromH264ParameterSets(kCFAllocatorDefault,
|
||||||
parameterSetPointers,
|
2, /* count of parameter sets */
|
||||||
parameterSetSizes,
|
parameterSetPointers,
|
||||||
NAL_LENGTH_PREFIX_SIZE,
|
parameterSetSizes,
|
||||||
&formatDesc);
|
NAL_LENGTH_PREFIX_SIZE,
|
||||||
if (status != noErr) {
|
&formatDesc);
|
||||||
Log(LOG_E, @"Failed to create format description: %d", (int)status);
|
if (status != noErr) {
|
||||||
formatDesc = NULL;
|
Log(LOG_E, @"Failed to create H264 format description: %d", (int)status);
|
||||||
|
formatDesc = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const uint8_t* const parameterSetPointers[] = { [vpsData bytes], [spsData bytes], [ppsData bytes] };
|
||||||
|
const size_t parameterSetSizes[] = { [vpsData length], [spsData length], [ppsData length] };
|
||||||
|
|
||||||
|
Log(LOG_I, @"Constructing new HEVC format description");
|
||||||
|
if (@available(iOS 11.0, *)) {
|
||||||
|
status = CMVideoFormatDescriptionCreateFromHEVCParameterSets(kCFAllocatorDefault,
|
||||||
|
3, /* count of parameter sets */
|
||||||
|
parameterSetPointers,
|
||||||
|
parameterSetSizes,
|
||||||
|
NAL_LENGTH_PREFIX_SIZE,
|
||||||
|
nil,
|
||||||
|
&formatDesc);
|
||||||
|
} else {
|
||||||
|
// This means Moonlight-common-c decided to give us an HEVC stream
|
||||||
|
// even though we said we couldn't support it. All we can do is abort().
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (status != noErr) {
|
||||||
|
Log(LOG_E, @"Failed to create HEVC format description: %d", (int)status);
|
||||||
|
formatDesc = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,12 +286,6 @@
|
|||||||
return DR_OK;
|
return DR_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nalType != 0x1 && nalType != 0x5) {
|
|
||||||
// Don't submit parameter set data
|
|
||||||
free(data);
|
|
||||||
return DR_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we're decoding actual frame data here
|
// Now we're decoding actual frame data here
|
||||||
CMBlockBufferRef blockBuffer;
|
CMBlockBufferRef blockBuffer;
|
||||||
|
|
||||||
@@ -252,7 +337,7 @@
|
|||||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
|
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DisplayImmediately, kCFBooleanTrue);
|
||||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_IsDependedOnByOthers, kCFBooleanTrue);
|
CFDictionarySetValue(dict, kCMSampleAttachmentKey_IsDependedOnByOthers, kCFBooleanTrue);
|
||||||
|
|
||||||
if (nalType == 1) {
|
if (![self isNalReferencePicture:nalType]) {
|
||||||
// P-frame
|
// P-frame
|
||||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_NotSync, kCFBooleanTrue);
|
CFDictionarySetValue(dict, kCMSampleAttachmentKey_NotSync, kCFBooleanTrue);
|
||||||
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DependsOnOthers, kCFBooleanTrue);
|
CFDictionarySetValue(dict, kCMSampleAttachmentKey_DependsOnOthers, kCFBooleanTrue);
|
||||||
|
|||||||
@@ -7,17 +7,17 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
#import "App.h"
|
#import "TemporaryApp.h"
|
||||||
|
|
||||||
@protocol AppCallback <NSObject>
|
@protocol AppCallback <NSObject>
|
||||||
|
|
||||||
- (void) appClicked:(App*) app;
|
- (void) appClicked:(TemporaryApp*) app;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface UIAppView : UIView
|
@interface UIAppView : UIView
|
||||||
|
|
||||||
- (id) initWithApp:(App*)app andCallback:(id<AppCallback>)callback;
|
- (id) initWithApp:(TemporaryApp*)app cache:(NSCache*)cache andCallback:(id<AppCallback>)callback;
|
||||||
- (void) updateAppImage;
|
- (void) updateAppImage;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,40 +9,43 @@
|
|||||||
#import "UIAppView.h"
|
#import "UIAppView.h"
|
||||||
|
|
||||||
@implementation UIAppView {
|
@implementation UIAppView {
|
||||||
App* _app;
|
TemporaryApp* _app;
|
||||||
UIButton* _appButton;
|
UIButton* _appButton;
|
||||||
UILabel* _appLabel;
|
UILabel* _appLabel;
|
||||||
UIImageView* _appOverlay;
|
UIImageView* _appOverlay;
|
||||||
|
NSCache* _artCache;
|
||||||
id<AppCallback> _callback;
|
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];
|
self = [super init];
|
||||||
_app = app;
|
_app = app;
|
||||||
_callback = callback;
|
_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];
|
_appButton = [UIButton buttonWithType:UIButtonTypeCustom];
|
||||||
UIImage* noImage = [UIImage imageNamed:@"NoAppImage"];
|
|
||||||
[_appButton setBackgroundImage:noImage forState:UIControlStateNormal];
|
[_appButton setBackgroundImage:noImage forState:UIControlStateNormal];
|
||||||
[_appButton setContentEdgeInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
|
[_appButton setContentEdgeInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
|
||||||
[_appButton sizeToFit];
|
[_appButton sizeToFit];
|
||||||
[_appButton addTarget:self action:@selector(appClicked) forControlEvents:UIControlEventTouchUpInside];
|
[_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:_appButton];
|
||||||
[self addSubview:_appOverlay];
|
|
||||||
[self sizeToFit];
|
[self sizeToFit];
|
||||||
|
|
||||||
_appButton.frame = CGRectMake(0, 0, noImage.size.width, noImage.size.height);
|
_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);
|
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;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -52,15 +55,40 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void) updateAppImage {
|
- (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
|
// TODO: Improve no-app image detection
|
||||||
BOOL noAppImage = false;
|
BOOL noAppImage = false;
|
||||||
|
|
||||||
if (_app.image != nil) {
|
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.
|
// 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);
|
_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);
|
self.frame = CGRectMake(0, 0, appImage.size.width / 2, appImage.size.height / 2);
|
||||||
_appOverlay.frame = CGRectMake(0, 0, self.frame.size.width / 2.f, self.frame.size.height / 4.f);
|
_appOverlay.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 <UIKit/UIKit.h>
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
|
|
||||||
@protocol HostCallback <NSObject>
|
@protocol HostCallback <NSObject>
|
||||||
|
|
||||||
- (void) hostClicked:(Host*)host view:(UIView*)view;
|
- (void) hostClicked:(TemporaryHost*)host view:(UIView*)view;
|
||||||
- (void) hostLongClicked:(Host*)host view:(UIView*)view;
|
- (void) hostLongClicked:(TemporaryHost*)host view:(UIView*)view;
|
||||||
- (void) addHostClicked;
|
- (void) addHostClicked;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface UIComputerView : UIView
|
@interface UIComputerView : UIView
|
||||||
|
|
||||||
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback;
|
- (id) initWithComputer:(TemporaryHost*)host andCallback:(id<HostCallback>)callback;
|
||||||
- (id) initForAddWithCallback:(id<HostCallback>)callback;
|
- (id) initForAddWithCallback:(id<HostCallback>)callback;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
#import "UIComputerView.h"
|
#import "UIComputerView.h"
|
||||||
|
|
||||||
@implementation UIComputerView {
|
@implementation UIComputerView {
|
||||||
Host* _host;
|
TemporaryHost* _host;
|
||||||
UIButton* _hostButton;
|
UIButton* _hostButton;
|
||||||
UILabel* _hostLabel;
|
UILabel* _hostLabel;
|
||||||
UILabel* _hostStatus;
|
UILabel* _hostStatus;
|
||||||
@@ -72,7 +72,7 @@ static const int LABEL_DY = 20;
|
|||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback {
|
- (id) initWithComputer:(TemporaryHost*)host andCallback:(id<HostCallback>)callback {
|
||||||
self = [self init];
|
self = [self init];
|
||||||
_host = host;
|
_host = host;
|
||||||
_callback = callback;
|
_callback = callback;
|
||||||
@@ -123,7 +123,7 @@ static const int LABEL_DY = 20;
|
|||||||
self.frame = CGRectMake(x, y, width, height);
|
self.frame = CGRectMake(x, y, width, height);
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) updateContentsForHost:(Host*)host {
|
- (void) updateContentsForHost:(TemporaryHost*)host {
|
||||||
_hostLabel.text = _host.name;
|
_hostLabel.text = _host.name;
|
||||||
_hostLabel.textColor = [UIColor whiteColor];
|
_hostLabel.textColor = [UIColor whiteColor];
|
||||||
[_hostLabel sizeToFit];
|
[_hostLabel sizeToFit];
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
@import ImageIO;
|
||||||
|
|
||||||
#import "MainFrameViewController.h"
|
#import "MainFrameViewController.h"
|
||||||
#import "CryptoManager.h"
|
#import "CryptoManager.h"
|
||||||
#import "HttpManager.h"
|
#import "HttpManager.h"
|
||||||
@@ -13,19 +15,21 @@
|
|||||||
#import "Utils.h"
|
#import "Utils.h"
|
||||||
#import "UIComputerView.h"
|
#import "UIComputerView.h"
|
||||||
#import "UIAppView.h"
|
#import "UIAppView.h"
|
||||||
#import "App.h"
|
|
||||||
#import "SettingsViewController.h"
|
#import "SettingsViewController.h"
|
||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
#import "Settings.h"
|
#import "TemporarySettings.h"
|
||||||
#import "WakeOnLanManager.h"
|
#import "WakeOnLanManager.h"
|
||||||
#import "AppListResponse.h"
|
#import "AppListResponse.h"
|
||||||
#import "ServerInfoResponse.h"
|
#import "ServerInfoResponse.h"
|
||||||
#import "StreamFrameViewController.h"
|
#import "StreamFrameViewController.h"
|
||||||
#import "LoadingFrameViewController.h"
|
#import "LoadingFrameViewController.h"
|
||||||
|
#import "ComputerScrollView.h"
|
||||||
|
#import "TemporaryApp.h"
|
||||||
|
#import "IdManager.h"
|
||||||
|
|
||||||
@implementation MainFrameViewController {
|
@implementation MainFrameViewController {
|
||||||
NSOperationQueue* _opQueue;
|
NSOperationQueue* _opQueue;
|
||||||
Host* _selectedHost;
|
TemporaryHost* _selectedHost;
|
||||||
NSString* _uniqueId;
|
NSString* _uniqueId;
|
||||||
NSData* _cert;
|
NSData* _cert;
|
||||||
DiscoveryManager* _discMan;
|
DiscoveryManager* _discMan;
|
||||||
@@ -35,6 +39,7 @@
|
|||||||
UIScrollView* hostScrollView;
|
UIScrollView* hostScrollView;
|
||||||
int currentPosition;
|
int currentPosition;
|
||||||
NSArray* _sortedAppList;
|
NSArray* _sortedAppList;
|
||||||
|
NSCache* _boxArtCache;
|
||||||
}
|
}
|
||||||
static NSMutableSet* hostList;
|
static NSMutableSet* hostList;
|
||||||
|
|
||||||
@@ -43,27 +48,45 @@ static NSMutableSet* hostList;
|
|||||||
_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing"
|
_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing"
|
||||||
message:[NSString stringWithFormat:@"Enter the following PIN on the host machine: %@", PIN]
|
message:[NSString stringWithFormat:@"Enter the following PIN on the host machine: %@", PIN]
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
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];
|
[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 {
|
- (void)pairFailed:(NSString *)message {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[_pairAlert dismissViewControllerAnimated:YES completion:nil];
|
if (_pairAlert != nil) {
|
||||||
_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing Failed"
|
[_pairAlert dismissViewControllerAnimated:YES completion:^{
|
||||||
message:message
|
[self displayFailureDialog:message];
|
||||||
preferredStyle:UIAlertControllerStyleAlert];
|
}];
|
||||||
[_pairAlert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
|
_pairAlert = nil;
|
||||||
[self presentViewController:_pairAlert animated:YES completion:nil];
|
}
|
||||||
|
else {
|
||||||
[_discMan startDiscovery];
|
[self displayFailureDialog:message];
|
||||||
[self hideLoadingFrame];
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pairSuccessful {
|
- (void)pairSuccessful {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[_pairAlert dismissViewControllerAnimated:YES completion:nil];
|
[_pairAlert dismissViewControllerAnimated:YES completion:nil];
|
||||||
|
_pairAlert = nil;
|
||||||
|
|
||||||
[_discMan startDiscovery];
|
[_discMan startDiscovery];
|
||||||
[self alreadyPaired];
|
[self alreadyPaired];
|
||||||
});
|
});
|
||||||
@@ -74,7 +97,7 @@ static NSMutableSet* hostList;
|
|||||||
|
|
||||||
// Capture the host here because it can change once we
|
// Capture the host here because it can change once we
|
||||||
// leave the main thread
|
// leave the main thread
|
||||||
Host* host = _selectedHost;
|
TemporaryHost* host = _selectedHost;
|
||||||
|
|
||||||
if ([host.appList count] > 0) {
|
if ([host.appList count] > 0) {
|
||||||
usingCachedAppList = true;
|
usingCachedAppList = true;
|
||||||
@@ -94,11 +117,26 @@ static NSMutableSet* hostList;
|
|||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.activeAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
|
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
|
// Exempt this host from discovery while handling the applist query
|
||||||
[_discMan removeHostFromDiscovery:host];
|
[_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];
|
[_discMan addHostToDiscovery:host];
|
||||||
|
|
||||||
if (appListResp == nil || ![appListResp isStatusOk] || [appListResp getAppList] == nil) {
|
if (appListResp == nil || ![appListResp isStatusOk] || [appListResp getAppList] == nil) {
|
||||||
@@ -120,7 +158,7 @@ static NSMutableSet* hostList;
|
|||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[self mergeAppLists:[appListResp getAppList] forHost:host];
|
[self updateApplist:[appListResp getAppList] forHost:host];
|
||||||
|
|
||||||
if (host != _selectedHost) {
|
if (host != _selectedHost) {
|
||||||
return;
|
return;
|
||||||
@@ -138,51 +176,73 @@ static NSMutableSet* hostList;
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) mergeAppLists:(NSArray*) newList forHost:(Host*)host {
|
- (void) updateApplist:(NSSet*) newList forHost:(TemporaryHost*)host {
|
||||||
DataManager* database = [[DataManager alloc] init];
|
DataManager* database = [[DataManager alloc] init];
|
||||||
for (App* app in newList) {
|
|
||||||
BOOL appAlreadyInList = NO;
|
for (TemporaryApp* app in newList) {
|
||||||
for (App* savedApp in host.appList) {
|
BOOL appAlreadyInList = NO;
|
||||||
|
for (TemporaryApp* savedApp in host.appList) {
|
||||||
if ([app.id isEqualToString:savedApp.id]) {
|
if ([app.id isEqualToString:savedApp.id]) {
|
||||||
savedApp.isRunning = app.isRunning;
|
savedApp.name = app.name;
|
||||||
appAlreadyInList = YES;
|
appAlreadyInList = YES;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!appAlreadyInList) {
|
if (!appAlreadyInList) {
|
||||||
app.host = host;
|
app.host = host;
|
||||||
[host addAppListObject:app];
|
[host.appList addObject:app];
|
||||||
} else {
|
|
||||||
[database removeApp:app];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (App* app in host.appList) {
|
BOOL appWasRemoved;
|
||||||
BOOL appWasRemoved = YES;
|
do {
|
||||||
for (App* mergedApp in newList) {
|
appWasRemoved = NO;
|
||||||
if ([mergedApp.id isEqualToString:app.id]) {
|
|
||||||
appWasRemoved = NO;
|
for (TemporaryApp* app in host.appList) {
|
||||||
|
appWasRemoved = YES;
|
||||||
|
for (TemporaryApp* mergedApp in newList) {
|
||||||
|
if ([mergedApp.id isEqualToString:app.id]) {
|
||||||
|
appWasRemoved = NO;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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.
|
||||||
|
|
||||||
|
[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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (appWasRemoved) {
|
|
||||||
[host removeAppListObject:app];
|
// Keep looping until the list is no longer being mutated
|
||||||
[database removeApp:app];
|
} while (appWasRemoved);
|
||||||
}
|
|
||||||
}
|
[database updateAppsForExistingHost:host];
|
||||||
[database saveData];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)showHostSelectionView {
|
- (void)showHostSelectionView {
|
||||||
[_appManager stopRetrieving];
|
[_appManager stopRetrieving];
|
||||||
[[[DataManager alloc] init] saveData];
|
|
||||||
_selectedHost = nil;
|
_selectedHost = nil;
|
||||||
_computerNameButton.title = @"No Host Selected";
|
_computerNameButton.title = @"No Host Selected";
|
||||||
[self.collectionView reloadData];
|
[self.collectionView reloadData];
|
||||||
[self.view addSubview:hostScrollView];
|
[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(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[self.collectionView reloadData];
|
[self.collectionView reloadData];
|
||||||
});
|
});
|
||||||
@@ -196,7 +256,7 @@ static NSMutableSet* hostList;
|
|||||||
[self presentViewController:alert animated:YES completion:nil];
|
[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
|
// Treat clicks on offline hosts to be long clicks
|
||||||
// This shows the context menu with wake, delete, etc. rather
|
// This shows the context menu with wake, delete, etc. rather
|
||||||
// than just hanging for a while and failing as we would in this
|
// than just hanging for a while and failing as we would in this
|
||||||
@@ -212,8 +272,10 @@ static NSMutableSet* hostList;
|
|||||||
|
|
||||||
// If we are online, paired, and have a cached app list, skip straight
|
// 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
|
// to the app grid without a loading frame. This is the fast path that users
|
||||||
// should hit most.
|
// should hit most. Check for a valid view because we don't want to hit the fast
|
||||||
if (host.online && host.pairState == PairStatePaired && host.appList.count > 0) {
|
// 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];
|
[self alreadyPaired];
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -262,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);
|
Log(LOG_D, @"Long clicked host: %@", host.name);
|
||||||
UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
|
UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
|
||||||
if (!host.online) {
|
if (!host.online) {
|
||||||
@@ -288,8 +350,8 @@ static NSMutableSet* hostList;
|
|||||||
[dataMan removeHost:host];
|
[dataMan removeHost:host];
|
||||||
@synchronized(hostList) {
|
@synchronized(hostList) {
|
||||||
[hostList removeObject:host];
|
[hostList removeObject:host];
|
||||||
|
[self updateAllHosts:[hostList allObjects]];
|
||||||
}
|
}
|
||||||
[self updateAllHosts:[hostList allObjects]];
|
|
||||||
|
|
||||||
}]];
|
}]];
|
||||||
[longClickAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
[longClickAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
|
||||||
@@ -311,10 +373,8 @@ static NSMutableSet* hostList;
|
|||||||
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
|
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
|
||||||
NSString* hostAddress = ((UITextField*)[[alertController textFields] objectAtIndex:0]).text;
|
NSString* hostAddress = ((UITextField*)[[alertController textFields] objectAtIndex:0]).text;
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
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) {
|
if (host != nil) {
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
|
||||||
[dataMan saveData];
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
@synchronized(hostList) {
|
@synchronized(hostList) {
|
||||||
[hostList addObject:host];
|
[hostList addObject:host];
|
||||||
@@ -335,14 +395,14 @@ static NSMutableSet* hostList;
|
|||||||
[self presentViewController:alertController animated:YES completion:nil];
|
[self presentViewController:alertController animated:YES completion:nil];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) appClicked:(App *)app {
|
- (void) appClicked:(TemporaryApp *)app {
|
||||||
Log(LOG_D, @"Clicked app: %@", app.name);
|
Log(LOG_D, @"Clicked app: %@", app.name);
|
||||||
_streamConfig = [[StreamConfiguration alloc] init];
|
_streamConfig = [[StreamConfiguration alloc] init];
|
||||||
_streamConfig.host = app.host.activeAddress;
|
_streamConfig.host = app.host.activeAddress;
|
||||||
_streamConfig.appID = app.id;
|
_streamConfig.appID = app.id;
|
||||||
|
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
Settings* streamSettings = [dataMan retrieveSettings];
|
TemporarySettings* streamSettings = [dataMan getSettings];
|
||||||
|
|
||||||
_streamConfig.frameRate = [streamSettings.framerate intValue];
|
_streamConfig.frameRate = [streamSettings.framerate intValue];
|
||||||
_streamConfig.bitRate = [streamSettings.bitrate intValue];
|
_streamConfig.bitRate = [streamSettings.bitrate intValue];
|
||||||
@@ -355,7 +415,7 @@ static NSMutableSet* hostList;
|
|||||||
[[self revealViewController] revealToggle:self];
|
[[self revealViewController] revealToggle:self];
|
||||||
}
|
}
|
||||||
|
|
||||||
App* currentApp = [self findRunningApp:app.host];
|
TemporaryApp* currentApp = [self findRunningApp:app.host];
|
||||||
if (currentApp != nil) {
|
if (currentApp != nil) {
|
||||||
UIAlertController* alertController = [UIAlertController
|
UIAlertController* alertController = [UIAlertController
|
||||||
alertControllerWithTitle: app.name
|
alertControllerWithTitle: app.name
|
||||||
@@ -376,6 +436,17 @@ static NSMutableSet* hostList;
|
|||||||
// Exempt this host from discovery while handling the quit operation
|
// Exempt this host from discovery while handling the quit operation
|
||||||
[_discMan removeHostFromDiscovery:app.host];
|
[_discMan removeHostFromDiscovery:app.host];
|
||||||
[hMan executeRequestSynchronously:quitRequest];
|
[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];
|
[_discMan addHostToDiscovery:app.host];
|
||||||
|
|
||||||
UIAlertController* alert;
|
UIAlertController* alert;
|
||||||
@@ -389,7 +460,7 @@ static NSMutableSet* hostList;
|
|||||||
}
|
}
|
||||||
// If it succeeds and we're to start streaming, segue to the stream and return
|
// If it succeeds and we're to start streaming, segue to the stream and return
|
||||||
else if (![app.id isEqualToString:currentApp.id]) {
|
else if (![app.id isEqualToString:currentApp.id]) {
|
||||||
currentApp.isRunning = NO;
|
app.host.currentGame = @"0";
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
[self updateAppsForHost:app.host];
|
[self updateAppsForHost:app.host];
|
||||||
@@ -400,7 +471,7 @@ static NSMutableSet* hostList;
|
|||||||
}
|
}
|
||||||
// Otherwise, display a dialog to notify the user that the app was quit
|
// Otherwise, display a dialog to notify the user that the app was quit
|
||||||
else {
|
else {
|
||||||
currentApp.isRunning = NO;
|
app.host.currentGame = @"0";
|
||||||
|
|
||||||
alert = [UIAlertController alertControllerWithTitle:@"Quitting App"
|
alert = [UIAlertController alertControllerWithTitle:@"Quitting App"
|
||||||
message:@"The app was quit successfully."
|
message:@"The app was quit successfully."
|
||||||
@@ -421,9 +492,9 @@ static NSMutableSet* hostList;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (App*) findRunningApp:(Host*)host {
|
- (TemporaryApp*) findRunningApp:(TemporaryHost*)host {
|
||||||
for (App* app in host.appList) {
|
for (TemporaryApp* app in host.appList) {
|
||||||
if (app.isRunning) {
|
if ([app.id isEqualToString:host.currentGame]) {
|
||||||
return app;
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -477,7 +548,7 @@ static NSMutableSet* hostList;
|
|||||||
|
|
||||||
// Set up crypto
|
// Set up crypto
|
||||||
[CryptoManager generateKeyPairUsingSSl];
|
[CryptoManager generateKeyPairUsingSSl];
|
||||||
_uniqueId = [CryptoManager getUniqueID];
|
_uniqueId = [IdManager getUniqueId];
|
||||||
_cert = [CryptoManager readCertFromFile];
|
_cert = [CryptoManager readCertFromFile];
|
||||||
|
|
||||||
_appManager = [[AppAssetManager alloc] initWithCallback:self];
|
_appManager = [[AppAssetManager alloc] initWithCallback:self];
|
||||||
@@ -488,22 +559,60 @@ static NSMutableSet* hostList;
|
|||||||
hostList = [[NSMutableSet alloc] init];
|
hostList = [[NSMutableSet alloc] init];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_boxArtCache = [[NSCache alloc] init];
|
||||||
|
|
||||||
[self setAutomaticallyAdjustsScrollViewInsets:NO];
|
[self setAutomaticallyAdjustsScrollViewInsets:NO];
|
||||||
|
|
||||||
hostScrollView = [[UIScrollView alloc] init];
|
hostScrollView = [[ComputerScrollView alloc] init];
|
||||||
hostScrollView.frame = CGRectMake(0, self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height, self.view.frame.size.width, self.view.frame.size.height / 2);
|
hostScrollView.frame = CGRectMake(0, self.navigationController.navigationBar.frame.origin.y + self.navigationController.navigationBar.frame.size.height, self.view.frame.size.width, self.view.frame.size.height / 2);
|
||||||
[hostScrollView setShowsHorizontalScrollIndicator:NO];
|
[hostScrollView setShowsHorizontalScrollIndicator:NO];
|
||||||
|
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 / 6 - pullArrow.frame.size.height / 2 - self.navigationController.navigationBar.frame.size.height,
|
||||||
|
pullArrow.frame.size.width,
|
||||||
|
pullArrow.frame.size.height);
|
||||||
|
|
||||||
|
self.collectionView.delaysContentTouches = NO;
|
||||||
|
self.collectionView.allowsMultipleSelection = NO;
|
||||||
|
self.collectionView.multipleTouchEnabled = NO;
|
||||||
|
|
||||||
[self retrieveSavedHosts];
|
[self retrieveSavedHosts];
|
||||||
_discMan = [[DiscoveryManager alloc] initWithHosts:[hostList allObjects] andCallback:self];
|
_discMan = [[DiscoveryManager alloc] initWithHosts:[hostList allObjects] andCallback:self];
|
||||||
|
|
||||||
|
[[NSNotificationCenter defaultCenter] addObserver: self
|
||||||
|
selector: @selector(handleReturnToForeground)
|
||||||
|
name: UIApplicationWillEnterForegroundNotification
|
||||||
|
object: nil];
|
||||||
|
|
||||||
[self updateHosts];
|
[self updateHosts];
|
||||||
[self.view addSubview:hostScrollView];
|
[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
|
- (void)viewDidAppear:(BOOL)animated
|
||||||
{
|
{
|
||||||
[super viewDidAppear:animated];
|
[super viewDidAppear:animated];
|
||||||
|
|
||||||
|
[[self revealViewController] setPrimaryViewController:self];
|
||||||
|
|
||||||
[self.navigationController setNavigationBarHidden:NO animated:YES];
|
[self.navigationController setNavigationBarHidden:NO animated:YES];
|
||||||
|
|
||||||
// Hide 1px border line
|
// Hide 1px border line
|
||||||
@@ -513,10 +622,7 @@ static NSMutableSet* hostList;
|
|||||||
|
|
||||||
[_discMan startDiscovery];
|
[_discMan startDiscovery];
|
||||||
|
|
||||||
// This will refresh the applist
|
[self handleReturnToForeground];
|
||||||
if (_selectedHost != nil) {
|
|
||||||
[self hostClicked:_selectedHost view:nil];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)viewDidDisappear:(BOOL)animated
|
- (void)viewDidDisappear:(BOOL)animated
|
||||||
@@ -525,18 +631,18 @@ static NSMutableSet* hostList;
|
|||||||
// when discovery stops, we must create a new instance because you cannot restart an NSOperation when it is finished
|
// when discovery stops, we must create a new instance because you cannot restart an NSOperation when it is finished
|
||||||
[_discMan stopDiscovery];
|
[_discMan stopDiscovery];
|
||||||
|
|
||||||
// In case the host objects were updated in the background
|
// Purge the box art cache
|
||||||
[[[DataManager alloc] init] saveData];
|
[_boxArtCache removeAllObjects];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) retrieveSavedHosts {
|
- (void) retrieveSavedHosts {
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
NSArray* hosts = [dataMan retrieveHosts];
|
NSArray* hosts = [dataMan getHosts];
|
||||||
@synchronized(hostList) {
|
@synchronized(hostList) {
|
||||||
[hostList addObjectsFromArray:hosts];
|
[hostList addObjectsFromArray:hosts];
|
||||||
|
|
||||||
// Initialize the non-persistent host state
|
// Initialize the non-persistent host state
|
||||||
for (Host* host in hostList) {
|
for (TemporaryHost* host in hostList) {
|
||||||
if (host.activeAddress == nil) {
|
if (host.activeAddress == nil) {
|
||||||
host.activeAddress = host.localAddress;
|
host.activeAddress = host.localAddress;
|
||||||
}
|
}
|
||||||
@@ -553,7 +659,7 @@ static NSMutableSet* hostList;
|
|||||||
- (void) updateAllHosts:(NSArray *)hosts {
|
- (void) updateAllHosts:(NSArray *)hosts {
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
Log(LOG_D, @"New host list:");
|
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);
|
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) {
|
@synchronized(hostList) {
|
||||||
@@ -571,13 +677,16 @@ static NSMutableSet* hostList;
|
|||||||
UIComputerView* compView;
|
UIComputerView* compView;
|
||||||
float prevEdge = -1;
|
float prevEdge = -1;
|
||||||
@synchronized (hostList) {
|
@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 = [[UIComputerView alloc] initWithComputer:comp andCallback:self];
|
||||||
compView.center = CGPointMake([self getCompViewX:compView addComp:addComp prevEdge:prevEdge], hostScrollView.frame.size.height / 2);
|
compView.center = CGPointMake([self getCompViewX:compView addComp:addComp prevEdge:prevEdge], hostScrollView.frame.size.height / 2);
|
||||||
prevEdge = compView.frame.origin.x + compView.frame.size.width;
|
prevEdge = compView.frame.origin.x + compView.frame.size.width;
|
||||||
[hostScrollView addSubview:compView];
|
[hostScrollView addSubview:compView];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
prevEdge = [self getCompViewX:addComp addComp:addComp prevEdge:prevEdge];
|
prevEdge = [self getCompViewX:addComp addComp:addComp prevEdge:prevEdge];
|
||||||
addComp.center = CGPointMake(prevEdge, hostScrollView.frame.size.height / 2);
|
addComp.center = CGPointMake(prevEdge, hostScrollView.frame.size.height / 2);
|
||||||
|
|
||||||
@@ -593,7 +702,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) {
|
if (host != _selectedHost) {
|
||||||
Log(LOG_W, @"Mismatched host during app update");
|
Log(LOG_W, @"Mismatched host during app update");
|
||||||
return;
|
return;
|
||||||
@@ -602,6 +735,33 @@ static NSMutableSet* hostList;
|
|||||||
_sortedAppList = [host.appList allObjects];
|
_sortedAppList = [host.appList allObjects];
|
||||||
_sortedAppList = [_sortedAppList sortedArrayUsingSelector:@selector(compareName:)];
|
_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];
|
[hostScrollView removeFromSuperview];
|
||||||
[self.collectionView reloadData];
|
[self.collectionView reloadData];
|
||||||
}
|
}
|
||||||
@@ -609,8 +769,8 @@ static NSMutableSet* hostList;
|
|||||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
|
||||||
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"AppCell" forIndexPath:indexPath];
|
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"AppCell" forIndexPath:indexPath];
|
||||||
|
|
||||||
App* app = _sortedAppList[indexPath.row];
|
TemporaryApp* app = _sortedAppList[indexPath.row];
|
||||||
UIAppView* appView = [[UIAppView alloc] initWithApp:app andCallback:self];
|
UIAppView* appView = [[UIAppView alloc] initWithApp:app cache:_boxArtCache andCallback:self];
|
||||||
[appView updateAppImage];
|
[appView updateAppImage];
|
||||||
|
|
||||||
if (appView.bounds.size.width > 10.0) {
|
if (appView.bounds.size.width > 10.0) {
|
||||||
@@ -621,7 +781,19 @@ static NSMutableSet* hostList;
|
|||||||
|
|
||||||
[cell.subviews.firstObject removeFromSuperview]; // Remove a view that was previously added
|
[cell.subviews.firstObject removeFromSuperview]; // Remove a view that was previously added
|
||||||
[cell addSubview:appView];
|
[cell addSubview:appView];
|
||||||
|
|
||||||
|
|
||||||
|
UIBezierPath *shadowPath = [UIBezierPath bezierPathWithRect:cell.bounds];
|
||||||
|
cell.layer.masksToBounds = NO;
|
||||||
|
cell.layer.shadowColor = [UIColor blackColor].CGColor;
|
||||||
|
cell.layer.shadowOffset = CGSizeMake(1.0f, 5.0f);
|
||||||
|
cell.layer.shadowOpacity = 0.5f;
|
||||||
|
cell.layer.shadowPath = shadowPath.CGPath;
|
||||||
|
|
||||||
|
cell.layer.borderColor = [[UIColor colorWithRed:0 green:0 blue:0 alpha:0.3f] CGColor];
|
||||||
|
cell.layer.borderWidth = 1;
|
||||||
|
cell.exclusiveTouch = YES;
|
||||||
|
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ typedef NS_ENUM(NSInteger, SWRevealToggleAnimationType)
|
|||||||
|
|
||||||
@interface SWRevealViewController : UIViewController
|
@interface SWRevealViewController : UIViewController
|
||||||
|
|
||||||
|
- (void)setPrimaryViewController:(UIViewController*)viewController;
|
||||||
|
|
||||||
/* Basic API */
|
/* Basic API */
|
||||||
|
|
||||||
// Object instance init and rear view setting
|
// Object instance init and rear view setting
|
||||||
|
|||||||
@@ -583,6 +583,7 @@ static CGFloat scaledValue( CGFloat v1, CGFloat min2, CGFloat max2, CGFloat min1
|
|||||||
FrontViewPosition _panInitialFrontPosition;
|
FrontViewPosition _panInitialFrontPosition;
|
||||||
NSMutableArray *_animationQueue;
|
NSMutableArray *_animationQueue;
|
||||||
BOOL _userInteractionStore;
|
BOOL _userInteractionStore;
|
||||||
|
UIViewController *_primaryViewController;
|
||||||
}
|
}
|
||||||
|
|
||||||
const int FrontViewPositionNone = 0xff;
|
const int FrontViewPositionNone = 0xff;
|
||||||
@@ -1364,6 +1365,26 @@ const int FrontViewPositionNone = 0xff;
|
|||||||
_enqueue( [theSelf _performTransitionOperation:operation withViewController:newViewController animated:animated] );
|
_enqueue( [theSelf _performTransitionOperation:operation withViewController:newViewController animated:animated] );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)setPrimaryViewController:(UIViewController*)viewController
|
||||||
|
{
|
||||||
|
_primaryViewController = viewController;
|
||||||
|
|
||||||
|
// These are derived from the primary view controller
|
||||||
|
if (@available(iOS 11.0, *)) {
|
||||||
|
[self setNeedsUpdateOfHomeIndicatorAutoHidden];
|
||||||
|
[self setNeedsUpdateOfScreenEdgesDeferringSystemGestures];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIViewController*)childViewControllerForHomeIndicatorAutoHidden
|
||||||
|
{
|
||||||
|
return _primaryViewController;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIViewController*)childViewControllerForScreenEdgesDeferringSystemGestures
|
||||||
|
{
|
||||||
|
return _primaryViewController;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark Animated view controller deployment and layout
|
#pragma mark Animated view controller deployment and layout
|
||||||
|
|
||||||
|
|||||||
@@ -7,22 +7,43 @@
|
|||||||
//
|
//
|
||||||
|
|
||||||
#import "SettingsViewController.h"
|
#import "SettingsViewController.h"
|
||||||
#import "Settings.h"
|
#import "TemporarySettings.h"
|
||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
|
|
||||||
#define BITRATE_INTERVAL 500 // in kbps
|
#define BITRATE_INTERVAL 500 // in kbps
|
||||||
|
|
||||||
@implementation SettingsViewController {
|
@implementation SettingsViewController {
|
||||||
NSInteger _bitrate;
|
NSInteger _bitrate;
|
||||||
|
Boolean _adjustedForSafeArea;
|
||||||
}
|
}
|
||||||
static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
|
static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
|
||||||
|
|
||||||
|
- (void)viewDidAppear:(BOOL)animated
|
||||||
|
{
|
||||||
|
[super viewDidAppear:animated];
|
||||||
|
|
||||||
|
// Adjust the subviews for the safe area on the iPhone X.
|
||||||
|
if (!_adjustedForSafeArea) {
|
||||||
|
if (@available(iOS 11.0, *)) {
|
||||||
|
for (UIView* view in self.view.subviews) {
|
||||||
|
// HACK: The official safe area is much too large for our purposes
|
||||||
|
// so we'll just use the presence of any safe area to indicate we should
|
||||||
|
// pad by 20.
|
||||||
|
if (self.view.safeAreaInsets.left >= 20 || self.view.safeAreaInsets.right >= 20) {
|
||||||
|
view.frame = CGRectMake(view.frame.origin.x + 20, view.frame.origin.y, view.frame.size.width, view.frame.size.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_adjustedForSafeArea = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidLoad {
|
- (void)viewDidLoad {
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
|
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
Settings* currentSettings = [dataMan retrieveSettings];
|
TemporarySettings* currentSettings = [dataMan getSettings];
|
||||||
|
|
||||||
// Bitrate is persisted in kbps
|
// Bitrate is persisted in kbps
|
||||||
_bitrate = [currentSettings.bitrate integerValue];
|
_bitrate = [currentSettings.bitrate integerValue];
|
||||||
@@ -33,18 +54,44 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
|
|||||||
} else if ([currentSettings.height integerValue] == 1080) {
|
} else if ([currentSettings.height integerValue] == 1080) {
|
||||||
resolution = 1;
|
resolution = 1;
|
||||||
} else {
|
} else {
|
||||||
resolution = 2;
|
resolution = 0;
|
||||||
}
|
}
|
||||||
NSInteger onscreenControls = [currentSettings.onscreenControls integerValue];
|
NSInteger onscreenControls = [currentSettings.onscreenControls integerValue];
|
||||||
|
|
||||||
[self.resolutionSelector setSelectedSegmentIndex:resolution];
|
[self.resolutionSelector setSelectedSegmentIndex:resolution];
|
||||||
|
[self.resolutionSelector addTarget:self action:@selector(newResolutionFpsChosen) forControlEvents:UIControlEventValueChanged];
|
||||||
[self.framerateSelector setSelectedSegmentIndex:framerate];
|
[self.framerateSelector setSelectedSegmentIndex:framerate];
|
||||||
|
[self.framerateSelector addTarget:self action:@selector(newResolutionFpsChosen) forControlEvents:UIControlEventValueChanged];
|
||||||
[self.onscreenControlSelector setSelectedSegmentIndex:onscreenControls];
|
[self.onscreenControlSelector setSelectedSegmentIndex:onscreenControls];
|
||||||
[self.bitrateSlider setValue:(_bitrate / BITRATE_INTERVAL) animated:YES];
|
[self.bitrateSlider setValue:(_bitrate / BITRATE_INTERVAL) animated:YES];
|
||||||
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
|
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
|
||||||
[self updateBitrateText];
|
[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 {
|
- (void) bitrateSliderMoved {
|
||||||
_bitrate = BITRATE_INTERVAL * (int)self.bitrateSlider.value;
|
_bitrate = BITRATE_INTERVAL * (int)self.bitrateSlider.value;
|
||||||
[self updateBitrateText];
|
[self updateBitrateText];
|
||||||
@@ -55,25 +102,23 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
|
|||||||
[self.bitrateLabel setText:[NSString stringWithFormat:bitrateFormat, _bitrate / 1000.]];
|
[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 {
|
- (void) saveSettings {
|
||||||
DataManager* dataMan = [[DataManager alloc] init];
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
NSInteger framerate = [self.framerateSelector selectedSegmentIndex] == 0 ? 30 : 60;
|
NSInteger framerate = [self getChosenFrameRate];
|
||||||
NSInteger height;
|
NSInteger height = [self getChosenStreamHeight];
|
||||||
NSInteger width;
|
NSInteger width = [self getChosenStreamWidth];
|
||||||
if ([self.resolutionSelector selectedSegmentIndex] == 2) {
|
|
||||||
// Get screen native resolution
|
|
||||||
height = [UIScreen mainScreen].bounds.size.height * [UIScreen mainScreen].scale;
|
|
||||||
width = [UIScreen mainScreen].bounds.size.width * [UIScreen mainScreen].scale;
|
|
||||||
|
|
||||||
UIAlertController *alertResolution = [UIAlertController alertControllerWithTitle:@"Native resolution" message:[NSString stringWithFormat:@"You must select the following resolution in the game settings: %lix%li", (long)width, (long)height] preferredStyle:UIAlertControllerStyleAlert];
|
|
||||||
[alertResolution addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleCancel handler:nil]];
|
|
||||||
[self presentViewController:alertResolution animated:YES completion:nil];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
height = [self.resolutionSelector selectedSegmentIndex] == 0 ? 720 : 1080;
|
|
||||||
width = height == 720 ? 1280 : 1920;
|
|
||||||
}
|
|
||||||
NSInteger onscreenControls = [self.onscreenControlSelector selectedSegmentIndex];
|
NSInteger onscreenControls = [self.onscreenControlSelector selectedSegmentIndex];
|
||||||
[dataMan saveSettingsWithBitrate:_bitrate framerate:framerate height:height width:width onscreenControls:onscreenControls];
|
[dataMan saveSettingsWithBitrate:_bitrate framerate:framerate height:height width:width onscreenControls:onscreenControls];
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,6 +21,13 @@
|
|||||||
StreamManager *_streamMan;
|
StreamManager *_streamMan;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)viewDidAppear:(BOOL)animated
|
||||||
|
{
|
||||||
|
[super viewDidAppear:animated];
|
||||||
|
|
||||||
|
[[self revealViewController] setPrimaryViewController:self];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)viewDidLoad
|
- (void)viewDidLoad
|
||||||
{
|
{
|
||||||
[super viewDidLoad];
|
[super viewDidLoad];
|
||||||
@@ -84,10 +91,10 @@
|
|||||||
[self presentViewController:conTermAlert animated:YES completion:nil];
|
[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);
|
Log(LOG_I, @"Starting %s", stageName);
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
NSString* lowerCase = [NSString stringWithFormat:@"%s in progress...", stageName];
|
NSString* lowerCase = [NSString stringWithFormat:@"%s in progress...", stageName];
|
||||||
@@ -98,10 +105,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);
|
Log(LOG_I, @"Stage %s failed: %ld", stageName, errorCode);
|
||||||
|
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
@@ -114,6 +121,8 @@
|
|||||||
}]];
|
}]];
|
||||||
[self presentViewController:alert animated:YES completion:nil];
|
[self presentViewController:alert animated:YES completion:nil];
|
||||||
});
|
});
|
||||||
|
|
||||||
|
[_streamMan stopStream];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) launchFailed:(NSString*)message {
|
- (void) launchFailed:(NSString*)message {
|
||||||
@@ -130,11 +139,11 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) displayMessage:(char*)message {
|
- (void) displayMessage:(const char*)message {
|
||||||
Log(LOG_I, @"Display message: %s", 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);
|
Log(LOG_I, @"Display transient message: %s", message);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -144,6 +153,11 @@
|
|||||||
// Dispose of any resources that can be recreated.
|
// Dispose of any resources that can be recreated.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Require a confirmation when streaming to activate a system gesture
|
||||||
|
- (UIRectEdge)preferredScreenEdgesDeferringSystemGestures {
|
||||||
|
return UIRectEdgeAll;
|
||||||
|
}
|
||||||
|
|
||||||
- (BOOL)shouldAutorotate {
|
- (BOOL)shouldAutorotate {
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,11 +3,14 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 46;
|
objectVersion = 47;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
987140041B04542F00AB57D5 /* libmoonlight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FB1E43101AE8B0F200AFF679 /* libmoonlight-common.a */; };
|
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9832D1351BBCD5C50036EF48 /* TemporaryApp.m */; };
|
||||||
|
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 */; };
|
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 */; };
|
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 */; };
|
9E5D600E1A5A5A3900689918 /* Roboto-Bold.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */; };
|
||||||
@@ -15,6 +18,10 @@
|
|||||||
9E5D60131A5A5A3900689918 /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D60001A5A5A3900689918 /* Roboto-Medium.ttf */; };
|
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 */; };
|
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 */; };
|
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 */; };
|
FB290CF219B2C406004C83CF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF119B2C406004C83CF /* Foundation.framework */; };
|
||||||
FB290CF419B2C406004C83CF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF319B2C406004C83CF /* CoreGraphics.framework */; };
|
FB290CF419B2C406004C83CF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF319B2C406004C83CF /* CoreGraphics.framework */; };
|
||||||
FB290CF619B2C406004C83CF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF519B2C406004C83CF /* UIKit.framework */; };
|
FB290CF619B2C406004C83CF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF519B2C406004C83CF /* UIKit.framework */; };
|
||||||
@@ -34,6 +41,7 @@
|
|||||||
FB4678FF1A565DAC00377732 /* WakeOnLanManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4678FE1A565DAC00377732 /* WakeOnLanManager.m */; };
|
FB4678FF1A565DAC00377732 /* WakeOnLanManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4678FE1A565DAC00377732 /* WakeOnLanManager.m */; };
|
||||||
FB4679011A57048000377732 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB4679001A57048000377732 /* CoreFoundation.framework */; };
|
FB4679011A57048000377732 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB4679001A57048000377732 /* CoreFoundation.framework */; };
|
||||||
FB4A23B81A9D3637004D2EF2 /* LoadingFrameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4A23B71A9D3637004D2EF2 /* LoadingFrameViewController.m */; };
|
FB4A23B81A9D3637004D2EF2 /* LoadingFrameViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4A23B71A9D3637004D2EF2 /* LoadingFrameViewController.m */; };
|
||||||
|
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB53E1421BE5DC4400CD6ECE /* IdManager.m */; };
|
||||||
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */ = {isa = PBXBuildFile; fileRef = FB6549551A57907E001C8F39 /* DiscoveryWorker.m */; };
|
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */ = {isa = PBXBuildFile; fileRef = FB6549551A57907E001C8F39 /* DiscoveryWorker.m */; };
|
||||||
FB7E794419C8B71B00A15F68 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB7E794319C8B71B00A15F68 /* libiconv.dylib */; };
|
FB7E794419C8B71B00A15F68 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB7E794319C8B71B00A15F68 /* libiconv.dylib */; };
|
||||||
FB89462819F646E200339C8A /* CryptoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89460619F646E200339C8A /* CryptoManager.m */; };
|
FB89462819F646E200339C8A /* CryptoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89460619F646E200339C8A /* CryptoManager.m */; };
|
||||||
@@ -60,7 +68,6 @@
|
|||||||
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD391A7E05CE00872C98 /* ServerInfoResponse.m */; };
|
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD391A7E05CE00872C98 /* ServerInfoResponse.m */; };
|
||||||
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD3C1A7E111600872C98 /* AppAssetResponse.m */; };
|
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD3C1A7E111600872C98 /* AppAssetResponse.m */; };
|
||||||
FB9AFD401A7E127D00872C98 /* AppListResponse.m in Sources */ = {isa = PBXBuildFile; fileRef = FB9AFD3F1A7E127D00872C98 /* AppListResponse.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 */; };
|
FBD1C8E21A8AD71400C6703C /* Logger.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD1C8E11A8AD71400C6703C /* Logger.m */; };
|
||||||
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494219FC9C04002D2A60 /* AppAssetManager.m */; };
|
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494219FC9C04002D2A60 /* AppAssetManager.m */; };
|
||||||
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494F19FF2174002D2A60 /* SettingsViewController.m */; };
|
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494F19FF2174002D2A60 /* SettingsViewController.m */; };
|
||||||
@@ -74,24 +81,37 @@
|
|||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
/* Begin PBXContainerItemProxy section */
|
/* Begin PBXContainerItemProxy section */
|
||||||
987140011B04541A00AB57D5 /* PBXContainerItemProxy */ = {
|
98AB2E831CAD46840089BB98 /* PBXContainerItemProxy */ = {
|
||||||
isa = PBXContainerItemProxy;
|
isa = PBXContainerItemProxy;
|
||||||
containerPortal = 98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */;
|
containerPortal = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
|
||||||
proxyType = 1;
|
|
||||||
remoteGlobalIDString = FB290E2D19B37A4E004C83CF;
|
|
||||||
remoteInfo = "moonlight-common";
|
|
||||||
};
|
|
||||||
FB1E430F1AE8B0F200AFF679 /* PBXContainerItemProxy */ = {
|
|
||||||
isa = PBXContainerItemProxy;
|
|
||||||
containerPortal = 98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */;
|
|
||||||
proxyType = 2;
|
proxyType = 2;
|
||||||
remoteGlobalIDString = FB290E2E19B37A4E004C83CF;
|
remoteGlobalIDString = FB290E2E19B37A4E004C83CF;
|
||||||
remoteInfo = "moonlight-common";
|
remoteInfo = "moonlight-common";
|
||||||
};
|
};
|
||||||
|
98AB2E851CAD468B0089BB98 /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = FB290E2D19B37A4E004C83CF;
|
||||||
|
remoteInfo = "moonlight-common";
|
||||||
|
};
|
||||||
|
D46A73A51CBC7CB60039F1EE /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = FB290CE619B2C406004C83CF /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = FB290CED19B2C406004C83CF;
|
||||||
|
remoteInfo = Moonlight;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "moonlight-common.xcodeproj"; path = "limelight-common-c/moonlight-common.xcodeproj"; sourceTree = "<group>"; };
|
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>"; };
|
||||||
|
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>"; };
|
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>"; };
|
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>"; };
|
9E5D5FFB1A5A5A3900689918 /* Roboto-Bold.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Bold.ttf"; sourceTree = "<group>"; };
|
||||||
@@ -99,6 +119,16 @@
|
|||||||
9E5D60001A5A5A3900689918 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Medium.ttf"; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
||||||
|
FB1D59991BBCCD7E00F482CA /* AppCollectionView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppCollectionView.m; sourceTree = "<group>"; };
|
||||||
FB290CEE19B2C406004C83CF /* Moonlight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Moonlight.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
FB290CEE19B2C406004C83CF /* Moonlight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Moonlight.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
FB290CF119B2C406004C83CF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
FB290CF119B2C406004C83CF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
|
||||||
FB290CF319B2C406004C83CF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
FB290CF319B2C406004C83CF /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
|
||||||
@@ -127,6 +157,9 @@
|
|||||||
FB4679001A57048000377732 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
FB4679001A57048000377732 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; };
|
||||||
FB4A23B61A9D3637004D2EF2 /* LoadingFrameViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadingFrameViewController.h; sourceTree = "<group>"; };
|
FB4A23B61A9D3637004D2EF2 /* LoadingFrameViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LoadingFrameViewController.h; sourceTree = "<group>"; };
|
||||||
FB4A23B71A9D3637004D2EF2 /* LoadingFrameViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoadingFrameViewController.m; sourceTree = "<group>"; };
|
FB4A23B71A9D3637004D2EF2 /* LoadingFrameViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LoadingFrameViewController.m; sourceTree = "<group>"; };
|
||||||
|
FB53E1411BE5DC4400CD6ECE /* IdManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IdManager.h; sourceTree = "<group>"; };
|
||||||
|
FB53E1421BE5DC4400CD6ECE /* IdManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = IdManager.m; sourceTree = "<group>"; };
|
||||||
|
FB53E1441BE5DCBC00CD6ECE /* Moonlight v1.0-2.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.0-2.xcdatamodel"; sourceTree = "<group>"; };
|
||||||
FB6549541A57907E001C8F39 /* DiscoveryWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiscoveryWorker.h; sourceTree = "<group>"; };
|
FB6549541A57907E001C8F39 /* DiscoveryWorker.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DiscoveryWorker.h; sourceTree = "<group>"; };
|
||||||
FB6549551A57907E001C8F39 /* DiscoveryWorker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DiscoveryWorker.m; sourceTree = "<group>"; };
|
FB6549551A57907E001C8F39 /* DiscoveryWorker.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DiscoveryWorker.m; sourceTree = "<group>"; };
|
||||||
FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Limelight 0.3.1.xcdatamodel"; sourceTree = "<group>"; };
|
FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Limelight 0.3.1.xcdatamodel"; sourceTree = "<group>"; };
|
||||||
@@ -255,8 +288,6 @@
|
|||||||
FB9AFD3C1A7E111600872C98 /* AppAssetResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppAssetResponse.m; sourceTree = "<group>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
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>"; };
|
FBD1C8E11A8AD71400C6703C /* Logger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Logger.m; sourceTree = "<group>"; };
|
||||||
@@ -284,11 +315,18 @@
|
|||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
|
D46A739D1CBC7CB60039F1EE /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
FB290CEB19B2C406004C83CF /* Frameworks */ = {
|
FB290CEB19B2C406004C83CF /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
987140041B04542F00AB57D5 /* libmoonlight-common.a in Frameworks */,
|
98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */,
|
||||||
FB8946ED19F6AFE800339C8A /* libopus.a in Frameworks */,
|
FB8946ED19F6AFE800339C8A /* libopus.a in Frameworks */,
|
||||||
FB8946EB19F6AFE100339C8A /* libcrypto.a in Frameworks */,
|
FB8946EB19F6AFE100339C8A /* libcrypto.a in Frameworks */,
|
||||||
FB8946EC19F6AFE400339C8A /* libssl.a in Frameworks */,
|
FB8946EC19F6AFE400339C8A /* libssl.a in Frameworks */,
|
||||||
@@ -307,6 +345,14 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
98AB2E801CAD46830089BB98 /* Products */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
98AB2E841CAD46840089BB98 /* libmoonlight-common.a */,
|
||||||
|
);
|
||||||
|
name = Products;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
9E5D5FF61A5A5A3900689918 /* Font */ = {
|
9E5D5FF61A5A5A3900689918 /* Font */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -329,19 +375,30 @@
|
|||||||
path = Roboto;
|
path = Roboto;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
FB1E430C1AE8B0F200AFF679 /* Products */ = {
|
D46A73A11CBC7CB60039F1EE /* MoonlightUnitTests */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
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>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
FB290CE519B2C406004C83CF = {
|
FB290CE519B2C406004C83CF = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */,
|
98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */,
|
||||||
FB290CF919B2C406004C83CF /* Limelight */,
|
FB290CF919B2C406004C83CF /* Moonlight */,
|
||||||
|
D46A73A11CBC7CB60039F1EE /* MoonlightUnitTests */,
|
||||||
FB290CF019B2C406004C83CF /* Frameworks */,
|
FB290CF019B2C406004C83CF /* Frameworks */,
|
||||||
FB290CEF19B2C406004C83CF /* Products */,
|
FB290CEF19B2C406004C83CF /* Products */,
|
||||||
);
|
);
|
||||||
@@ -351,6 +408,7 @@
|
|||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
FB290CEE19B2C406004C83CF /* Moonlight.app */,
|
FB290CEE19B2C406004C83CF /* Moonlight.app */,
|
||||||
|
D46A73A01CBC7CB60039F1EE /* MoonlightUnitTests.xctest */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -374,9 +432,10 @@
|
|||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
FB290CF919B2C406004C83CF /* Limelight */ = {
|
FB290CF919B2C406004C83CF /* Moonlight */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
D4746EEA1CBC740C006FB401 /* Moonlight-Bridging-Header.h */,
|
||||||
9E5D5FF61A5A5A3900689918 /* Font */,
|
9E5D5FF61A5A5A3900689918 /* Font */,
|
||||||
FB89460419F646E200339C8A /* Crypto */,
|
FB89460419F646E200339C8A /* Crypto */,
|
||||||
FB89460919F646E200339C8A /* Input */,
|
FB89460919F646E200339C8A /* Input */,
|
||||||
@@ -397,7 +456,12 @@
|
|||||||
FB89463719F6473800339C8A /* Launch Screen.xib */,
|
FB89463719F6473800339C8A /* Launch Screen.xib */,
|
||||||
FB290D0819B2C406004C83CF /* Images.xcassets */,
|
FB290D0819B2C406004C83CF /* Images.xcassets */,
|
||||||
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */,
|
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */,
|
||||||
|
FB1D59951BBCCB6400F482CA /* ComputerScrollView.h */,
|
||||||
|
FB1D59961BBCCB6400F482CA /* ComputerScrollView.m */,
|
||||||
|
FB1D59981BBCCD7E00F482CA /* AppCollectionView.h */,
|
||||||
|
FB1D59991BBCCD7E00F482CA /* AppCollectionView.m */,
|
||||||
);
|
);
|
||||||
|
name = Moonlight;
|
||||||
path = Limelight;
|
path = Limelight;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
@@ -419,6 +483,8 @@
|
|||||||
FB89460619F646E200339C8A /* CryptoManager.m */,
|
FB89460619F646E200339C8A /* CryptoManager.m */,
|
||||||
FB89460719F646E200339C8A /* mkcert.c */,
|
FB89460719F646E200339C8A /* mkcert.c */,
|
||||||
FB89460819F646E200339C8A /* mkcert.h */,
|
FB89460819F646E200339C8A /* mkcert.h */,
|
||||||
|
FB53E1411BE5DC4400CD6ECE /* IdManager.h */,
|
||||||
|
FB53E1421BE5DC4400CD6ECE /* IdManager.m */,
|
||||||
);
|
);
|
||||||
path = Crypto;
|
path = Crypto;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -428,8 +494,7 @@
|
|||||||
children = (
|
children = (
|
||||||
FB89460A19F646E200339C8A /* ControllerSupport.h */,
|
FB89460A19F646E200339C8A /* ControllerSupport.h */,
|
||||||
FB89460B19F646E200339C8A /* ControllerSupport.m */,
|
FB89460B19F646E200339C8A /* ControllerSupport.m */,
|
||||||
FB9AFD411A7F0C6900872C98 /* Controller.h */,
|
D4746EEB1CBC740C006FB401 /* Controller.swift */,
|
||||||
FB9AFD421A7F0C6900872C98 /* Controller.m */,
|
|
||||||
FB89460C19F646E200339C8A /* StreamView.h */,
|
FB89460C19F646E200339C8A /* StreamView.h */,
|
||||||
FB89460D19F646E200339C8A /* StreamView.m */,
|
FB89460D19F646E200339C8A /* StreamView.m */,
|
||||||
FB4678EB1A50C40900377732 /* OnScreenControls.h */,
|
FB4678EB1A50C40900377732 /* OnScreenControls.h */,
|
||||||
@@ -712,6 +777,12 @@
|
|||||||
FBD3495D1A004412002D2A60 /* Settings.m */,
|
FBD3495D1A004412002D2A60 /* Settings.m */,
|
||||||
FBD349601A0089F6002D2A60 /* DataManager.h */,
|
FBD349601A0089F6002D2A60 /* DataManager.h */,
|
||||||
FBD349611A0089F6002D2A60 /* DataManager.m */,
|
FBD349611A0089F6002D2A60 /* DataManager.m */,
|
||||||
|
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */,
|
||||||
|
9832D1351BBCD5C50036EF48 /* TemporaryApp.m */,
|
||||||
|
98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */,
|
||||||
|
98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */,
|
||||||
|
98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */,
|
||||||
|
98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */,
|
||||||
);
|
);
|
||||||
name = Database;
|
name = Database;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -719,6 +790,24 @@
|
|||||||
/* End PBXGroup section */
|
/* End PBXGroup section */
|
||||||
|
|
||||||
/* Begin PBXNativeTarget 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 */ = {
|
FB290CED19B2C406004C83CF /* Moonlight */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = FB290D2019B2C406004C83CF /* Build configuration list for PBXNativeTarget "Moonlight" */;
|
buildConfigurationList = FB290D2019B2C406004C83CF /* Build configuration list for PBXNativeTarget "Moonlight" */;
|
||||||
@@ -730,7 +819,7 @@
|
|||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
987140021B04541A00AB57D5 /* PBXTargetDependency */,
|
98AB2E861CAD468B0089BB98 /* PBXTargetDependency */,
|
||||||
);
|
);
|
||||||
name = Moonlight;
|
name = Moonlight;
|
||||||
productName = Limelight;
|
productName = Limelight;
|
||||||
@@ -743,16 +832,23 @@
|
|||||||
FB290CE619B2C406004C83CF /* Project object */ = {
|
FB290CE619B2C406004C83CF /* Project object */ = {
|
||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
LastUpgradeCheck = 0700;
|
LastSwiftUpdateCheck = 0730;
|
||||||
ORGANIZATIONNAME = "Limelight Stream";
|
LastUpgradeCheck = 0800;
|
||||||
|
ORGANIZATIONNAME = "Moonlight Stream";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
|
D46A739F1CBC7CB60039F1EE = {
|
||||||
|
CreatedOnToolsVersion = 7.3;
|
||||||
|
LastSwiftMigration = 0800;
|
||||||
|
TestTargetID = FB290CED19B2C406004C83CF;
|
||||||
|
};
|
||||||
FB290CED19B2C406004C83CF = {
|
FB290CED19B2C406004C83CF = {
|
||||||
DevelopmentTeam = DM46QST4M7;
|
DevelopmentTeam = DM46QST4M7;
|
||||||
|
LastSwiftMigration = 0800;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Moonlight" */;
|
buildConfigurationList = FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Moonlight" */;
|
||||||
compatibilityVersion = "Xcode 3.2";
|
compatibilityVersion = "Xcode 6.3";
|
||||||
developmentRegion = English;
|
developmentRegion = English;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
@@ -763,28 +859,36 @@
|
|||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectReferences = (
|
projectReferences = (
|
||||||
{
|
{
|
||||||
ProductGroup = FB1E430C1AE8B0F200AFF679 /* Products */;
|
ProductGroup = 98AB2E801CAD46830089BB98 /* Products */;
|
||||||
ProjectRef = 98A03B4519F3514B00861ACA /* moonlight-common.xcodeproj */;
|
ProjectRef = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
FB290CED19B2C406004C83CF /* Moonlight */,
|
FB290CED19B2C406004C83CF /* Moonlight */,
|
||||||
|
D46A739F1CBC7CB60039F1EE /* MoonlightUnitTests */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
|
|
||||||
/* Begin PBXReferenceProxy section */
|
/* Begin PBXReferenceProxy section */
|
||||||
FB1E43101AE8B0F200AFF679 /* libmoonlight-common.a */ = {
|
98AB2E841CAD46840089BB98 /* libmoonlight-common.a */ = {
|
||||||
isa = PBXReferenceProxy;
|
isa = PBXReferenceProxy;
|
||||||
fileType = archive.ar;
|
fileType = archive.ar;
|
||||||
path = "libmoonlight-common.a";
|
path = "libmoonlight-common.a";
|
||||||
remoteRef = FB1E430F1AE8B0F200AFF679 /* PBXContainerItemProxy */;
|
remoteRef = 98AB2E831CAD46840089BB98 /* PBXContainerItemProxy */;
|
||||||
sourceTree = BUILT_PRODUCTS_DIR;
|
sourceTree = BUILT_PRODUCTS_DIR;
|
||||||
};
|
};
|
||||||
/* End PBXReferenceProxy section */
|
/* End PBXReferenceProxy section */
|
||||||
|
|
||||||
/* Begin PBXResourcesBuildPhase section */
|
/* Begin PBXResourcesBuildPhase section */
|
||||||
|
D46A739E1CBC7CB60039F1EE /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
FB290CEC19B2C406004C83CF /* Resources */ = {
|
FB290CEC19B2C406004C83CF /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -807,6 +911,14 @@
|
|||||||
/* End PBXResourcesBuildPhase section */
|
/* End PBXResourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXSourcesBuildPhase section */
|
/* Begin PBXSourcesBuildPhase section */
|
||||||
|
D46A739C1CBC7CB60039F1EE /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D46A73AD1CBC7D090039F1EE /* ControllerUnitTests.swift in Sources */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
FB290CEA19B2C406004C83CF /* Sources */ = {
|
FB290CEA19B2C406004C83CF /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -821,31 +933,37 @@
|
|||||||
FB89462F19F646E200339C8A /* Connection.m in Sources */,
|
FB89462F19F646E200339C8A /* Connection.m in Sources */,
|
||||||
FB9AFD321A7D867C00872C98 /* AppAssetRetriever.m in Sources */,
|
FB9AFD321A7D867C00872C98 /* AppAssetRetriever.m in Sources */,
|
||||||
FB4678FF1A565DAC00377732 /* WakeOnLanManager.m in Sources */,
|
FB4678FF1A565DAC00377732 /* WakeOnLanManager.m in Sources */,
|
||||||
|
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */,
|
||||||
FB89462919F646E200339C8A /* mkcert.c in Sources */,
|
FB89462919F646E200339C8A /* mkcert.c in Sources */,
|
||||||
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
|
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
|
||||||
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */,
|
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */,
|
||||||
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */,
|
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */,
|
||||||
FBFCB3311B50B29400089F8A /* Host.m in Sources */,
|
FBFCB3311B50B29400089F8A /* Host.m in Sources */,
|
||||||
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */,
|
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */,
|
||||||
|
FB1D59971BBCCB6400F482CA /* ComputerScrollView.m in Sources */,
|
||||||
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */,
|
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */,
|
||||||
FB89462C19F646E200339C8A /* HttpManager.m in Sources */,
|
FB89462C19F646E200339C8A /* HttpManager.m in Sources */,
|
||||||
FB89462D19F646E200339C8A /* MDNSManager.m in Sources */,
|
FB89462D19F646E200339C8A /* MDNSManager.m in Sources */,
|
||||||
FB89462B19F646E200339C8A /* StreamView.m in Sources */,
|
FB89462B19F646E200339C8A /* StreamView.m in Sources */,
|
||||||
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
|
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
|
||||||
|
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */,
|
||||||
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
|
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
|
||||||
FBD1C8E21A8AD71400C6703C /* Logger.m in Sources */,
|
FBD1C8E21A8AD71400C6703C /* Logger.m in Sources */,
|
||||||
|
FB1D599A1BBCCD7E00F482CA /* AppCollectionView.m in Sources */,
|
||||||
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */,
|
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */,
|
||||||
|
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */,
|
||||||
|
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */,
|
||||||
FB89462819F646E200339C8A /* CryptoManager.m in Sources */,
|
FB89462819F646E200339C8A /* CryptoManager.m in Sources */,
|
||||||
FB89462E19F646E200339C8A /* PairManager.m in Sources */,
|
FB89462E19F646E200339C8A /* PairManager.m in Sources */,
|
||||||
FB9AFD371A7E02DB00872C98 /* HttpRequest.m in Sources */,
|
FB9AFD371A7E02DB00872C98 /* HttpRequest.m in Sources */,
|
||||||
FB4678ED1A50C40900377732 /* OnScreenControls.m in Sources */,
|
FB4678ED1A50C40900377732 /* OnScreenControls.m in Sources */,
|
||||||
FB290D0019B2C406004C83CF /* main.m in Sources */,
|
FB290D0019B2C406004C83CF /* main.m in Sources */,
|
||||||
FB9AFD431A7F0C6900872C98 /* Controller.m in Sources */,
|
|
||||||
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */,
|
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */,
|
||||||
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */,
|
FB6549561A57907E001C8F39 /* DiscoveryWorker.m in Sources */,
|
||||||
FB89462A19F646E200339C8A /* ControllerSupport.m in Sources */,
|
FB89462A19F646E200339C8A /* ControllerSupport.m in Sources */,
|
||||||
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */,
|
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */,
|
||||||
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */,
|
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */,
|
||||||
|
D4746EEC1CBC740C006FB401 /* Controller.swift in Sources */,
|
||||||
FBFCB3351B50B29400089F8A /* App.m in Sources */,
|
FBFCB3351B50B29400089F8A /* App.m in Sources */,
|
||||||
FB4A23B81A9D3637004D2EF2 /* LoadingFrameViewController.m in Sources */,
|
FB4A23B81A9D3637004D2EF2 /* LoadingFrameViewController.m in Sources */,
|
||||||
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */,
|
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */,
|
||||||
@@ -856,10 +974,15 @@
|
|||||||
/* End PBXSourcesBuildPhase section */
|
/* End PBXSourcesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXTargetDependency section */
|
/* Begin PBXTargetDependency section */
|
||||||
987140021B04541A00AB57D5 /* PBXTargetDependency */ = {
|
98AB2E861CAD468B0089BB98 /* PBXTargetDependency */ = {
|
||||||
isa = PBXTargetDependency;
|
isa = PBXTargetDependency;
|
||||||
name = "moonlight-common";
|
name = "moonlight-common";
|
||||||
targetProxy = 987140011B04541A00AB57D5 /* PBXContainerItemProxy */;
|
targetProxy = 98AB2E851CAD468B0089BB98 /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
|
D46A73A61CBC7CB60039F1EE /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = FB290CED19B2C406004C83CF /* Moonlight */;
|
||||||
|
targetProxy = D46A73A51CBC7CB60039F1EE /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
@@ -875,6 +998,54 @@
|
|||||||
/* End PBXVariantGroup section */
|
/* End PBXVariantGroup section */
|
||||||
|
|
||||||
/* Begin XCBuildConfiguration 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 */ = {
|
FB290D1E19B2C406004C83CF /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
@@ -888,15 +1059,20 @@
|
|||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
COPY_PHASE_STRIP = NO;
|
COPY_PHASE_STRIP = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
ENABLE_TESTABILITY = YES;
|
ENABLE_TESTABILITY = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
GCC_DYNAMIC_NO_PIC = NO;
|
GCC_DYNAMIC_NO_PIC = NO;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_OPTIMIZATION_LEVEL = 0;
|
GCC_OPTIMIZATION_LEVEL = 0;
|
||||||
GCC_PREPROCESSOR_DEFINITIONS = (
|
GCC_PREPROCESSOR_DEFINITIONS = (
|
||||||
"DEBUG=1",
|
"DEBUG=1",
|
||||||
@@ -929,14 +1105,19 @@
|
|||||||
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
|
||||||
CLANG_WARN_EMPTY_BODY = YES;
|
CLANG_WARN_EMPTY_BODY = YES;
|
||||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||||
|
CLANG_WARN_INFINITE_RECURSION = YES;
|
||||||
CLANG_WARN_INT_CONVERSION = YES;
|
CLANG_WARN_INT_CONVERSION = YES;
|
||||||
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
|
||||||
|
CLANG_WARN_SUSPICIOUS_MOVE = YES;
|
||||||
|
CLANG_WARN_UNREACHABLE_CODE = YES;
|
||||||
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
CODE_SIGN_IDENTITY = "iPhone Distribution";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
||||||
COPY_PHASE_STRIP = YES;
|
COPY_PHASE_STRIP = YES;
|
||||||
ENABLE_NS_ASSERTIONS = NO;
|
ENABLE_NS_ASSERTIONS = NO;
|
||||||
|
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||||
|
GCC_NO_COMMON_BLOCKS = YES;
|
||||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||||
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
|
||||||
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
GCC_WARN_UNDECLARED_SELECTOR = YES;
|
||||||
@@ -955,6 +1136,7 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
@@ -963,11 +1145,12 @@
|
|||||||
HEADER_SEARCH_PATHS = (
|
HEADER_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
/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/**",
|
"$(SDKROOT)/usr/include/libxml2/**",
|
||||||
"$(PROJECT_DIR)/libs/**",
|
"$(PROJECT_DIR)/libs/**",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
|
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
LIBRARY_SEARCH_PATHS = (
|
LIBRARY_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/libs/opus/lib",
|
"$(PROJECT_DIR)/libs/opus/lib",
|
||||||
@@ -977,6 +1160,9 @@
|
|||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE = "";
|
PROVISIONING_PROFILE = "";
|
||||||
SKIP_INSTALL = NO;
|
SKIP_INSTALL = NO;
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Limelight/Input/Moonlight-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
WRAPPER_EXTENSION = app;
|
WRAPPER_EXTENSION = app;
|
||||||
};
|
};
|
||||||
name = Debug;
|
name = Debug;
|
||||||
@@ -985,19 +1171,21 @@
|
|||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
CLANG_ENABLE_MODULES = YES;
|
||||||
CODE_SIGN_IDENTITY = "iPhone Developer";
|
CODE_SIGN_IDENTITY = "iPhone Developer";
|
||||||
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
|
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
GCC_PRECOMPILE_PREFIX_HEADER = YES;
|
||||||
GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch";
|
GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch";
|
||||||
HEADER_SEARCH_PATHS = (
|
HEADER_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
|
/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/**",
|
"$(SDKROOT)/usr/include/libxml2/**",
|
||||||
"$(PROJECT_DIR)/libs/**",
|
"$(PROJECT_DIR)/libs/**",
|
||||||
);
|
);
|
||||||
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
|
INFOPLIST_FILE = "Limelight/Limelight-Info.plist";
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
|
||||||
LIBRARY_SEARCH_PATHS = (
|
LIBRARY_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"$(PROJECT_DIR)/libs/opus/lib",
|
"$(PROJECT_DIR)/libs/opus/lib",
|
||||||
@@ -1007,6 +1195,9 @@
|
|||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
PROVISIONING_PROFILE = "";
|
PROVISIONING_PROFILE = "";
|
||||||
SKIP_INSTALL = NO;
|
SKIP_INSTALL = NO;
|
||||||
|
SWIFT_OBJC_BRIDGING_HEADER = "Limelight/Input/Moonlight-Bridging-Header.h";
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
|
||||||
|
SWIFT_VERSION = 3.0;
|
||||||
WRAPPER_EXTENSION = app;
|
WRAPPER_EXTENSION = app;
|
||||||
};
|
};
|
||||||
name = Release;
|
name = Release;
|
||||||
@@ -1014,6 +1205,15 @@
|
|||||||
/* End XCBuildConfiguration section */
|
/* End XCBuildConfiguration section */
|
||||||
|
|
||||||
/* Begin XCConfigurationList 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" */ = {
|
FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Moonlight" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
@@ -1038,12 +1238,13 @@
|
|||||||
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */ = {
|
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */ = {
|
||||||
isa = XCVersionGroup;
|
isa = XCVersionGroup;
|
||||||
children = (
|
children = (
|
||||||
|
FB53E1441BE5DCBC00CD6ECE /* Moonlight v1.0-2.xcdatamodel */,
|
||||||
FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */,
|
FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */,
|
||||||
FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */,
|
FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */,
|
||||||
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */,
|
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */,
|
||||||
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */,
|
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */,
|
||||||
);
|
);
|
||||||
currentVersion = FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */;
|
currentVersion = FB53E1441BE5DCBC00CD6ECE /* Moonlight v1.0-2.xcdatamodel */;
|
||||||
path = Limelight.xcdatamodeld;
|
path = Limelight.xcdatamodeld;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
versionGroupType = wrapper.xcdatamodel;
|
versionGroupType = wrapper.xcdatamodel;
|
||||||
|
|||||||
@@ -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,12 +1,14 @@
|
|||||||
#Moonlight iOS
|
#Moonlight iOS
|
||||||
|
|
||||||
[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
|
#### Now available on the [App Store](https://itunes.apple.com/us/app/moonlight-game-streaming/id1000551566?mt=8)
|
||||||
|
|
||||||
|
[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.
|
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.
|
##### Questions?
|
||||||
|
Check out our [wiki](https://github.com/moonlight-stream/moonlight-docs/wiki).
|
||||||
Please be patient as we work to bring Moonlight to more platforms.
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" initialViewController="EVd-wq-ego">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15B38b" targetRuntime="iOS.CocoaTouch.iPad" propertyAccessControl="none" initialViewController="EVd-wq-ego">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<customFonts key="customFonts">
|
<customFonts key="customFonts">
|
||||||
<mutableArray key="Roboto-Regular.ttf">
|
<mutableArray key="Roboto-Regular.ttf">
|
||||||
@@ -13,9 +14,11 @@
|
|||||||
<scene sceneID="Me4-Nr-liz">
|
<scene sceneID="Me4-Nr-liz">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="wb7-af-jn8" customClass="MainFrameViewController" sceneMemberID="viewController">
|
<viewController id="wb7-af-jn8" customClass="MainFrameViewController" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" indicatorStyle="black" dataMode="prototypes" id="TZj-Lc-M9d">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" indicatorStyle="black" dataMode="prototypes" id="TZj-Lc-M9d" customClass="AppCollectionView">
|
||||||
<rect key="frame" x="0.0" y="64" width="1024" height="704"/>
|
<rect key="frame" x="0.0" y="64" width="1024" height="704"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<animations/>
|
||||||
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
<inset key="contentInset" minX="40" minY="20" maxX="40" maxY="20"/>
|
<inset key="contentInset" minX="40" minY="20" maxX="40" maxY="20"/>
|
||||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="f7l-kG-hJc">
|
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="f7l-kG-hJc">
|
||||||
<size key="itemSize" width="150" height="200"/>
|
<size key="itemSize" width="150" height="200"/>
|
||||||
@@ -24,14 +27,16 @@
|
|||||||
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
|
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
|
||||||
</collectionViewFlowLayout>
|
</collectionViewFlowLayout>
|
||||||
<cells>
|
<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="20" width="150" height="200"/>
|
<rect key="frame" x="20" y="40" width="150" height="200"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="150" height="200"/>
|
<rect key="frame" x="0.0" y="0.0" width="150" height="200"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
|
<animations/>
|
||||||
</collectionViewCell>
|
</collectionViewCell>
|
||||||
</cells>
|
</cells>
|
||||||
<connections>
|
<connections>
|
||||||
@@ -42,14 +47,15 @@
|
|||||||
<navigationItem key="navigationItem" id="pSu-bl-gL9">
|
<navigationItem key="navigationItem" id="pSu-bl-gL9">
|
||||||
<barButtonItem key="leftBarButtonItem" style="done" id="mSL-ru-nRm">
|
<barButtonItem key="leftBarButtonItem" style="done" id="mSL-ru-nRm">
|
||||||
<button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="Tiq-VS-Ua5">
|
<button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="Tiq-VS-Ua5">
|
||||||
<rect key="frame" x="101" y="236" width="109" height="46"/>
|
<rect key="frame" x="20" y="-1" width="109" height="46"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" name="Roboto-Regular" family="Roboto" pointSize="16"/>
|
<fontDescription key="fontDescription" name="Roboto-Regular" family="Roboto" pointSize="16"/>
|
||||||
<state key="normal" title="Moonlight" image="Logo">
|
<state key="normal" title="Moonlight" image="Logo">
|
||||||
<color key="titleColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
|
||||||
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
</state>
|
</state>
|
||||||
</button>
|
</button>
|
||||||
|
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
</barButtonItem>
|
</barButtonItem>
|
||||||
<barButtonItem key="rightBarButtonItem" title="No Host Selected" id="KDy-JC-2sU">
|
<barButtonItem key="rightBarButtonItem" title="No Host Selected" id="KDy-JC-2sU">
|
||||||
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
@@ -77,6 +83,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Bitrate: 10 Mbps" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="lMt-4H-fkV">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Bitrate: 10 Mbps" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="lMt-4H-fkV">
|
||||||
<rect key="frame" x="16" y="39" width="151" height="21"/>
|
<rect key="frame" x="16" y="39" width="151" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
@@ -85,11 +92,13 @@
|
|||||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="20" minValue="1" maxValue="100" id="JAY-nj-UNz">
|
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="20" minValue="1" maxValue="100" id="JAY-nj-UNz">
|
||||||
<rect key="frame" x="14" y="68" width="213" height="31"/>
|
<rect key="frame" x="14" y="68" width="213" height="31"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</slider>
|
</slider>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Framerate" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Aiv-r8-9k2">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Framerate" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Aiv-r8-9k2">
|
||||||
<rect key="frame" x="16" y="106" width="79" height="21"/>
|
<rect key="frame" x="16" y="106" width="79" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
@@ -98,6 +107,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Resolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="pYZ-GR-EwO">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Resolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="pYZ-GR-EwO">
|
||||||
<rect key="frame" x="16" y="171" width="82" height="21"/>
|
<rect key="frame" x="16" y="171" width="82" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
@@ -106,16 +116,17 @@
|
|||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" id="ckc-Dm-8ex">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" id="ckc-Dm-8ex">
|
||||||
<rect key="frame" x="16" y="200" width="209" height="29"/>
|
<rect key="frame" x="16" y="200" width="209" height="29"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="720p"/>
|
<segment title="720p"/>
|
||||||
<segment title="1080p"/>
|
<segment title="1080p"/>
|
||||||
<segment title="Native"/>
|
|
||||||
</segments>
|
</segments>
|
||||||
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="On-Screen Controls" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="LGV-5y-piG">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="On-Screen Controls" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="LGV-5y-piG">
|
||||||
<rect key="frame" x="16" y="236" width="153" height="21"/>
|
<rect key="frame" x="16" y="236" width="153" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
@@ -124,6 +135,7 @@
|
|||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="qSU-wh-tqA">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="qSU-wh-tqA">
|
||||||
<rect key="frame" x="16" y="265" width="209" height="29"/>
|
<rect key="frame" x="16" y="265" width="209" height="29"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="Off"/>
|
<segment title="Off"/>
|
||||||
<segment title="Auto"/>
|
<segment title="Auto"/>
|
||||||
@@ -135,6 +147,7 @@
|
|||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="lGK-vl-pdw">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="lGK-vl-pdw">
|
||||||
<rect key="frame" x="16" y="135" width="209" height="29"/>
|
<rect key="frame" x="16" y="135" width="209" height="29"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="30 Hz"/>
|
<segment title="30 Hz"/>
|
||||||
<segment title="60 Hz"/>
|
<segment title="60 Hz"/>
|
||||||
@@ -142,6 +155,7 @@
|
|||||||
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" cocoaTouchSystemColor="viewFlipsideBackgroundColor"/>
|
<color key="backgroundColor" cocoaTouchSystemColor="viewFlipsideBackgroundColor"/>
|
||||||
</view>
|
</view>
|
||||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
@@ -164,6 +178,7 @@
|
|||||||
<view key="view" contentMode="scaleToFill" id="hGs-BR-t4b">
|
<view key="view" contentMode="scaleToFill" id="hGs-BR-t4b">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
|
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
@@ -184,6 +199,8 @@
|
|||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" translucent="NO" id="RUe-14-4Ya">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" translucent="NO" id="RUe-14-4Ya">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="768" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="768" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<animations/>
|
||||||
|
<color key="barTintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
</navigationBar>
|
</navigationBar>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="wb7-af-jn8" kind="relationship" relationship="rootViewController" id="nkY-JG-Wki"/>
|
<segue destination="wb7-af-jn8" kind="relationship" relationship="rootViewController" id="nkY-JG-Wki"/>
|
||||||
@@ -204,16 +221,19 @@
|
|||||||
<activityIndicatorView opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="white" id="iOs-1X-mSU">
|
<activityIndicatorView opaque="NO" clearsContextBeforeDrawing="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="white" id="iOs-1X-mSU">
|
||||||
<rect key="frame" x="502" y="374" width="20" height="20"/>
|
<rect key="frame" x="502" y="374" width="20" height="20"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dDs-kT-po6">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dDs-kT-po6">
|
||||||
<rect key="frame" x="491" y="402" width="42" height="21"/>
|
<rect key="frame" x="491" y="402" width="42" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
<animations/>
|
||||||
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" id="iUf-9X-GeA"/>
|
<navigationItem key="navigationItem" id="iUf-9X-GeA"/>
|
||||||
<nil key="simulatedStatusBarMetrics"/>
|
<nil key="simulatedStatusBarMetrics"/>
|
||||||
@@ -241,8 +261,10 @@
|
|||||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="whiteLarge" id="N0D-dj-EuF">
|
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="whiteLarge" id="N0D-dj-EuF">
|
||||||
<rect key="frame" x="494" y="365" width="37" height="37"/>
|
<rect key="frame" x="494" y="365" width="37" height="37"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.5" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="0.0" alpha="0.5" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="7706" systemVersion="14D136" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="DL0-L5-LOv">
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="8191" systemVersion="15B38b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" initialViewController="DL0-L5-LOv">
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="7703"/>
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<customFonts key="customFonts">
|
<customFonts key="customFonts">
|
||||||
<mutableArray key="Roboto-Regular.ttf">
|
<mutableArray key="Roboto-Regular.ttf">
|
||||||
@@ -13,9 +14,11 @@
|
|||||||
<scene sceneID="emz-kO-L7q">
|
<scene sceneID="emz-kO-L7q">
|
||||||
<objects>
|
<objects>
|
||||||
<viewController id="dgh-JZ-Q7z" customClass="MainFrameViewController" sceneMemberID="viewController">
|
<viewController id="dgh-JZ-Q7z" customClass="MainFrameViewController" sceneMemberID="viewController">
|
||||||
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" indicatorStyle="black" dataMode="prototypes" id="Rtu-AT-Alw">
|
<collectionView key="view" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" dataMode="prototypes" id="Rtu-AT-Alw" customClass="AppCollectionView">
|
||||||
<rect key="frame" x="0.0" y="64" width="568" height="256"/>
|
<rect key="frame" x="0.0" y="64" width="568" height="256"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<animations/>
|
||||||
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
<inset key="contentInset" minX="40" minY="20" maxX="40" maxY="20"/>
|
<inset key="contentInset" minX="40" minY="20" maxX="40" maxY="20"/>
|
||||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="YcZ-cR-3tK">
|
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="YcZ-cR-3tK">
|
||||||
<size key="itemSize" width="90" height="120"/>
|
<size key="itemSize" width="90" height="120"/>
|
||||||
@@ -24,14 +27,16 @@
|
|||||||
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
|
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
|
||||||
</collectionViewFlowLayout>
|
</collectionViewFlowLayout>
|
||||||
<cells>
|
<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="20" width="90" height="120"/>
|
<rect key="frame" x="20" y="40" width="90" height="120"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="90" height="120"/>
|
<rect key="frame" x="0.0" y="0.0" width="90" height="120"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
|
<animations/>
|
||||||
</collectionViewCell>
|
</collectionViewCell>
|
||||||
</cells>
|
</cells>
|
||||||
<connections>
|
<connections>
|
||||||
@@ -43,8 +48,9 @@
|
|||||||
<navigationItem key="navigationItem" id="1jn-Sf-Xky">
|
<navigationItem key="navigationItem" id="1jn-Sf-Xky">
|
||||||
<barButtonItem key="leftBarButtonItem" style="done" id="zAn-CM-7Yz">
|
<barButtonItem key="leftBarButtonItem" style="done" id="zAn-CM-7Yz">
|
||||||
<button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="pZ9-ft-T24">
|
<button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="pZ9-ft-T24">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="109" height="46"/>
|
<rect key="frame" x="20" y="-1" width="109" height="46"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" name="Roboto-Regular" family="Roboto" pointSize="16"/>
|
<fontDescription key="fontDescription" name="Roboto-Regular" family="Roboto" pointSize="16"/>
|
||||||
<state key="normal" title="Moonlight" image="Logo">
|
<state key="normal" title="Moonlight" image="Logo">
|
||||||
<color key="titleColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="titleColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
@@ -74,6 +80,7 @@
|
|||||||
<view key="view" contentMode="scaleToFill" id="Usg-e0-g4a">
|
<view key="view" contentMode="scaleToFill" id="Usg-e0-g4a">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="568" height="320"/>
|
<rect key="frame" x="0.0" y="0.0" width="568" height="320"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
@@ -97,11 +104,13 @@
|
|||||||
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="20" minValue="1" maxValue="100" id="3nn-MI-9Xu">
|
<slider opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" value="20" minValue="1" maxValue="100" id="3nn-MI-9Xu">
|
||||||
<rect key="frame" x="14" y="49" width="204" height="31"/>
|
<rect key="frame" x="14" y="49" width="204" height="31"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</slider>
|
</slider>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Bitrate: 10 Mbps" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="SBv-Wn-LB7">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Bitrate: 10 Mbps" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="SBv-Wn-LB7">
|
||||||
<rect key="frame" x="16" y="20" width="151" height="21"/>
|
<rect key="frame" x="16" y="20" width="151" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -109,6 +118,7 @@
|
|||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="dLF-qJ-2nY">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="dLF-qJ-2nY">
|
||||||
<rect key="frame" x="16" y="116" width="200" height="29"/>
|
<rect key="frame" x="16" y="116" width="200" height="29"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="30 Hz"/>
|
<segment title="30 Hz"/>
|
||||||
<segment title="60 Hz"/>
|
<segment title="60 Hz"/>
|
||||||
@@ -118,6 +128,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Framerate" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Kkv-DF-MAl">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Framerate" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Kkv-DF-MAl">
|
||||||
<rect key="frame" x="16" y="87" width="79" height="21"/>
|
<rect key="frame" x="16" y="87" width="79" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -125,6 +136,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Resolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8zy-ri-Dqc">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Resolution" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="8zy-ri-Dqc">
|
||||||
<rect key="frame" x="16" y="152" width="82" height="21"/>
|
<rect key="frame" x="16" y="152" width="82" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -132,16 +144,17 @@
|
|||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" id="PCM-t4-Sha">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="0" id="PCM-t4-Sha">
|
||||||
<rect key="frame" x="16" y="181" width="200" height="29"/>
|
<rect key="frame" x="16" y="181" width="200" height="29"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="720p"/>
|
<segment title="720p"/>
|
||||||
<segment title="1080p"/>
|
<segment title="1080p"/>
|
||||||
<segment title="Native"/>
|
|
||||||
</segments>
|
</segments>
|
||||||
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="On-Screen Controls" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HZT-dd-DuQ">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="On-Screen Controls" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="HZT-dd-DuQ">
|
||||||
<rect key="frame" x="16" y="217" width="153" height="21"/>
|
<rect key="frame" x="16" y="217" width="153" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -149,6 +162,7 @@
|
|||||||
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="WGf-9d-eAm">
|
<segmentedControl opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="top" segmentControlStyle="plain" selectedSegmentIndex="1" id="WGf-9d-eAm">
|
||||||
<rect key="frame" x="16" y="246" width="200" height="29"/>
|
<rect key="frame" x="16" y="246" width="200" height="29"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<segments>
|
<segments>
|
||||||
<segment title="Off"/>
|
<segment title="Off"/>
|
||||||
<segment title="Auto"/>
|
<segment title="Auto"/>
|
||||||
@@ -158,6 +172,7 @@
|
|||||||
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</segmentedControl>
|
</segmentedControl>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" red="0.12156862745098039" green="0.12941176470588237" blue="0.14117647058823529" alpha="1" colorSpace="calibratedRGB"/>
|
<color key="backgroundColor" red="0.12156862745098039" green="0.12941176470588237" blue="0.14117647058823529" alpha="1" colorSpace="calibratedRGB"/>
|
||||||
</view>
|
</view>
|
||||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
@@ -181,6 +196,8 @@
|
|||||||
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" translucent="NO" id="0ZA-Ec-QgD">
|
<navigationBar key="navigationBar" contentMode="scaleToFill" barStyle="black" translucent="NO" id="0ZA-Ec-QgD">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<animations/>
|
||||||
|
<color key="barTintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
<textAttributes key="titleTextAttributes">
|
<textAttributes key="titleTextAttributes">
|
||||||
<offsetWrapper key="textShadowOffset" horizontal="0.0" vertical="0.0"/>
|
<offsetWrapper key="textShadowOffset" horizontal="0.0" vertical="0.0"/>
|
||||||
</textAttributes>
|
</textAttributes>
|
||||||
@@ -204,6 +221,7 @@
|
|||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Stage" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2HK-Z5-4Ch">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Stage" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2HK-Z5-4Ch">
|
||||||
<rect key="frame" x="262" y="149" width="45" height="21"/>
|
<rect key="frame" x="262" y="149" width="45" height="21"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -211,9 +229,11 @@
|
|||||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="white" id="0vm-Iv-K4b">
|
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" hidesWhenStopped="YES" animating="YES" style="white" id="0vm-Iv-K4b">
|
||||||
<rect key="frame" x="274" y="121" width="20" height="20"/>
|
<rect key="frame" x="274" y="121" width="20" height="20"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
|
<animations/>
|
||||||
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" id="8uX-4T-BiC"/>
|
<navigationItem key="navigationItem" id="8uX-4T-BiC"/>
|
||||||
<nil key="simulatedStatusBarMetrics"/>
|
<nil key="simulatedStatusBarMetrics"/>
|
||||||
@@ -239,8 +259,10 @@
|
|||||||
<subviews>
|
<subviews>
|
||||||
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="oNu-Gu-QeM">
|
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" animating="YES" style="whiteLarge" translatesAutoresizingMaskIntoConstraints="NO" id="oNu-Gu-QeM">
|
||||||
<rect key="frame" x="266" y="141" width="37" height="37"/>
|
<rect key="frame" x="266" y="141" width="37" height="37"/>
|
||||||
|
<animations/>
|
||||||
</activityIndicatorView>
|
</activityIndicatorView>
|
||||||
</subviews>
|
</subviews>
|
||||||
|
<animations/>
|
||||||
<color key="backgroundColor" white="0.0" alpha="0.5" colorSpace="calibratedWhite"/>
|
<color key="backgroundColor" white="0.0" alpha="0.5" colorSpace="calibratedWhite"/>
|
||||||
</view>
|
</view>
|
||||||
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
@@ -256,9 +278,4 @@
|
|||||||
<resources>
|
<resources>
|
||||||
<image name="Logo" width="32" height="32"/>
|
<image name="Logo" width="32" height="32"/>
|
||||||
</resources>
|
</resources>
|
||||||
<simulatedMetricsContainer key="defaultSimulatedMetrics">
|
|
||||||
<simulatedStatusBarMetrics key="statusBar"/>
|
|
||||||
<simulatedOrientationMetrics key="orientation"/>
|
|
||||||
<simulatedScreenMetrics key="destination" type="retina4"/>
|
|
||||||
</simulatedMetricsContainer>
|
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -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 */;
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
@@ -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"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||