Compare commits

...
166 Commits
Author SHA1 Message Date
Diego Waxemberg cb68b10475 Removed "Headers" build phase from common and created v1.0.4 2016-03-31 20:36:07 -07:00
Cameron Gutman 11c854ce44 Update common-c to support Gen 7 2016-03-31 11:27:02 -04:00
Cameron Gutman 9636f4742b Implement pairing for Gen 7 servers 2016-03-31 11:20:18 -04:00
Cameron Gutman 5867317526 Move the submodule and subproject to their new locations 2016-03-31 07:59:35 -04:00
Cameron Gutman 8a8f7b6903 Remove old submodule 2016-03-31 07:23:37 -04:00
Diego Waxemberg 61b6e25a91 Bumping app version for 1.0.3 2016-03-08 22:35:06 -08:00
Diego Waxemberg 50cff820de Added app icon for ipad pro 2016-03-08 22:34:15 -08:00
Cameron Gutman 4e586a28c8 Update common-c to fix RTSP timeout issue 2016-03-08 13:15:33 -08:00
Cameron Gutman 0702b4ed57 Fix a performance regression in handling the applist response 2016-03-07 16:12:10 -08:00
Cameron Gutman 4a2132a682 Update common-c to support GFE 2.11 2016-03-07 14:45:05 -08:00
Diego Waxemberg ba81d1d6a9 Bumping version and creating build 1.0.2 2016-02-19 13:08:01 -08:00
Cameron Gutman 402ce4b3ec Update common-c to support Gen 5 servers 2016-02-19 15:09:37 -05:00
Cameron Gutman fc713453ad Merge branch 'master' of github.com:moonlight-stream/moonlight-ios 2016-02-16 10:38:25 -05:00
Cameron Gutman b222ccffbb Fix analysis warning 2016-02-16 10:37:59 -05:00
Michelle Bergeron 56ce7329d2 Point to website, add wiki link. 2016-02-15 22:39:32 -08:00
Michelle Bergeron 99ab6db557 Added note about Apple TV in effort to stave off some emails 2016-02-07 21:53:55 -08:00
Cameron Gutman d7adf96f3a Newer GFE versions don't mind resuming another device's stream 2016-02-06 23:10:36 -05:00
Cameron Gutman 0ae58c61a9 Remove apps from the database when they are removed from the app list 2016-01-21 16:24:02 -05:00
Cameron Gutman 2ec7d1d2f1 Use the main queue for the managed object context as a hack to prevent merge conflicts 2016-01-21 16:17:05 -05:00
Cameron Gutman ad1b9059ee Ensure the host matches for app entries 2016-01-21 15:01:15 -05:00
Cameron Gutman 4439c7cce6 Fix initial app list loading after pairing 2016-01-21 14:14:29 -05:00
Cameron Gutman b8a4093c75 Preserve app art when updating the app list 2016-01-21 14:03:07 -05:00
Cameron Gutman ec3748b26e Implement hash and isEqual for TemporaryApp and TemporaryHost 2016-01-21 13:34:34 -05:00
Cameron Gutman 1c1f22e047 Update the database on each server info poll 2016-01-21 12:09:49 -05:00
Cameron Gutman 9aa9b0fc5a Copy the pair state into the temporary host 2016-01-21 11:42:19 -05:00
Cameron Gutman f8e2ca8500 We can't hold onto managed objects in our temporary objects because they can disappear from under us, so do the lookup when we propagate values 2016-01-21 11:29:17 -05:00
Cameron Gutman 3076e29335 Basic database access is working 2015-12-02 00:25:38 -08:00
Cameron Gutman fe616d86c5 Reduce usage of DataManager 2015-12-01 20:56:08 -08:00
Cameron Gutman bfa4856bbe Move non-CoreData backed fields out of CoreData objects 2015-12-01 20:36:08 -08:00
Cameron Gutman 5ea92a7b48 Stop using CoreData-backed objects in any non-DataManager code 2015-12-01 20:31:24 -08:00
Diego Waxemberg 4ba71db7b2 bumped build version 2015-11-14 13:07:31 -08:00
Diego Waxemberg c1e6aeb43c Merge branch 'master' of github.com:moonlight-stream/moonlight-ios 2015-11-14 12:33:44 -08:00
Diego Waxemberg e3ffb66ef0 bumping version code 2015-11-14 12:33:41 -08:00
Cameron Gutman 5daa82b0ba Show the hosts in alphabetical order rather than in an undefined order 2015-11-13 19:55:18 -08:00
Cameron Gutman a8bcc6afba Split the work into 2 jobs per computer to retrieve assets faster 2015-11-13 19:52:35 -08:00
Cameron Gutman e6aa16ad01 Revert "Fix concurrent modification crash in app asset caching code"
This reverts commit ad0705d126.
2015-11-13 19:07:15 -08:00
Cameron Gutman ad0705d126 Fix concurrent modification crash in app asset caching code 2015-11-13 18:30:12 -08:00
Cameron Gutman 2f31f93bf8 Add support for GFE 2.8 2015-11-11 18:24:36 -08:00
Cameron Gutman ea3be613c5 Try 5 times to get the app list before failing 2015-11-11 18:14:59 -08:00
Cameron Gutman b495246f34 Only mark a PC offline if server info failed after 3 straight tries 2015-11-11 18:14:04 -08:00
Cameron Gutman 814470f4bf Set the default bitrate based on the selected resolution and FPS combo 2015-11-11 18:11:33 -08:00
Cameron Gutman 82293a08b6 Increase the request timeout to 7 seconds to give a bit more time for slow app lists to come in 2015-11-11 17:53:13 -08:00
Cameron Gutman 20d66336a7 Cache decoded UIImage objects for the scroll view to fix janky scrolling 2015-11-10 21:23:00 -08:00
Cameron Gutman c8441ec9fa Rasterize the cell layer to increase scrolling performance 2015-11-10 20:48:39 -08:00
Cameron Gutman f72135c227 Mark collection cells opaque for better performance 2015-11-10 20:47:09 -08:00
Michelle Bergeron 100e6e4ce8 Remove info about the beta 2015-11-09 21:53:58 -08:00
Michelle Bergeron ec8be20d62 Download link 2015-11-09 21:53:24 -08:00
Diego Waxemberg 55d48101ef Bumped build version
This is the first attempt at submission to the App Store
2015-11-01 00:12:39 -07:00
Cameron Gutman c36f4c5f84 Remove abort calls 2015-10-31 23:45:37 -07:00
Diego Waxemberg 06289ac4d2 No longer use IDFA, now generate UUID and persist in Core Data. Bumped version to 1.0.0 2015-10-31 23:04:32 -07:00
Cameron Gutman e6a2d5d425 Update project file after Xcode 7.1 2015-10-31 19:00:44 -07:00
Cameron Gutman ea8db9c4ea Update common with new bitrate logic 2015-10-31 19:00:05 -07:00
Cameron Gutman 3773e841d1 Update common to support GFE 2.7 2015-10-25 13:28:24 -07:00
Diego Waxemberg ad1ddd04f3 no longer allow multiple apps to be selected at the same time 2015-10-18 16:52:14 -07:00
Diego Waxemberg 67a8b232b9 added pull arrow to side of screen 2015-10-17 16:16:13 -07:00
Diego Waxemberg 5293c07fc0 fixed issue where we wouldn't terminate the stream on failure 2015-10-17 03:46:09 -07:00
Diego Waxemberg e3a42db007 On-screen controls revamp
- controls are bigger
- dead zone around buttons to avoid accidental mouse clicks and movement
- finished implementing control setup for AutoGCGamepad
- swiping to close stream requires swipe to 1/4 the screen width
- no longer send mouse movement if delta is too small
2015-10-17 03:02:55 -07:00
Diego Waxemberg 3b1462af22 removed support for native resolution stream 2015-10-16 23:38:14 -07:00
Cameron Gutman 74a0c5b1cd Merge branch 'master' of github.com:moonlight-stream/moonlight-ios 2015-09-30 20:44:26 -07:00
Cameron Gutman 05a5e4fa64 Fix a crash when apps are removed from GFE 2015-09-30 20:44:14 -07:00
Cameron Gutman b6445295a7 Use a temporary app object and database lock to avoid saving while the database is not in a consistent state 2015-09-30 20:34:52 -07:00
Diego Waxemberg 391605ef36 ignored the new xcsmblueprint files 2015-09-30 19:18:21 -07:00
Diego Waxemberg 695499dea9 host and app buttons now have feedback when tapped 2015-09-30 19:13:37 -07:00
Cameron Gutman 9ba7f35444 Require full-screen since the streaming game will be the primary interaction for the device 2015-09-30 18:00:52 -07:00
Cameron Gutman 37dc00735b Enabling bit code is causing linker errors when deploying to real devices for some reason. Turning it back off. 2015-09-29 00:06:27 -07:00
Cameron Gutman 920cbadc91 Add a workaround/hack to fix duplicating machines 2015-09-29 00:04:40 -07:00
Cameron Gutman bc53b4dc32 First stab at fixing on screen controls on various devices 2015-09-28 23:20:27 -07:00
Cameron Gutman 6015c38d17 Only display the native resolution dialog if the user has just chosen native resolution. Make the dialog a little nicer too. 2015-09-28 22:50:54 -07:00
Cameron Gutman 4ea8694a7d Fix status bar hiding while streaming on iPad 2015-09-28 21:49:46 -07:00
Cameron Gutman 00f01196fb Update placeholder app images to be the correct aspect ratio and invert the colors to better show against the new background 2015-09-28 21:40:10 -07:00
Diego Waxemberg 543639c93e Merge branch 'master' of github.com:moonlight-stream/moonlight-ios 2015-09-28 21:19:18 -07:00
Diego Waxemberg 1da877fed7 Changed theme to light/dark gray and updated launch screen. Also added a border and drop shadow to app icons 2015-09-28 21:18:35 -07:00
Cameron Gutman 396b5fc156 Update common 2015-09-28 19:22:28 -07:00
Cameron Gutman 297dfd4159 Update project file
- Change organization name
- Enable bit code
- Update Xcode compatibility version
2015-09-28 19:09:49 -07:00
Cameron Gutman 23e9d48b0d Update common-c and use the new LiInitializeXXX() functions 2015-08-16 12:27:21 -07:00
Cameron Gutman 9ec650a84f Zero audio renderer callbacks before populating 2015-08-12 01:18:22 -07:00
Cameron Gutman 90bdbc4ae0 Update common library 2015-08-12 01:11:38 -07:00
Cameron Gutman dd5f06723b Update common library to get assertions and a GFE 2.5.11 fix 2015-07-20 17:37:13 -07:00
Michelle Bergeron 55b2871b83 Update about beta program 2015-07-16 16:14:28 -07:00
Diego Waxemberg c8b13126d0 Adding build 0.9.2 2015-07-15 20:24:13 -07:00
Diego Waxemberg 96cfe0b70d bumping build number for new beta 2015-07-15 20:21:29 -07:00
Cameron Gutman 6dbb938368 Speed up app icon load time by 2 seconds by only waiting if it failed 2015-07-12 00:43:20 -07:00
Cameron Gutman 46fe7a8aed Don't show error messages if the PC isn't selected anymore 2015-07-12 00:30:44 -07:00
Cameron Gutman 3151ac6bf0 Remove hosts from discovery while they're handling operations the for UI. Sometimes these operations take a while and block the server from responding to our serverinfo queries that determine its online status. 2015-07-12 00:23:48 -07:00
Cameron Gutman dc5210f691 Propagate the running flag to the applist cache 2015-07-12 00:12:53 -07:00
Cameron Gutman 1f02265003 Fix a race condition that could cause an app to be populated with a null host 2015-07-11 23:59:09 -07:00
Cameron Gutman e4af9032e2 Implement a fast path to the app grid for online, paired machines with cached app lists. 2015-07-11 21:59:41 -07:00
Cameron Gutman e8650b2420 Don't use lightweight generics for Xcode 6 compatibility 2015-07-11 21:59:01 -07:00
Diego Waxemberg 9c6b718be2 fixed issue with apps duplicating in app list 2015-07-11 18:47:05 -07:00
Cameron Gutman 8f12114a56 Merge branch 'master' into persist-app-list 2015-07-11 01:38:30 -07:00
Cameron Gutman dc6ebffab1 Allow unpaired computer to be deleted. Remove the unpairing option since it hasn't worked for ages. 2015-07-11 01:29:28 -07:00
Cameron Gutman 13e894e9a3 Refactor app list to be non-static and sorted in alphabetical order 2015-07-11 01:28:52 -07:00
Cameron Gutman 4c95773131 Long clicking hosts that aren't paired doesn't bring up any useful options, so disable it 2015-07-11 00:13:58 -07:00
Cameron Gutman 38776a01e4 Only create an app if an app ID was found 2015-07-11 00:10:13 -07:00
Cameron Gutman b2563e534d Null terminate strings before passing them to BIO_puts 2015-07-10 22:33:09 -07:00
Diego Waxemberg 37f25c1f97 fixed some bugs with saving app list to database 2015-07-10 22:19:25 -07:00
Diego Waxemberg 642085ca32 App lists are now persisted in the database 2015-07-10 21:22:57 -07:00
Cameron Gutman 5dee29a21c Add a play indicator for running apps 2015-07-10 18:09:12 -07:00
Cameron Gutman b01d13976b Improve speed and reliability of host detection 2015-07-10 12:18:09 -07:00
Cameron Gutman ae1c83a011 Fix returning to the host selection screen after a failure 2015-07-10 11:52:27 -07:00
Cameron Gutman e5f962dc3f Perform stricter status checks during pairing to fix a crash when paired=3 2015-07-10 11:43:47 -07:00
Cameron Gutman 54dd79d2dd Remove OK button from pairing PIN dialog, since it dismisses automatically 2015-07-10 11:37:32 -07:00
Cameron Gutman 935fb6ffe3 Fix streaming over the external IP address when discovered via mDNS 2015-07-10 00:28:51 -07:00
Cameron Gutman 48d1c1a080 Commit host removals immediately so they remain if the app is unexpectedly terminated 2015-07-09 23:52:05 -07:00
Cameron Gutman 2d02ce2a1b Change the PC status to offline and return to the host selection screen if server info or applist is unavailable 2015-07-09 23:48:18 -07:00
Cameron Gutman 29fda59a72 Add applist and server info fetching error dialogs. Open the options menu when a user taps an offline PC. 2015-07-09 21:15:52 -07:00
Cameron Gutman 05f0dfd4f5 Replace dispatch_sync with dispatch_async in pairing 2015-07-09 21:02:19 -07:00
Cameron Gutman 0bdc5a83f1 Go directly to the app list after pairing like Android 2015-07-09 20:39:15 -07:00
Cameron Gutman 8688bf1210 Add failure handling for quitting apps 2015-07-09 20:33:23 -07:00
Cameron Gutman bf0858d57e Fix spelling mistake 2015-07-09 20:32:03 -07:00
Cameron Gutman 8d4d391310 For real this time - Update common to pickup Xcode 7 changes 2015-07-08 23:49:34 -07:00
Cameron Gutman 8fb15336c4 Update common to pickup Xcode 7 changes 2015-07-08 23:45:20 -07:00
Cameron Gutman 883385c42b Merge branch 'xcode-7.0' 2015-07-08 23:43:03 -07:00
Cameron Gutman 6d1139796e Cherry pick e58eb5f - Removing LimelightTests target 2015-07-08 23:25:37 -07:00
Cameron Gutman e58eb5f56a Remove LimelightTests target since it's old and unused 2015-07-08 23:21:05 -07:00
Cameron Gutman 2b0ce49646 Merge branch 'master' into xcode-7.0
Conflicts:
	limelight-common-c
2015-07-08 23:13:55 -07:00
Cameron Gutman 73364127d2 Fix pairing with GFE 2.4.5.57+ 2015-07-08 23:03:23 -07:00
Cameron Gutman 84a986bc88 Switch from deprecated NSURLConnection to NSURLSession 2015-07-08 22:35:25 -07:00
Cameron Gutman f13051aa31 Prepare for HTTP requests 2015-07-08 21:31:47 -07:00
Cameron Gutman 6bb559303b Remove executeRequest from HttpManager. It has some show-stopping bugs, like leaking semaphore counts (since it never waited) and being generally thread-unsafe. Implementing it in a way that would be asynchronous and thread-safe is a non-trivial task, so I've opted to remove it and change callers to use executeRequestSynchronously. 2015-07-08 21:26:01 -07:00
Cameron Gutman b7324f9a44 Remove a parameter from LiStartConnection 2015-07-08 19:17:58 -07:00
Cameron Gutman c0b2bbe552 Remove a parameter from LiStartConnection 2015-07-08 19:16:48 -07:00
Cameron Gutman 8c36cf40fd Update common for a leak fix and other minor bugs 2015-07-08 19:16:17 -07:00
Diego Waxemberg 717296269f updating common to xcode 7.0 settings 2015-07-04 11:23:31 -07:00
Diego Waxemberg 4be29abede updated project settings for xcode 7.0 2015-07-04 11:13:05 -07:00
Cameron Gutman 528af9684e Update common-c to fix scrolling issues 2015-06-25 21:54:39 -07:00
Cameron Gutman ff7a4ef190 Update common with better error messages 2015-06-25 00:11:09 -07:00
Cameron Gutman 99a2dbb956 Switch from deprecated UIAlertView to UIAlertController for pairing 2015-06-23 22:23:12 -07:00
Cameron Gutman 280341791a Use non-deprecated NSManagedObjectContext initializer 2015-06-23 22:09:08 -07:00
Cameron Gutman 1759565920 Removed supportedInterfaceOrientations since it didn't do anything and caused a warning on iOS 9 because the prototype seems to have changed 2015-06-23 22:01:59 -07:00
Cameron Gutman f57fa678f6 Escaping the URL strings is not required because no reserved characters are ever sent. Plus it's deprecated in iOS 9. 2015-06-23 21:58:32 -07:00
Cameron Gutman f8b5b16109 Create alert dialogs on the main thread 2015-06-23 21:46:58 -07:00
Cameron Gutman 005a678089 Disable App Transport Security since we need to make requests over HTTP and HTTPS to servers with self-signed certificates 2015-06-20 13:11:49 -07:00
Cameron Gutman 315dd53dcb Disable bitcode until native libraries are rebuilt for it 2015-06-20 13:06:02 -07:00
Cameron Gutman bb24495b3f Warning fix (char* -> const char*) 2015-06-19 20:53:14 -07:00
Cameron Gutman b9f2764990 Update common 2015-06-17 23:48:58 -07:00
Cameron Gutman a9a00629b1 Use API 1.1 common in preparation for IPv6 requirement 2015-06-17 23:32:00 -07:00
Diego Waxemberg 1223a9013f updated libopus and Opus build scrips 2015-06-01 22:25:56 -07:00
Diego Waxemberg ab019eef0f got rid of dumb compiler warnings 2015-06-01 00:36:21 -07:00
Diego Waxemberg 20f82ff739 updated project to Moonlight and created build 0.9.1 2015-05-31 23:57:47 -07:00
Diego Waxemberg 4d55a6a7e9 missed a file in earlier commit, this actually fixes the on screen control issues 2015-05-31 23:57:04 -07:00
Cameron Gutman d7ec41d56e Fix a controller batching bug 2015-06-01 01:30:18 -05:00
Diego Waxemberg a6a1929a43 updated icons to have different resolutions and fixed layout for smaller iPhones 2015-05-31 23:22:20 -07:00
Cameron Gutman 722850ceb6 Fix mouse batching bug 2015-05-29 16:42:00 -05:00
Diego Waxemberg 5a976764c3 now use custom edge swipe detection 2015-05-29 00:46:43 -07:00
Diego Waxemberg f90becb2f6 no longer try to parse responses when a network error occurs 2015-05-29 00:15:48 -07:00
Diego Waxemberg 5296b2eb39 now stop app asset requests before attempting to start a stream 2015-05-28 23:47:30 -07:00
Diego Waxemberg 987a30e15f updated style for moonlight 2015-05-28 23:39:13 -07:00
Diego Waxemberg 0880c3639c Merge branch 'master' of github.com:limelight-stream/limelight-ios 2015-05-28 23:38:09 -07:00
Diego Waxemberg 2972d40d92 added limit to app asset request 2015-05-28 23:37:55 -07:00
Cameron Gutman c4430ef18d Use the new optimizations added to common-c 2015-05-28 15:17:37 -05:00
Cameron Gutman 6b97af13bf Update common-c and remove unused callbacks 2015-05-13 23:13:20 -05:00
Cameron Gutman cd18ca64bb Fix build of tests and a warning in the main app 2015-05-13 23:07:05 -05:00
Diego Waxemberg d3c6302681 bumping common 2015-05-12 21:54:00 -04:00
Diego Waxemberg 58bd3cc706 Merge branch 'master' of github.com:limelight-stream/limelight-ios 2015-05-12 21:49:31 -04:00
Diego Waxemberg 8d3401f962 Changed name from Limelight to Moonlight due to C&D from Limelight
Networks, Inc.
2015-05-12 21:48:30 -04:00
Cameron Gutman dfc86015bd Renaming projects to Moonlight 2015-04-21 21:43:57 -04:00
Diego Waxemberg 772ee3a680 v0.9.0 first release candidate 2015-04-05 22:02:45 -07:00
Cameron Gutman f217ca9bbe Set the bitrate slider value based on the real interval instead of 1000 2015-04-06 00:48:54 -04:00
Cameron Gutman fab8d604d2 Check UUID length is non-zero before adding a new host 2015-04-06 00:27:36 -04:00
Cameron Gutman 7767ae497b Revert "Added a hack to de-duplicate hosts and some more checks when adding a host to minimize the chances for dupes"
This reverts commit fd9ee45dac.
2015-04-06 00:22:51 -04:00
Cameron Gutman 58e41dfcf1 Revert "forgot to add project file"
This reverts commit dfa07bf94b.
2015-04-06 00:22:45 -04:00
Diego Waxemberg 796ab2bf90 should now save hosts discovered through mdns 2015-04-05 21:18:22 -07:00
Diego Waxemberg dfa07bf94b forgot to add project file 2015-04-05 20:30:44 -07:00
Diego Waxemberg f43c74d59b trim whitespace from server info responses 2015-04-05 20:30:13 -07:00
Diego Waxemberg fd9ee45dac Added a hack to de-duplicate hosts and some more checks when adding a host to minimize the chances for dupes 2015-04-05 20:08:21 -07:00
269 changed files with 3331 additions and 1476 deletions
+1
View File
@@ -1,2 +1,3 @@
**/xcuserdata/
**/Moonlight.xcscmblueprint
Build
+3 -3
View File
@@ -1,3 +1,3 @@
[submodule "limelight-common-c"]
path = limelight-common-c
url = git@github.com:limelight-stream/limelight-common-c.git
[submodule "moonlight-common/moonlight-common-c"]
path = moonlight-common/moonlight-common-c
url = https://github.com/moonlight-stream/moonlight-common-c.git
+27 -11
View File
@@ -31,43 +31,44 @@ do
exit 1
fi
echo "Compiling source for $ARCH in directory $OPUS_DIR"
echo "cd $OPUS_DIR"
cd $OPUS_DIR
DIST_DIR=$DIST_DIR_BASE-$ARCH
echo "mkdir -p $DIST_DIR"
mkdir -p $DIST_DIR
CFLAGS_ARCH=$ARCH
case $ARCH in
armv7)
EXTRA_FLAGS="--with-pic --enable-fixed-point"
EXTRA_CFLAGS="-mcpu=cortex-a8 -mfpu=neon"
EXTRA_CFLAGS="-mcpu=cortex-a8 -mfpu=neon -miphoneos-version-min=7.1"
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
IOSSDK=iPhoneOS${IOSSDK_VER}
IOSSDK=iPhoneOS
;;
armv7s)
EXTRA_FLAGS="--with-pic --enable-fixed-point"
EXTRA_CFLAGS="-mcpu=cortex-a9 -mfpu=neon -miphoneos-version-min=6.0"
EXTRA_CFLAGS="-mcpu=cortex-a9 -mfpu=neon -miphoneos-version-min=7.1"
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
IOSSDK=iPhoneOS${IOSSDK_VER}
IOSSDK=iPhoneOS
;;
aarch64)
CFLAGS_ARCH="arm64"
EXTRA_FLAGS="--with-pic --enable-fixed-point"
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
IOSSDK=iPhoneOS${IOSSDK_VER}
IOSSDK=iPhoneOS
;;
x86_64)
EXTRA_FLAGS="--with-pic"
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
IOSSDK=iPhoneSimulator${IOSSDK_VER}
IOSSDK=iPhoneSimulator
;;
i386)
EXTRA_FLAGS="--with-pic"
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
IOSSDK=iPhoneSimulator${IOSSDK_VER}
IOSSDK=iPhoneSimulator
;;
*)
echo "Unsupported architecture ${ARCH}"
@@ -76,7 +77,7 @@ do
esac
echo "Configuring opus for $ARCH..."
echo "./autogen.sh"
./autogen.sh
CFLAGS="-g -O2 -pipe -arch ${CFLAGS_ARCH} \
@@ -86,7 +87,10 @@ do
LDFLAGS="-arch ${CFLAGS_ARCH} \
-isysroot ${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
-L${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk/usr/lib"
echo "CFLAGS=$CFLAGS"
echo "LDFLAGS=$LDFLAGS"
export CFLAGS
export LDFLAGS
@@ -100,7 +104,15 @@ do
export NM="/usr/bin/nm"
export RANLIB="/usr/bin/ranlib"
export STRIP="/usr/bin/strip"
echo "./configure \
--prefix=$DIST_DIR \
--host=${ARCH}-apple-darwin \
--with-sysroot=${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
--enable-static=yes \
--enable-shared=no \
--disable-doc \
${EXTRA_FLAGS}"
./configure \
--prefix=$DIST_DIR \
--host=${ARCH}-apple-darwin \
@@ -111,10 +123,14 @@ do
${EXTRA_FLAGS}
echo "Installing opus for $ARCH..."
echo "make clean"
make clean
echo "make -j$NJOB V=1"
make -j$NJOB V=1
echo "make install"
make install
echo "cd $SCRIPT_DIR"
cd $SCRIPT_DIR
if [ -d $DIST_DIR/bin ]
-1
View File
@@ -7,7 +7,6 @@ source config.sh
SCRIPT_DIR=$( (cd -P $(dirname $0) && pwd) )
DIST_DIR_BASE=${DIST_DIR_BASE:="$SCRIPT_DIR/dist"}
git submodule update --init opus
cd opus
git checkout master
git pull origin master
Binary file not shown.
Binary file not shown.
+41 -31
View File
@@ -1,41 +1,51 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14C81f" 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>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text=" Copyright (c) 2014 Limelight Stream. All rights reserved." textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" minimumFontSize="9" translatesAutoresizingMaskIntoConstraints="NO" id="8ie-xW-0ye">
<rect key="frame" x="22" y="439" width="437" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="0.070588235294117646" green="0.45490196078431372" blue="0.074509803921568626" alpha="1" colorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
<variation key="widthClass=compact">
<fontDescription key="fontDescription" type="system" pointSize="11"/>
</variation>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Limelight Flat Design Banner" translatesAutoresizingMaskIntoConstraints="NO" id="lr8-1h-ydW">
<rect key="frame" x="-8" y="115" width="496" height="251"/>
</imageView>
</subviews>
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
<constraints>
<constraint firstAttribute="centerY" secondItem="lr8-1h-ydW" secondAttribute="centerY" id="C8A-9E-cM6"/>
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Gnz-uJ-CDw"/>
<constraint firstAttribute="centerX" secondItem="lr8-1h-ydW" secondAttribute="centerX" id="WCv-Cd-TyR"/>
<constraint firstAttribute="centerX" secondItem="8ie-xW-0ye" secondAttribute="centerX" id="ZEH-qu-HZ9"/>
</constraints>
<nil key="simulatedStatusBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<point key="canvasLocation" x="404" y="445"/>
</view>
<navigationController id="vV9-32-ww6">
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" id="y2P-aE-Haa">
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<color key="barTintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
</navigationBar>
<viewControllers>
<viewController id="l6V-ue-5Om">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="rEZ-vx-akr"/>
<viewControllerLayoutGuide type="bottom" id="gBD-cy-cth"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="6lF-fc-kpK">
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="rW0-BH-s7l">
<barButtonItem key="leftBarButtonItem" enabled="NO" id="d9R-Zo-Uml">
<button key="customView" opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" id="9JC-B5-BAE">
<rect key="frame" x="-23" y="-15" width="46" height="30"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<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>
<resources>
<image name="Limelight Flat Design Banner" width="496" height="251"/>
<image name="Logo" width="32" height="32"/>
</resources>
</document>
-18
View File
@@ -1,18 +0,0 @@
//
// App.h
// Limelight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface App : NSObject
@property NSString* appId;
@property NSString* appName;
@property UIImage* appImage;
@property BOOL isRunning;
@end
-15
View File
@@ -1,15 +0,0 @@
//
// App.m
// Limelight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
//
#import "App.h"
#import "HttpManager.h"
@implementation App
@synthesize appId, appName, appImage, isRunning;
@end
+13
View File
@@ -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
+28
View File
@@ -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
+2 -2
View File
@@ -1,9 +1,9 @@
//
// AppDelegate.h
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/17/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
+13 -33
View File
@@ -1,9 +1,9 @@
//
// AppDelegate.m
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/17/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "AppDelegate.h"
@@ -83,10 +83,7 @@ static NSOperationQueue* mainQueue;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// 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();
Log(LOG_E, @"Critical database error: %@, %@", error, [error userInfo]);
}
}
}
@@ -103,7 +100,7 @@ static NSOperationQueue* mainQueue;
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
@@ -136,32 +133,15 @@ static NSOperationQueue* mainQueue;
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
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.
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
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();
}
// Log the error
Log(LOG_E, @"Critical database error: %@, %@", error, [error userInfo]);
// Drop the database
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil];
// Try again
return [self persistentStoreCoordinator];
}
return _persistentStoreCoordinator;
}
+13
View File
@@ -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
+28
View File
@@ -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
+6 -4
View File
@@ -1,9 +1,9 @@
//
// CryptoManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/14/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -11,14 +11,16 @@
@interface CryptoManager : NSObject
+ (void) generateKeyPairUsingSSl;
+ (NSString*) getUniqueID;
+ (NSData*) readCertFromFile;
+ (NSData*) readKeyFromFile;
+ (NSData*) readP12FromFile;
+ (NSData*) getSignatureFromCert:(NSData*)cert;
+ (NSData*) nullTerminateString:(NSData*)data;
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN;
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN;
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN;
- (NSData*) SHA1HashData:(NSData*)data;
- (NSData*) SHA256HashData:(NSData*)data;
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
+27 -24
View File
@@ -1,14 +1,13 @@
//
// CryptoManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/14/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "CryptoManager.h"
#import "mkcert.h"
#import <AdSupport/ASIdentifierManager.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
@@ -17,19 +16,31 @@
#include <openssl/evp.h>
@implementation CryptoManager
static const int SHA1_DIGEST_LENGTH = 20;
static const int SHA1_HASH_LENGTH = 20;
static const int SHA256_HASH_LENGTH = 32;
static NSData* key = nil;
static NSData* cert = nil;
static NSData* p12 = nil;
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN {
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN {
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
}
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN {
return [[self SHA256HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
}
- (NSData*) SHA1HashData:(NSData*)data {
unsigned char sha1[SHA1_DIGEST_LENGTH];
unsigned char sha1[SHA1_HASH_LENGTH];
SHA1([data bytes], [data length], sha1);
NSData* bytes = [NSData dataWithBytes:sha1 length:20];
NSData* bytes = [NSData dataWithBytes:sha1 length:sizeof(sha1)];
return bytes;
}
- (NSData*) SHA256HashData:(NSData*)data {
unsigned char sha256[SHA256_HASH_LENGTH];
SHA256([data bytes], [data length], sha256);
NSData* bytes = [NSData dataWithBytes:sha256 length:sizeof(sha256)];
return bytes;
}
@@ -76,8 +87,14 @@ static NSData* p12 = nil;
return (((int)[data length] + 15) / 16) * 16;
}
+ (NSData*) nullTerminateString:(NSData*)data {
NSMutableData* mutData = [NSMutableData dataWithData:data];
[mutData appendBytes:"" length:1];
return mutData;
}
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert {
const char* buffer = [cert bytes];
const char* buffer = [[CryptoManager nullTerminateString:cert] bytes];
X509* x509;
BIO* bio = BIO_new(BIO_s_mem());
BIO_puts(bio, buffer);
@@ -105,7 +122,7 @@ static NSData* p12 = nil;
}
- (NSData *)signData:(NSData *)data withKey:(NSData *)key {
const char* buffer = [key bytes];
const char* buffer = [[CryptoManager nullTerminateString:key] bytes];
BIO* bio = BIO_new(BIO_s_mem());
BIO_puts(bio, buffer);
@@ -188,7 +205,7 @@ static NSData* p12 = nil;
}
+ (NSData *)getSignatureFromCert:(NSData *)cert {
const char* buffer = [cert bytes];
const char* buffer = [[CryptoManager nullTerminateString:cert] bytes];
X509* x509;
BIO* bio = BIO_new(BIO_s_mem());
BIO_puts(bio, buffer);
@@ -223,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
+15
View File
@@ -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
+32
View File
@@ -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
-2
View File
@@ -85,7 +85,6 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
if (*pkeyp == NULL) {
if ((pk=EVP_PKEY_new()) == NULL) {
abort();
return(0);
}
} 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);
if (!EVP_PKEY_assign_RSA(pk, rsa)) {
abort();
goto err;
}
+2 -2
View File
@@ -1,9 +1,9 @@
//
// mkcert.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/16/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#ifndef Limelight_mkcert_h
@@ -0,0 +1,25 @@
//
// App+CoreDataProperties.h
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
// Delete this file and regenerate it using "Create NSManagedObject Subclass…"
// to keep your implementation up to date with your model.
//
#import "App.h"
NS_ASSUME_NONNULL_BEGIN
@interface App (CoreDataProperties)
@property (nullable, nonatomic, retain) NSString *id;
@property (nullable, nonatomic, retain) NSData *image;
@property (nullable, nonatomic, retain) NSString *name;
@property (nullable, nonatomic, retain) Host *host;
@end
NS_ASSUME_NONNULL_END
+18
View File
@@ -0,0 +1,18 @@
//
// App.h
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
@class Host;
@interface App : NSManagedObject
@end
#import "App+CoreDataProperties.h"
+13
View File
@@ -0,0 +1,13 @@
//
// App.m
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import "App.h"
@implementation App
@end
+17 -11
View File
@@ -1,25 +1,31 @@
//
// DataManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Settings.h"
#import "AppDelegate.h"
#import "Host.h"
#import "TemporaryHost.h"
#import "TemporaryApp.h"
#import "TemporarySettings.h"
@interface DataManager : NSObject
@property (strong, nonatomic) AppDelegate* appDelegate;
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls;
- (Settings*) retrieveSettings;
- (NSArray*) retrieveHosts;
- (void) saveHosts;
- (Host*) createHost;
- (void) removeHost:(Host*)host;
- (NSArray*) getHosts;
- (void) updateHost:(TemporaryHost*)host;
- (void) updateAppsForExistingHost:(TemporaryHost *)host;
- (void) updateIconForExistingApp:(TemporaryApp*)app;
- (void) removeHost:(TemporaryHost*)host;
- (void) removeApp:(TemporaryApp*)app;
- (TemporarySettings*) getSettings;
- (void) updateUniqueId:(NSString*)uniqueId;
- (NSString*) getUniqueId;
@end
+173 -34
View File
@@ -1,43 +1,138 @@
//
// DataManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "DataManager.h"
#import "TemporaryApp.h"
#import "TemporarySettings.h"
#import "Settings.h"
@implementation DataManager
@implementation DataManager {
NSManagedObjectContext *_managedObjectContext;
AppDelegate *_appDelegate;
}
- (id) init {
self = [super init];
self.appDelegate = [[UIApplication sharedApplication] delegate];
_appDelegate = [[UIApplication sharedApplication] delegate];
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_managedObjectContext setPersistentStoreCoordinator:_appDelegate.persistentStoreCoordinator];
return self;
}
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
Settings* settingsToSave = [self retrieveSettings];
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
// Bitrate is persisted in kbps
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
settingsToSave.height = [NSNumber numberWithInteger:height];
settingsToSave.width = [NSNumber numberWithInteger:width];
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
- (void) updateUniqueId:(NSString*)uniqueId {
[_managedObjectContext performBlockAndWait:^{
[self retrieveSettings].uniqueId = uniqueId;
[self saveData];
}];
}
NSError* error;
if (![[self.appDelegate managedObjectContext] save:&error]) {
Log(LOG_E, @"Unable to save settings to database: %@", error);
}
[self.appDelegate saveContext];
- (NSString*) getUniqueId {
__block NSString *uid;
[_managedObjectContext performBlockAndWait:^{
uid = [self retrieveSettings].uniqueId;
}];
return uid;
}
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
[_managedObjectContext performBlockAndWait:^{
Settings* settingsToSave = [self retrieveSettings];
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
// Bitrate is persisted in kbps
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
settingsToSave.height = [NSNumber numberWithInteger:height];
settingsToSave.width = [NSNumber numberWithInteger:width];
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
[self saveData];
}];
}
- (void) updateHost:(TemporaryHost *)host {
[_managedObjectContext performBlockAndWait:^{
// Add a new persistent managed object if one doesn't exist
Host* parent = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
if (parent == nil) {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:_managedObjectContext];
parent = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
}
// Push changes from the temp host to the persistent one
[host propagateChangesToParent:parent];
[self saveData];
}];
}
- (void) updateAppsForExistingHost:(TemporaryHost *)host {
[_managedObjectContext performBlockAndWait:^{
Host* parent = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
if (parent == nil) {
// The host must exist to be updated
return;
}
NSMutableSet *applist = [[NSMutableSet alloc] init];
NSArray *appRecords = [self fetchRecords:@"App"];
for (TemporaryApp* app in host.appList) {
// Add a new persistent managed object if one doesn't exist
App* parentApp = [self getAppForTemporaryApp:app withAppRecords:appRecords];
if (parentApp == nil) {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"App" inManagedObjectContext:_managedObjectContext];
parentApp = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
}
[app propagateChangesToParent:parentApp withHost:parent];
[applist addObject:parentApp];
}
parent.appList = applist;
[self saveData];
}];
}
- (void) updateIconForExistingApp:(TemporaryApp*)app {
[_managedObjectContext performBlockAndWait:^{
App* parentApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
if (parentApp == nil) {
// The app must exist to be updated
return;
}
parentApp.image = app.image;
[self saveData];
}];
}
- (TemporarySettings*) getSettings {
__block TemporarySettings *tempSettings;
[_managedObjectContext performBlockAndWait:^{
tempSettings = [[TemporarySettings alloc] initFromSettings:[self retrieveSettings]];
}];
return tempSettings;
}
- (Settings*) retrieveSettings {
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
if (fetchedRecords.count == 0) {
// create a new settings object with the default values
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:[self.appDelegate managedObjectContext]];
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:_managedObjectContext];
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
return settings;
} else {
@@ -46,40 +141,84 @@
}
}
- (Host*) createHost {
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]];
Host* host = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
return host;
- (void) removeApp:(TemporaryApp*)app {
[_managedObjectContext performBlockAndWait:^{
App* managedApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
if (managedApp != nil) {
[_managedObjectContext deleteObject:managedApp];
[self saveData];
}
}];
}
- (void) removeHost:(Host*)host {
[[self.appDelegate managedObjectContext] deleteObject:host];
- (void) removeHost:(TemporaryHost*)host {
[_managedObjectContext performBlockAndWait:^{
Host* managedHost = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
if (managedHost != nil) {
[_managedObjectContext deleteObject:managedHost];
[self saveData];
}
}];
}
- (void) saveHosts {
- (void) saveData {
NSError* error;
if (![[self.appDelegate managedObjectContext] save:&error]) {
if (![_managedObjectContext save:&error]) {
Log(LOG_E, @"Unable to save hosts to database: %@", error);
}
[self.appDelegate saveContext];
[_appDelegate saveContext];
}
- (NSArray*) retrieveHosts {
return [self fetchRecords:@"Host"];
- (NSArray*) getHosts {
__block NSMutableArray *tempHosts = [[NSMutableArray alloc] init];
[_managedObjectContext performBlockAndWait:^{
NSArray *hosts = [self fetchRecords:@"Host"];
for (Host* host in hosts) {
[tempHosts addObject:[[TemporaryHost alloc] initFromHost:host]];
}
}];
return tempHosts;
}
// Only call from within performBlockAndWait!!!
- (Host*) getHostForTemporaryHost:(TemporaryHost*)tempHost withHostRecords:(NSArray*)hosts {
for (Host* host in hosts) {
if ([tempHost.uuid isEqualToString:host.uuid]) {
return host;
}
}
return nil;
}
// Only call from within performBlockAndWait!!!
- (App*) getAppForTemporaryApp:(TemporaryApp*)tempApp withAppRecords:(NSArray*)apps {
for (App* app in apps) {
if ([app.id isEqualToString:tempApp.id] &&
[app.host.uuid isEqualToString:app.host.uuid]) {
return app;
}
}
return nil;
}
- (NSArray*) fetchRecords:(NSString*)entityName {
NSArray* fetchedRecords;
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 setAffectedStores:[NSArray arrayWithObjects:[[self.appDelegate persistentStoreCoordinator] persistentStoreForURL:[self.appDelegate getStoreURL]], nil]];
NSError* error;
NSArray* fetchedRecords = [[self.appDelegate managedObjectContext] executeFetchRequest:fetchRequest error:&error];
fetchedRecords = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
//TODO: handle errors
return fetchedRecords;
}
@end
@@ -0,0 +1,38 @@
//
// Host+CoreDataProperties.h
// Moonlight
//
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
// Delete this file and regenerate it using "Create NSManagedObject Subclass…"
// to keep your implementation up to date with your model.
//
#import "Host.h"
NS_ASSUME_NONNULL_BEGIN
@interface Host (CoreDataProperties)
@property (nullable, nonatomic, retain) NSString *address;
@property (nullable, nonatomic, retain) NSString *externalAddress;
@property (nullable, nonatomic, retain) NSString *localAddress;
@property (nullable, nonatomic, retain) NSString *mac;
@property (nullable, nonatomic, retain) NSString *name;
@property (nullable, nonatomic, retain) NSNumber *pairState;
@property (nullable, nonatomic, retain) NSString *uuid;
@property (nullable, nonatomic, retain) NSSet *appList;
@end
@interface Host (CoreDataGeneratedAccessors)
- (void)addAppListObject:(NSManagedObject *)value;
- (void)removeAppListObject:(NSManagedObject *)value;
- (void)addAppList:(NSSet *)values;
- (void)removeAppList:(NSSet *)values;
@end
NS_ASSUME_NONNULL_END
+5 -12
View File
@@ -1,9 +1,9 @@
//
// Host.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -12,13 +12,6 @@
@interface Host : NSManagedObject
@property (nonatomic, retain) NSString * name;
@property (nonatomic, retain) NSString * address;
@property (nonatomic, retain) NSString * localAddress;
@property (nonatomic, retain) NSString * externalAddress;
@property (nonatomic, retain) NSString * uuid;
@property (nonatomic, retain) NSString * mac;
@property (nonatomic) BOOL online;
@property (nonatomic) PairState pairState;
@end
#import "Host+CoreDataProperties.h"
+3 -13
View File
@@ -1,23 +1,13 @@
//
// Host.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Created by Diego Waxemberg on 7/10/15.
// Copyright © 2015 Limelight Stream. All rights reserved.
//
#import "Host.h"
@implementation Host
@dynamic name;
@dynamic address;
@dynamic localAddress;
@dynamic externalAddress;
@dynamic uuid;
@dynamic mac;
@dynamic pairState;
@synthesize online;
@end
+3 -2
View File
@@ -1,9 +1,9 @@
//
// Settings.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -17,5 +17,6 @@
@property (nonatomic, retain) NSNumber * height;
@property (nonatomic, retain) NSNumber * width;
@property (nonatomic, retain) NSNumber * onscreenControls;
@property (nonatomic, retain) NSString * uniqueId;
@end
+3 -2
View File
@@ -1,9 +1,9 @@
//
// Settings.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "Settings.h"
@@ -16,5 +16,6 @@
@dynamic height;
@dynamic width;
@dynamic onscreenControls;
@dynamic uniqueId;
@end
+31
View File
@@ -0,0 +1,31 @@
//
// 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 (nonatomic) BOOL isRunning;
@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
+52
View File
@@ -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
+37
View File
@@ -0,0 +1,37 @@
//
// 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;
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
+77
View File
@@ -0,0 +1,77 @@
//
// 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];
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
+25
View File
@@ -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
+28
View File
@@ -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
+5 -6
View File
@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "a_button.png"
"filename" : "[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "a_button-1.png"
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "a_button-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

@@ -1,80 +1,86 @@
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x",
"filename" : "Icon-Small@2x.png"
"idiom" : "iphone",
"filename" : "app_icon_settings_58x58_@2x-1.png",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "3x",
"filename" : "Icon-Small@3x.png"
"idiom" : "iphone",
"filename" : "app_icon_settings_87x87_@3x.png",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x",
"filename" : "Icon-40@2x.png"
"idiom" : "iphone",
"filename" : "app_icon_spotlight_80x80_@2x-1.png",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "3x",
"filename" : "Icon-40@3x.png"
"idiom" : "iphone",
"filename" : "app_icon_spotlight_120x120_@3x.png",
"scale" : "3x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x",
"filename" : "[email protected]"
},
{
"idiom" : "iphone",
"filename" : "[email protected]",
"scale" : "2x"
},
{
"size" : "60x60",
"scale" : "3x",
"filename" : "Icon-60@3x.png"
"idiom" : "iphone",
"filename" : "app_icon_180x180_@3x.png",
"scale" : "3x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x",
"filename" : "Icon-Small.png"
"idiom" : "ipad",
"filename" : "app_icon_settings_29x29_@1x.png",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x",
"filename" : "Icon-Small@2x.png"
"idiom" : "ipad",
"filename" : "app_icon_settings_58x58_@2x.png",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x",
"filename" : "Icon-40.png"
"idiom" : "ipad",
"filename" : "app_icon_spotlight_40x40_@1x.png",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x",
"filename" : "Icon-40@2x.png"
"idiom" : "ipad",
"filename" : "app_icon_spotlight_80x80_@2x.png",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x",
"filename" : "Icon-76.png"
"idiom" : "ipad",
"filename" : "app_icon_76x76_@1x.png",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x",
"filename" : "Icon-76@2x.png"
"idiom" : "ipad",
"filename" : "app_icon_152x152_@2x.png",
"scale" : "2x"
},
{
"size" : "83.5x83.5",
"idiom" : "ipad",
"filename" : "[email protected]",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "makeappicon"
"author" : "xcode"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 59 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 66 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

+5 -6
View File
@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "b_button.png"
"filename" : "[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "b_button-1.png"
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "b_button-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

+6
View File
@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "down.png"
"filename" : "[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "down-1.png"
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "down-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 455 B

Before

Width:  |  Height:  |  Size: 455 B

After

Width:  |  Height:  |  Size: 455 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

+3 -3
View File
@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "L1-1.png"
"filename" : "L1_40x40@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "L1.png"
"filename" : "L1_80x80@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "L1-2.png"
"filename" : "L1_120x120@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

+3 -3
View File
@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "L2.png"
"filename" : "L2_60x60@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "L2-1.png"
"filename" : "L2_120x120@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "L2-2.png"
"filename" : "L2_180x180@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.9 KiB

+3 -3
View File
@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "L3.png"
"filename" : "L3_80x80@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "L3-1.png"
"filename" : "L3_160x160@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "L3-2.png"
"filename" : "L3_240x240@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 77 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

@@ -1,51 +0,0 @@
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"subtype" : "retina4",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "left.png"
"filename" : "[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "left-1.png"
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "left-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

Before

Width:  |  Height:  |  Size: 525 B

After

Width:  |  Height:  |  Size: 525 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

+10 -1
View File
@@ -2,7 +2,16 @@
"images" : [
{
"idiom" : "universal",
"filename" : "Limelight-logo.pdf"
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "logo_universal.png"
},
{
"idiom" : "universal",
"scale" : "3x"
}
],
"info" : {
Binary file not shown.
Binary file not shown.

After

Width:  |  Height:  |  Size: 36 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -7,7 +7,7 @@
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Limelight Flat Design Banner.png"
"filename" : "play.png"
},
{
"idiom" : "universal",
Binary file not shown.

After

Width:  |  Height:  |  Size: 17 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"
}
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 901 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 812 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+3 -3
View File
@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "R1.png"
"filename" : "R1_40x40@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "R1-1.png"
"filename" : "R1_80x80@1x-1.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "R1-2.png"
"filename" : "R1_120x120@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.0 KiB

+3 -3
View File
@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "R2-1.png"
"filename" : "R2_60x60@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "R2.png"
"filename" : "R2_120x120@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "R2-2.png"
"filename" : "R2_120x120@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

+3 -3
View File
@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "R3.png"
"filename" : "R3_80x80@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "R3-1.png"
"filename" : "R3_160x160@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "R3-2.png"
"filename" : "R3_240x240@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "right.png"
"filename" : "[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "right-1.png"
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "right-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 549 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

Before

Width:  |  Height:  |  Size: 549 B

After

Width:  |  Height:  |  Size: 549 B

@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "select_button-1.png"
"filename" : "select_button_54x24@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "select_button.png"
"filename" : "select_button_108x48@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "select_button-2.png"
"filename" : "select_button_162x72@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 735 B

Before

Width:  |  Height:  |  Size: 735 B

After

Width:  |  Height:  |  Size: 735 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

@@ -1,23 +0,0 @@
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "settings_1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "settings_2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "settings_3x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.2 KiB

@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "start_button-1.png"
"filename" : "start_button_54x24@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "start_button.png"
"filename" : "start_button_108x48@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "start_button-2.png"
"filename" : "start_button_162x72@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 774 B

Before

Width:  |  Height:  |  Size: 774 B

After

Width:  |  Height:  |  Size: 774 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "stick_inner-1.png"
"filename" : "stick_inner_48x49@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "stick_inner.png"
"filename" : "stick_inner_96x97@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "stick_inner-2.png"
"filename" : "stick_inner_144x146@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.1 KiB

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

@@ -3,17 +3,17 @@
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "stick_outer-1.png"
"filename" : "stick_outer_80x80@1x.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "stick_outer.png"
"filename" : "stick_outer_160x160@2x.png"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "stick_outer-2.png"
"filename" : "stick_outer_240x240@3x.png"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

+5 -6
View File
@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "up-1.png"
"filename" : "[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "up.png"
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "up-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 452 B

Before

Width:  |  Height:  |  Size: 452 B

After

Width:  |  Height:  |  Size: 452 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 KiB

+5 -6
View File
@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "x_button-1.png"
"filename" : "x[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "x_button.png"
"filename" : "x[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "x_button-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

+5 -6
View File
@@ -2,18 +2,17 @@
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "y_button.png"
"filename" : "[email protected]",
"scale" : "1x"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "y_button-1.png"
"filename" : "[email protected]",
"scale" : "2x"
},
{
"idiom" : "universal",
"scale" : "3x",
"filename" : "y_button-2.png"
"scale" : "3x"
}
],
"info" : {
Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

Before

Width:  |  Height:  |  Size: 969 B

After

Width:  |  Height:  |  Size: 969 B

+2 -2
View File
@@ -1,9 +1,9 @@
//
// Controller.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
+2 -2
View File
@@ -1,9 +1,9 @@
//
// Controller.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "Controller.h"
+2 -2
View File
@@ -1,9 +1,9 @@
//
// ControllerSupport.h
// Limelight
// Moonlight
//
// Created by Cameron Gutman on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
+2 -2
View File
@@ -1,9 +1,9 @@
//
// ControllerSupport.m
// Limelight
// Moonlight
//
// Created by Cameron Gutman on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "ControllerSupport.h"
+4 -3
View File
@@ -1,12 +1,13 @@
//
// OnScreenControls.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 12/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "StreamView.h"
@class ControllerSupport;
@@ -23,7 +24,7 @@ typedef NS_ENUM(NSInteger, OnScreenControlsLevel) {
OnScreenControlsLevelAutoGCExtendedGamepad,
};
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport;
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)edgeDelegate;
- (BOOL) handleTouchDownEvent:(NSSet*)touches;
- (BOOL) handleTouchUpEvent:(NSSet*)touches;
- (BOOL) handleTouchMovedEvent:(NSSet*)touches;
+335 -116
View File
@@ -1,9 +1,9 @@
//
// OnScreenControls.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 12/28/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "OnScreenControls.h"
@@ -35,6 +35,7 @@
CALayer* _l1Button;
CALayer* _l2Button;
CALayer* _l3Button;
CALayer* _edge;
UITouch* _aTouch;
UITouch* _bTouch;
@@ -54,6 +55,7 @@
UITouch* _l1Touch;
UITouch* _l2Touch;
UITouch* _l3Touch;
UITouch* _edgeTouch;
NSDate* l3TouchStart;
NSDate* r3TouchStart;
@@ -61,47 +63,45 @@
BOOL l3Set;
BOOL r3Set;
BOOL _iPad;
CGRect _controlArea;
UIView* _view;
OnScreenControlsLevel _level;
ControllerSupport *_controllerSupport;
Controller *_controller;
id<EdgeDetectionDelegate> _edgeDelegate;
NSMutableArray* _deadTouches;
}
static const float BUTTON_SIZE = 50;
static const float EDGE_WIDTH = .05;
//static const float BUTTON_SIZE = 50;
static const float BUTTON_DIST = 20;
static float BUTTON_CENTER_X;
static float BUTTON_CENTER_Y;
static const float D_PAD_SHORT = 50;
static const float D_PAD_LONG = 65;
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_Y;
static const float DEAD_ZONE_PADDING = 15;
static const double STICK_CLICK_RATE = 100;
static const float STICK_INNER_SIZE = 80;
static const float STICK_OUTER_SIZE = 120;
static const float STICK_DEAD_ZONE = .1;
static float STICK_INNER_SIZE;
static float STICK_OUTER_SIZE;
static float LS_CENTER_X;
static float LS_CENTER_Y;
static float RS_CENTER_X;
static float RS_CENTER_Y;
static const float START_WIDTH = 50;
static const float START_HEIGHT = 30;
static float START_X;
static float START_Y;
static const float SELECT_WIDTH = 50;
static const float SELECT_HEIGHT = 30;
static float SELECT_X;
static float SELECT_Y;
static const float BUMPER_SIZE = 45;
static const float TRIGGER_SIZE = 60;
static const float L3R3_SIZE = 80;
static float R1_X;
static float R1_Y;
static float R2_X;
@@ -115,12 +115,28 @@ static float L2_Y;
static float L3_X;
static float L3_Y;
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport {
- (id) initWithView:(UIView*)view controllerSup:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate {
self = [self init];
_view = view;
_controllerSupport = controllerSupport;
_controller = [[Controller alloc] init];
_controller.playerIndex = 0;
_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];
_bButton = [CALayer layer];
@@ -142,7 +158,10 @@ static float L3_Y;
_rightStickBackground = [CALayer layer];
_leftStick = [CALayer layer];
_rightStick = [CALayer layer];
_edge = [CALayer layer];
[self setupEdgeDetection];
return self;
}
@@ -168,10 +187,10 @@ static float L3_Y;
[self hideButtons];
[self hideBumpers];
[self hideL3R3];
[self drawTriggers];
[self drawStartSelect];
[self drawSticks];
[self drawL3R3];
break;
case OnScreenControlsLevelAutoGCExtendedGamepad:
// GCExtendedGamepad is missing R3, L3, and select
@@ -210,13 +229,18 @@ static float L3_Y;
}
}
- (void) setupEdgeDetection {
_edge.frame = CGRectMake(0, 0, _view.frame.size.width * EDGE_WIDTH, _view.frame.size.height);
[_view.layer addSublayer:_edge];
}
// For GCExtendedGamepad controls we move start, select, L3, and R3 to the button
- (void) setupExtendedGamepadControls {
// Start with the default complex layout
[self setupComplexControls];
START_Y = _view.frame.size.height * .9;
SELECT_Y = _view.frame.size.height * .9;
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
}
// For GCGamepad controls we move triggers, start, and select
@@ -225,7 +249,42 @@ static float L3_Y;
// Start with the default complex layout
[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
@@ -233,154 +292,192 @@ static float L3_Y;
// Start with the default complex layout
[self setupComplexControls];
START_Y = _view.frame.size.height * .9;
SELECT_Y = _view.frame.size.height * .9;
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;
L1_Y = _view.frame.size.height * .75;
L2_Y = _view.frame.size.height * .9;
R1_Y = _view.frame.size.height * .75;
R2_Y = _view.frame.size.height * .9;
R2_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
R2_X = _controlArea.size.width * .9 + _controlArea.origin.x;
}
- (void) setupComplexControls
{
D_PAD_CENTER_X = _view.frame.size.width * .15;
D_PAD_CENTER_Y = _view.frame.size.height * .55;
BUTTON_CENTER_X = _view.frame.size.width * .85;
BUTTON_CENTER_Y = _view.frame.size.height * .55;
D_PAD_CENTER_X = _controlArea.size.width * .1 + _controlArea.origin.x;
D_PAD_CENTER_Y = _controlArea.size.height * .60 + _controlArea.origin.y;
BUTTON_CENTER_X = _controlArea.size.width * .9 + _controlArea.origin.x;
BUTTON_CENTER_Y = _controlArea.size.height * .60 + _controlArea.origin.y;
LS_CENTER_X = _view.frame.size.width * .35;
LS_CENTER_Y = _view.frame.size.height * .75;
RS_CENTER_X = _view.frame.size.width * .65;
RS_CENTER_Y = _view.frame.size.height * .75;
if (_iPad)
{
// The analog sticks are kept closer to the sides on iPad
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 * .55;
START_Y = _view.frame.size.height * .1;
SELECT_X = _view.frame.size.width * .45;
SELECT_Y = _view.frame.size.height * .1;
START_X = _controlArea.size.width * .9 + _controlArea.origin.x;
START_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
SELECT_X = _controlArea.size.width * .1 + _controlArea.origin.x;
SELECT_Y = _controlArea.size.height * .9 + _controlArea.origin.y;
L1_X = _view.frame.size.width * .15;
L1_Y = _view.frame.size.height * .25;
L2_X = _view.frame.size.width * .15;
L2_Y = _view.frame.size.height * .1;
R1_X = _view.frame.size.width * .85;
R1_Y = _view.frame.size.height * .25;
R2_X = _view.frame.size.width * .85;
R2_Y = _view.frame.size.height * .1;
L3_X = _view.frame.size.width * .25;
L3_Y = _view.frame.size.height * .85;
R3_X = _view.frame.size.width * .75;
R3_Y = _view.frame.size.height * .85;
L1_X = _controlArea.size.width * .1 + _controlArea.origin.x;
L1_Y = _controlArea.size.height * .27 + _controlArea.origin.y;
L2_X = _controlArea.size.width * .1 + _controlArea.origin.x;
L2_Y = _controlArea.size.height * .1 + _controlArea.origin.y;
R1_X = _controlArea.size.width * .9 + _controlArea.origin.x;
R1_Y = _controlArea.size.height * .27 + _controlArea.origin.y;
R2_X = _controlArea.size.width * .9 + _controlArea.origin.x;
R2_Y = _controlArea.size.height * .1 + _controlArea.origin.y;
L3_X = _controlArea.size.width * .25 + _controlArea.origin.x;
L3_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
R3_X = _controlArea.size.width * .75 + _controlArea.origin.x;
R3_Y = _controlArea.size.height * .75 + _controlArea.origin.y;
}
- (void) drawButtons {
// create A button
_aButton.contents = (id) [UIImage imageNamed:@"AButton"].CGImage;
_aButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_SIZE / 2, BUTTON_CENTER_Y + BUTTON_DIST, BUTTON_SIZE, BUTTON_SIZE);
UIImage* aButtonImage = [UIImage imageNamed:@"AButton"];
_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);
[_view.layer addSublayer:_aButton];
// create B button
_bButton.frame = CGRectMake(BUTTON_CENTER_X + BUTTON_DIST, BUTTON_CENTER_Y - BUTTON_SIZE / 2, BUTTON_SIZE, BUTTON_SIZE);
_bButton.contents = (id) [UIImage imageNamed:@"BButton"].CGImage;
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.contents = (id) bButtonImage.CGImage;
[_view.layer addSublayer:_bButton];
// create X Button
_xButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_DIST - BUTTON_SIZE, BUTTON_CENTER_Y - BUTTON_SIZE / 2, BUTTON_SIZE, BUTTON_SIZE);
_xButton.contents = (id) [UIImage imageNamed:@"XButton"].CGImage;
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.contents = (id) xButtonImage.CGImage;
[_view.layer addSublayer:_xButton];
// create Y Button
_yButton.frame = CGRectMake(BUTTON_CENTER_X - BUTTON_SIZE / 2, BUTTON_CENTER_Y - BUTTON_DIST - BUTTON_SIZE, BUTTON_SIZE, BUTTON_SIZE);
_yButton.contents = (id) [UIImage imageNamed:@"YButton"].CGImage;
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.contents = (id) yButtonImage.CGImage;
[_view.layer addSublayer:_yButton];
// create Down button
_downButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_SHORT / 2, D_PAD_CENTER_Y + D_PAD_DIST, D_PAD_SHORT, D_PAD_LONG);
_downButton.contents = (id) [UIImage imageNamed:@"DownButton"].CGImage;
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.contents = (id) downButtonImage.CGImage;
[_view.layer addSublayer:_downButton];
// create Right button
_rightButton.frame = CGRectMake(D_PAD_CENTER_X + D_PAD_DIST, D_PAD_CENTER_Y - D_PAD_SHORT / 2, D_PAD_LONG, D_PAD_SHORT);
_rightButton.contents = (id) [UIImage imageNamed:@"RightButton"].CGImage;
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.contents = (id) rightButtonImage.CGImage;
[_view.layer addSublayer:_rightButton];
// create Up button
_upButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_SHORT / 2, D_PAD_CENTER_Y - D_PAD_DIST - D_PAD_LONG, D_PAD_SHORT, D_PAD_LONG);
_upButton.contents = (id) [UIImage imageNamed:@"UpButton"].CGImage;
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.contents = (id) upButtonImage.CGImage;
[_view.layer addSublayer:_upButton];
// create Left button
_leftButton.frame = CGRectMake(D_PAD_CENTER_X - D_PAD_DIST - D_PAD_LONG, D_PAD_CENTER_Y - D_PAD_SHORT / 2, D_PAD_LONG, D_PAD_SHORT);
_leftButton.contents = (id) [UIImage imageNamed:@"LeftButton"].CGImage;
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.contents = (id) leftButtonImage.CGImage;
[_view.layer addSublayer:_leftButton];
}
- (void) drawStartSelect {
// create Start button
_startButton.frame = CGRectMake(START_X - START_WIDTH / 2, START_Y - START_HEIGHT / 2, START_WIDTH, START_HEIGHT);
_startButton.contents = (id) [UIImage imageNamed:@"StartButton"].CGImage;
UIImage* startButtonImage = [UIImage imageNamed:@"StartButton"];
_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;
[_view.layer addSublayer:_startButton];
// create Select button
_selectButton.frame = CGRectMake(SELECT_X - SELECT_WIDTH / 2, SELECT_Y - SELECT_HEIGHT / 2, SELECT_WIDTH, SELECT_HEIGHT);
_selectButton.contents = (id) [UIImage imageNamed:@"SelectButton"].CGImage;
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.contents = (id) selectButtonImage.CGImage;
[_view.layer addSublayer:_selectButton];
}
- (void) drawBumpers {
// create L1 button
_l1Button.frame = CGRectMake(L1_X - BUMPER_SIZE / 2, L1_Y - BUMPER_SIZE / 2, BUMPER_SIZE, BUMPER_SIZE);
_l1Button.contents = (id) [UIImage imageNamed:@"L1"].CGImage;
UIImage* l1ButtonImage = [UIImage imageNamed:@"L1"];
_l1Button.frame = CGRectMake(L1_X - l1ButtonImage.size.width / 2, L1_Y - l1ButtonImage.size.height / 2, l1ButtonImage.size.width, l1ButtonImage.size.height);
_l1Button.contents = (id) l1ButtonImage.CGImage;
[_view.layer addSublayer:_l1Button];
// create R1 button
_r1Button.frame = CGRectMake(R1_X - BUMPER_SIZE / 2, R1_Y - BUMPER_SIZE / 2, BUMPER_SIZE, BUMPER_SIZE);
_r1Button.contents = (id) [UIImage imageNamed:@"R1"].CGImage;
UIImage* r1ButtonImage = [UIImage imageNamed:@"R1"];
_r1Button.frame = CGRectMake(R1_X - r1ButtonImage.size.width / 2, R1_Y - r1ButtonImage.size.height / 2, r1ButtonImage.size.width, r1ButtonImage.size.height);
_r1Button.contents = (id) r1ButtonImage.CGImage;
[_view.layer addSublayer:_r1Button];
}
- (void) drawTriggers {
// create L2 button
_l2Button.frame = CGRectMake(L2_X - TRIGGER_SIZE / 2, L2_Y - TRIGGER_SIZE / 2, TRIGGER_SIZE, TRIGGER_SIZE);
_l2Button.contents = (id) [UIImage imageNamed:@"L2"].CGImage;
UIImage* l2ButtonImage = [UIImage imageNamed:@"L2"];
_l2Button.frame = CGRectMake(L2_X - l2ButtonImage.size.width / 2, L2_Y - l2ButtonImage.size.height / 2, l2ButtonImage.size.width, l2ButtonImage.size.height);
_l2Button.contents = (id) l2ButtonImage.CGImage;
[_view.layer addSublayer:_l2Button];
// create R2 button
_r2Button.frame = CGRectMake(R2_X - TRIGGER_SIZE / 2, R2_Y - TRIGGER_SIZE / 2, TRIGGER_SIZE, TRIGGER_SIZE);
_r2Button.contents = (id) [UIImage imageNamed:@"R2"].CGImage;
UIImage* r2ButtonImage = [UIImage imageNamed:@"R2"];
_r2Button.frame = CGRectMake(R2_X - r2ButtonImage.size.width / 2, R2_Y - r2ButtonImage.size.height / 2, r2ButtonImage.size.width, r2ButtonImage.size.height);
_r2Button.contents = (id) r2ButtonImage.CGImage;
[_view.layer addSublayer:_r2Button];
}
- (void) drawSticks {
// create left analog stick
_leftStickBackground.frame = CGRectMake(LS_CENTER_X - STICK_OUTER_SIZE / 2, LS_CENTER_Y - STICK_OUTER_SIZE / 2, STICK_OUTER_SIZE, STICK_OUTER_SIZE);
_leftStickBackground.contents = (id) [UIImage imageNamed:@"StickOuter"].CGImage;
UIImage* leftStickBgImage = [UIImage imageNamed:@"StickOuter"];
_leftStickBackground.frame = CGRectMake(LS_CENTER_X - leftStickBgImage.size.width / 2, LS_CENTER_Y - leftStickBgImage.size.height / 2, leftStickBgImage.size.width, leftStickBgImage.size.height);
_leftStickBackground.contents = (id) leftStickBgImage.CGImage;
[_view.layer addSublayer:_leftStickBackground];
_leftStick.frame = CGRectMake(LS_CENTER_X - STICK_INNER_SIZE / 2, LS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
_leftStick.contents = (id) [UIImage imageNamed:@"StickInner"].CGImage;
UIImage* leftStickImage = [UIImage imageNamed:@"StickInner"];
_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;
[_view.layer addSublayer:_leftStick];
// create right analog stick
_rightStickBackground.frame = CGRectMake(RS_CENTER_X - STICK_OUTER_SIZE / 2, RS_CENTER_Y - STICK_OUTER_SIZE / 2, STICK_OUTER_SIZE, STICK_OUTER_SIZE);
_rightStickBackground.contents = (id) [UIImage imageNamed:@"StickOuter"].CGImage;
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.contents = (id) rightStickBgImage.CGImage;
[_view.layer addSublayer:_rightStickBackground];
_rightStick.frame = CGRectMake(RS_CENTER_X - STICK_INNER_SIZE / 2, RS_CENTER_Y - STICK_INNER_SIZE / 2, STICK_INNER_SIZE, STICK_INNER_SIZE);
_rightStick.contents = (id) [UIImage imageNamed:@"StickInner"].CGImage;
UIImage* rightStickImage = [UIImage imageNamed:@"StickInner"];
_rightStick.frame = CGRectMake(RS_CENTER_X - rightStickImage.size.width / 2, RS_CENTER_Y - rightStickImage.size.height / 2, rightStickImage.size.width, rightStickImage.size.height);
_rightStick.contents = (id) rightStickImage.CGImage;
[_view.layer addSublayer:_rightStick];
STICK_INNER_SIZE = rightStickImage.size.width;
STICK_OUTER_SIZE = rightStickBgImage.size.width;
}
- (void) drawL3R3 {
_l3Button.frame = CGRectMake(L3_X - L3R3_SIZE / 2, L3_Y - L3R3_SIZE / 2, L3R3_SIZE, L3R3_SIZE);
_l3Button.contents = (id) [UIImage imageNamed:@"L3"].CGImage;
_l3Button.cornerRadius = L3R3_SIZE / 2;
UIImage* l3ButtonImage = [UIImage imageNamed:@"L3"];
_l3Button.frame = CGRectMake(L3_X - l3ButtonImage.size.width / 2, L3_Y - l3ButtonImage.size.height / 2, l3ButtonImage.size.width, l3ButtonImage.size.height);
_l3Button.contents = (id) l3ButtonImage.CGImage;
_l3Button.cornerRadius = l3ButtonImage.size.width / 2;
_l3Button.borderColor = [UIColor colorWithRed:15.f/255 green:160.f/255 blue:40.f/255 alpha:1.f].CGColor;
[_view.layer addSublayer:_l3Button];
_r3Button.frame = CGRectMake(R3_X - L3R3_SIZE / 2, R3_Y - L3R3_SIZE / 2, L3R3_SIZE, L3R3_SIZE);
_r3Button.contents = (id) [UIImage imageNamed:@"R3"].CGImage;
_r3Button.cornerRadius = L3R3_SIZE / 2;
UIImage* r3ButtonImage = [UIImage imageNamed:@"R3"];
_r3Button.frame = CGRectMake(R3_X - r3ButtonImage.size.width / 2, R3_Y - r3ButtonImage.size.height / 2, r3ButtonImage.size.width, r3ButtonImage.size.height);
_r3Button.contents = (id) r3ButtonImage.CGImage;
_r3Button.cornerRadius = r3ButtonImage.size.width / 2;
_r3Button.borderColor = [UIColor colorWithRed:15.f/255 green:160.f/255 blue:40.f/255 alpha:1.f].CGColor;
[_view.layer addSublayer:_r3Button];
}
@@ -434,7 +531,7 @@ static float L3_Y;
float lsMaxY = LS_CENTER_Y + STICK_OUTER_SIZE / 2;
float lsMinX = LS_CENTER_X - STICK_OUTER_SIZE / 2;
float lsMinY = LS_CENTER_Y - STICK_OUTER_SIZE / 2;
for (UITouch* touch in touches) {
CGPoint touchLocation = [touch locationInView:_view];
float xLoc = touchLocation.x;
@@ -444,34 +541,34 @@ static float L3_Y;
if (xLoc < lsMinX) xLoc = lsMinX;
if (yLoc > lsMaxY) yLoc = lsMaxY;
if (yLoc < lsMinY) yLoc = lsMinY;
_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 yStickVal = (yLoc - LS_CENTER_Y) / (lsMaxY - LS_CENTER_Y);
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
[_controllerSupport updateLeftStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
updated = true;
} else if (touch == _rsTouch) {
if (xLoc > rsMaxX) xLoc = rsMaxX;
if (xLoc < rsMinX) xLoc = rsMinX;
if (yLoc > rsMaxY) yLoc = rsMaxY;
if (yLoc < rsMinY) yLoc = rsMinY;
_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 yStickVal = (yLoc - RS_CENTER_Y) / (rsMaxY - RS_CENTER_Y);
if (fabsf(xStickVal) < STICK_DEAD_ZONE) xStickVal = 0;
if (fabsf(yStickVal) < STICK_DEAD_ZONE) yStickVal = 0;
[_controllerSupport updateRightStick:_controller x:0x7FFE * xStickVal y:0x7FFE * -yStickVal];
updated = true;
} else if (touch == _aTouch) {
buttonTouch = true;
@@ -506,11 +603,14 @@ static float L3_Y;
} else if (touch == _r3Touch) {
buttonTouch = true;
}
if ([_deadTouches containsObject:touch]) {
updated = true;
}
}
if (updated) {
[_controllerSupport updateFinished:_controller];
}
return updated || buttonTouch;
return updated || buttonTouch;
}
- (BOOL)handleTouchDownEvent:touches {
@@ -518,7 +618,7 @@ static float L3_Y;
BOOL stickTouch = false;
for (UITouch* touch in touches) {
CGPoint touchLocation = [touch locationInView:_view];
if ([_aButton.presentationLayer hitTest:touchLocation]) {
[_controllerSupport setButtonFlag:_controller flags:A_FLAG];
_aTouch = touch;
@@ -621,6 +721,12 @@ static float L3_Y;
}
_rsTouch = touch;
stickTouch = true;
} else if ([_edge.presentationLayer hitTest:touchLocation]) {
_edgeTouch = touch;
}
if (!updated && !stickTouch && [self isInDeadZone:touch]) {
[_deadTouches addObject:touch];
updated = true;
}
}
if (updated) {
@@ -711,12 +817,125 @@ static float L3_Y;
else if (touch == _r3Touch) {
_r3Touch = nil;
touched = true;
} else if (touch == _edgeTouch) {
_edgeTouch = nil;
if ([touch locationInView:_view].x >= _view.frame.size.width / 4) {
[_edgeDelegate edgeSwiped];
}
}
if ([_deadTouches containsObject:touch]) {
[_deadTouches removeObject:touch];
updated = true;
}
}
if (updated) {
[_controllerSupport updateFinished:_controller];
}
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
+9 -3
View File
@@ -1,17 +1,23 @@
//
// StreamView.h
// Limelight
// Moonlight
//
// Created by Cameron Gutman on 10/19/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "ControllerSupport.h"
@protocol EdgeDetectionDelegate <NSObject>
- (void) edgeSwiped;
@end
@interface StreamView : UIView
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport;
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate;
- (void) setMouseDeltaFactors:(float)x y:(float)y;
@end
+19 -18
View File
@@ -1,9 +1,9 @@
//
// StreamView.m
// Limelight
// Moonlight
//
// Created by Cameron Gutman on 10/19/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "StreamView.h"
@@ -29,10 +29,10 @@
screenFactor = [[UIScreen mainScreen] scale];
}
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport {
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport];
- (void) setupOnScreenControls:(ControllerSupport*)controllerSupport swipeDelegate:(id<EdgeDetectionDelegate>)swipeDelegate {
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate];
DataManager* dataMan = [[DataManager alloc] init];
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan retrieveSettings].onscreenControls integerValue];
OnScreenControlsLevel level = (OnScreenControlsLevel)[[dataMan getSettings].onscreenControls integerValue];
if (level == OnScreenControlsLevelAuto) {
[controllerSupport initAutoOnScreenControlMode:onScreenControls];
@@ -67,15 +67,16 @@
deltaX *= xDeltaFactor * screenFactor;
deltaY *= yDeltaFactor * screenFactor;
LiSendMouseMoveEvent(deltaX, deltaY);
touchMoved = true;
touchLocation = currentLocation;
if (deltaX != 0 || deltaY != 0) {
LiSendMouseMoveEvent(deltaX, deltaY);
touchMoved = true;
touchLocation = currentLocation;
}
}
} else if ([[event allTouches] count] == 2) {
CGPoint firstLocation = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:self];
CGPoint secondLocation = [[[[event allTouches] allObjects] objectAtIndex:1] locationInView:self];
CGPoint avgLocation = CGPointMake((firstLocation.x + secondLocation.x) / 2, (firstLocation.y + secondLocation.y) / 2);
if (touchLocation.y != avgLocation.y) {
LiSendScrollEvent(avgLocation.y - touchLocation.y);
@@ -93,23 +94,23 @@
if (!touchMoved) {
if ([[event allTouches] count] == 2) {
Log(LOG_D, @"Sending right mouse button press");
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
// Wait 100 ms to simulate a real button press
usleep(100 * 1000);
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
} else {
Log(LOG_D, @"Sending left mouse button press");
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
// Wait 100 ms to simulate a real button press
usleep(100 * 1000);
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
}
}
+11 -4
View File
@@ -9,7 +9,7 @@
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>com.limelight-stream.$(PRODUCT_NAME:rfc1034identifier)</string>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
@@ -17,7 +17,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.4.1</string>
<string>1.0.4</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
@@ -26,6 +26,11 @@
<string>public.app-category.games</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
<key>UIAppFonts</key>
<array>
<string>Roboto-Black.ttf</string>
@@ -45,9 +50,9 @@
<array>
<string>armv7</string>
</array>
<key>UIStatusBarHidden</key>
<key>UIRequiresFullScreen</key>
<true/>
<key>UIStatusBarHidden~ipad</key>
<key>UIStatusBarHidden</key>
<true/>
<key>UISupportedInterfaceOrientations</key>
<array>
@@ -59,5 +64,7 @@
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
@@ -3,6 +3,6 @@
<plist version="1.0">
<dict>
<key>_XCCurrentVersionName</key>
<string>Limelight 0.3.1.xcdatamodel</string>
<string>Moonlight v1.0-2.xcdatamodel</string>
</dict>
</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>
@@ -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" optional="YES" 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>
+6 -6
View File
@@ -1,26 +1,26 @@
//
// AppManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/25/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "App.h"
#import "TemporaryApp.h"
#import "HttpManager.h"
#import "Host.h"
#import "TemporaryHost.h"
@protocol AppAssetCallback <NSObject>
- (void) receivedAssetForApp:(App*)app;
- (void) receivedAssetForApp:(TemporaryApp*)app;
@end
@interface AppAssetManager : NSObject
- (id) initWithCallback:(id<AppAssetCallback>)callback;
- (void) retrieveAssets:(NSArray*)appList fromHost:(Host*)host;
- (void) retrieveAssetsFromHost:(TemporaryHost*)host;
- (void) stopRetrieving;
@end
+17 -23
View File
@@ -1,9 +1,9 @@
//
// AppManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/25/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "AppAssetManager.h"
@@ -15,35 +15,29 @@
@implementation AppAssetManager {
NSOperationQueue* _opQueue;
id<AppAssetCallback> _callback;
Host* _host;
NSMutableDictionary* _imageCache;
}
static const int MAX_REQUEST_COUNT = 4;
- (id) initWithCallback:(id<AppAssetCallback>)callback {
self = [super init];
_callback = callback;
_opQueue = [[NSOperationQueue alloc] init];
_imageCache = [[NSMutableDictionary alloc] init];
[_opQueue setMaxConcurrentOperationCount:MAX_REQUEST_COUNT];
return self;
}
- (void) retrieveAssets:(NSArray*)appList fromHost:(Host*)host {
Host* oldHost = _host;
_host = host;
BOOL useCache = [oldHost.uuid isEqualToString:_host.uuid];
Log(LOG_I, @"Using cached app images: %d", useCache);
if (!useCache) {
[_imageCache removeAllObjects];
}
for (App* app in appList) {
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
retriever.app = app;
retriever.host = _host;
retriever.callback = _callback;
retriever.cache = _imageCache;
retriever.useCache = useCache;
[_opQueue addOperation:retriever];
- (void) retrieveAssetsFromHost:(TemporaryHost*)host {
for (TemporaryApp* app in host.appList) {
if (app.image == nil) {
AppAssetRetriever* retriever = [[AppAssetRetriever alloc] init];
retriever.app = app;
retriever.host = host;
retriever.callback = _callback;
[_opQueue addOperation:retriever];
}
}
}
@@ -51,7 +45,7 @@
[_opQueue cancelAllOperations];
}
- (void) sendCallBackForApp:(App*)app {
- (void) sendCallBackForApp:(TemporaryApp*)app {
[_callback receivedAssetForApp:app];
}
+2 -2
View File
@@ -1,9 +1,9 @@
//
// AppAssetResponse.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
+2 -2
View File
@@ -1,9 +1,9 @@
//
// AppAssetResponse.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "AppAssetResponse.h"
+6 -8
View File
@@ -1,22 +1,20 @@
//
// AppAssetRetriever.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/31/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Host.h"
#import "App.h"
#import "TemporaryHost.h"
#import "TemporaryApp.h"
#import "AppAssetManager.h"
@interface AppAssetRetriever : NSOperation
@property (nonatomic) Host* host;
@property (nonatomic) App* app;
@property (nonatomic) NSMutableDictionary* cache;
@property (nonatomic) TemporaryHost* host;
@property (nonatomic) TemporaryApp* app;
@property (nonatomic) id<AppAssetCallback> callback;
@property (nonatomic) BOOL useCache;
@end
+14 -27
View File
@@ -1,9 +1,9 @@
//
// AppAssetRetriever.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/31/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "AppAssetRetriever.h"
@@ -11,45 +11,32 @@
#import "CryptoManager.h"
#import "AppAssetResponse.h"
#import "HttpRequest.h"
#import "IdManager.h"
@implementation AppAssetRetriever
static const double RETRY_DELAY = 2; // seconds
static const int MAX_ATTEMPTS = 5;
- (void) main {
UIImage* appImage = nil;
int attempts = 0;
while (![self isCancelled] && appImage == nil && attempts++ < MAX_ATTEMPTS) {
if (self.useCache) {
@synchronized(self.cache) {
UIImage* cachedImage = [self.cache objectForKey:self.app.appId];
if (cachedImage != nil) {
appImage = cachedImage;
self.app.appImage = appImage;
}
}
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.activeAddress uniqueId:[IdManager getUniqueId] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.id]]];
appImage = [UIImage imageWithData:appAssetResp.data];
self.app.image = UIImagePNGRepresentation(appImage);
if (![self isCancelled] && appImage == nil) {
[NSThread sleepForTimeInterval:RETRY_DELAY];
}
if (appImage == nil) {
HttpManager* hMan = [[HttpManager alloc] initWithHost:_host.address uniqueId:[CryptoManager getUniqueID] deviceName:deviceName cert:[CryptoManager readCertFromFile]];
AppAssetResponse* appAssetResp = [[AppAssetResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appAssetResp withUrlRequest:[hMan newAppAssetRequestWithAppId:self.app.appId]]];
appImage = [UIImage imageWithData:appAssetResp.data];
self.app.appImage = appImage;
if (appImage != nil) {
@synchronized(self.cache) {
[self.cache setObject:appImage forKey:self.app.appId];
}
}
}
[NSThread sleepForTimeInterval:RETRY_DELAY];
}
[self performSelectorOnMainThread:@selector(sendCallbackForApp:) withObject:self.app waitUntilDone:NO];
}
- (void) sendCallbackForApp:(App*)app {
- (void) sendCallbackForApp:(TemporaryApp*)app {
[self.callback receivedAssetForApp:app];
}
+3 -3
View File
@@ -1,9 +1,9 @@
//
// AppListResponse.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "HttpResponse.h"
@@ -11,7 +11,7 @@
@interface AppListResponse : NSObject <Response>
- (void)populateWithData:(NSData *)data;
- (NSArray*) getAppList;
- (NSSet*) getAppList;
- (BOOL) isStatusOk;
@end
+14 -13
View File
@@ -1,17 +1,18 @@
//
// AppListResponse.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "AppListResponse.h"
#import "App.h"
#import "TemporaryApp.h"
#import "DataManager.h"
#import <libxml2/libxml/xmlreader.h>
@implementation AppListResponse {
NSMutableArray* _appList;
NSMutableSet* _appList;
}
@synthesize data, statusCode, statusMessage;
@@ -22,7 +23,7 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
- (void)populateWithData:(NSData *)xml {
self.data = xml;
_appList = [[NSMutableArray alloc] init];
_appList = [[NSMutableSet alloc] init];
[self parseData];
}
@@ -64,8 +65,8 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
//Log(LOG_D, @"node: %s", node->name);
if (!xmlStrcmp(node->name, (xmlChar*)TAG_APP)) {
xmlNodePtr appInfoNode = node->xmlChildrenNode;
NSString* appName;
NSString* appId;
NSString* appName = @"";
NSString* appId = nil;
BOOL appIsRunning = NO;
while (appInfoNode != NULL) {
if (!xmlStrcmp(appInfoNode->name, (xmlChar*)TAG_APP_TITLE)) {
@@ -93,11 +94,11 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
}
appInfoNode = appInfoNode->next;
}
App* app = [[App alloc] init];
app.appName = appName;
app.appId = appId;
app.isRunning = appIsRunning;
if (app.appId != nil) {
if (appId != nil) {
TemporaryApp* app = [[TemporaryApp alloc] init];
app.name = appName;
app.id = appId;
app.isRunning = appIsRunning;
[_appList addObject:app];
}
}
@@ -107,7 +108,7 @@ static const char* TAG_APP_IS_RUNNING = "IsRunning";
xmlFreeDoc(docPtr);
}
- (NSArray*) getAppList {
- (NSSet*) getAppList {
return _appList;
}
+6 -6
View File
@@ -1,14 +1,14 @@
//
// DiscoveryManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "MDNSManager.h"
#import "Host.h"
#import "TemporaryHost.h"
@protocol DiscoveryCallback <NSObject>
@@ -22,8 +22,8 @@
- (void) startDiscovery;
- (void) stopDiscovery;
- (void) stopDiscoveryBlocking;
- (BOOL) addHostToDiscovery:(Host*)host;
- (void) removeHostFromDiscovery:(Host*)host;
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(Host*, NSString*))callback;
- (BOOL) addHostToDiscovery:(TemporaryHost*)host;
- (void) removeHostFromDiscovery:(TemporaryHost*)host;
- (void) discoverHost:(NSString*)hostAddress withCallback:(void (^)(TemporaryHost*, NSString*))callback;
@end
+28 -23
View File
@@ -1,9 +1,9 @@
//
// DiscoveryManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "DiscoveryManager.h"
@@ -13,10 +13,10 @@
#import "DataManager.h"
#import "DiscoveryWorker.h"
#import "ServerInfoResponse.h"
#import "IdManager.h"
@implementation DiscoveryManager {
NSMutableArray* _hostQueue;
NSMutableArray* _discoveredHosts;
id<DiscoveryCallback> _callback;
MDNSManager* _mdnsMan;
NSOperationQueue* _opQueue;
@@ -27,31 +27,38 @@
- (id)initWithHosts:(NSArray *)hosts andCallback:(id<DiscoveryCallback>)callback {
self = [super init];
_hostQueue = [NSMutableArray arrayWithArray:hosts];
// Using addHostToDiscovery ensures no duplicates
// will make it into the list from the database
_callback = callback;
shouldDiscover = NO;
_hostQueue = [NSMutableArray array];
for (TemporaryHost* host in hosts)
{
[self addHostToDiscovery:host];
}
[_callback updateAllHosts:_hostQueue];
_opQueue = [[NSOperationQueue alloc] init];
_mdnsMan = [[MDNSManager alloc] initWithCallback:self];
[CryptoManager generateKeyPairUsingSSl];
_uniqueId = [CryptoManager getUniqueID];
_uniqueId = [IdManager getUniqueId];
_cert = [CryptoManager readCertFromFile];
shouldDiscover = NO;
return self;
}
- (void) discoverHost:(NSString *)hostAddress withCallback:(void (^)(Host *, NSString*))callback {
- (void) discoverHost:(NSString *)hostAddress withCallback:(void (^)(TemporaryHost *, NSString*))callback {
HttpManager* hMan = [[HttpManager alloc] initWithHost:hostAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
ServerInfoResponse* serverInfoResponse = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest]]];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResponse withUrlRequest:[hMan newServerInfoRequest] fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
Host* host = nil;
TemporaryHost* host = nil;
if ([serverInfoResponse isStatusOk]) {
DataManager* dataMan = [[DataManager alloc] init];
host = [dataMan createHost];
host.address = hostAddress;
host = [[TemporaryHost alloc] init];
host.activeAddress = host.address = hostAddress;
host.online = YES;
[serverInfoResponse populateHost:host];
if (![self addHostToDiscovery:host]) {
[dataMan removeHost:host];
callback(nil, @"Host already added");
} else {
callback(host, nil);
@@ -66,7 +73,7 @@
Log(LOG_I, @"Starting discovery");
shouldDiscover = YES;
[_mdnsMan searchForHosts];
for (Host* host in _hostQueue) {
for (TemporaryHost* host in _hostQueue) {
[_opQueue addOperation:[self createWorkerForHost:host]];
}
}
@@ -87,8 +94,8 @@
Log(LOG_I, @"All discovery workers stopped");
}
- (BOOL) addHostToDiscovery:(Host *)host {
if (![self isHostInDiscovery:host]) {
- (BOOL) addHostToDiscovery:(TemporaryHost *)host {
if (host.uuid.length > 0 && ![self isHostInDiscovery:host]) {
[_hostQueue addObject:host];
if (shouldDiscover) {
[_opQueue addOperation:[self createWorkerForHost:host]];
@@ -98,7 +105,7 @@
return NO;
}
- (void) removeHostFromDiscovery:(Host *)host {
- (void) removeHostFromDiscovery:(TemporaryHost *)host {
for (DiscoveryWorker* worker in [_opQueue operations]) {
if ([worker getHost] == host) {
[worker cancel];
@@ -110,9 +117,8 @@
// Override from MDNSCallback
- (void)updateHosts:(NSArray *)hosts {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
DataManager* dataMan = [[DataManager alloc] init];
// Discover the hosts before adding to eliminate duplicates
for (Host* host in hosts) {
for (TemporaryHost* host in hosts) {
Log(LOG_I, @"Found host through MDNS: %@:", host.name);
// Since this is on a background thread, we do not need to use the opQueue
DiscoveryWorker* worker = (DiscoveryWorker*)[self createWorkerForHost:host];
@@ -122,15 +128,14 @@
[_callback updateAllHosts:_hostQueue];
} else {
Log(LOG_I, @"Not adding host to discovery: %@", host.name);
[dataMan removeHost:host];
}
}
});
}
- (BOOL) isHostInDiscovery:(Host*)host {
- (BOOL) isHostInDiscovery:(TemporaryHost*)host {
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]) {
return YES;
}
@@ -138,7 +143,7 @@
return NO;
}
- (NSOperation*) createWorkerForHost:(Host*)host {
- (NSOperation*) createWorkerForHost:(TemporaryHost*)host {
DiscoveryWorker* worker = [[DiscoveryWorker alloc] initWithHost:host uniqueId:_uniqueId cert:_cert];
return worker;
}
+5 -5
View File
@@ -1,18 +1,18 @@
//
// DiscoveryWorker.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/2/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Host.h"
#import "TemporaryHost.h"
@interface DiscoveryWorker : NSOperation
- (id) initWithHost:(Host*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert;
- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert;
- (void) discoverHost;
- (Host*) getHost;
- (TemporaryHost*) getHost;
@end
+85 -19
View File
@@ -1,9 +1,9 @@
//
// DiscoveryWorker.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/2/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "DiscoveryWorker.h"
@@ -11,16 +11,17 @@
#import "HttpManager.h"
#import "ServerInfoResponse.h"
#import "HttpRequest.h"
#import "DataManager.h"
@implementation DiscoveryWorker {
Host* _host;
TemporaryHost* _host;
NSString* _uniqueId;
NSData* _cert;
}
static const float POLL_RATE = 2.0f; // Poll every 2 seconds
- (id) initWithHost:(Host*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert {
- (id) initWithHost:(TemporaryHost*)host uniqueId:(NSString*)uniqueId cert:(NSData*)cert {
self = [super init];
_host = host;
_uniqueId = uniqueId;
@@ -28,7 +29,7 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
return self;
}
- (Host*) getHost {
- (TemporaryHost*) getHost {
return _host;
}
@@ -41,23 +42,88 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
}
}
- (NSArray*) getHostAddressList {
NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:3];
if (_host.localAddress != nil) {
[array addObject:_host.localAddress];
}
if (_host.externalAddress != nil) {
[array addObject:_host.externalAddress];
}
if (_host.address != nil) {
[array addObject:_host.address];
}
// Remove duplicate addresses from the list.
// This is done using an array rather than a set
// to preserve insertion order of addresses.
for (int i = 0; i < [array count]; i++) {
NSString *addr1 = [array objectAtIndex:i];
for (int j = 1; j < [array count]; j++) {
if (i == j) {
continue;
}
NSString *addr2 = [array objectAtIndex:j];
if ([addr1 isEqualToString:addr2]) {
// Remove the last address
[array removeObjectAtIndex:j];
// Begin searching again from the start
i = -1;
break;
}
}
}
return array;
}
- (void) discoverHost {
BOOL receivedResponse = NO;
if (!self.cancelled && _host.localAddress != nil) {
ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:_host.localAddress];
receivedResponse = [self checkResponse:serverInfoResp];
}
if (!self.cancelled && !receivedResponse && _host.externalAddress != nil) {
ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:_host.externalAddress];
receivedResponse = [self checkResponse:serverInfoResp];
}
if (!self.cancelled && !receivedResponse && _host.address != nil) {
ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:_host.address];
receivedResponse = [self checkResponse:serverInfoResp];
NSArray *addresses = [self getHostAddressList];
Log(LOG_D, @"%@ has %d unique addresses", _host.name, [addresses count]);
// Give the PC 3 tries to respond before declaring it offline
for (int i = 0; i < 3; i++) {
for (NSString *address in addresses) {
if (self.cancelled) {
// Get out without updating the status because
// it might not have finished checking the various
// addresses
return;
}
ServerInfoResponse* serverInfoResp = [self requestInfoAtAddress:address];
receivedResponse = [self checkResponse:serverInfoResp];
if (receivedResponse) {
[serverInfoResp populateHost:_host];
_host.activeAddress = address;
// Update the database using the response
DataManager *dataManager = [[DataManager alloc] init];
[dataManager updateHost:_host];
break;
}
}
if (receivedResponse) {
Log(LOG_I, @"Received serverinfo response on try %d", i);
break;
}
else {
// Wait for one second then retry
[NSThread sleepForTimeInterval:1];
}
}
_host.online = receivedResponse;
if (receivedResponse) {
Log(LOG_D, @"Received response from: %@\n{\n\t address:%@ \n\t localAddress:%@ \n\t externalAddress:%@ \n\t uuid:%@ \n\t mac:%@ \n\t pairState:%d \n\t online:%d \n}", _host.name, _host.address, _host.localAddress, _host.externalAddress, _host.uuid, _host.mac, _host.pairState, _host.online);
Log(LOG_D, @"Received response from: %@\n{\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);
}
}
@@ -68,7 +134,8 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
cert:_cert];
ServerInfoResponse* response = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:response
withUrlRequest:[hMan newServerInfoRequest]]];
withUrlRequest:[hMan newServerInfoRequest]
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
return response;
}
@@ -76,7 +143,6 @@ static const float POLL_RATE = 2.0f; // Poll every 2 seconds
if ([response isStatusOk]) {
// If the response is from a different host then do not update this host
if ((_host.uuid == nil || [[response getStringTag:TAG_UNIQUE_ID] isEqualToString:_host.uuid])) {
[response populateHost:_host];
return YES;
} else {
Log(LOG_I, @"Received response from incorrect host: %@ expected: %@", [response getStringTag:TAG_UNIQUE_ID], _host.uuid);
+4 -5
View File
@@ -1,17 +1,16 @@
//
// HttpManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/16/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Host.h"
#import "HttpResponse.h"
#import "HttpRequest.h"
@interface HttpManager : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate>
@interface HttpManager : NSObject <NSURLSessionDelegate>
- (id) initWithHost:(NSString*) host uniqueId:(NSString*) uniqueId deviceName:(NSString*) deviceName cert:(NSData*) cert;
- (NSURLRequest*) newPairRequest:(NSData*)salt;
@@ -22,12 +21,12 @@
- (NSURLRequest*) newPairChallenge;
- (NSURLRequest*) newAppListRequest;
- (NSURLRequest*) newServerInfoRequest;
- (NSURLRequest*) newHttpServerInfoRequest;
- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid;
- (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId;
- (NSURLRequest*) newQuitAppRequest;
- (NSURLRequest*) newAppAssetRequestWithAppId:(NSString*)appId;
- (void) executeRequestSynchronously:(HttpRequest*)request;
- (void) executeRequest:(HttpRequest*)request;
@end
+89 -63
View File
@@ -1,21 +1,23 @@
//
// HttpManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/16/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "HttpManager.h"
#import "HttpRequest.h"
#import "CryptoManager.h"
#import "App.h"
#import "TemporaryApp.h"
#include <libxml2/libxml/xmlreader.h>
#include <string.h>
@implementation HttpManager {
NSString* _baseURL;
NSURLSession* _urlSession;
NSString* _baseHTTPURL;
NSString* _baseHTTPSURL;
NSString* _host;
NSString* _uniqueId;
NSString* _deviceName;
@@ -23,9 +25,12 @@
NSMutableData* _respData;
NSData* _requestResp;
dispatch_semaphore_t _requestLock;
BOOL _errorOccurred;
}
static const NSString* PORT = @"47984";
static const NSString* HTTP_PORT = @"47989";
static const NSString* HTTPS_PORT = @"47984";
+ (NSData*) fixXmlVersion:(NSData*) xmlData {
NSString* dataString = [[NSString alloc] initWithData:xmlData encoding:NSUTF8StringEncoding];
@@ -40,36 +45,63 @@ static const NSString* PORT = @"47984";
_uniqueId = uniqueId;
_deviceName = deviceName;
_cert = cert;
_baseURL = [[NSString stringWithFormat:@"https://%@:%@", host, PORT]
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
_baseHTTPURL = [NSString stringWithFormat:@"http://%@:%@", host, HTTP_PORT];
_baseHTTPSURL = [NSString stringWithFormat:@"https://%@:%@", host, HTTPS_PORT];
_requestLock = dispatch_semaphore_create(0);
_respData = [[NSMutableData alloc] init];
NSURLSessionConfiguration* config = [NSURLSessionConfiguration ephemeralSessionConfiguration];
_urlSession = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil];
return self;
}
- (void) executeRequestSynchronously:(HttpRequest*)request {
Log(LOG_D, @"Making Request: %@", request);
[_respData setLength:0];
dispatch_sync(dispatch_get_main_queue(), ^{
[NSURLConnection connectionWithRequest:request.request delegate:self];
});
dispatch_semaphore_wait(_requestLock, DISPATCH_TIME_FOREVER);
if (request.response) {
[request.response populateWithData:_requestResp];
}
}
[[_urlSession dataTaskWithRequest:request.request completionHandler:^(NSData * __nullable data, NSURLResponse * __nullable response, NSError * __nullable error) {
if (error != NULL) {
Log(LOG_D, @"Connection error: %@", error);
_errorOccurred = true;
}
else {
Log(LOG_D, @"Received response: %@", response);
- (void) executeRequest:(HttpRequest*)request {
[NSURLConnection connectionWithRequest:request.request delegate:self];
if (data != NULL) {
Log(LOG_D, @"\n\nReceived data: %@\n\n", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
[_respData appendData:data];
if ([[NSString alloc] initWithData:_respData encoding:NSUTF8StringEncoding] != nil) {
_requestResp = [HttpManager fixXmlVersion:_respData];
} else {
_requestResp = _respData;
}
}
}
dispatch_semaphore_signal(_requestLock);
}] resume];
dispatch_semaphore_wait(_requestLock, DISPATCH_TIME_FOREVER);
if (!_errorOccurred && request.response) {
[request.response populateWithData:_requestResp];
// If the fallback error code was detected, issue the fallback request
if (request.response.statusCode == request.fallbackError && request.fallbackRequest != NULL) {
Log(LOG_D, @"Request failed with fallback error code: %d", request.fallbackError);
request.request = request.fallbackRequest;
request.fallbackError = 0;
request.fallbackRequest = NULL;
[self executeRequestSynchronously:request];
}
}
_errorOccurred = false;
}
- (NSURLRequest*) createRequestFromString:(NSString*) urlString enableTimeout:(BOOL)normalTimeout {
NSString* escapedUrl = [urlString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL* url = [[NSURL alloc] initWithString:escapedUrl];
NSURL* url = [[NSURL alloc] initWithString:urlString];
NSMutableURLRequest* request = [NSMutableURLRequest requestWithURL:url];
if (normalTimeout) {
// Timeout the request after 5 seconds
[request setTimeoutInterval:5];
// Timeout the request after 7 seconds
[request setTimeoutInterval:7];
}
else {
// Timeout the request after 60 seconds
@@ -80,67 +112,72 @@ static const NSString* PORT = @"47984";
- (NSURLRequest*) newPairRequest:(NSData*)salt {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=getservercert&salt=%@&clientcert=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]];
_baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:salt], [self bytesToHex:_cert]];
// This call blocks while waiting for the user to input the PIN on the PC
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newUnpairRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/unpair?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newChallengeRequest:(NSData*)challenge {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientchallenge=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:challenge]];
_baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:challenge]];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newChallengeRespRequest:(NSData*)challengeResp {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&serverchallengeresp=%@",
_baseURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]];
_baseHTTPSURL, _uniqueId, _deviceName, [self bytesToHex:challengeResp]];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newClientSecretRespRequest:(NSString*)clientPairSecret {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientpairingsecret=%@", _baseURL, _uniqueId, _deviceName, clientPairSecret];
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&clientpairingsecret=%@", _baseHTTPSURL, _uniqueId, _deviceName, clientPairSecret];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newPairChallenge {
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=pairchallenge", _baseURL, _uniqueId, _deviceName];
NSString* urlString = [NSString stringWithFormat:@"%@/pair?uniqueid=%@&devicename=%@&updateState=1&phrase=pairchallenge", _baseHTTPSURL, _uniqueId, _deviceName];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest *)newAppListRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/applist?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/applist?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest *)newServerInfoRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest *)newHttpServerInfoRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/serverinfo", _baseHTTPURL];
return [self createRequestFromString:urlString enableTimeout:TRUE];
}
- (NSURLRequest*) newLaunchRequest:(NSString*)appId width:(int)width height:(int)height refreshRate:(int)refreshRate rikey:(NSString*)rikey rikeyid:(int)rikeyid {
NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=1&rikey=%@&rikeyid=%d", _baseURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid];
NSString* urlString = [NSString stringWithFormat:@"%@/launch?uniqueid=%@&appid=%@&mode=%dx%dx%d&additionalStates=1&sops=1&rikey=%@&rikeyid=%d", _baseHTTPSURL, _uniqueId, appId, width, height, refreshRate, rikey, rikeyid];
// This blocks while the app is launching
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newResumeRequestWithRiKey:(NSString*)riKey riKeyId:(int)riKeyId {
NSString* urlString = [NSString stringWithFormat:@"%@/resume?uniqueid=%@&rikey=%@&rikeyid=%d", _baseURL, _uniqueId, riKey, riKeyId];
NSString* urlString = [NSString stringWithFormat:@"%@/resume?uniqueid=%@&rikey=%@&rikeyid=%d", _baseHTTPSURL, _uniqueId, riKey, riKeyId];
// This blocks while the app is resuming
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newQuitAppRequest {
NSString* urlString = [NSString stringWithFormat:@"%@/cancel?uniqueid=%@", _baseURL, _uniqueId];
NSString* urlString = [NSString stringWithFormat:@"%@/cancel?uniqueid=%@", _baseHTTPSURL, _uniqueId];
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
- (NSURLRequest*) newAppAssetRequestWithAppId:(NSString *)appId {
NSString* urlString = [NSString stringWithFormat:@"%@/appasset?uniqueid=%@&appid=%@&AssetType=2&AssetIdx=0", _baseURL, _uniqueId, appId];
NSString* urlString = [NSString stringWithFormat:@"%@/appasset?uniqueid=%@&appid=%@&AssetType=2&AssetIdx=0", _baseHTTPSURL, _uniqueId, appId];
return [self createRequestFromString:urlString enableTimeout:FALSE];
}
@@ -153,33 +190,6 @@ static const NSString* PORT = @"47984";
return hex;
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
Log(LOG_D, @"Received response: %@", response);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
Log(LOG_D, @"\n\nReceived data: %@\n\n", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
[_respData appendData:data];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
if ([[NSString alloc] initWithData:_respData encoding:NSUTF8StringEncoding] != nil) {
_requestResp = [HttpManager fixXmlVersion:_respData];
} else {
_requestResp = _respData;
}
dispatch_semaphore_signal(_requestLock);
}
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge {
SecIdentityRef identity = [self getClientCertificate];
NSArray *certArray = [self getCertificate:identity];
NSURLCredential *newCredential = [NSURLCredential credentialWithIdentity:identity certificates:certArray persistence:NSURLCredentialPersistencePermanent];
[challenge.sender useCredential:newCredential forAuthenticationChallenge:challenge];
}
// Returns an array containing the certificate
- (NSArray*)getCertificate:(SecIdentityRef) identity {
SecCertificateRef certificate = nil;
@@ -215,9 +225,25 @@ static const NSString* PORT = @"47984";
return identityApp;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
Log(LOG_D, @"connection error: %@", error);
dispatch_semaphore_signal(_requestLock);
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(nonnull void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * __nullable))completionHandler {
// Allow untrusted server certificates
if([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust])
{
completionHandler(NSURLSessionAuthChallengeUseCredential,
[NSURLCredential credentialForTrust: challenge.protectionSpace.serverTrust]);
}
// Respond to client certificate challenge with our certificate
else if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodClientCertificate])
{
SecIdentityRef identity = [self getClientCertificate];
NSArray* certArray = [self getCertificate:identity];
NSURLCredential* newCredential = [NSURLCredential credentialWithIdentity:identity certificates:certArray persistence:NSURLCredentialPersistencePermanent];
completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
}
else
{
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, NULL);
}
}
@end
+5 -2
View File
@@ -1,9 +1,9 @@
//
// HttpRequest.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -13,7 +13,10 @@
@property (nonatomic) id<Response> response;
@property (nonatomic) NSURLRequest* request;
@property (nonatomic) int fallbackError;
@property (nonatomic) NSURLRequest* fallbackRequest;
+ (instancetype) requestForResponse:(id<Response>)response withUrlRequest:(NSURLRequest*)req fallbackError:(int)error fallbackRequest:(NSURLRequest*) fallbackReq;
+ (instancetype) requestForResponse:(id<Response>)response withUrlRequest:(NSURLRequest*)req;
+ (instancetype) requestWithUrlRequest:(NSURLRequest*)req;
+11 -2
View File
@@ -1,9 +1,9 @@
//
// HttpRequest.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "HttpRequest.h"
@@ -25,4 +25,13 @@
return request;
}
+ (HttpRequest*) requestForResponse:(id<Response>)response withUrlRequest:(NSURLRequest*)req fallbackError:(int)error fallbackRequest:(NSURLRequest*) fallbackReq {
HttpRequest* request = [[HttpRequest alloc] init];
request.request = req;
request.response = response;
request.fallbackError = error;
request.fallbackRequest = fallbackReq;
return request;
}
@end
+2 -3
View File
@@ -1,13 +1,12 @@
//
// HttpResponse.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/30/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Host.h"
static NSString* TAG_STATUS_CODE = @"status_code";
static NSString* TAG_STATUS_MESSAGE = @"status_message";
+3 -3
View File
@@ -1,13 +1,13 @@
//
// HttpResponse.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/30/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "HttpResponse.h"
#import "App.h"
#import "TemporaryApp.h"
#import <libxml2/libxml/xmlreader.h>
@implementation HttpResponse {
+2 -2
View File
@@ -1,9 +1,9 @@
//
// MDNSManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/14/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
+5 -7
View File
@@ -1,14 +1,13 @@
//
// MDNSManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/14/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "MDNSManager.h"
#import "Host.h"
#import "DataManager.h"
#import "TemporaryHost.h"
@implementation MDNSManager {
NSNetServiceBrowser* mDNSBrowser;
@@ -47,11 +46,10 @@ static NSString* NV_SERVICE_TYPE = @"_nvstream._tcp";
- (NSArray*) getFoundHosts {
NSMutableArray* hosts = [[NSMutableArray alloc] init];
DataManager* dataMan = [[DataManager alloc] init];
for (NSNetService* service in services) {
if (service.hostName != nil) {
Host* host = [dataMan createHost];
host.address = service.hostName;
TemporaryHost* host = [[TemporaryHost alloc] init];
host.activeAddress = host.address = service.hostName;
host.name = host.address;
[hosts addObject:host];
}
+3 -3
View File
@@ -1,9 +1,9 @@
//
// PairManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/19/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -22,6 +22,6 @@
- (id) initWithManager:(HttpManager*)httpManager andCert:(NSData*)cert callback:(id<PairCallback>)callback;
- (NSString*) generatePIN;
- (NSData*) saltPIN:(NSString*)PIN;
- (void) initiatePair;
- (void) initiatePair:(int)serverMajorVersion;
@end
+57 -24
View File
@@ -1,9 +1,9 @@
//
// PairManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/19/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "PairManager.h"
@@ -31,23 +31,31 @@
- (void) main {
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
[_httpManager executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[_httpManager newServerInfoRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[_httpManager newServerInfoRequest]
fallbackError:401 fallbackRequest:[_httpManager newHttpServerInfoRequest]]];
if (serverInfoResp == nil) {
[_callback pairFailed:@"Unable to connect to PC"];
return;
}
if ([serverInfoResp isStatusOk]) {
if (![[serverInfoResp getStringTag:@"currentgame"] isEqual:@"0"]) {
if (![[serverInfoResp getStringTag:@"state"] hasSuffix:@"_SERVER_AVAILABLE"]) {
[_callback pairFailed:@"You must stop streaming before attempting to pair."];
} else if (![[serverInfoResp getStringTag:@"PairStatus"] isEqual:@"1"]) {
[self initiatePair];
NSString* appversion = [serverInfoResp getStringTag:@"appversion"];
if (appversion == nil) {
[_callback pairFailed:@"Missing XML element"];
return;
}
[self initiatePair: [[appversion substringToIndex:1] intValue]];
} else {
[_callback alreadyPaired];
}
}
}
- (void) initiatePair {
- (void) initiatePair:(int)serverMajorVersion {
Log(LOG_I, @"Pairing with generation %d server", serverMajorVersion);
NSString* PIN = [self generatePIN];
NSData* salt = [self saltPIN:PIN];
Log(LOG_I, @"PIN: %@, saltedPIN: %@", PIN, salt);
@@ -60,7 +68,7 @@
}
NSInteger pairedStatus;
if (![pairResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing was declined by the target."];
return;
}
@@ -68,7 +76,18 @@
NSString* plainCert = [pairResp getStringTag:@"plaincert"];
CryptoManager* cryptoMan = [[CryptoManager alloc] init];
NSData* aesKey = [cryptoMan createAESKeyFromSalt:salt];
NSData* aesKey;
// Gen 7 servers use SHA256 to get the key
int hashLength;
if (serverMajorVersion >= 7) {
aesKey = [cryptoMan createAESKeyFromSaltSHA256:salt];
hashLength = 32;
}
else {
aesKey = [cryptoMan createAESKeyFromSaltSHA1:salt];
hashLength = 20;
}
NSData* randomChallenge = [Utils randomBytes:16];
NSData* encryptedChallenge = [cryptoMan aesEncrypt:randomChallenge withKey:aesKey];
@@ -78,8 +97,8 @@
if (![self verifyResponseStatus:challengeResp]) {
return;
}
if (![challengeResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
if (![challengeResp getIntTag:@"paired" value:&pairedStatus] || pairedStatus != 1) {
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #2 failed"];
return;
}
@@ -87,11 +106,18 @@
NSData* encServerChallengeResp = [Utils hexToBytes:[challengeResp getStringTag:@"challengeresponse"]];
NSData* decServerChallengeResp = [cryptoMan aesDecrypt:encServerChallengeResp withKey:aesKey];
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, 20)];
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(20, 16)];
NSData* serverResponse = [decServerChallengeResp subdataWithRange:NSMakeRange(0, hashLength)];
NSData* serverChallenge = [decServerChallengeResp subdataWithRange:NSMakeRange(hashLength, 16)];
NSData* clientSecret = [Utils randomBytes:16];
NSData* challengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret]];
NSData* challengeRespHashInput = [self concatData:[self concatData:serverChallenge with:[CryptoManager getSignatureFromCert:_cert]] with:clientSecret];
NSData* challengeRespHash;
if (serverMajorVersion >= 7) {
challengeRespHash = [cryptoMan SHA256HashData: challengeRespHashInput];
}
else {
challengeRespHash = [cryptoMan SHA1HashData: challengeRespHashInput];
}
NSData* challengeRespEncrypted = [cryptoMan aesEncrypt:challengeRespHash withKey:aesKey];
HttpResponse* secretResp = [[HttpResponse alloc] init];
@@ -99,8 +125,8 @@
if (![self verifyResponseStatus:secretResp]) {
return;
}
if (![secretResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
if (![secretResp getIntTag:@"paired" value:&pairedStatus] || pairedStatus != 1) {
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #3 failed"];
return;
}
@@ -110,14 +136,21 @@
NSData* serverSignature = [serverSecretResp subdataWithRange:NSMakeRange(16, 256)];
if (![cryptoMan verifySignature:serverSecret withSignature:serverSignature andCert:[Utils hexToBytes:plainCert]]) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Server certificate invalid"];
return;
}
NSData* serverChallengeRespHash = [cryptoMan SHA1HashData:[self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret]];
NSData* serverChallengeRespHashInput = [self concatData:[self concatData:randomChallenge with:[CryptoManager getSignatureFromCert:[Utils hexToBytes:plainCert]]] with:serverSecret];
NSData* serverChallengeRespHash;
if (serverMajorVersion >= 7) {
serverChallengeRespHash = [cryptoMan SHA256HashData: serverChallengeRespHashInput];
}
else {
serverChallengeRespHash = [cryptoMan SHA1HashData: serverChallengeRespHashInput];
}
if (![serverChallengeRespHash isEqual:serverResponse]) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Incorrect PIN"];
return;
}
@@ -128,8 +161,8 @@
if (![self verifyResponseStatus:clientSecretResp]) {
return;
}
if (![clientSecretResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
if (![clientSecretResp getIntTag:@"paired" value:&pairedStatus] || pairedStatus != 1) {
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #4 failed"];
return;
}
@@ -139,8 +172,8 @@
if (![self verifyResponseStatus:clientPairChallengeResp]) {
return;
}
if (![clientPairChallengeResp getIntTag:@"paired" value:&pairedStatus] || !pairedStatus) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
if (![clientPairChallengeResp getIntTag:@"paired" value:&pairedStatus] || pairedStatus != 1) {
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Pairing stage #5 failed"];
return;
}
@@ -149,11 +182,11 @@
- (BOOL) verifyResponseStatus:(HttpResponse*)resp {
if (resp == nil) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:@"Network error occured."];
return false;
} else if (![resp isStatusOk]) {
[_httpManager executeRequest:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_httpManager executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[_httpManager newUnpairRequest]]];
[_callback pairFailed:resp.statusMessage];
return false;
} else {
+4 -3
View File
@@ -1,12 +1,13 @@
//
// ServerInfoResponse.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "HttpResponse.h"
#import "TemporaryHost.h"
#define TAG_HOSTNAME @"hostname"
#define TAG_EXTERNAL_IP @"ExternalIP"
@@ -18,7 +19,7 @@
@interface ServerInfoResponse : HttpResponse <Response>
- (void) populateWithData:(NSData *)data;
- (void) populateHost:(Host*)host;
- (void) populateHost:(TemporaryHost*)host;
@end
+8 -8
View File
@@ -1,9 +1,9 @@
//
// ServerInfoResponse.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/1/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "ServerInfoResponse.h"
@@ -17,12 +17,12 @@
[super parseData];
}
- (void) populateHost:(Host*)host {
host.name = [self getStringTag:TAG_HOSTNAME];
host.externalAddress = [self getStringTag:TAG_EXTERNAL_IP];
host.localAddress = [self getStringTag:TAG_LOCAL_IP];
host.uuid = [self getStringTag:TAG_UNIQUE_ID];
host.mac = [self getStringTag:TAG_MAC_ADDRESS];
- (void) populateHost:(TemporaryHost*)host {
host.name = [[self getStringTag:TAG_HOSTNAME] trim];
host.externalAddress = [[self getStringTag:TAG_EXTERNAL_IP] trim];
host.localAddress = [[self getStringTag:TAG_LOCAL_IP] trim];
host.uuid = [[self getStringTag:TAG_UNIQUE_ID] trim];
host.mac = [[self getStringTag:TAG_MAC_ADDRESS] trim];
NSInteger pairStatus;
if ([self getIntTag:TAG_PAIR_STATUS value:&pairStatus]) {
+4 -4
View File
@@ -1,16 +1,16 @@
//
// WakeOnLanManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/2/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Host.h"
#import "TemporaryHost.h"
@interface WakeOnLanManager : NSObject
+ (void) wakeHost:(Host*)host;
+ (void) wakeHost:(TemporaryHost*)host;
@end
+4 -4
View File
@@ -1,9 +1,9 @@
//
// WakeOnLanManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 1/2/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "WakeOnLanManager.h"
@@ -18,7 +18,7 @@
static const int numPorts = 5;
static const int ports[numPorts] = {7, 9, 47998, 47999, 48000};
+ (void) wakeHost:(Host*)host {
+ (void) wakeHost:(TemporaryHost*)host {
NSData* wolPayload = [WakeOnLanManager createPayload:host];
CFDataRef dataPayload = CFDataCreate(kCFAllocatorDefault, [wolPayload bytes], [wolPayload length]);
CFSocketRef wolSocket = CFSocketCreate(kCFAllocatorDefault, PF_INET, SOCK_DGRAM, IPPROTO_UDP, 0, NULL, NULL);
@@ -56,7 +56,7 @@ static const int ports[numPorts] = {7, 9, 47998, 47999, 48000};
CFRelease(dataPayload);
}
+ (NSData*) createPayload:(Host*)host {
+ (NSData*) createPayload:(TemporaryHost*)host {
NSMutableData* payload = [[NSMutableData alloc] initWithCapacity:102];
// 6 bytes of FF
+2 -2
View File
@@ -1,9 +1,9 @@
//
// Connection.h
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/19/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
+34 -61
View File
@@ -1,9 +1,9 @@
//
// Connection.m
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/19/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "Connection.h"
@@ -15,7 +15,7 @@
#include "opus.h"
@implementation Connection {
IP_ADDRESS _host;
const char* _host;
STREAM_CONFIGURATION _streamConfig;
CONNECTION_LISTENER_CALLBACKS _clCallbacks;
DECODER_RENDERER_CALLBACKS _drCallbacks;
@@ -45,10 +45,6 @@ static int audioBufferQueueLength;
static AudioComponentInstance audioUnit;
static VideoDecoderRenderer* renderer;
void DrSetup(int width, int height, int fps, void* context, int drFlags)
{
}
int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit)
{
int offset = 0;
@@ -69,23 +65,16 @@ int DrSubmitDecodeUnit(PDECODE_UNIT decodeUnit)
return [renderer submitDecodeBuffer:data length:decodeUnit->fullLength];
}
void DrStart(void)
{
}
void DrStop(void)
{
}
void DrRelease(void)
{
}
void ArInit(void)
void ArInit(int audioConfiguration, POPUS_MULTISTREAM_CONFIGURATION opusConfig)
{
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];
@@ -93,9 +82,9 @@ void ArInit(void)
NSError *audioSessionError = nil;
AVAudioSession* audioSession = [AVAudioSession sharedInstance];
[audioSession setPreferredSampleRate:48000.0 error:&audioSessionError];
[audioSession setPreferredSampleRate:opusConfig->sampleRate 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 setActive: YES error: &audioSessionError];
@@ -115,11 +104,11 @@ void ArInit(void)
}
AudioStreamBasicDescription audioFormat = {0};
audioFormat.mSampleRate = 48000;
audioFormat.mSampleRate = opusConfig->sampleRate;
audioFormat.mBitsPerChannel = 16;
audioFormat.mFormatID = kAudioFormatLinearPCM;
audioFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked;
audioFormat.mChannelsPerFrame = 2;
audioFormat.mChannelsPerFrame = opusConfig->channelCount;
audioFormat.mBytesPerFrame = audioFormat.mChannelsPerFrame * (audioFormat.mBitsPerChannel / 8);
audioFormat.mBytesPerPacket = audioFormat.mBytesPerFrame;
audioFormat.mFramesPerPacket = audioFormat.mBytesPerPacket / audioFormat.mBytesPerFrame;
@@ -153,16 +142,26 @@ void ArInit(void)
if (status) {
Log(LOG_E, @"Unable to initialize audioUnit: %d", (int32_t)status);
}
status = AudioOutputUnitStart(audioUnit);
if (status) {
Log(LOG_E, @"Unable to start audioUnit: %d", (int32_t)status);
}
}
void ArRelease(void)
void ArCleanup(void)
{
if (opusDecoder != NULL) {
opus_decoder_destroy(opusDecoder);
opusDecoder = NULL;
}
OSStatus status = AudioUnitUninitialize(audioUnit);
OSStatus status = AudioOutputUnitStop(audioUnit);
if (status) {
Log(LOG_E, @"Unable to stop audioUnit: %d", (int32_t)status);
}
status = AudioUnitUninitialize(audioUnit);
if (status) {
Log(LOG_E, @"Unable to uninitialize audioUnit: %d", (int32_t)status);
}
@@ -182,22 +181,6 @@ void ArRelease(void)
}
}
void ArStart(void)
{
OSStatus status = AudioOutputUnitStart(audioUnit);
if (status) {
Log(LOG_E, @"Unable to start audioUnit: %d", (int32_t)status);
}
}
void ArStop(void)
{
OSStatus status = AudioOutputUnitStop(audioUnit);
if (status) {
Log(LOG_E, @"Unable to stop audioUnit: %d", (int32_t)status);
}
}
void ArDecodeAndPlaySample(char* sampleData, int sampleLength)
{
int decodedLength = opus_decode(opusDecoder, (unsigned char*)sampleData, sampleLength, decodedPcmBuffer, PCM_BUFFER_SIZE / 2, 0);
@@ -290,7 +273,7 @@ void ClDisplayTransientMessage(char* message)
-(void) terminate
{
// We're guaranteed to not be on a limelight-common thread
// We're guaranteed to not be on a moonlight-common thread
// here so it's safe to call stop directly
LiStopConnection();
}
@@ -298,10 +281,12 @@ void ClDisplayTransientMessage(char* message)
-(id) initWithConfig:(StreamConfiguration*)config renderer:(VideoDecoderRenderer*)myRenderer connectionCallbacks:(id<ConnectionCallbacks>)callbacks serverMajorVersion:(int)serverMajorVersion
{
self = [super init];
_host = config.hostAddr;
_host = [config.host cStringUsingEncoding:NSUTF8StringEncoding];
renderer = myRenderer;
_callbacks = callbacks;
_serverMajorVersion = serverMajorVersion;
LiInitializeStreamConfiguration(&_streamConfig);
_streamConfig.width = config.width;
_streamConfig.height = config.height;
_streamConfig.fps = config.frameRate;
@@ -315,18 +300,15 @@ void ClDisplayTransientMessage(char* message)
int riKeyId = htonl(config.riKeyId);
memcpy(_streamConfig.remoteInputAesIv, &riKeyId, sizeof(riKeyId));
_drCallbacks.setup = DrSetup;
_drCallbacks.start = DrStart;
_drCallbacks.stop = DrStop;
_drCallbacks.release = DrRelease;
LiInitializeVideoCallbacks(&_drCallbacks);
_drCallbacks.submitDecodeUnit = DrSubmitDecodeUnit;
LiInitializeAudioCallbacks(&_arCallbacks);
_arCallbacks.init = ArInit;
_arCallbacks.start = ArStart;
_arCallbacks.stop = ArStop;
_arCallbacks.release = ArRelease;
_arCallbacks.cleanup = ArCleanup;
_arCallbacks.decodeAndPlaySample = ArDecodeAndPlaySample;
LiInitializeConnectionCallbacks(&_clCallbacks);
_clCallbacks.stageStarting = ClStageStarting;
_clCallbacks.stageComplete = ClStageComplete;
_clCallbacks.stageFailed = ClStageFailed;
@@ -421,21 +403,12 @@ static OSStatus playbackCallback(void *inRefCon,
-(void) main
{
PLATFORM_CALLBACKS dummyPlCallbacks;
// Only used on Windows
dummyPlCallbacks.threadStart = NULL;
dummyPlCallbacks.debugPrint = NULL;
LiStartConnection(_host,
&_streamConfig,
&_clCallbacks,
&_drCallbacks,
&_arCallbacks,
&dummyPlCallbacks,
NULL, 0, _serverMajorVersion);
}
@end
+2 -3
View File
@@ -1,9 +1,9 @@
//
// StreamConfiguration.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -12,7 +12,6 @@
@property NSString* host;
@property NSString* appID;
@property int hostAddr;
@property int width;
@property int height;
@property int frameRate;
+3 -3
View File
@@ -1,13 +1,13 @@
//
// StreamConfiguration.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "StreamConfiguration.h"
@implementation StreamConfiguration
@synthesize host, appID, hostAddr, width, height, frameRate, bitRate, riKeyId, riKey;
@synthesize host, appID, width, height, frameRate, bitRate, riKeyId, riKey;
@end
+2 -2
View File
@@ -1,9 +1,9 @@
//
// StreamManager.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
+11 -15
View File
@@ -1,9 +1,9 @@
//
// StreamManager.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "StreamManager.h"
@@ -15,6 +15,7 @@
#import "ServerInfoResponse.h"
#import "HttpResponse.h"
#import "HttpRequest.h"
#import "IdManager.h"
@implementation StreamManager {
StreamConfiguration* _config;
@@ -36,7 +37,7 @@
- (void)main {
[CryptoManager generateKeyPairUsingSSl];
NSString* uniqueId = [CryptoManager getUniqueID];
NSString* uniqueId = [IdManager getUniqueId];
NSData* cert = [CryptoManager readCertFromFile];
HttpManager* hMan = [[HttpManager alloc] initWithHost:_config.host
@@ -45,12 +46,12 @@
cert:cert];
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]]];
NSString* currentGame = [serverInfoResp getStringTag:@"currentgame"];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
NSString* pairStatus = [serverInfoResp getStringTag:@"PairStatus"];
NSString* currentClient = [serverInfoResp getStringTag:@"CurrentClient"];
NSString* appversion = [serverInfoResp getStringTag:@"appversion"];
if (![serverInfoResp isStatusOk] || currentGame == NULL || pairStatus == NULL || appversion == NULL) {
NSString* serverState = [serverInfoResp getStringTag:@"state"];
if (![serverInfoResp isStatusOk] || pairStatus == NULL || appversion == NULL || serverState == NULL) {
[_callbacks launchFailed:@"Failed to connect to PC"];
return;
}
@@ -62,12 +63,7 @@
}
// resumeApp and launchApp handle calling launchFailed
if (![currentGame isEqualToString:@"0"]) {
if (![currentClient isEqualToString:@"1"]) {
// The server is streaming to someone else
[_callbacks launchFailed:@"There is another stream in progress"];
return;
}
if ([serverState hasSuffix:@"_SERVER_BUSY"]) {
// App already running, resume it
if (![self resumeApp:hMan]) {
return;
@@ -96,14 +92,14 @@
}
// This should NEVER be called from within a thread
// owned by limelight-common
// owned by moonlight-common
- (void) stopStream
{
[_connection terminate];
}
// This should only be called from within a thread
// owned by limelight-common
// owned by moonlight-common
- (void) stopStreamInternal
{
[_connection terminateInternal];
+2 -2
View File
@@ -1,9 +1,9 @@
//
// VideoDecoderRenderer.h
// Limelight
// Moonlight
//
// Created by Cameron Gutman on 10/18/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
+2 -2
View File
@@ -1,9 +1,9 @@
//
// VideoDecoderRenderer.m
// Limelight
// Moonlight
//
// Created by Cameron Gutman on 10/18/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "VideoDecoderRenderer.h"
+5 -5
View File
@@ -1,23 +1,23 @@
//
// UIAppView.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "App.h"
#import "TemporaryApp.h"
@protocol AppCallback <NSObject>
- (void) appClicked:(App*) app;
- (void) appClicked:(TemporaryApp*) app;
@end
@interface UIAppView : UIView
- (id) initWithApp:(App*)app andCallback:(id<AppCallback>)callback;
- (id) initWithApp:(TemporaryApp*)app cache:(NSCache*)cache andCallback:(id<AppCallback>)callback;
- (void) updateAppImage;
@end
+69 -31
View File
@@ -1,62 +1,108 @@
//
// UIAppView.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "UIAppView.h"
@implementation UIAppView {
App* _app;
TemporaryApp* _app;
UIButton* _appButton;
UILabel* _appLabel;
UIImageView* _appOverlay;
NSCache* _artCache;
id<AppCallback> _callback;
}
static int LABEL_DY = 20;
- (id) initWithApp:(App*)app andCallback:(id<AppCallback>)callback {
static UIImage* noImage;
- (id) initWithApp:(TemporaryApp*)app cache:(NSCache*)cache andCallback:(id<AppCallback>)callback {
self = [super init];
_app = app;
_callback = callback;
_artCache = cache;
// Cache the NoAppImage ourselves to avoid
// having to load it each time
if (noImage == nil) {
noImage = [UIImage imageNamed:@"NoAppImage"];
}
_appButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage* noImage = [UIImage imageNamed:@"NoAppImage"];
[_appButton setBackgroundImage:noImage forState:UIControlStateNormal];
[_appButton setContentEdgeInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
[_appButton setContentEdgeInsets:UIEdgeInsetsMake(0, 4, 0, 4)];
[_appButton sizeToFit];
[_appButton addTarget:self action:@selector(appClicked) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:_appButton];
[self sizeToFit];
_appButton.frame = CGRectMake(0, 0, noImage.size.width, noImage.size.height);
self.frame = CGRectMake(0, 0, noImage.size.width, noImage.size.height);
// Rasterizing the cell layer increases rendering performance by quite a bit
self.layer.shouldRasterize = YES;
self.layer.rasterizationScale = [UIScreen mainScreen].scale;
return self;
}
- (void) updateBounds {
float x = _appButton.frame.origin.x < _appLabel.frame.origin.x ? _appButton.frame.origin.x : _appLabel.frame.origin.x;
float y = _appButton.frame.origin.y < _appLabel.frame.origin.y ? _appButton.frame.origin.y : _appLabel.frame.origin.y;
self.bounds = CGRectMake(x , y, _appButton.frame.size.width > _appLabel.frame.size.width ? _appButton.frame.size.width : _appLabel.frame.size.width, _appButton.frame.size.height + _appLabel.frame.size.height + LABEL_DY / 2);
self.frame = CGRectMake(x , y, _appButton.frame.size.width > _appLabel.frame.size.width ? _appButton.frame.size.width : _appLabel.frame.size.width, _appButton.frame.size.height + _appLabel.frame.size.height + LABEL_DY / 2);
}
- (void) appClicked {
[_callback appClicked:_app];
}
- (void) updateAppImage {
if (_app.appImage != nil) {
_appButton.frame = CGRectMake(0, 0, _app.appImage.size.width / 2, _app.appImage.size.height / 2);
self.frame = CGRectMake(0, 0, _app.appImage.size.width / 2, _app.appImage.size.height / 2);
[_appButton setBackgroundImage:_app.appImage forState:UIControlStateNormal];
[self setNeedsDisplay];
if (_appOverlay != nil) {
[_appOverlay removeFromSuperview];
_appOverlay = nil;
}
if (_app.isRunning) {
// 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
if (_app.appImage == nil || (_app.appImage.size.width == 130.f && _app.appImage.size.height == 180.f)) { // This size of image might be blank image received from GameStream.
BOOL noAppImage = false;
if (_app.image != nil) {
// Load the decoded image from the cache
UIImage* appImage = [_artCache objectForKey:_app];
if (appImage == nil) {
// Not cached; we have to decode this now
appImage = [UIImage imageWithData:_app.image];
[_artCache setObject:appImage forKey:_app];
}
// This size of image might be blank image received from GameStream.
if (!(appImage.size.width == 130.f && appImage.size.height == 180.f)) {
_appButton.frame = CGRectMake(0, 0, appImage.size.width / 2, appImage.size.height / 2);
self.frame = CGRectMake(0, 0, appImage.size.width / 2, appImage.size.height / 2);
_appOverlay.frame = CGRectMake(0, 0, self.frame.size.width / 2.f, self.frame.size.height / 4.f);
_appOverlay.layer.shadowRadius = 4.0;
[_appOverlay setCenter:CGPointMake(self.frame.size.width/2, self.frame.size.height/6)];
[_appButton setBackgroundImage:appImage forState:UIControlStateNormal];
[self setNeedsDisplay];
} else {
noAppImage = true;
}
} else {
noAppImage = true;
}
if (noAppImage) {
_appLabel = [[UILabel alloc] init];
CGFloat padding = 4.f;
[_appLabel setFrame: CGRectMake(padding, padding, _appButton.frame.size.width - 2 * padding, _appButton.frame.size.height - 2 * padding)];
@@ -66,18 +112,10 @@ static int LABEL_DY = 20;
[_appLabel setTextAlignment:NSTextAlignmentCenter];
[_appLabel setLineBreakMode:NSLineBreakByWordWrapping];
[_appLabel setNumberOfLines:0];
[_appLabel setText:_app.appName];
[_appLabel setText:_app.name];
[_appButton addSubview:_appLabel];
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect {
// Drawing code
}
*/
@end
+6 -6
View File
@@ -1,25 +1,25 @@
//
// UIComputerView.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "Host.h"
#import "TemporaryHost.h"
@protocol HostCallback <NSObject>
- (void) hostClicked:(Host*)host;
- (void) hostLongClicked:(Host*)host view:(UIView*)view;
- (void) hostClicked:(TemporaryHost*)host view:(UIView*)view;
- (void) hostLongClicked:(TemporaryHost*)host view:(UIView*)view;
- (void) addHostClicked;
@end
@interface UIComputerView : UIView
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback;
- (id) initWithComputer:(TemporaryHost*)host andCallback:(id<HostCallback>)callback;
- (id) initForAddWithCallback:(id<HostCallback>)callback;
@end
+6 -6
View File
@@ -1,15 +1,15 @@
//
// UIComputerView.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/22/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "UIComputerView.h"
@implementation UIComputerView {
Host* _host;
TemporaryHost* _host;
UIButton* _hostButton;
UILabel* _hostLabel;
UILabel* _hostStatus;
@@ -72,7 +72,7 @@ static const int LABEL_DY = 20;
return self;
}
- (id) initWithComputer:(Host*)host andCallback:(id<HostCallback>)callback {
- (id) initWithComputer:(TemporaryHost*)host andCallback:(id<HostCallback>)callback {
self = [self init];
_host = host;
_callback = callback;
@@ -123,7 +123,7 @@ static const int LABEL_DY = 20;
self.frame = CGRectMake(x, y, width, height);
}
- (void) updateContentsForHost:(Host*)host {
- (void) updateContentsForHost:(TemporaryHost*)host {
_hostLabel.text = _host.name;
_hostLabel.textColor = [UIColor whiteColor];
[_hostLabel sizeToFit];
@@ -171,7 +171,7 @@ static const int LABEL_DY = 20;
}
- (void) hostClicked {
[_callback hostClicked:_host];
[_callback hostClicked:_host view:self];
}
- (void) addClicked {
+2 -2
View File
@@ -1,9 +1,9 @@
//
// Logger.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/10/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#ifndef Limelight_Logger_h
+2 -2
View File
@@ -1,9 +1,9 @@
//
// Logger.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/10/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "Logger.h"
+8 -2
View File
@@ -1,9 +1,9 @@
//
// Utils.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <Foundation/Foundation.h>
@@ -24,3 +24,9 @@ FOUNDATION_EXPORT NSString *const deviceName;
+ (int) resolveHost:(NSString*)host;
@end
@interface NSString (NSStringWithTrim)
- (NSString*) trim;
@end
+9 -2
View File
@@ -1,9 +1,9 @@
//
// Utils.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/20/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "Utils.h"
@@ -73,5 +73,12 @@ NSString *const deviceName = @"roth";
}
}
@end
@implementation NSString (NSStringWithTrim)
- (NSString *)trim {
return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
}
@end
@@ -1,9 +1,9 @@
//
// LoadingFrameViewController.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/24/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
@@ -1,9 +1,9 @@
//
// LoadingFrameViewController.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 2/24/15.
// Copyright (c) 2015 Limelight Stream. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "LoadingFrameViewController.h"
@@ -1,9 +1,9 @@
//
// MainFrameViewController.h
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/17/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
@@ -1,10 +1,12 @@
// MainFrameViewController.m
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/17/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
@import ImageIO;
#import "MainFrameViewController.h"
#import "CryptoManager.h"
#import "HttpManager.h"
@@ -13,98 +15,220 @@
#import "Utils.h"
#import "UIComputerView.h"
#import "UIAppView.h"
#import "App.h"
#import "SettingsViewController.h"
#import "DataManager.h"
#import "Settings.h"
#import "TemporarySettings.h"
#import "WakeOnLanManager.h"
#import "AppListResponse.h"
#import "ServerInfoResponse.h"
#import "StreamFrameViewController.h"
#import "LoadingFrameViewController.h"
#import "ComputerScrollView.h"
#import "TemporaryApp.h"
#import "IdManager.h"
@implementation MainFrameViewController {
NSOperationQueue* _opQueue;
Host* _selectedHost;
TemporaryHost* _selectedHost;
NSString* _uniqueId;
NSData* _cert;
NSString* _currentGame;
DiscoveryManager* _discMan;
AppAssetManager* _appManager;
StreamConfiguration* _streamConfig;
UIAlertView* _pairAlert;
UIAlertController* _pairAlert;
UIScrollView* hostScrollView;
int currentPosition;
NSArray* _sortedAppList;
NSCache* _boxArtCache;
}
static NSMutableSet* hostList;
static NSArray* appList;
- (void)showPIN:(NSString *)PIN {
dispatch_sync(dispatch_get_main_queue(), ^{
_pairAlert = [[UIAlertView alloc] initWithTitle:@"Pairing" message:[NSString stringWithFormat:@"Enter the following PIN on the host machine: %@", PIN]delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[_pairAlert show];
dispatch_async(dispatch_get_main_queue(), ^{
_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing"
message:[NSString stringWithFormat:@"Enter the following PIN on the host machine: %@", PIN]
preferredStyle:UIAlertControllerStyleAlert];
[self presentViewController:_pairAlert animated:YES completion:nil];
});
}
- (void)pairFailed:(NSString *)message {
dispatch_sync(dispatch_get_main_queue(), ^{
[_pairAlert dismissWithClickedButtonIndex:0 animated:NO];
_pairAlert = [[UIAlertView alloc] initWithTitle:@"Pairing Failed" message:message delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[_pairAlert show];
dispatch_async(dispatch_get_main_queue(), ^{
[_pairAlert dismissViewControllerAnimated:YES completion:nil];
_pairAlert = [UIAlertController alertControllerWithTitle:@"Pairing Failed"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[_pairAlert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
[self presentViewController:_pairAlert animated:YES completion:nil];
[_discMan startDiscovery];
[self hideLoadingFrame];
});
}
- (void)pairSuccessful {
dispatch_sync(dispatch_get_main_queue(), ^{
[_pairAlert dismissWithClickedButtonIndex:0 animated:NO];
_pairAlert = [[UIAlertView alloc] initWithTitle:@"Pairing Succesful" message:@"Successfully paired to host" delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil, nil];
[_pairAlert show];
dispatch_async(dispatch_get_main_queue(), ^{
[_pairAlert dismissViewControllerAnimated:YES completion:nil];
[_discMan startDiscovery];
[self hideLoadingFrame];
[self alreadyPaired];
});
}
- (void)alreadyPaired {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
BOOL usingCachedAppList = false;
// Capture the host here because it can change once we
// leave the main thread
TemporaryHost* host = _selectedHost;
if ([host.appList count] > 0) {
usingCachedAppList = true;
dispatch_async(dispatch_get_main_queue(), ^{
_computerNameButton.title = _selectedHost.name;
if (host != _selectedHost) {
return;
}
_computerNameButton.title = host.name;
[self.navigationController.navigationBar setNeedsLayout];
[self updateAppsForHost:host];
[self hideLoadingFrame];
});
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
}
Log(LOG_I, @"Using cached app list: %d", usingCachedAppList);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.activeAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
AppListResponse* appListResp = [[AppListResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:appListResp withUrlRequest:[hMan newAppListRequest]]];
if (appListResp == nil || ![appListResp isStatusOk]) {
Log(LOG_W, @"Failed to get applist: %@", appListResp.statusMessage);
} else {
appList = [appListResp getAppList];
if (appList == nil) {
Log(LOG_W, @"Failed to parse applist");
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateApps];
});
// Exempt this host from discovery while handling the applist query
[_discMan removeHostFromDiscovery:host];
// 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);
[_appManager stopRetrieving];
[_appManager retrieveAssets:appList fromHost:_selectedHost];
// Wait for one second then retry
[NSThread sleepForTimeInterval:1];
}
else {
Log(LOG_I, @"App list successfully retreived - took %d tries", i);
break;
}
}
[self hideLoadingFrame];
[_discMan addHostToDiscovery:host];
if (appListResp == nil || ![appListResp isStatusOk] || [appListResp getAppList] == nil) {
Log(LOG_W, @"Failed to get applist: %@", appListResp.statusMessage);
dispatch_async(dispatch_get_main_queue(), ^{
[self hideLoadingFrame];
if (host != _selectedHost) {
return;
}
UIAlertController* applistAlert = [UIAlertController alertControllerWithTitle:@"Fetching App List Failed"
message:@"The connection to the PC was interrupted."
preferredStyle:UIAlertControllerStyleAlert];
[applistAlert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
[self presentViewController:applistAlert animated:YES completion:nil];
host.online = NO;
[self showHostSelectionView];
});
} else {
dispatch_async(dispatch_get_main_queue(), ^{
[self updateApplist:[appListResp getAppList] forHost:host];
if (host != _selectedHost) {
return;
}
_computerNameButton.title = host.name;
[self.navigationController.navigationBar setNeedsLayout];
[self updateAppsForHost:host];
[_appManager stopRetrieving];
[_appManager retrieveAssetsFromHost:host];
[self hideLoadingFrame];
});
}
});
}
- (void) updateApplist:(NSSet*) newList forHost:(TemporaryHost*)host {
DataManager* database = [[DataManager alloc] init];
for (TemporaryApp* app in newList) {
BOOL appAlreadyInList = NO;
for (TemporaryApp* savedApp in host.appList) {
if ([app.id isEqualToString:savedApp.id]) {
savedApp.name = app.name;
savedApp.isRunning = app.isRunning;
appAlreadyInList = YES;
break;
}
}
if (!appAlreadyInList) {
app.host = host;
[host.appList addObject:app];
}
}
BOOL appWasRemoved;
do {
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;
}
}
// Keep looping until the list is no longer being mutated
} while (appWasRemoved);
[database updateAppsForExistingHost:host];
}
- (void)showHostSelectionView {
appList = [[NSArray alloc] init];
[_appManager stopRetrieving];
_selectedHost = nil;
_computerNameButton.title = @"No Host Selected";
[self.collectionView reloadData];
[self.view addSubview:hostScrollView];
}
- (void) receivedAssetForApp:(App*)app {
[self.collectionView reloadData];
- (void) receivedAssetForApp:(TemporaryApp*)app {
// Update the box art cache now so we don't have to do it
// on the main thread
[self updateBoxArtCacheForApp:app];
DataManager* dataManager = [[DataManager alloc] init];
[dataManager updateIconForExistingApp: app];
dispatch_async(dispatch_get_main_queue(), ^{
[self.collectionView reloadData];
});
}
- (void)displayDnsFailedDialog {
@@ -115,17 +239,56 @@ static NSArray* appList;
[self presentViewController:alert animated:YES completion:nil];
}
- (void) hostClicked:(Host *)host {
- (void) hostClicked:(TemporaryHost *)host view:(UIView *)view {
// Treat clicks on offline hosts to be long clicks
// This shows the context menu with wake, delete, etc. rather
// than just hanging for a while and failing as we would in this
// code path.
if (!host.online && view != nil) {
[self hostLongClicked:host view:view];
return;
}
Log(LOG_D, @"Clicked host: %@", host.name);
[self showLoadingFrame];
_selectedHost = host;
[self disableNavigation];
// If we are online, paired, and have a cached app list, skip straight
// to the app grid without a loading frame. This is the fast path that users
// should hit most.
if (host.online && host.pairState == PairStatePaired && host.appList.count > 0) {
[self alreadyPaired];
return;
}
[self showLoadingFrame];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.activeAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
ServerInfoResponse* serverInfoResp = [[ServerInfoResponse alloc] init];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]]];
// Exempt this host from discovery while handling the serverinfo request
[_discMan removeHostFromDiscovery:host];
[hMan executeRequestSynchronously:[HttpRequest requestForResponse:serverInfoResp withUrlRequest:[hMan newServerInfoRequest]
fallbackError:401 fallbackRequest:[hMan newHttpServerInfoRequest]]];
[_discMan addHostToDiscovery:host];
if (serverInfoResp == nil || ![serverInfoResp isStatusOk]) {
Log(LOG_W, @"Failed to get server info: %@", serverInfoResp.statusMessage);
[self hideLoadingFrame];
dispatch_async(dispatch_get_main_queue(), ^{
[self hideLoadingFrame];
if (host != _selectedHost) {
return;
}
UIAlertController* applistAlert = [UIAlertController alertControllerWithTitle:@"Fetching Server Info Failed"
message:@"The connection to the PC was interrupted."
preferredStyle:UIAlertControllerStyleAlert];
[applistAlert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
[self presentViewController:applistAlert animated:YES completion:nil];
host.online = NO;
[self showHostSelectionView];
});
} else {
Log(LOG_D, @"server info pair status: %@", [serverInfoResp getStringTag:@"PairStatus"]);
if ([[serverInfoResp getStringTag:@"PairStatus"] isEqualToString:@"1"]) {
@@ -142,17 +305,10 @@ static NSArray* appList;
});
}
- (void)hostLongClicked:(Host *)host view:(UIView *)view {
- (void)hostLongClicked:(TemporaryHost *)host view:(UIView *)view {
Log(LOG_D, @"Long clicked host: %@", host.name);
UIAlertController* longClickAlert = [UIAlertController alertControllerWithTitle:host.name message:@"" preferredStyle:UIAlertControllerStyleActionSheet];
if (host.online) {
[longClickAlert addAction:[UIAlertAction actionWithTitle:@"Unpair" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:host.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
[hMan executeRequest:[HttpRequest requestWithUrlRequest:[hMan newUnpairRequest]]];
});
}]];
} else {
if (!host.online) {
[longClickAlert addAction:[UIAlertAction actionWithTitle:@"Wake" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
UIAlertController* wolAlert = [UIAlertController alertControllerWithTitle:@"Wake On Lan" message:@"" preferredStyle:UIAlertControllerStyleAlert];
[wolAlert addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil]];
@@ -175,8 +331,8 @@ static NSArray* appList;
[dataMan removeHost:host];
@synchronized(hostList) {
[hostList removeObject:host];
[self updateAllHosts:[hostList allObjects]];
}
[self updateAllHosts:[hostList allObjects]];
}]];
[longClickAlert addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
@@ -198,10 +354,8 @@ static NSArray* appList;
[alertController addAction:[UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
NSString* hostAddress = ((UITextField*)[[alertController textFields] objectAtIndex:0]).text;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
[_discMan discoverHost:hostAddress withCallback:^(Host* host, NSString* error){
[_discMan discoverHost:hostAddress withCallback:^(TemporaryHost* host, NSString* error){
if (host != nil) {
DataManager* dataMan = [[DataManager alloc] init];
[dataMan saveHosts];
dispatch_async(dispatch_get_main_queue(), ^{
@synchronized(hostList) {
[hostList addObject:host];
@@ -222,54 +376,83 @@ static NSArray* appList;
[self presentViewController:alertController animated:YES completion:nil];
}
- (void) appClicked:(App *)app {
Log(LOG_D, @"Clicked app: %@", app.appName);
- (void) appClicked:(TemporaryApp *)app {
Log(LOG_D, @"Clicked app: %@", app.name);
_streamConfig = [[StreamConfiguration alloc] init];
_streamConfig.host = _selectedHost.address;
_streamConfig.hostAddr = [Utils resolveHost:_selectedHost.address];
_streamConfig.appID = app.appId;
if (_streamConfig.hostAddr == 0) {
[self displayDnsFailedDialog];
return;
}
_streamConfig.host = app.host.activeAddress;
_streamConfig.appID = app.id;
DataManager* dataMan = [[DataManager alloc] init];
Settings* streamSettings = [dataMan retrieveSettings];
TemporarySettings* streamSettings = [dataMan getSettings];
_streamConfig.frameRate = [streamSettings.framerate intValue];
_streamConfig.bitRate = [streamSettings.bitrate intValue];
_streamConfig.height = [streamSettings.height intValue];
_streamConfig.width = [streamSettings.width intValue];
[_appManager stopRetrieving];
if (currentPosition != FrontViewPositionLeft) {
[[self revealViewController] revealToggle:self];
}
App* currentApp = [self findRunningApp];
TemporaryApp* currentApp = [self findRunningApp:app.host];
if (currentApp != nil) {
UIAlertController* alertController = [UIAlertController
alertControllerWithTitle: app.appName
message: [app.appId isEqualToString:currentApp.appId] ? @"" : [NSString stringWithFormat:@"%@ is currently running", currentApp.appName]preferredStyle:UIAlertControllerStyleAlert];
alertControllerWithTitle: app.name
message: [app.id isEqualToString:currentApp.id] ? @"" : [NSString stringWithFormat:@"%@ is currently running", currentApp.name]preferredStyle:UIAlertControllerStyleAlert];
[alertController addAction:[UIAlertAction
actionWithTitle:[app.appId isEqualToString:currentApp.appId] ? @"Resume App" : @"Resume Running App" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
Log(LOG_I, @"Resuming application: %@", currentApp.appName);
actionWithTitle:[app.id isEqualToString:currentApp.id] ? @"Resume App" : @"Resume Running App" style:UIAlertActionStyleDefault handler:^(UIAlertAction* action){
Log(LOG_I, @"Resuming application: %@", currentApp.name);
[self performSegueWithIdentifier:@"createStreamFrame" sender:nil];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:
[app.appId isEqualToString:currentApp.appId] ? @"Quit App" : @"Quit Running App and Start" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
Log(LOG_I, @"Quitting application: %@", currentApp.appName);
[app.id isEqualToString:currentApp.id] ? @"Quit App" : @"Quit Running App and Start" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
Log(LOG_I, @"Quitting application: %@", currentApp.name);
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
HttpManager* hMan = [[HttpManager alloc] initWithHost:_selectedHost.address uniqueId:_uniqueId deviceName:deviceName cert:_cert];
[hMan executeRequestSynchronously:[HttpRequest requestWithUrlRequest:[hMan newQuitAppRequest]]];
// TODO: handle failure to quit app
currentApp.isRunning = NO;
HttpManager* hMan = [[HttpManager alloc] initWithHost:app.host.activeAddress uniqueId:_uniqueId deviceName:deviceName cert:_cert];
HttpResponse* quitResponse = [[HttpResponse alloc] init];
HttpRequest* quitRequest = [HttpRequest requestForResponse: quitResponse withUrlRequest:[hMan newQuitAppRequest]];
if (![app.appId isEqualToString:currentApp.appId]) {
// Exempt this host from discovery while handling the quit operation
[_discMan removeHostFromDiscovery:app.host];
[hMan executeRequestSynchronously:quitRequest];
[_discMan addHostToDiscovery:app.host];
UIAlertController* alert;
// If it fails, display an error and stop the current operation
if (quitResponse.statusCode != 200) {
alert = [UIAlertController alertControllerWithTitle:@"Quitting App Failed"
message:@"Failed to quit app. If this app was started by "
"another device, you'll need to quit from that device."
preferredStyle:UIAlertControllerStyleAlert];
}
// If it succeeds and we're to start streaming, segue to the stream and return
else if (![app.id isEqualToString:currentApp.id]) {
currentApp.isRunning = NO;
dispatch_async(dispatch_get_main_queue(), ^{
[self updateAppsForHost:app.host];
[self performSegueWithIdentifier:@"createStreamFrame" sender:nil];
});
return;
}
// Otherwise, display a dialog to notify the user that the app was quit
else {
currentApp.isRunning = NO;
alert = [UIAlertController alertControllerWithTitle:@"Quitting App"
message:@"The app was quit successfully."
preferredStyle:UIAlertControllerStyleAlert];
}
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:nil]];
dispatch_async(dispatch_get_main_queue(), ^{
[self updateAppsForHost:app.host];
[self presentViewController:alert animated:YES completion:nil];
});
});
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"Cancel" style:UIAlertActionStyleCancel handler:nil]];
@@ -279,8 +462,8 @@ static NSArray* appList;
}
}
- (App*) findRunningApp {
for (App* app in appList) {
- (TemporaryApp*) findRunningApp:(TemporaryHost*)host {
for (TemporaryApp* app in host.appList) {
if (app.isRunning) {
return app;
}
@@ -310,6 +493,7 @@ static NSArray* appList;
- (void) hideLoadingFrame {
[self dismissViewControllerAnimated:YES completion:nil];
[self enableNavigation];
}
- (void)viewDidLoad
@@ -334,7 +518,7 @@ static NSArray* appList;
// Set up crypto
[CryptoManager generateKeyPairUsingSSl];
_uniqueId = [CryptoManager getUniqueID];
_uniqueId = [IdManager getUniqueId];
_cert = [CryptoManager readCertFromFile];
_appManager = [[AppAssetManager alloc] initWithCallback:self];
@@ -345,19 +529,54 @@ static NSArray* appList;
hostList = [[NSMutableSet alloc] init];
}
_boxArtCache = [[NSCache alloc] init];
[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 setShowsHorizontalScrollIndicator:NO];
hostScrollView.delaysContentTouches = NO;
UIButton* pullArrow = [[UIButton alloc] init];
[pullArrow setImage:[UIImage imageNamed:@"PullArrow"] forState:UIControlStateNormal];
[pullArrow sizeToFit];
pullArrow.frame = CGRectMake(0,
self.collectionView.frame.size.height / 2 - pullArrow.frame.size.height / 2 - self.navigationController.navigationBar.frame.size.height,
pullArrow.frame.size.width,
pullArrow.frame.size.height);
[self.view addSubview:pullArrow];
self.collectionView.delaysContentTouches = NO;
self.collectionView.allowsMultipleSelection = NO;
self.collectionView.multipleTouchEnabled = NO;
[self retrieveSavedHosts];
_discMan = [[DiscoveryManager alloc] initWithHosts:[hostList allObjects] andCallback:self];
[[NSNotificationCenter defaultCenter] addObserver: self
selector: @selector(handleReturnToForeground)
name: UIApplicationWillEnterForegroundNotification
object: nil];
[self updateHosts];
[self.view addSubview:hostScrollView];
}
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)handleReturnToForeground
{
// This will refresh the applist
if (_selectedHost != nil) {
[self hostClicked:_selectedHost view:nil];
}
}
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
@@ -370,10 +589,7 @@ static NSArray* appList;
[_discMan startDiscovery];
// This will refresh the applist
if (_selectedHost != nil) {
[self hostClicked:_selectedHost];
}
[self handleReturnToForeground];
}
- (void)viewDidDisappear:(BOOL)animated
@@ -382,23 +598,36 @@ static NSArray* appList;
// when discovery stops, we must create a new instance because you cannot restart an NSOperation when it is finished
[_discMan stopDiscovery];
// In case the host objects were updated in the background
[[[DataManager alloc] init] saveHosts];
// Purge the box art cache
[_boxArtCache removeAllObjects];
}
- (void) retrieveSavedHosts {
DataManager* dataMan = [[DataManager alloc] init];
NSArray* hosts = [dataMan retrieveHosts];
NSArray* hosts = [dataMan getHosts];
@synchronized(hostList) {
[hostList addObjectsFromArray:hosts];
// Initialize the non-persistent host state
for (TemporaryHost* host in hostList) {
if (host.activeAddress == nil) {
host.activeAddress = host.localAddress;
}
if (host.activeAddress == nil) {
host.activeAddress = host.externalAddress;
}
if (host.activeAddress == nil) {
host.activeAddress = host.address;
}
}
}
}
- (void) updateAllHosts:(NSArray *)hosts {
dispatch_async(dispatch_get_main_queue(), ^{
Log(LOG_D, @"New host list:");
for (Host* 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}", host.name, host.address, host.localAddress, host.externalAddress, host.uuid, host.mac, host.pairState, host.online);
for (TemporaryHost* host in hosts) {
Log(LOG_D, @"Host: \n{\n\t name:%@ \n\t address:%@ \n\t localAddress:%@ \n\t externalAddress:%@ \n\t uuid:%@ \n\t mac:%@ \n\t pairState:%d \n\t online:%d \n\t activeAddress:%@ \n}", host.name, host.address, host.localAddress, host.externalAddress, host.uuid, host.mac, host.pairState, host.online, host.activeAddress);
}
@synchronized(hostList) {
[hostList removeAllObjects];
@@ -415,13 +644,16 @@ static NSArray* appList;
UIComputerView* compView;
float prevEdge = -1;
@synchronized (hostList) {
for (Host* comp in hostList) {
// Sort the host list in alphabetical order
NSArray* sortedHostList = [[hostList allObjects] sortedArrayUsingSelector:@selector(compareName:)];
for (TemporaryHost* comp in sortedHostList) {
compView = [[UIComputerView alloc] initWithComputer:comp andCallback:self];
compView.center = CGPointMake([self getCompViewX:compView addComp:addComp prevEdge:prevEdge], hostScrollView.frame.size.height / 2);
prevEdge = compView.frame.origin.x + compView.frame.size.width;
[hostScrollView addSubview:compView];
}
}
prevEdge = [self getCompViewX:addComp addComp:addComp prevEdge:prevEdge];
addComp.center = CGPointMake(prevEdge, hostScrollView.frame.size.height / 2);
@@ -437,7 +669,66 @@ static NSArray* appList;
}
}
- (void) updateApps {
// This function forces immediate decoding of the UIImage, rather
// than the default lazy decoding that results in janky scrolling.
+ (UIImage*) loadBoxArtForCaching:(TemporaryApp*)app {
CGImageSourceRef source = CGImageSourceCreateWithData((__bridge CFDataRef)app.image, NULL);
CGImageRef cgImage = CGImageSourceCreateImageAtIndex(source, 0, (__bridge CFDictionaryRef)@{(id)kCGImageSourceShouldCacheImmediately: (id)kCFBooleanTrue});
UIImage *boxArt = [UIImage imageWithCGImage:cgImage];
CGImageRelease(cgImage);
CFRelease(source);
return boxArt;
}
- (void) updateBoxArtCacheForApp:(TemporaryApp*)app {
if (app.image == nil) {
[_boxArtCache removeObjectForKey:app];
}
else if ([_boxArtCache objectForKey:app] == nil) {
[_boxArtCache setObject:[MainFrameViewController loadBoxArtForCaching:app] forKey:app];
}
}
- (void) updateAppsForHost:(TemporaryHost*)host {
if (host != _selectedHost) {
Log(LOG_W, @"Mismatched host during app update");
return;
}
_sortedAppList = [host.appList allObjects];
_sortedAppList = [_sortedAppList sortedArrayUsingSelector:@selector(compareName:)];
// Split the sorted array in half to allow 2 jobs to process app assets at once
NSArray *firstHalf;
NSArray *secondHalf;
NSRange range;
range.location = 0;
range.length = [_sortedAppList count] / 2;
firstHalf = [_sortedAppList subarrayWithRange:range];
range.location = range.length;
range.length = [_sortedAppList count] - range.length;
secondHalf = [_sortedAppList subarrayWithRange:range];
// Start 2 jobs
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (TemporaryApp* app in firstHalf) {
[self updateBoxArtCacheForApp:app];
}
});
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
for (TemporaryApp* app in secondHalf) {
[self updateBoxArtCacheForApp:app];
}
});
[hostScrollView removeFromSuperview];
[self.collectionView reloadData];
}
@@ -445,8 +736,8 @@ static NSArray* appList;
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell* cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"AppCell" forIndexPath:indexPath];
App* app = appList[indexPath.row];
UIAppView* appView = [[UIAppView alloc] initWithApp:app andCallback:self];
TemporaryApp* app = _sortedAppList[indexPath.row];
UIAppView* appView = [[UIAppView alloc] initWithApp:app cache:_boxArtCache andCallback:self];
[appView updateAppImage];
if (appView.bounds.size.width > 10.0) {
@@ -457,7 +748,19 @@ static NSArray* appList;
[cell.subviews.firstObject removeFromSuperview]; // Remove a view that was previously added
[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;
}
@@ -466,7 +769,12 @@ static NSArray* appList;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return appList.count;
if (_selectedHost != nil) {
return _selectedHost.appList.count;
}
else {
return 0;
}
}
- (void)didReceiveMemoryWarning
@@ -488,4 +796,12 @@ static NSArray* appList;
return YES;
}
- (void) disableNavigation {
self.navigationController.navigationBar.topItem.rightBarButtonItem.enabled = NO;
}
- (void) enableNavigation {
self.navigationController.navigationBar.topItem.rightBarButtonItem.enabled = YES;
}
@end
@@ -554,8 +554,8 @@ static CGFloat scaledValue( CGFloat v1, CGFloat min2, CGFloat max2, CGFloat min1
UITouch *touch = [touches anyObject];
CGPoint nowPoint = [touch locationInView:self.view];
if (abs(nowPoint.x - _beginPoint.x) > kDirectionPanThreshold) _dragging = YES;
else if (abs(nowPoint.y - _beginPoint.y) > kDirectionPanThreshold) self.state = UIGestureRecognizerStateFailed;
if (fabs(nowPoint.x - _beginPoint.x) > kDirectionPanThreshold) _dragging = YES;
else if (fabs(nowPoint.y - _beginPoint.y) > kDirectionPanThreshold) self.state = UIGestureRecognizerStateFailed;
}
@end
@@ -742,15 +742,6 @@ const int FrontViewPositionNone = 0xff;
_userInteractionStore = _contentView.userInteractionEnabled;
}
- (NSUInteger)supportedInterfaceOrientations
{
// we could have simply not implemented this, but we choose to call super to make explicit that we
// want the default behavior.
return [super supportedInterfaceOrientations];
}
#pragma mark - Public methods and property accessors
- (void)setFrontViewController:(UIViewController *)frontViewController
@@ -1274,7 +1265,7 @@ const int FrontViewPositionNone = 0xff;
NSTimeInterval duration = _toggleAnimationDuration;
// Velocity driven change:
if (fabsf(velocity) > _quickFlickVelocity)
if (fabs(velocity) > _quickFlickVelocity)
{
// we may need to set the drag position and to adjust the animation duration
CGFloat journey = xLocation;
@@ -1292,7 +1283,7 @@ const int FrontViewPositionNone = 0xff;
}
}
duration = fabsf(journey/velocity);
duration = fabs(journey/velocity);
}
// Position driven change:
@@ -1349,7 +1340,7 @@ const int FrontViewPositionNone = 0xff;
NSTimeInterval duration = animated?_toggleAnimationDuration:0.0;
NSTimeInterval firstDuration = duration;
int initialPosDif = abs( _frontViewPosition - preReplacementPosition );
int initialPosDif = (int) labs( _frontViewPosition - preReplacementPosition );
if ( initialPosDif == 1 ) firstDuration *= 0.8;
else if ( initialPosDif == 0 ) firstDuration = 0;
@@ -1,9 +1,9 @@
//
// SettingsViewController.h
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/27/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
@@ -1,13 +1,13 @@
//
// SettingsViewController.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 10/27/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import "SettingsViewController.h"
#import "Settings.h"
#import "TemporarySettings.h"
#import "DataManager.h"
#define BITRATE_INTERVAL 500 // in kbps
@@ -22,7 +22,7 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
[super viewDidLoad];
DataManager* dataMan = [[DataManager alloc] init];
Settings* currentSettings = [dataMan retrieveSettings];
TemporarySettings* currentSettings = [dataMan getSettings];
// Bitrate is persisted in kbps
_bitrate = [currentSettings.bitrate integerValue];
@@ -33,18 +33,44 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
} else if ([currentSettings.height integerValue] == 1080) {
resolution = 1;
} else {
resolution = 2;
resolution = 0;
}
NSInteger onscreenControls = [currentSettings.onscreenControls integerValue];
[self.resolutionSelector setSelectedSegmentIndex:resolution];
[self.resolutionSelector addTarget:self action:@selector(newResolutionFpsChosen) forControlEvents:UIControlEventValueChanged];
[self.framerateSelector setSelectedSegmentIndex:framerate];
[self.framerateSelector addTarget:self action:@selector(newResolutionFpsChosen) forControlEvents:UIControlEventValueChanged];
[self.onscreenControlSelector setSelectedSegmentIndex:onscreenControls];
[self.bitrateSlider setValue:(_bitrate / 1000) animated:YES];
[self.bitrateSlider setValue:(_bitrate / BITRATE_INTERVAL) animated:YES];
[self.bitrateSlider addTarget:self action:@selector(bitrateSliderMoved) forControlEvents:UIControlEventValueChanged];
[self updateBitrateText];
}
- (void) newResolutionFpsChosen {
NSInteger frameRate = [self getChosenFrameRate];
NSInteger resHeight = [self getChosenStreamHeight];
NSInteger defaultBitrate;
// 1080p60 is 20 Mbps
if (frameRate == 60 && resHeight == 1080) {
defaultBitrate = 20000;
}
// 720p60 and 1080p30 are 10 Mbps
else if (frameRate == 60 || resHeight == 1080) {
defaultBitrate = 10000;
}
// 720p30 is 5 Mbps
else {
defaultBitrate = 5000;
}
_bitrate = defaultBitrate;
[self.bitrateSlider setValue:defaultBitrate / BITRATE_INTERVAL animated:YES];
[self updateBitrateText];
}
- (void) bitrateSliderMoved {
_bitrate = BITRATE_INTERVAL * (int)self.bitrateSlider.value;
[self updateBitrateText];
@@ -55,25 +81,23 @@ static NSString* bitrateFormat = @"Bitrate: %.1f Mbps";
[self.bitrateLabel setText:[NSString stringWithFormat:bitrateFormat, _bitrate / 1000.]];
}
- (NSInteger) getChosenFrameRate {
return [self.framerateSelector selectedSegmentIndex] == 0 ? 30 : 60;
}
- (NSInteger) getChosenStreamHeight {
return [self.resolutionSelector selectedSegmentIndex] == 0 ? 720 : 1080;
}
- (NSInteger) getChosenStreamWidth {
return [self getChosenStreamHeight] == 720 ? 1280 : 1920;
}
- (void) saveSettings {
DataManager* dataMan = [[DataManager alloc] init];
NSInteger framerate = [self.framerateSelector selectedSegmentIndex] == 0 ? 30 : 60;
NSInteger height;
NSInteger width;
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 framerate = [self getChosenFrameRate];
NSInteger height = [self getChosenStreamHeight];
NSInteger width = [self getChosenStreamWidth];
NSInteger onscreenControls = [self.onscreenControlSelector selectedSegmentIndex];
[dataMan saveSettingsWithBitrate:_bitrate framerate:framerate height:height width:width onscreenControls:onscreenControls];
}
@@ -1,17 +1,18 @@
//
// StreamFrameViewController.h
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/18/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "Connection.h"
#import "StreamConfiguration.h"
#import "StreamView.h"
#import <UIKit/UIKit.h>
@interface StreamFrameViewController : UIViewController <ConnectionCallbacks>
@interface StreamFrameViewController : UIViewController <ConnectionCallbacks, EdgeDetectionDelegate>
@property (strong, nonatomic) IBOutlet UILabel *stageLabel;
@property (strong, nonatomic) IBOutlet UIActivityIndicatorView *spinner;
@property (nonatomic) StreamConfiguration* streamConfig;
@@ -1,9 +1,9 @@
//
// StreamFrameViewController.m
// Limelight-iOS
// Moonlight
//
// Created by Diego Waxemberg on 1/18/14.
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
// Copyright (c) 2015 Moonlight Stream. All rights reserved.
//
#import "StreamFrameViewController.h"
@@ -11,7 +11,6 @@
#import "VideoDecoderRenderer.h"
#import "StreamManager.h"
#import "ControllerSupport.h"
#import "StreamView.h"
#include <sys/socket.h>
#include <netinet/in.h>
@@ -70,14 +69,7 @@
[self.spinner stopAnimating];
[self.stageLabel setText:@"Waiting for first frame..."];
[self.stageLabel sizeToFit];
[(StreamView*)self.view setupOnScreenControls: _controllerSupport];
UIScreenEdgePanGestureRecognizer* swipeGesture = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(edgeSwiped)];
swipeGesture.edges = UIRectEdgeLeft;
if (swipeGesture == nil) {
Log(LOG_E, @"An error occured trying to create UIScreenEdgePanGestureRecognizer");
} else {
[self.view addGestureRecognizer:swipeGesture];
}
[(StreamView*)self.view setupOnScreenControls: _controllerSupport swipeDelegate:self];
});
}
@@ -110,24 +102,34 @@
}
- (void) stageFailed:(char*)stageName withError:(long)errorCode {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Connection Failed"
message:[NSString stringWithFormat:@"%s failed with error %ld",
stageName, errorCode]
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
[self returnToMainFrame];
}]];
[self presentViewController:alert animated:YES completion:nil];
Log(LOG_I, @"Stage %s failed: %ld", stageName, errorCode);
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Connection Failed"
message:[NSString stringWithFormat:@"%s failed with error %ld",
stageName, errorCode]
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
[self returnToMainFrame];
}]];
[self presentViewController:alert animated:YES completion:nil];
});
[_streamMan stopStreamInternal];
}
- (void) launchFailed:(NSString*)message {
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Connection Failed"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
[self returnToMainFrame];
}]];
[self presentViewController:alert animated:YES completion:nil];
Log(LOG_I, @"Launch failed: %@", message);
dispatch_async(dispatch_get_main_queue(), ^{
UIAlertController* alert = [UIAlertController alertControllerWithTitle:@"Connection Failed"
message:message
preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"Ok" style:UIAlertActionStyleDestructive handler:^(UIAlertAction* action){
[self returnToMainFrame];
}]];
[self presentViewController:alert animated:YES completion:nil];
});
}
- (void) displayMessage:(char*)message {
+2 -2
View File
@@ -1,9 +1,9 @@
//
// main.m
// Limelight
// Moonlight
//
// Created by Diego Waxemberg on 8/30/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
//
#import <UIKit/UIKit.h>
-22
View File
@@ -1,22 +0,0 @@
<?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>com.limelight-stream.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</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>
-34
View File
@@ -1,34 +0,0 @@
//
// LimelightTests.m
// LimelightTests
//
// Created by Diego Waxemberg on 8/30/14.
// Copyright (c) 2014 Limelight Stream. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface LimelightTests : XCTestCase
@end
@implementation LimelightTests
- (void)setUp
{
[super setUp];
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown
{
// Put teardown code here. This method is called after the invocation of each test method in the class.
[super tearDown];
}
- (void)testExample
{
XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__);
}
@end
@@ -1,2 +0,0 @@
/* Localized versions of Info.plist keys */
@@ -3,11 +3,14 @@
archiveVersion = 1;
classes = {
};
objectVersion = 46;
objectVersion = 47;
objects = {
/* Begin PBXBuildFile section */
98A03B4D19F352EB00861ACA /* liblimelight-common.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 98A03B4A19F3514B00861ACA /* liblimelight-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 */; };
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 */; };
@@ -15,6 +18,8 @@
9E5D60131A5A5A3900689918 /* Roboto-Medium.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D60001A5A5A3900689918 /* Roboto-Medium.ttf */; };
9E5D60151A5A5A3900689918 /* Roboto-Regular.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D60021A5A5A3900689918 /* Roboto-Regular.ttf */; };
9E5D60161A5A5A3900689918 /* Roboto-Thin.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 9E5D60031A5A5A3900689918 /* Roboto-Thin.ttf */; };
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 */; };
FB290CF419B2C406004C83CF /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF319B2C406004C83CF /* CoreGraphics.framework */; };
FB290CF619B2C406004C83CF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF519B2C406004C83CF /* UIKit.framework */; };
@@ -24,11 +29,6 @@
FB290D0419B2C406004C83CF /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = FB290D0319B2C406004C83CF /* AppDelegate.m */; };
FB290D0719B2C406004C83CF /* Limelight.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */; };
FB290D0919B2C406004C83CF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = FB290D0819B2C406004C83CF /* Images.xcassets */; };
FB290D1119B2C406004C83CF /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF119B2C406004C83CF /* Foundation.framework */; };
FB290D1219B2C406004C83CF /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF519B2C406004C83CF /* UIKit.framework */; };
FB290D1319B2C406004C83CF /* CoreData.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290CF719B2C406004C83CF /* CoreData.framework */; };
FB290D1B19B2C406004C83CF /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = FB290D1919B2C406004C83CF /* InfoPlist.strings */; };
FB290D1D19B2C406004C83CF /* LimelightTests.m in Sources */ = {isa = PBXBuildFile; fileRef = FB290D1C19B2C406004C83CF /* LimelightTests.m */; };
FB290DB719B2C870004C83CF /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290DB619B2C870004C83CF /* libz.dylib */; };
FB290DB919B2C877004C83CF /* libbz2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290DB819B2C877004C83CF /* libbz2.dylib */; };
FB290DC419B2E98F004C83CF /* libxml2.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB290DC319B2E98F004C83CF /* libxml2.dylib */; };
@@ -39,6 +39,7 @@
FB4678FF1A565DAC00377732 /* WakeOnLanManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB4678FE1A565DAC00377732 /* WakeOnLanManager.m */; };
FB4679011A57048000377732 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = FB4679001A57048000377732 /* CoreFoundation.framework */; };
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 */; };
FB7E794419C8B71B00A15F68 /* libiconv.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = FB7E794319C8B71B00A15F68 /* libiconv.dylib */; };
FB89462819F646E200339C8A /* CryptoManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FB89460619F646E200339C8A /* CryptoManager.m */; };
@@ -70,40 +71,39 @@
FBD3494319FC9C04002D2A60 /* AppAssetManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494219FC9C04002D2A60 /* AppAssetManager.m */; };
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3494F19FF2174002D2A60 /* SettingsViewController.m */; };
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3495219FF36FB002D2A60 /* SWRevealViewController.m */; };
FBD3495B1A004411002D2A60 /* Host.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3495A1A004411002D2A60 /* Host.m */; };
FBD3495E1A004412002D2A60 /* Settings.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD3495D1A004412002D2A60 /* Settings.m */; };
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */ = {isa = PBXBuildFile; fileRef = FBD349611A0089F6002D2A60 /* DataManager.m */; };
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */ = {isa = PBXBuildFile; fileRef = FBDE86DF19F7A837001C18A8 /* UIComputerView.m */; };
FBDE86E619F82297001C18A8 /* UIAppView.m in Sources */ = {isa = PBXBuildFile; fileRef = FBDE86E519F82297001C18A8 /* UIAppView.m */; };
FBDE86E919F82315001C18A8 /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FBDE86E819F82315001C18A8 /* App.m */; };
FBFCB3311B50B29400089F8A /* Host.m in Sources */ = {isa = PBXBuildFile; fileRef = FBFCB3301B50B29400089F8A /* Host.m */; };
FBFCB3351B50B29400089F8A /* App.m in Sources */ = {isa = PBXBuildFile; fileRef = FBFCB3341B50B29400089F8A /* App.m */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
98A03B4919F3514B00861ACA /* PBXContainerItemProxy */ = {
98AB2E831CAD46840089BB98 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 98A03B4519F3514B00861ACA /* limelight-common.xcodeproj */;
containerPortal = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = FB290E2E19B37A4E004C83CF;
remoteInfo = "limelight-common";
remoteInfo = "moonlight-common";
};
98A03B4B19F3517100861ACA /* PBXContainerItemProxy */ = {
98AB2E851CAD468B0089BB98 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 98A03B4519F3514B00861ACA /* limelight-common.xcodeproj */;
containerPortal = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = FB290E2D19B37A4E004C83CF;
remoteInfo = "limelight-common";
};
FB290D1419B2C406004C83CF /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = FB290CE619B2C406004C83CF /* Project object */;
proxyType = 1;
remoteGlobalIDString = FB290CED19B2C406004C83CF;
remoteInfo = Limelight;
remoteInfo = "moonlight-common";
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
98A03B4519F3514B00861ACA /* limelight-common.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = "limelight-common.xcodeproj"; path = "limelight-common-c/limelight-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>"; };
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>"; };
@@ -111,7 +111,11 @@
9E5D60001A5A5A3900689918 /* Roboto-Medium.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Medium.ttf"; sourceTree = "<group>"; };
9E5D60021A5A5A3900689918 /* Roboto-Regular.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Regular.ttf"; sourceTree = "<group>"; };
9E5D60031A5A5A3900689918 /* Roboto-Thin.ttf */ = {isa = PBXFileReference; lastKnownFileType = file; path = "Roboto-Thin.ttf"; sourceTree = "<group>"; };
FB290CEE19B2C406004C83CF /* Limelight.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Limelight.app; sourceTree = BUILT_PRODUCTS_DIR; };
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; };
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; };
FB290CF519B2C406004C83CF /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@@ -124,10 +128,6 @@
FB290D0319B2C406004C83CF /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Limelight.xcdatamodel; sourceTree = "<group>"; };
FB290D0819B2C406004C83CF /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = "<group>"; };
FB290D0E19B2C406004C83CF /* LimelightTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = LimelightTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
FB290D1819B2C406004C83CF /* LimelightTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "LimelightTests-Info.plist"; sourceTree = "<group>"; };
FB290D1A19B2C406004C83CF /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
FB290D1C19B2C406004C83CF /* LimelightTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = LimelightTests.m; sourceTree = "<group>"; };
FB290DB619B2C870004C83CF /* libz.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libz.dylib; path = usr/lib/libz.dylib; sourceTree = SDKROOT; };
FB290DB819B2C877004C83CF /* libbz2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libbz2.dylib; path = usr/lib/libbz2.dylib; sourceTree = SDKROOT; };
FB290DC319B2E98F004C83CF /* libxml2.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libxml2.dylib; path = usr/lib/libxml2.dylib; sourceTree = SDKROOT; };
@@ -143,9 +143,13 @@
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>"; };
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>"; };
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>"; };
FB6DDEF31AE739100096499A /* libmoonlight-common.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libmoonlight-common.a"; path = "limelight-common-c/build/Debug-iphoneos/libmoonlight-common.a"; sourceTree = "<group>"; };
FB7E794319C8B71B00A15F68 /* libiconv.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libiconv.dylib; path = usr/lib/libiconv.dylib; sourceTree = SDKROOT; };
FB89460519F646E200339C8A /* CryptoManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CryptoManager.h; sourceTree = "<group>"; };
FB89460619F646E200339C8A /* CryptoManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CryptoManager.m; sourceTree = "<group>"; };
@@ -272,6 +276,7 @@
FB9AFD3F1A7E127D00872C98 /* AppListResponse.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppListResponse.m; sourceTree = "<group>"; };
FB9AFD411A7F0C6900872C98 /* Controller.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Controller.h; sourceTree = "<group>"; };
FB9AFD421A7F0C6900872C98 /* Controller.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Controller.m; sourceTree = "<group>"; };
FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.0.xcdatamodel"; sourceTree = "<group>"; };
FBD1C8E01A8AD69E00C6703C /* Logger.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Logger.h; sourceTree = "<group>"; };
FBD1C8E11A8AD71400C6703C /* Logger.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = Logger.m; sourceTree = "<group>"; };
FBD3494119FC9C04002D2A60 /* AppAssetManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppAssetManager.h; sourceTree = "<group>"; };
@@ -281,8 +286,6 @@
FBD3495119FF36FB002D2A60 /* SWRevealViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SWRevealViewController.h; sourceTree = "<group>"; };
FBD3495219FF36FB002D2A60 /* SWRevealViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SWRevealViewController.m; sourceTree = "<group>"; };
FBD349571A003F05002D2A60 /* libsqlite3.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libsqlite3.dylib; path = usr/lib/libsqlite3.dylib; sourceTree = SDKROOT; };
FBD349591A004411002D2A60 /* Host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Host.h; path = Database/Host.h; sourceTree = "<group>"; };
FBD3495A1A004411002D2A60 /* Host.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Host.m; path = Database/Host.m; sourceTree = "<group>"; };
FBD3495C1A004412002D2A60 /* Settings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Settings.h; path = Database/Settings.h; sourceTree = "<group>"; };
FBD3495D1A004412002D2A60 /* Settings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Settings.m; path = Database/Settings.m; sourceTree = "<group>"; };
FBD349601A0089F6002D2A60 /* DataManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = DataManager.h; path = Database/DataManager.h; sourceTree = "<group>"; };
@@ -291,8 +294,12 @@
FBDE86DF19F7A837001C18A8 /* UIComputerView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIComputerView.m; sourceTree = "<group>"; };
FBDE86E419F82297001C18A8 /* UIAppView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UIAppView.h; sourceTree = "<group>"; };
FBDE86E519F82297001C18A8 /* UIAppView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UIAppView.m; sourceTree = "<group>"; };
FBDE86E719F82315001C18A8 /* App.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = App.h; path = ../App.h; sourceTree = "<group>"; };
FBDE86E819F82315001C18A8 /* App.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = App.m; path = ../App.m; sourceTree = "<group>"; };
FBFCB32E1B50B29400089F8A /* Host+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "Host+CoreDataProperties.h"; path = "Database/Host+CoreDataProperties.h"; sourceTree = "<group>"; };
FBFCB32F1B50B29400089F8A /* Host.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Host.h; path = Database/Host.h; sourceTree = "<group>"; };
FBFCB3301B50B29400089F8A /* Host.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Host.m; path = Database/Host.m; sourceTree = "<group>"; };
FBFCB3321B50B29400089F8A /* App+CoreDataProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "App+CoreDataProperties.h"; path = "Database/App+CoreDataProperties.h"; sourceTree = "<group>"; };
FBFCB3331B50B29400089F8A /* App.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = App.h; path = Database/App.h; sourceTree = "<group>"; };
FBFCB3341B50B29400089F8A /* App.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = App.m; path = Database/App.m; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -300,7 +307,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
98A03B4D19F352EB00861ACA /* liblimelight-common.a in Frameworks */,
98CFB82F1CAD481B0048EF74 /* libmoonlight-common.a in Frameworks */,
FB8946ED19F6AFE800339C8A /* libopus.a in Frameworks */,
FB8946EB19F6AFE100339C8A /* libcrypto.a in Frameworks */,
FB8946EC19F6AFE400339C8A /* libssl.a in Frameworks */,
@@ -316,23 +323,13 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
FB290D0B19B2C406004C83CF /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
FB290D1319B2C406004C83CF /* CoreData.framework in Frameworks */,
FB290D1219B2C406004C83CF /* UIKit.framework in Frameworks */,
FB290D1119B2C406004C83CF /* Foundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
98A03B4619F3514B00861ACA /* Products */ = {
98AB2E801CAD46830089BB98 /* Products */ = {
isa = PBXGroup;
children = (
98A03B4A19F3514B00861ACA /* liblimelight-common.a */,
98AB2E841CAD46840089BB98 /* libmoonlight-common.a */,
);
name = Products;
sourceTree = "<group>";
@@ -362,9 +359,8 @@
FB290CE519B2C406004C83CF = {
isa = PBXGroup;
children = (
98A03B4519F3514B00861ACA /* limelight-common.xcodeproj */,
98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */,
FB290CF919B2C406004C83CF /* Limelight */,
FB290D1619B2C406004C83CF /* LimelightTests */,
FB290CF019B2C406004C83CF /* Frameworks */,
FB290CEF19B2C406004C83CF /* Products */,
);
@@ -373,8 +369,7 @@
FB290CEF19B2C406004C83CF /* Products */ = {
isa = PBXGroup;
children = (
FB290CEE19B2C406004C83CF /* Limelight.app */,
FB290D0E19B2C406004C83CF /* LimelightTests.xctest */,
FB290CEE19B2C406004C83CF /* Moonlight.app */,
);
name = Products;
sourceTree = "<group>";
@@ -382,6 +377,7 @@
FB290CF019B2C406004C83CF /* Frameworks */ = {
isa = PBXGroup;
children = (
FB6DDEF31AE739100096499A /* libmoonlight-common.a */,
FB4679001A57048000377732 /* CoreFoundation.framework */,
FBD349571A003F05002D2A60 /* libsqlite3.dylib */,
FB89468F19F6AFB800339C8A /* libs */,
@@ -420,6 +416,10 @@
FB89463719F6473800339C8A /* Launch Screen.xib */,
FB290D0819B2C406004C83CF /* Images.xcassets */,
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */,
FB1D59951BBCCB6400F482CA /* ComputerScrollView.h */,
FB1D59961BBCCB6400F482CA /* ComputerScrollView.m */,
FB1D59981BBCCD7E00F482CA /* AppCollectionView.h */,
FB1D59991BBCCD7E00F482CA /* AppCollectionView.m */,
);
path = Limelight;
sourceTree = "<group>";
@@ -435,24 +435,6 @@
name = "Supporting Files";
sourceTree = "<group>";
};
FB290D1619B2C406004C83CF /* LimelightTests */ = {
isa = PBXGroup;
children = (
FB290D1C19B2C406004C83CF /* LimelightTests.m */,
FB290D1719B2C406004C83CF /* Supporting Files */,
);
path = LimelightTests;
sourceTree = "<group>";
};
FB290D1719B2C406004C83CF /* Supporting Files */ = {
isa = PBXGroup;
children = (
FB290D1819B2C406004C83CF /* LimelightTests-Info.plist */,
FB290D1919B2C406004C83CF /* InfoPlist.strings */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
FB89460419F646E200339C8A /* Crypto */ = {
isa = PBXGroup;
children = (
@@ -460,6 +442,8 @@
FB89460619F646E200339C8A /* CryptoManager.m */,
FB89460719F646E200339C8A /* mkcert.c */,
FB89460819F646E200339C8A /* mkcert.h */,
FB53E1411BE5DC4400CD6ECE /* IdManager.h */,
FB53E1421BE5DC4400CD6ECE /* IdManager.m */,
);
path = Crypto;
sourceTree = "<group>";
@@ -484,7 +468,7 @@
children = (
FB9AFD2F1A7C979700872C98 /* Http */,
FB9AFD341A7D877B00872C98 /* Discovery */,
FB9AFD331A7D876F00872C98 /* AppAsset */,
FB9AFD331A7D876F00872C98 /* AppList */,
FB89461319F646E200339C8A /* PairManager.h */,
FB89461419F646E200339C8A /* PairManager.m */,
FB4678FD1A565DAC00377732 /* WakeOnLanManager.h */,
@@ -511,8 +495,6 @@
FB89461E19F646E200339C8A /* Utility */ = {
isa = PBXGroup;
children = (
FBDE86E719F82315001C18A8 /* App.h */,
FBDE86E819F82315001C18A8 /* App.m */,
FB89462119F646E200339C8A /* Utils.h */,
FB89462219F646E200339C8A /* Utils.m */,
FBD1C8E01A8AD69E00C6703C /* Logger.h */,
@@ -718,7 +700,7 @@
name = Http;
sourceTree = "<group>";
};
FB9AFD331A7D876F00872C98 /* AppAsset */ = {
FB9AFD331A7D876F00872C98 /* AppList */ = {
isa = PBXGroup;
children = (
FBD3494119FC9C04002D2A60 /* AppAssetManager.h */,
@@ -726,7 +708,7 @@
FB9AFD301A7D867C00872C98 /* AppAssetRetriever.h */,
FB9AFD311A7D867C00872C98 /* AppAssetRetriever.m */,
);
name = AppAsset;
name = AppList;
sourceTree = "<group>";
};
FB9AFD341A7D877B00872C98 /* Discovery */ = {
@@ -745,12 +727,22 @@
FBD3495F1A004453002D2A60 /* Database */ = {
isa = PBXGroup;
children = (
FBFCB3321B50B29400089F8A /* App+CoreDataProperties.h */,
FBFCB3331B50B29400089F8A /* App.h */,
FBFCB3341B50B29400089F8A /* App.m */,
FBFCB32E1B50B29400089F8A /* Host+CoreDataProperties.h */,
FBFCB32F1B50B29400089F8A /* Host.h */,
FBFCB3301B50B29400089F8A /* Host.m */,
FBD3495C1A004412002D2A60 /* Settings.h */,
FBD3495D1A004412002D2A60 /* Settings.m */,
FBD349591A004411002D2A60 /* Host.h */,
FBD3495A1A004411002D2A60 /* Host.m */,
FBD349601A0089F6002D2A60 /* DataManager.h */,
FBD349611A0089F6002D2A60 /* DataManager.m */,
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */,
9832D1351BBCD5C50036EF48 /* TemporaryApp.m */,
98D5856B1C0EA79600F6CC00 /* TemporaryHost.h */,
98D5856C1C0EA79600F6CC00 /* TemporaryHost.m */,
98D5856E1C0ED0E800F6CC00 /* TemporarySettings.h */,
98D5856F1C0ED0E800F6CC00 /* TemporarySettings.m */,
);
name = Database;
sourceTree = "<group>";
@@ -758,9 +750,9 @@
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
FB290CED19B2C406004C83CF /* Limelight */ = {
FB290CED19B2C406004C83CF /* Moonlight */ = {
isa = PBXNativeTarget;
buildConfigurationList = FB290D2019B2C406004C83CF /* Build configuration list for PBXNativeTarget "Limelight" */;
buildConfigurationList = FB290D2019B2C406004C83CF /* Build configuration list for PBXNativeTarget "Moonlight" */;
buildPhases = (
FB290CEA19B2C406004C83CF /* Sources */,
FB290CEB19B2C406004C83CF /* Frameworks */,
@@ -769,50 +761,29 @@
buildRules = (
);
dependencies = (
98A03B4C19F3517100861ACA /* PBXTargetDependency */,
98AB2E861CAD468B0089BB98 /* PBXTargetDependency */,
);
name = Limelight;
name = Moonlight;
productName = Limelight;
productReference = FB290CEE19B2C406004C83CF /* Limelight.app */;
productReference = FB290CEE19B2C406004C83CF /* Moonlight.app */;
productType = "com.apple.product-type.application";
};
FB290D0D19B2C406004C83CF /* LimelightTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = FB290D2319B2C406004C83CF /* Build configuration list for PBXNativeTarget "LimelightTests" */;
buildPhases = (
FB290D0A19B2C406004C83CF /* Sources */,
FB290D0B19B2C406004C83CF /* Frameworks */,
FB290D0C19B2C406004C83CF /* Resources */,
);
buildRules = (
);
dependencies = (
FB290D1519B2C406004C83CF /* PBXTargetDependency */,
);
name = LimelightTests;
productName = LimelightTests;
productReference = FB290D0E19B2C406004C83CF /* LimelightTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
FB290CE619B2C406004C83CF /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 0510;
ORGANIZATIONNAME = "Limelight Stream";
LastUpgradeCheck = 0700;
ORGANIZATIONNAME = "Moonlight Stream";
TargetAttributes = {
FB290CED19B2C406004C83CF = {
DevelopmentTeam = DM46QST4M7;
};
FB290D0D19B2C406004C83CF = {
TestTargetID = FB290CED19B2C406004C83CF;
};
};
};
buildConfigurationList = FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Limelight" */;
compatibilityVersion = "Xcode 3.2";
buildConfigurationList = FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Moonlight" */;
compatibilityVersion = "Xcode 6.3";
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
@@ -823,24 +794,23 @@
projectDirPath = "";
projectReferences = (
{
ProductGroup = 98A03B4619F3514B00861ACA /* Products */;
ProjectRef = 98A03B4519F3514B00861ACA /* limelight-common.xcodeproj */;
ProductGroup = 98AB2E801CAD46830089BB98 /* Products */;
ProjectRef = 98AB2E7F1CAD46830089BB98 /* moonlight-common.xcodeproj */;
},
);
projectRoot = "";
targets = (
FB290CED19B2C406004C83CF /* Limelight */,
FB290D0D19B2C406004C83CF /* LimelightTests */,
FB290CED19B2C406004C83CF /* Moonlight */,
);
};
/* End PBXProject section */
/* Begin PBXReferenceProxy section */
98A03B4A19F3514B00861ACA /* liblimelight-common.a */ = {
98AB2E841CAD46840089BB98 /* libmoonlight-common.a */ = {
isa = PBXReferenceProxy;
fileType = archive.ar;
path = "liblimelight-common.a";
remoteRef = 98A03B4919F3514B00861ACA /* PBXContainerItemProxy */;
path = "libmoonlight-common.a";
remoteRef = 98AB2E831CAD46840089BB98 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
@@ -865,14 +835,6 @@
);
runOnlyForDeploymentPostprocessing = 0;
};
FB290D0C19B2C406004C83CF /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FB290D1B19B2C406004C83CF /* InfoPlist.strings in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
@@ -890,21 +852,26 @@
FB89462F19F646E200339C8A /* Connection.m in Sources */,
FB9AFD321A7D867C00872C98 /* AppAssetRetriever.m in Sources */,
FB4678FF1A565DAC00377732 /* WakeOnLanManager.m in Sources */,
FB53E1431BE5DC4400CD6ECE /* IdManager.m in Sources */,
FB89462919F646E200339C8A /* mkcert.c in Sources */,
FB9AFD281A7C84ED00872C98 /* HttpResponse.m in Sources */,
FBDE86E019F7A837001C18A8 /* UIComputerView.m in Sources */,
FBDE86E919F82315001C18A8 /* App.m in Sources */,
FB89463019F646E200339C8A /* StreamConfiguration.m in Sources */,
FBFCB3311B50B29400089F8A /* Host.m in Sources */,
FBD3495319FF36FB002D2A60 /* SWRevealViewController.m in Sources */,
FB1D59971BBCCB6400F482CA /* ComputerScrollView.m in Sources */,
FBD3495019FF2174002D2A60 /* SettingsViewController.m in Sources */,
FB89462C19F646E200339C8A /* HttpManager.m in Sources */,
FB89462D19F646E200339C8A /* MDNSManager.m in Sources */,
FB89462B19F646E200339C8A /* StreamView.m in Sources */,
FB4678FA1A55FFAD00377732 /* DiscoveryManager.m in Sources */,
FBD3495B1A004411002D2A60 /* Host.m in Sources */,
98D5856D1C0EA79600F6CC00 /* TemporaryHost.m in Sources */,
FB89463519F646E200339C8A /* MainFrameViewController.m in Sources */,
FBD1C8E21A8AD71400C6703C /* Logger.m in Sources */,
FB1D599A1BBCCD7E00F482CA /* AppCollectionView.m in Sources */,
FB89463619F646E200339C8A /* StreamFrameViewController.m in Sources */,
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */,
98D585701C0ED0E800F6CC00 /* TemporarySettings.m in Sources */,
FB89462819F646E200339C8A /* CryptoManager.m in Sources */,
FB89462E19F646E200339C8A /* PairManager.m in Sources */,
FB9AFD371A7E02DB00872C98 /* HttpRequest.m in Sources */,
@@ -916,32 +883,20 @@
FB89462A19F646E200339C8A /* ControllerSupport.m in Sources */,
FB9AFD3D1A7E111600872C98 /* AppAssetResponse.m in Sources */,
FBD349621A0089F6002D2A60 /* DataManager.m in Sources */,
FBFCB3351B50B29400089F8A /* App.m in Sources */,
FB4A23B81A9D3637004D2EF2 /* LoadingFrameViewController.m in Sources */,
FB9AFD3A1A7E05CE00872C98 /* ServerInfoResponse.m in Sources */,
FB89463119F646E200339C8A /* StreamManager.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
FB290D0A19B2C406004C83CF /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
FB290D1D19B2C406004C83CF /* LimelightTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
98A03B4C19F3517100861ACA /* PBXTargetDependency */ = {
98AB2E861CAD468B0089BB98 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "limelight-common";
targetProxy = 98A03B4B19F3517100861ACA /* PBXContainerItemProxy */;
};
FB290D1519B2C406004C83CF /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = FB290CED19B2C406004C83CF /* Limelight */;
targetProxy = FB290D1419B2C406004C83CF /* PBXContainerItemProxy */;
name = "moonlight-common";
targetProxy = 98AB2E851CAD468B0089BB98 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
@@ -954,14 +909,6 @@
name = InfoPlist.strings;
sourceTree = "<group>";
};
FB290D1919B2C406004C83CF /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
FB290D1A19B2C406004C83CF /* en */,
);
name = InfoPlist.strings;
sourceTree = "<group>";
};
/* End PBXVariantGroup section */
/* Begin XCBuildConfiguration section */
@@ -984,6 +931,7 @@
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_OPTIMIZATION_LEVEL = 0;
@@ -1046,12 +994,13 @@
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
ENABLE_BITCODE = NO;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(PROJECT_DIR)/limelight-common-c/limelight-common",
"$(PROJECT_DIR)/moonlight-common/moonlight-common-c/src",
"$(SDKROOT)/usr/include/libxml2/**",
"$(PROJECT_DIR)/libs/**",
);
@@ -1061,6 +1010,7 @@
"$(PROJECT_DIR)/libs/opus/lib",
"$(PROJECT_DIR)/libs/openssl/lib",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.moonlight-stream.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SKIP_INSTALL = NO;
@@ -1072,14 +1022,15 @@
isa = XCBuildConfiguration;
buildSettings = {
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
CODE_SIGN_IDENTITY = "iPhone Distribution";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Distribution";
CODE_SIGN_IDENTITY = "iPhone Developer";
"CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
ENABLE_BITCODE = NO;
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch";
HEADER_SEARCH_PATHS = (
"$(inherited)",
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/include,
"$(PROJECT_DIR)/limelight-common-c/limelight-common",
"$(PROJECT_DIR)/moonlight-common/moonlight-common-c/src",
"$(SDKROOT)/usr/include/libxml2/**",
"$(PROJECT_DIR)/libs/**",
);
@@ -1089,6 +1040,7 @@
"$(PROJECT_DIR)/libs/opus/lib",
"$(PROJECT_DIR)/libs/openssl/lib",
);
PRODUCT_BUNDLE_IDENTIFIER = "com.moonlight-stream.$(PRODUCT_NAME:rfc1034identifier)";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE = "";
SKIP_INSTALL = NO;
@@ -1096,50 +1048,10 @@
};
name = Release;
};
FB290D2419B2C406004C83CF /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Limelight.app/Limelight";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch";
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
INFOPLIST_FILE = "LimelightTests/LimelightTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Debug;
};
FB290D2519B2C406004C83CF /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/Limelight.app/Limelight";
FRAMEWORK_SEARCH_PATHS = (
"$(SDKROOT)/Developer/Library/Frameworks",
"$(inherited)",
"$(DEVELOPER_FRAMEWORKS_DIR)",
);
GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = "Limelight/Limelight-Prefix.pch";
INFOPLIST_FILE = "LimelightTests/LimelightTests-Info.plist";
PRODUCT_NAME = "$(TARGET_NAME)";
TEST_HOST = "$(BUNDLE_LOADER)";
WRAPPER_EXTENSION = xctest;
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Limelight" */ = {
FB290CE919B2C406004C83CF /* Build configuration list for PBXProject "Moonlight" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FB290D1E19B2C406004C83CF /* Debug */,
@@ -1148,7 +1060,7 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FB290D2019B2C406004C83CF /* Build configuration list for PBXNativeTarget "Limelight" */ = {
FB290D2019B2C406004C83CF /* Build configuration list for PBXNativeTarget "Moonlight" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FB290D2119B2C406004C83CF /* Debug */,
@@ -1157,26 +1069,19 @@
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
FB290D2319B2C406004C83CF /* Build configuration list for PBXNativeTarget "LimelightTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
FB290D2419B2C406004C83CF /* Debug */,
FB290D2519B2C406004C83CF /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
/* Begin XCVersionGroup section */
FB290D0519B2C406004C83CF /* Limelight.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
FB53E1441BE5DCBC00CD6ECE /* Moonlight v1.0-2.xcdatamodel */,
FBB460391B50ACE400F3099C /* Moonlight v1.0.xcdatamodel */,
FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */,
FB4678F21A51BDCB00377732 /* Limelight 0.3.0.xcdatamodel */,
FB290D0619B2C406004C83CF /* Limelight.xcdatamodel */,
);
currentVersion = FB6549621A60B4A9001C8F39 /* Limelight 0.3.1.xcdatamodel */;
currentVersion = FB53E1441BE5DCBC00CD6ECE /* Moonlight v1.0-2.xcdatamodel */;
path = Limelight.xcdatamodeld;
sourceTree = "<group>";
versionGroupType = wrapper.xcdatamodel;
@@ -2,6 +2,6 @@
<Workspace
version = "1.0">
<FileRef
location = "self:Limelight.xcodeproj">
location = "self:Moonlight.xcodeproj">
</FileRef>
</Workspace>
@@ -0,0 +1,53 @@
<?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>AD7C6582-F39A-441A-A7FD-9EBF143920BA</string>
<key>IDESourceControlProjectName</key>
<string>Moonlight</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</key>
<string>github.com:limelight-stream/limelight-ios.git</string>
<key>EB99D631D5149240E91F8D168F0F298D7A5BAA89</key>
<string>github.com:limelight-stream/limelight-common-c.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>Moonlight.xcodeproj</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</key>
<string>../..</string>
<key>EB99D631D5149240E91F8D168F0F298D7A5BAA89</key>
<string>../../limelight-common-c</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>github.com:limelight-stream/limelight-ios.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>111</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>EB99D631D5149240E91F8D168F0F298D7A5BAA89</string>
<key>IDESourceControlWCCName</key>
<string>limelight-common-c</string>
</dict>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</string>
<key>IDESourceControlWCCName</key>
<string>moonlight-ios</string>
</dict>
</array>
</dict>
</plist>
@@ -0,0 +1,53 @@
<?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>6524503E-ED62-4E8E-8A67-B6DFB5A532FD</string>
<key>IDESourceControlProjectName</key>
<string>project</string>
<key>IDESourceControlProjectOriginsDictionary</key>
<dict>
<key>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</key>
<string>github.com:limelight-stream/limelight-ios.git</string>
<key>EB99D631D5149240E91F8D168F0F298D7A5BAA89</key>
<string>github.com:limelight-stream/limelight-common-c.git</string>
</dict>
<key>IDESourceControlProjectPath</key>
<string>Moonlight.xcodeproj/project.xcworkspace</string>
<key>IDESourceControlProjectRelativeInstallPathDictionary</key>
<dict>
<key>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</key>
<string>../..</string>
<key>EB99D631D5149240E91F8D168F0F298D7A5BAA89</key>
<string>../..limelight-common-c/</string>
</dict>
<key>IDESourceControlProjectURL</key>
<string>github.com:limelight-stream/limelight-ios.git</string>
<key>IDESourceControlProjectVersion</key>
<integer>111</integer>
<key>IDESourceControlProjectWCCIdentifier</key>
<string>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</string>
<key>IDESourceControlProjectWCConfigurations</key>
<array>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>EB99D631D5149240E91F8D168F0F298D7A5BAA89</string>
<key>IDESourceControlWCCName</key>
<string>limelight-common-c</string>
</dict>
<dict>
<key>IDESourceControlRepositoryExtensionIdentifierKey</key>
<string>public.vcs.git</string>
<key>IDESourceControlWCCIdentifierKey</key>
<string>A4B0849259F9566B0CBA84A6D3D4A0F895C03123</string>
<key>IDESourceControlWCCName</key>
<string>limelight-ios</string>
</dict>
</array>
</dict>
</plist>
+9 -7
View File
@@ -1,12 +1,14 @@
#Limelight iOS
#Moonlight iOS
[Limelight](https://github.com/limelight-stream) is an open source implementation of NVIDIA's GameStream, as used by the NVIDIA Shield, but built for iOS. Limelight 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.
This is actively being developed and will be available on the App Store soon - check back here or on [our website](http://limelight-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 Limelight users are eager for the opportunity to stream their Steam collection to their iOS devices. Limelight for iOS is in the testing stage and preliminary versions are available for beta testers.
##### Apple TV Note:
We current cannot write a port for 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/limelight-stream/limelight-android) and [PC](https://github.com/limelight-stream/limelight-pc). Also, a client for [Windows and Windows Phone](https://github.com/limelight-stream/limelight-windows) is in the works and actively being developed.
Please be patient as we work to bring Limelight to more platforms.
##### Questions?
Check out our [wiki](https://github.com/moonlight-stream/moonlight-android/wiki).
+50 -24
View File
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" 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>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
</dependencies>
<customFonts key="customFonts">
<mutableArray key="Roboto-Regular.ttf">
@@ -13,9 +14,11 @@
<scene sceneID="Me4-Nr-liz">
<objects>
<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">
<rect key="frame" x="0.0" y="0.0" width="1024" height="704"/>
<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"/>
<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"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="f7l-kG-hJc">
<size key="itemSize" width="150" height="200"/>
@@ -24,14 +27,16 @@
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="fv6-NS-qsK">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<collectionViewCell clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="fv6-NS-qsK">
<rect key="frame" x="20" y="40" width="150" height="200"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="150" height="200"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<animations/>
</collectionViewCell>
</cells>
<connections>
@@ -42,14 +47,15 @@
<navigationItem key="navigationItem" id="pSu-bl-gL9">
<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">
<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"/>
<animations/>
<fontDescription key="fontDescription" name="Roboto-Regular" family="Roboto" pointSize="16"/>
<state key="normal" title="Limelight" image="Logo">
<color key="titleColor" red="0.3921568627" green="0.91372549020000005" blue="0.17254901959999999" alpha="1" colorSpace="calibratedRGB"/>
<state key="normal" title="Moonlight" image="Logo">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
</button>
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" title="No Host Selected" id="KDy-JC-2sU">
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
@@ -77,6 +83,8 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
@@ -84,11 +92,14 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="tintColor" red="0.3921568627" green="0.91372549020000005" blue="0.17254901959999999" alpha="1" colorSpace="calibratedRGB"/>
<animations/>
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</slider>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
@@ -96,6 +107,8 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
@@ -103,25 +116,18 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<segments>
<segment title="720p"/>
<segment title="1080p"/>
<segment title="Native"/>
</segments>
<color key="tintColor" red="0.3921568627" green="0.91372549020000005" blue="0.17254901959999999" alpha="1" colorSpace="calibratedRGB"/>
</segmentedControl>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<segments>
<segment title="30 Hz"/>
<segment title="60 Hz"/>
</segments>
<color key="tintColor" red="0.3921568627" green="0.91372549020000005" blue="0.17254901959999999" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</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">
<rect key="frame" x="16" y="236" width="153" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<color key="tintColor" red="0.81533776120000001" green="0.85979419950000002" blue="0.91372549020000005" alpha="1" colorSpace="calibratedRGB"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<nil key="highlightedColor"/>
@@ -129,15 +135,27 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<segments>
<segment title="Off"/>
<segment title="Auto"/>
<segment title="Simple"/>
<segment title="Full"/>
</segments>
<color key="tintColor" red="0.3803921569" green="0.92156862750000001" blue="0.25882352939999997" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</segmentedControl>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<segments>
<segment title="30 Hz"/>
<segment title="60 Hz"/>
</segments>
<color key="tintColor" red="0.72941176470000002" green="0.69411764710000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</segmentedControl>
</subviews>
<animations/>
<color key="backgroundColor" cocoaTouchSystemColor="viewFlipsideBackgroundColor"/>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
@@ -160,6 +178,7 @@
<view key="view" contentMode="scaleToFill" id="hGs-BR-t4b">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
@@ -180,6 +199,8 @@
<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"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<color key="barTintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
</navigationBar>
<connections>
<segue destination="wb7-af-jn8" kind="relationship" relationship="rootViewController" id="nkY-JG-Wki"/>
@@ -200,16 +221,19 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
</activityIndicatorView>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<animations/>
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="iUf-9X-GeA"/>
<nil key="simulatedStatusBarMetrics"/>
@@ -237,8 +261,10 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
</activityIndicatorView>
</subviews>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.5" colorSpace="calibratedWhite"/>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
@@ -252,7 +278,7 @@
</scene>
</scenes>
<resources>
<image name="Logo" width="36" height="36"/>
<image name="Logo" width="32" height="32"/>
</resources>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar" statusBarStyle="lightContent"/>
+44 -27
View File
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="6254" systemVersion="14C109" 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>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
<deployment identifier="iOS"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
</dependencies>
<customFonts key="customFonts">
<mutableArray key="Roboto-Regular.ttf">
@@ -13,9 +14,11 @@
<scene sceneID="emz-kO-L7q">
<objects>
<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">
<rect key="frame" x="0.0" y="0.0" width="568" height="256"/>
<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"/>
<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"/>
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="20" minimumInteritemSpacing="20" id="YcZ-cR-3tK">
<size key="itemSize" width="90" height="120"/>
@@ -24,14 +27,16 @@
<inset key="sectionInset" minX="20" minY="20" maxX="20" maxY="20"/>
</collectionViewFlowLayout>
<cells>
<collectionViewCell opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="Uqv-Di-fzX">
<rect key="frame" x="0.0" y="0.0" width="50" height="50"/>
<collectionViewCell clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" reuseIdentifier="AppCell" id="Uqv-Di-fzX">
<rect key="frame" x="20" y="40" width="90" height="120"/>
<autoresizingMask key="autoresizingMask"/>
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center">
<rect key="frame" x="0.0" y="0.0" width="90" height="120"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="calibratedWhite"/>
</view>
<animations/>
</collectionViewCell>
</cells>
<connections>
@@ -43,17 +48,18 @@
<navigationItem key="navigationItem" id="1jn-Sf-Xky">
<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">
<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"/>
<animations/>
<fontDescription key="fontDescription" name="Roboto-Regular" family="Roboto" pointSize="16"/>
<state key="normal" title="Limelight" image="Logo">
<color key="titleColor" red="0.3921568627" green="0.91372549020000005" blue="0.17254901959999999" alpha="1" colorSpace="calibratedRGB"/>
<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="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
</button>
</barButtonItem>
<barButtonItem key="rightBarButtonItem" title="No Host Selected" id="L1H-n4-HB7">
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="tintColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</barButtonItem>
</navigationItem>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
@@ -74,6 +80,7 @@
<view key="view" contentMode="scaleToFill" id="Usg-e0-g4a">
<rect key="frame" x="0.0" y="0.0" width="568" height="320"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<animations/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
@@ -97,68 +104,76 @@
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<color key="tintColor" red="0.39215686274509803" green="0.9137254901960784" blue="0.17254901960784313" alpha="1" colorSpace="calibratedRGB"/>
<animations/>
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</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">
<rect key="frame" x="16" y="20" width="151" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<segments>
<segment title="30 Hz"/>
<segment title="60 Hz"/>
</segments>
<color key="tintColor" red="0.39215686274509803" green="0.9137254901960784" blue="0.17254901960784313" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</segmentedControl>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<segments>
<segment title="720p"/>
<segment title="1080p"/>
<segment title="Native"/>
</segments>
<color key="tintColor" red="0.39215686274509803" green="0.9137254901960784" blue="0.17254901960784313" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</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">
<rect key="frame" x="16" y="217" width="153" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
<color key="textColor" red="0.96078431372549022" green="0.98039215686274506" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<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"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<segments>
<segment title="Off"/>
<segment title="Auto"/>
<segment title="Simple"/>
<segment title="Full"/>
</segments>
<color key="tintColor" red="0.38039215686274508" green="0.92156862745098034" blue="0.25882352941176467" alpha="1" colorSpace="calibratedRGB"/>
<color key="tintColor" red="0.72941176470588232" green="0.69411764705882351" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</segmentedControl>
</subviews>
<color key="backgroundColor" cocoaTouchSystemColor="viewFlipsideBackgroundColor"/>
<animations/>
<color key="backgroundColor" red="0.12156862745098039" green="0.12941176470588237" blue="0.14117647058823529" alpha="1" colorSpace="calibratedRGB"/>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
<connections>
@@ -181,6 +196,8 @@
<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"/>
<autoresizingMask key="autoresizingMask"/>
<animations/>
<color key="barTintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
<textAttributes key="titleTextAttributes">
<offsetWrapper key="textShadowOffset" horizontal="0.0" vertical="0.0"/>
</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">
<rect key="frame" x="262" y="149" width="45" height="21"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<animations/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="calibratedRGB"/>
<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">
<rect key="frame" x="274" y="121" width="20" height="20"/>
<autoresizingMask key="autoresizingMask" flexibleMinX="YES" flexibleMaxX="YES" flexibleMinY="YES" flexibleMaxY="YES"/>
<animations/>
</activityIndicatorView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="1" colorSpace="calibratedWhite"/>
<animations/>
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
</view>
<navigationItem key="navigationItem" id="8uX-4T-BiC"/>
<nil key="simulatedStatusBarMetrics"/>
@@ -239,8 +259,10 @@
<subviews>
<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"/>
<animations/>
</activityIndicatorView>
</subviews>
<animations/>
<color key="backgroundColor" white="0.0" alpha="0.5" colorSpace="calibratedWhite"/>
</view>
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
@@ -254,11 +276,6 @@
</scene>
</scenes>
<resources>
<image name="Logo" width="36" height="36"/>
<image name="Logo" width="32" height="32"/>
</resources>
<simulatedMetricsContainer key="defaultSimulatedMetrics">
<simulatedStatusBarMetrics key="statusBar"/>
<simulatedOrientationMetrics key="orientation"/>
<simulatedScreenMetrics key="destination" type="retina4"/>
</simulatedMetricsContainer>
</document>
+4 -1
View File
@@ -616,7 +616,10 @@ OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, fl
* merged. Splitting valid Opus packets is always guaranteed to succeed,
* whereas merging valid packets only succeeds if all frames have the same
* mode, bandwidth, and frame size, and when the total duration of the merged
* packet is no more than 120 ms.
* packet is no more than 120 ms. The 120 ms limit comes from the
* specification and limits decoder memory requirements at a point where
* framing overhead becomes negligible.
*
* The repacketizer currently only operates on elementary Opus
* streams. It will not manipualte multistream packets successfully, except in
* the degenerate case where they consist of data from a single stream.
+4
View File
@@ -713,6 +713,10 @@ extern "C" {
OPUS_EXPORT const char *opus_strerror(int error);
/** Gets the libopus version string.
*
* Applications may look for the substring "-fixed" in the version string to
* determine whether they have a fixed-point or floating-point build at
* runtime.
*
* @returns Version string
*/
Binary file not shown.
@@ -0,0 +1,461 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 47;
objects = {
/* Begin PBXBuildFile section */
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 */
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 */
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 = (
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 = (
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 = 0700;
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 */,
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 */,
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_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "Mac Developer";
COPY_PHASE_STRIP = NO;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = 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_INT_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "3rd Party Mac Developer Application";
COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = 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"
}
]
}