Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15fe5a06c2 | ||
|
|
8d4c7bd705 | ||
|
|
b0d85abfa6 | ||
|
|
4295017324 | ||
|
|
d80d70215a | ||
|
|
a46f905aa6 | ||
|
|
453c50d505 | ||
|
|
61c7d9f2b3 | ||
|
|
34707e7743 | ||
|
|
9a9b9651a1 | ||
|
|
d4576a8739 | ||
|
|
87824c2650 | ||
|
|
283e735f90 | ||
|
|
202f968b98 | ||
|
|
62df1cd5ba | ||
|
|
f24c28c848 | ||
|
|
8fb465d3ca | ||
|
|
29dff2320b | ||
|
|
a40b30016b | ||
|
|
409b262a4f | ||
|
|
73197e4378 | ||
|
|
f51dbe4295 | ||
|
|
597aaa1bab | ||
|
|
b9656da8a5 | ||
|
|
422db1898c | ||
|
|
56691791b8 | ||
|
|
de2a5d3cd7 | ||
|
|
49fc10191c | ||
|
|
bf8aaa8198 | ||
|
|
9a4cdc9c94 | ||
|
|
f6153fe818 | ||
|
|
f2fa9e18ea | ||
|
|
aa013be6e6 | ||
|
|
7e21b131ac | ||
|
|
97681f3a0d | ||
|
|
e476cc407c | ||
|
|
f2e03bbf1f | ||
|
|
a6cef32c9a | ||
|
|
6d94897c21 | ||
|
|
a065c78b5f | ||
|
|
83479719a4 | ||
|
|
fd4ede58ca | ||
|
|
7ed5a9831f | ||
|
|
42b7fd35ce | ||
|
|
42c97eafaa | ||
|
|
5b82be0546 | ||
|
|
1529058f52 | ||
|
|
3dcca3a922 | ||
|
|
9b8f230c46 | ||
|
|
7699d9e574 | ||
|
|
641e1c5066 | ||
|
|
617ef7c6a6 | ||
|
|
c2620b8321 | ||
|
|
9e91d136bf | ||
|
|
9960d2a2ff | ||
|
|
311e77e01a | ||
|
|
c08df921da | ||
|
|
ba4e55aac4 | ||
|
|
af16f03703 | ||
|
|
8189d54703 | ||
|
|
ac8514e3cb | ||
|
|
8f4b8da3ce | ||
|
|
8337b3e708 | ||
|
|
cb527baead | ||
|
|
ed10612e2c | ||
|
|
7d3eaeef83 | ||
|
|
dd5ecb37c4 | ||
|
|
636143ee97 | ||
|
|
28ff29bb96 | ||
|
|
a508c6d855 | ||
|
|
dbd6eabd24 | ||
|
|
ad0a5935f7 | ||
|
|
dcd2dc97a6 | ||
|
|
f92544c7d2 | ||
|
|
797fa0f492 | ||
|
|
ff52adf4f8 | ||
|
|
8bb49ada11 | ||
|
|
3f709b616b | ||
|
|
83694f8141 | ||
|
|
a4352aae4d | ||
|
|
2ac19336d6 | ||
|
|
63b09c5b27 | ||
|
|
b2c2f0837a | ||
|
|
335b5aef1f | ||
|
|
918e1248f2 | ||
|
|
442a791e0c | ||
|
|
573b93329d | ||
|
|
40359c5e32 | ||
|
|
3b01b50503 | ||
|
|
76b55cc230 | ||
|
|
e136cd96c1 | ||
|
|
5028eaed59 | ||
|
|
d18c713684 | ||
|
|
08e169eb23 | ||
|
|
611358e35c | ||
|
|
63275130bb | ||
|
|
7c9313e04d | ||
|
|
d466a0af07 | ||
|
|
c8adc184c9 | ||
|
|
d40a29df71 | ||
|
|
85820bf812 | ||
|
|
5d4d10ac8a | ||
|
|
eca018ad15 | ||
|
|
90e582a263 | ||
|
|
3717228e28 | ||
|
|
8c0997ddcd | ||
|
|
d722c9e18d | ||
|
|
94c9433b99 | ||
|
|
befef62b2f | ||
|
|
dc00c1e3e7 | ||
|
|
3555d60a9b | ||
|
|
bd8b9f8bfb | ||
|
|
72dcd76e37 | ||
|
|
fbae7f88b5 | ||
|
|
791a5b1ea1 | ||
|
|
8c5a82573b | ||
|
|
cc56a36bbd | ||
|
|
336dbeed98 | ||
|
|
f8613cdbfd | ||
|
|
a5961dd9b5 | ||
|
|
17a5866fdd | ||
|
|
5e77380636 | ||
|
|
845af246b5 | ||
|
|
87cac4e562 | ||
|
|
70eb4fd69d | ||
|
|
c5120bec37 | ||
|
|
24fc9ac0a9 | ||
|
|
2c0624f1e7 | ||
|
|
8b227f28f7 | ||
|
|
23e9c3f236 | ||
|
|
eefde316de | ||
|
|
a3cfd787de | ||
|
|
410d0d367b | ||
|
|
39b04d46a4 | ||
|
|
0e8647ad07 | ||
|
|
73091e7e8c | ||
|
|
16a2ab3941 | ||
|
|
39a2e8be78 | ||
|
|
8e6dadfa79 | ||
|
|
c2134585df | ||
|
|
dedcbd9d3e | ||
|
|
bd379677a2 | ||
|
|
466ebe2840 | ||
|
|
736887b945 | ||
|
|
993bfca0ae | ||
|
|
5ad87f7400 | ||
|
|
e862dbd6b6 | ||
|
|
befde5eb28 | ||
|
|
7fd3b8df1c | ||
|
|
cee501d9b4 | ||
|
|
a103c0fd45 | ||
|
|
bf71ae003f | ||
|
|
5b102ce3d3 | ||
|
|
c2012fa195 | ||
|
|
003fc8c1f8 | ||
|
|
9123033bb3 | ||
|
|
253144188c | ||
|
|
4ccb9bebbf | ||
|
|
49f647748c | ||
|
|
e2e8f0121d | ||
|
|
b5ea4c3e50 | ||
|
|
90d47004e7 | ||
|
|
450960eaaf | ||
|
|
44550baaa9 | ||
|
|
293dc26b2e | ||
|
|
109fa6f463 | ||
|
|
44f64e1a35 | ||
|
|
2e479837ed | ||
|
|
1b681a8730 | ||
|
|
f988ce0278 | ||
|
|
1ef5c87afc | ||
|
|
f5b99b6b9c | ||
|
|
485dd4b001 | ||
|
|
92e2c0d7cc | ||
|
|
48ffca57ec | ||
|
|
e83a996cd5 | ||
|
|
57191e3b9a | ||
|
|
eadcf3b3eb | ||
|
|
71e0646659 | ||
|
|
f2edee1669 | ||
|
|
11948bf618 | ||
|
|
4a9294a4b7 | ||
|
|
a9b8f753a2 | ||
|
|
05761c787c | ||
|
|
9a7b3b1325 | ||
|
|
b04a4e72ff | ||
|
|
b0b9a614f3 | ||
|
|
76ab786e94 | ||
|
|
8afcdc92d4 | ||
|
|
907a2cd59b | ||
|
|
a85b931d87 | ||
|
|
62f1b3e595 | ||
|
|
b9381ad027 | ||
|
|
98d01f7775 | ||
|
|
de39c87185 | ||
|
|
10a00b0d28 | ||
|
|
4d8788add3 | ||
|
|
9c019be322 | ||
|
|
80254513c4 | ||
|
|
5a13e44fdb | ||
|
|
ec0a462092 | ||
|
|
25c7b18147 | ||
|
|
fb238e0d1d | ||
|
|
bfc0b89926 | ||
|
|
2f0e219726 | ||
|
|
2305f33572 | ||
|
|
d17f2f9dee | ||
|
|
a28049a58c | ||
|
|
2d2f71dcab | ||
|
|
59506a2364 | ||
|
|
2cec53ab6b | ||
|
|
42ef67d939 | ||
|
|
30ec68cd4e | ||
|
|
941c414930 | ||
|
|
b918005555 | ||
|
|
c74fa4d5b0 | ||
|
|
1a71e040c0 | ||
|
|
236c9d5c6e | ||
|
|
862b8632e3 | ||
|
|
cdb5f51ab8 | ||
|
|
314f32388a | ||
|
|
39b0b429d6 | ||
|
|
23a12ed101 | ||
|
|
653a789110 | ||
|
|
04b2fccaef | ||
|
|
ec0124e255 | ||
|
|
132a1fc410 | ||
|
|
63297c8483 | ||
|
|
5fd2c29a73 | ||
|
|
e6e7ec9202 | ||
|
|
fcc770d820 | ||
|
|
4243bcd5d1 | ||
|
|
67b08cd8b9 | ||
|
|
e697938afc | ||
|
|
275f6df8c1 | ||
|
|
aea2067e1c | ||
|
|
b5241a0c30 | ||
|
|
6cac2348b4 | ||
|
|
0293df7748 | ||
|
|
391872ddb8 | ||
|
|
4bafefbe16 | ||
|
|
812f3f3717 | ||
|
|
e498736af6 | ||
|
|
1842a11f56 | ||
|
|
85f81ca8c1 | ||
|
|
b792629943 | ||
|
|
7df76fcd93 | ||
|
|
8b60e79406 | ||
|
|
fcb6c7386c | ||
|
|
2729fad47c | ||
|
|
41eb933e11 | ||
|
|
f759f719e6 | ||
|
|
74283a6763 | ||
|
|
0a19c5950a | ||
|
|
e8832ed746 | ||
|
|
6cc165b589 | ||
|
|
1c86c4485d | ||
|
|
127e5ed54a | ||
|
|
3fee5d0a62 | ||
|
|
c913b3f04f | ||
|
|
dfd30c0624 | ||
|
|
5117a6ede5 | ||
|
|
fb9c071243 | ||
|
|
d0a8f0e0f1 | ||
|
|
6bb6c40bec | ||
|
|
af3bc82d0f | ||
|
|
b9d5d94d70 | ||
|
|
43f4804194 | ||
|
|
be26ce9a8f | ||
|
|
ca562e2251 | ||
|
|
d7ee0916e9 | ||
|
|
3bc9e050f1 | ||
|
|
4b9bd8398b | ||
|
|
20a61dd9f4 | ||
|
|
dc4ecbf262 | ||
|
|
68f55235ec | ||
|
|
5434b653c7 | ||
|
|
25d7af9453 | ||
|
|
5584083809 | ||
|
|
9f9aec70b0 | ||
|
|
a8d1770871 | ||
|
|
d0d60b8ffc | ||
|
|
86f7112789 | ||
|
|
da1115e529 | ||
|
|
593da7ef3e | ||
|
|
de5377a95d | ||
|
|
7d7500b187 | ||
|
|
45dbd46da1 | ||
|
|
89d8bc6009 | ||
|
|
b99988836a | ||
|
|
3e94613eb3 | ||
|
|
832b9189f8 | ||
|
|
3464539bd3 | ||
|
|
815592117d | ||
|
|
b51341ef54 | ||
|
|
9ffbb5f155 | ||
|
|
9716867ade | ||
|
|
7c141c1fd2 | ||
|
|
42c4e7ca58 | ||
|
|
6a6ea4a79a | ||
|
|
5d0ca8451d | ||
|
|
4641f68eb8 | ||
|
|
dd33f57b9a | ||
|
|
f6b225ca9c | ||
|
|
4ac3f11ff8 | ||
|
|
62aaf27293 | ||
|
|
eac2d985e2 | ||
|
|
61ea7f3f1c | ||
|
|
40f7faa1b1 | ||
|
|
9e18b8021b | ||
|
|
ce95f2c153 | ||
|
|
fd50b71b16 | ||
|
|
39ab472cf6 | ||
|
|
48ba7eb2dc | ||
|
|
42edaa1bad | ||
|
|
955fb59156 | ||
|
|
2fbc67ef00 | ||
|
|
23564a3028 | ||
|
|
9a07d5a33a | ||
|
|
84c037f235 | ||
|
|
c13df82f5b | ||
|
|
b15d61a5bf | ||
|
|
5aff719984 | ||
|
|
b0c2978405 | ||
|
|
91dcb505de | ||
|
|
d1f35d938b | ||
|
|
359b822951 | ||
|
|
39580e4352 | ||
|
|
7b3d099449 | ||
|
|
b17c45e9ca | ||
|
|
4c7a2cecdd | ||
|
|
175074ece8 | ||
|
|
8a5ec513bf | ||
|
|
7cfb7f73a2 | ||
|
|
c608685737 | ||
|
|
3beca2fc72 | ||
|
|
c59aafb4bb | ||
|
|
256e40acdc | ||
|
|
39b1b65e16 | ||
|
|
1783abec13 | ||
|
|
983c65d399 | ||
|
|
4caa9672c9 | ||
|
|
15be6a3f75 | ||
|
|
d38eb0a3ba | ||
|
|
e8ea942ad2 | ||
|
|
cb68b10475 | ||
|
|
11c854ce44 | ||
|
|
9636f4742b | ||
|
|
5867317526 | ||
|
|
8a8f7b6903 | ||
|
|
61b6e25a91 | ||
|
|
50cff820de | ||
|
|
4e586a28c8 | ||
|
|
0702b4ed57 | ||
|
|
4a2132a682 | ||
|
|
ba81d1d6a9 | ||
|
|
402ce4b3ec | ||
|
|
fc713453ad | ||
|
|
b222ccffbb | ||
|
|
56ce7329d2 | ||
|
|
99ab6db557 | ||
|
|
d7adf96f3a | ||
|
|
0ae58c61a9 | ||
|
|
2ec7d1d2f1 | ||
|
|
ad1b9059ee | ||
|
|
4439c7cce6 | ||
|
|
b8a4093c75 | ||
|
|
ec3748b26e | ||
|
|
1c1f22e047 | ||
|
|
9aa9b0fc5a | ||
|
|
f8e2ca8500 | ||
|
|
3076e29335 | ||
|
|
fe616d86c5 | ||
|
|
bfa4856bbe | ||
|
|
5ea92a7b48 | ||
|
|
4ba71db7b2 | ||
|
|
c1e6aeb43c | ||
|
|
e3ffb66ef0 | ||
|
|
5daa82b0ba | ||
|
|
a8bcc6afba | ||
|
|
e6aa16ad01 | ||
|
|
ad0705d126 | ||
|
|
2f31f93bf8 | ||
|
|
ea3be613c5 | ||
|
|
b495246f34 | ||
|
|
814470f4bf | ||
|
|
82293a08b6 | ||
|
|
20d66336a7 | ||
|
|
c8441ec9fa | ||
|
|
f72135c227 | ||
|
|
100e6e4ce8 | ||
|
|
ec8be20d62 | ||
|
|
55d48101ef | ||
|
|
c36f4c5f84 | ||
|
|
06289ac4d2 | ||
|
|
e6a2d5d425 | ||
|
|
ea8db9c4ea | ||
|
|
3773e841d1 | ||
|
|
ad1ddd04f3 | ||
|
|
67a8b232b9 | ||
|
|
5293c07fc0 | ||
|
|
e3a42db007 | ||
|
|
3b1462af22 | ||
|
|
74a0c5b1cd | ||
|
|
05a5e4fa64 | ||
|
|
b6445295a7 | ||
|
|
391605ef36 | ||
|
|
695499dea9 | ||
|
|
9ba7f35444 | ||
|
|
37dc00735b | ||
|
|
920cbadc91 | ||
|
|
bc53b4dc32 | ||
|
|
6015c38d17 | ||
|
|
4ea8694a7d | ||
|
|
00f01196fb | ||
|
|
543639c93e | ||
|
|
1da877fed7 | ||
|
|
396b5fc156 | ||
|
|
297dfd4159 | ||
|
|
23e9d48b0d | ||
|
|
9ec650a84f | ||
|
|
90bdbc4ae0 | ||
|
|
dd5f06723b | ||
|
|
55b2871b83 | ||
|
|
c8b13126d0 | ||
|
|
96cfe0b70d | ||
|
|
6dbb938368 | ||
|
|
46fe7a8aed | ||
|
|
3151ac6bf0 | ||
|
|
dc5210f691 | ||
|
|
1f02265003 | ||
|
|
e4af9032e2 | ||
|
|
e8650b2420 | ||
|
|
9c6b718be2 | ||
|
|
8f12114a56 | ||
|
|
dc6ebffab1 | ||
|
|
13e894e9a3 | ||
|
|
4c95773131 | ||
|
|
38776a01e4 | ||
|
|
b2563e534d | ||
|
|
37f25c1f97 | ||
|
|
642085ca32 | ||
|
|
5dee29a21c | ||
|
|
b01d13976b | ||
|
|
ae1c83a011 | ||
|
|
e5f962dc3f | ||
|
|
54dd79d2dd | ||
|
|
935fb6ffe3 | ||
|
|
48d1c1a080 | ||
|
|
2d02ce2a1b | ||
|
|
29fda59a72 | ||
|
|
05f0dfd4f5 | ||
|
|
0bdc5a83f1 | ||
|
|
8688bf1210 | ||
|
|
bf0858d57e | ||
|
|
8d4d391310 | ||
|
|
8fb15336c4 | ||
|
|
883385c42b | ||
|
|
6d1139796e | ||
|
|
e58eb5f56a | ||
|
|
2b0ce49646 | ||
|
|
73364127d2 | ||
|
|
84a986bc88 | ||
|
|
f13051aa31 | ||
|
|
6bb559303b | ||
|
|
b7324f9a44 | ||
|
|
c0b2bbe552 | ||
|
|
8c36cf40fd | ||
|
|
717296269f | ||
|
|
4be29abede | ||
|
|
528af9684e | ||
|
|
ff7a4ef190 | ||
|
|
99a2dbb956 | ||
|
|
280341791a | ||
|
|
1759565920 | ||
|
|
f57fa678f6 | ||
|
|
f8b5b16109 | ||
|
|
005a678089 | ||
|
|
315dd53dcb | ||
|
|
bb24495b3f | ||
|
|
b9f2764990 | ||
|
|
a9a00629b1 | ||
|
|
1223a9013f | ||
|
|
ab019eef0f | ||
|
|
20f82ff739 | ||
|
|
4d55a6a7e9 | ||
|
|
d7ec41d56e | ||
|
|
a6a1929a43 | ||
|
|
722850ceb6 | ||
|
|
5a976764c3 | ||
|
|
f90becb2f6 | ||
|
|
5296b2eb39 | ||
|
|
987a30e15f | ||
|
|
0880c3639c | ||
|
|
2972d40d92 | ||
|
|
c4430ef18d | ||
|
|
6b97af13bf | ||
|
|
cd18ca64bb | ||
|
|
d3c6302681 | ||
|
|
58bd3cc706 | ||
|
|
8d3401f962 | ||
|
|
dfc86015bd | ||
|
|
772ee3a680 | ||
|
|
f217ca9bbe | ||
|
|
fab8d604d2 | ||
|
|
7767ae497b | ||
|
|
58e41dfcf1 | ||
|
|
796ab2bf90 | ||
|
|
dfa07bf94b | ||
|
|
f43c74d59b | ||
|
|
fd9ee45dac | ||
|
|
40a04eb08b | ||
|
|
e9cff8f7b7 | ||
|
|
acee0af9df | ||
|
|
8d3e81ed25 | ||
|
|
5f8b0672f7 | ||
|
|
62bbec3c5d |
No files matched your search
@@ -0,0 +1,8 @@
|
|||||||
|
# ProBot No Response (https://probot.github.io/apps/no-response/)
|
||||||
|
|
||||||
|
daysUntilClose: 7
|
||||||
|
responseRequiredLabel: 'need more info'
|
||||||
|
closeComment: >
|
||||||
|
This issue has been automatically closed because there was no response to a
|
||||||
|
request for more information from the issue opener. Please leave a comment or
|
||||||
|
open a new issue if you have additional information related to this issue.
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
# ProBot Stale (https://probot.github.io/apps/stale/)
|
||||||
|
|
||||||
|
daysUntilStale: 90
|
||||||
|
daysUntilClose: 7
|
||||||
|
exemptLabels:
|
||||||
|
- accepted
|
||||||
|
- bug
|
||||||
|
- enhancement
|
||||||
|
- meta
|
||||||
|
staleLabel: stale
|
||||||
|
markComment: >
|
||||||
|
This issue has been automatically marked as stale because it has not had
|
||||||
|
recent activity. It will be closed if no further activity occurs.
|
||||||
|
closeComment: false
|
||||||
@@ -1,2 +1,4 @@
|
|||||||
**/xcuserdata/
|
**/xcuserdata/
|
||||||
|
**/Moonlight.xcscmblueprint
|
||||||
Build
|
Build
|
||||||
|
DerivedData
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
[submodule "limelight-common-c"]
|
[submodule "moonlight-common/moonlight-common-c"]
|
||||||
path = limelight-common-c
|
path = moonlight-common/moonlight-common-c
|
||||||
url = git@github.com:limelight-stream/limelight-common-c.git
|
url = https://github.com/moonlight-stream/moonlight-common-c.git
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
language: objective-c
|
||||||
|
|
||||||
|
git:
|
||||||
|
depth: 1
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
include:
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode11
|
||||||
|
env:
|
||||||
|
- SCHEME="Moonlight"
|
||||||
|
- TARGET="platform=iOS Simulator,OS=12.1,name=iPhone SE"
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode11
|
||||||
|
env:
|
||||||
|
- SCHEME="Moonlight"
|
||||||
|
- TARGET="platform=iOS Simulator,OS=12.1,name=iPad Pro (9.7-inch)"
|
||||||
|
- os: osx
|
||||||
|
osx_image: xcode11
|
||||||
|
env:
|
||||||
|
- SCHEME="Moonlight TV"
|
||||||
|
- TARGET="platform=tvOS Simulator,OS=12.1,name=Apple TV 4K"
|
||||||
|
|
||||||
|
script:
|
||||||
|
- set -o pipefail && xcodebuild -project Moonlight.xcodeproj -scheme "$SCHEME" -destination "$TARGET" build | xcpretty
|
||||||
@@ -31,43 +31,44 @@ do
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
echo "Compiling source for $ARCH in directory $OPUS_DIR"
|
echo "Compiling source for $ARCH in directory $OPUS_DIR"
|
||||||
|
echo "cd $OPUS_DIR"
|
||||||
cd $OPUS_DIR
|
cd $OPUS_DIR
|
||||||
|
|
||||||
DIST_DIR=$DIST_DIR_BASE-$ARCH
|
DIST_DIR=$DIST_DIR_BASE-$ARCH
|
||||||
|
echo "mkdir -p $DIST_DIR"
|
||||||
mkdir -p $DIST_DIR
|
mkdir -p $DIST_DIR
|
||||||
CFLAGS_ARCH=$ARCH
|
CFLAGS_ARCH=$ARCH
|
||||||
case $ARCH in
|
case $ARCH in
|
||||||
armv7)
|
armv7)
|
||||||
EXTRA_FLAGS="--with-pic --enable-fixed-point"
|
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"
|
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
|
||||||
IOSSDK=iPhoneOS${IOSSDK_VER}
|
IOSSDK=iPhoneOS
|
||||||
;;
|
;;
|
||||||
armv7s)
|
armv7s)
|
||||||
EXTRA_FLAGS="--with-pic --enable-fixed-point"
|
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"
|
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
|
||||||
IOSSDK=iPhoneOS${IOSSDK_VER}
|
IOSSDK=iPhoneOS
|
||||||
;;
|
;;
|
||||||
aarch64)
|
aarch64)
|
||||||
CFLAGS_ARCH="arm64"
|
CFLAGS_ARCH="arm64"
|
||||||
EXTRA_FLAGS="--with-pic --enable-fixed-point"
|
EXTRA_FLAGS="--with-pic --enable-fixed-point"
|
||||||
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
||||||
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
|
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
|
||||||
IOSSDK=iPhoneOS${IOSSDK_VER}
|
IOSSDK=iPhoneOS
|
||||||
;;
|
;;
|
||||||
x86_64)
|
x86_64)
|
||||||
EXTRA_FLAGS="--with-pic"
|
EXTRA_FLAGS="--with-pic"
|
||||||
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
||||||
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
|
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
|
||||||
IOSSDK=iPhoneSimulator${IOSSDK_VER}
|
IOSSDK=iPhoneSimulator
|
||||||
;;
|
;;
|
||||||
i386)
|
i386)
|
||||||
EXTRA_FLAGS="--with-pic"
|
EXTRA_FLAGS="--with-pic"
|
||||||
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
||||||
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
|
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
|
||||||
IOSSDK=iPhoneSimulator${IOSSDK_VER}
|
IOSSDK=iPhoneSimulator
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Unsupported architecture ${ARCH}"
|
echo "Unsupported architecture ${ARCH}"
|
||||||
@@ -76,7 +77,7 @@ do
|
|||||||
esac
|
esac
|
||||||
|
|
||||||
echo "Configuring opus for $ARCH..."
|
echo "Configuring opus for $ARCH..."
|
||||||
|
echo "./autogen.sh"
|
||||||
./autogen.sh
|
./autogen.sh
|
||||||
|
|
||||||
CFLAGS="-g -O2 -pipe -arch ${CFLAGS_ARCH} \
|
CFLAGS="-g -O2 -pipe -arch ${CFLAGS_ARCH} \
|
||||||
@@ -87,6 +88,9 @@ do
|
|||||||
-isysroot ${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
|
-isysroot ${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
|
||||||
-L${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk/usr/lib"
|
-L${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk/usr/lib"
|
||||||
|
|
||||||
|
echo "CFLAGS=$CFLAGS"
|
||||||
|
echo "LDFLAGS=$LDFLAGS"
|
||||||
|
|
||||||
export CFLAGS
|
export CFLAGS
|
||||||
export LDFLAGS
|
export LDFLAGS
|
||||||
|
|
||||||
@@ -100,6 +104,14 @@ do
|
|||||||
export NM="/usr/bin/nm"
|
export NM="/usr/bin/nm"
|
||||||
export RANLIB="/usr/bin/ranlib"
|
export RANLIB="/usr/bin/ranlib"
|
||||||
export STRIP="/usr/bin/strip"
|
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 \
|
./configure \
|
||||||
--prefix=$DIST_DIR \
|
--prefix=$DIST_DIR \
|
||||||
@@ -111,10 +123,14 @@ do
|
|||||||
${EXTRA_FLAGS}
|
${EXTRA_FLAGS}
|
||||||
|
|
||||||
echo "Installing opus for $ARCH..."
|
echo "Installing opus for $ARCH..."
|
||||||
|
echo "make clean"
|
||||||
make clean
|
make clean
|
||||||
|
echo "make -j$NJOB V=1"
|
||||||
make -j$NJOB V=1
|
make -j$NJOB V=1
|
||||||
|
echo "make install"
|
||||||
make install
|
make install
|
||||||
|
|
||||||
|
echo "cd $SCRIPT_DIR"
|
||||||
cd $SCRIPT_DIR
|
cd $SCRIPT_DIR
|
||||||
|
|
||||||
if [ -d $DIST_DIR/bin ]
|
if [ -d $DIST_DIR/bin ]
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ source config.sh
|
|||||||
SCRIPT_DIR=$( (cd -P $(dirname $0) && pwd) )
|
SCRIPT_DIR=$( (cd -P $(dirname $0) && pwd) )
|
||||||
DIST_DIR_BASE=${DIST_DIR_BASE:="$SCRIPT_DIR/dist"}
|
DIST_DIR_BASE=${DIST_DIR_BASE:="$SCRIPT_DIR/dist"}
|
||||||
|
|
||||||
git submodule update --init opus
|
|
||||||
cd opus
|
cd opus
|
||||||
git checkout master
|
git checkout master
|
||||||
git pull origin master
|
git pull origin master
|
||||||
|
|||||||
@@ -1,41 +1,35 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<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="14868" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES" colorMatched="YES">
|
||||||
|
<device id="retina6_1" orientation="landscape" appearance="light"/>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14824"/>
|
||||||
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<objects>
|
<objects>
|
||||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
<view contentMode="scaleToFill" id="iN0-l3-epB">
|
<navigationController id="vV9-32-ww6">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="480" height="480"/>
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="y2P-aE-Haa">
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<rect key="frame" x="0.0" y="0.0" width="896" height="44"/>
|
||||||
<subviews>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<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">
|
<color key="barTintColor" red="0.66666668653488159" green="0.66666668653488159" blue="0.66666668653488159" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<rect key="frame" x="22" y="439" width="437" height="21"/>
|
</navigationBar>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
<viewControllers>
|
||||||
<color key="textColor" red="0.070588235294117646" green="0.45490196078431372" blue="0.074509803921568626" alpha="1" colorSpace="calibratedRGB"/>
|
<viewController id="l6V-ue-5Om">
|
||||||
<nil key="highlightedColor"/>
|
<layoutGuides>
|
||||||
<variation key="widthClass=compact">
|
<viewControllerLayoutGuide type="top" id="rEZ-vx-akr"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="11"/>
|
<viewControllerLayoutGuide type="bottom" id="gBD-cy-cth"/>
|
||||||
</variation>
|
</layoutGuides>
|
||||||
</label>
|
<view key="view" contentMode="scaleToFill" id="6lF-fc-kpK">
|
||||||
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Limelight Flat Design Banner" translatesAutoresizingMaskIntoConstraints="NO" id="lr8-1h-ydW">
|
<rect key="frame" x="0.0" y="0.0" width="896" height="414"/>
|
||||||
<rect key="frame" x="-8" y="115" width="496" height="251"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
</imageView>
|
<color key="backgroundColor" red="0.3333333432674408" green="0.3333333432674408" blue="0.3333333432674408" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
</subviews>
|
</view>
|
||||||
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="1" colorSpace="calibratedRGB"/>
|
<navigationItem key="navigationItem" id="rW0-BH-s7l"/>
|
||||||
<constraints>
|
</viewController>
|
||||||
<constraint firstAttribute="centerY" secondItem="lr8-1h-ydW" secondAttribute="centerY" id="C8A-9E-cM6"/>
|
</viewControllers>
|
||||||
<constraint firstAttribute="bottom" secondItem="8ie-xW-0ye" secondAttribute="bottom" constant="20" id="Gnz-uJ-CDw"/>
|
<point key="canvasLocation" x="34" y="149"/>
|
||||||
<constraint firstAttribute="centerX" secondItem="lr8-1h-ydW" secondAttribute="centerX" id="WCv-Cd-TyR"/>
|
</navigationController>
|
||||||
<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>
|
|
||||||
</objects>
|
</objects>
|
||||||
<resources>
|
|
||||||
<image name="Limelight Flat Design Banner" width="496" height="251"/>
|
|
||||||
</resources>
|
|
||||||
</document>
|
</document>
|
||||||
@@ -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
|
|
||||||
@@ -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
|
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// AppCollectionView.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppCollectionView : UICollectionView
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// AppCollectionView.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppCollectionView.h"
|
||||||
|
|
||||||
|
@implementation AppCollectionView
|
||||||
|
|
||||||
|
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
|
||||||
|
if ([view isKindOfClass:[UIButton class]]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return [super touchesShouldCancelInContentView:view];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Only override drawRect: if you perform custom drawing.
|
||||||
|
// An empty implementation adversely affects performance during animation.
|
||||||
|
- (void)drawRect:(CGRect)rect {
|
||||||
|
// Drawing code
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -1,16 +1,24 @@
|
|||||||
//
|
//
|
||||||
// AppDelegate.h
|
// AppDelegate.h
|
||||||
// Limelight-iOS
|
// Moonlight
|
||||||
//
|
//
|
||||||
// Created by Diego Waxemberg on 1/17/14.
|
// Created by Diego Waxemberg on 1/17/14.
|
||||||
// Copyright (c) 2014 Diego Waxemberg. All rights reserved.
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||||
|
|
||||||
@property (strong, nonatomic) UIWindow *window;
|
@property (strong, nonatomic) UIWindow *window;
|
||||||
|
#else
|
||||||
|
#import <Cocoa/Cocoa.h>
|
||||||
|
@interface AppDelegate : NSObject <NSApplicationDelegate>
|
||||||
|
|
||||||
|
@property (readonly, strong) NSPersistentContainer *persistentContainer;
|
||||||
|
@property (strong, nonatomic) NSWindow *window;
|
||||||
|
#endif
|
||||||
|
|
||||||
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
|
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
|
||||||
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
|
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
//
|
//
|
||||||
// AppDelegate.m
|
// AppDelegate.m
|
||||||
// Limelight-iOS
|
// Moonlight
|
||||||
//
|
//
|
||||||
// Created by Diego Waxemberg on 1/17/14.
|
// 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"
|
#import "AppDelegate.h"
|
||||||
@@ -16,35 +16,17 @@
|
|||||||
|
|
||||||
static NSOperationQueue* mainQueue;
|
static NSOperationQueue* mainQueue;
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
static NSString* DB_NAME = @"Moonlight_tvOS.bin";
|
||||||
|
#elif TARGET_OS_IPHONE
|
||||||
|
static NSString* DB_NAME = @"Limelight_iOS.sqlite";
|
||||||
|
#else
|
||||||
|
static NSString* DB_NAME = @"moonlight_mac.sqlite";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
|
||||||
{
|
{
|
||||||
[[UILabel appearance] setFont:[UIFont fontWithName:@"Roboto-Regular" size:[UIFont systemFontSize]]];
|
|
||||||
[[UIButton appearance].titleLabel setFont:[UIFont fontWithName:@"Roboto-Regular" size:[UIFont systemFontSize]]];
|
|
||||||
|
|
||||||
|
|
||||||
// Generate selected segment background image
|
|
||||||
CGSize borderImageSize = CGSizeMake(1.f, 100.f);
|
|
||||||
|
|
||||||
UIGraphicsBeginImageContext(borderImageSize);
|
|
||||||
CGContextRef context = UIGraphicsGetCurrentContext();
|
|
||||||
|
|
||||||
CGContextSetStrokeColorWithColor(context, [UIColor whiteColor].CGColor);
|
|
||||||
CGContextFillRect(context, CGRectMake(0.f, borderImageSize.height * 0.8, borderImageSize.width, borderImageSize.height));
|
|
||||||
|
|
||||||
UIImage *selectedSegmentBG = UIGraphicsGetImageFromCurrentImageContext();
|
|
||||||
UIGraphicsEndImageContext();
|
|
||||||
|
|
||||||
// Clear default border and background color
|
|
||||||
[[UISegmentedControl appearance] setBackgroundImage:[[UIImage alloc] init] forState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
|
||||||
[[UISegmentedControl appearance] setDividerImage:[[UIImage alloc] init] forLeftSegmentState:UIControlStateNormal rightSegmentState:UIControlStateNormal barMetrics:UIBarMetricsDefault];
|
|
||||||
|
|
||||||
// Set selected segment background image
|
|
||||||
[[UISegmentedControl appearance] setBackgroundImage:[selectedSegmentBG imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate] forState:UIControlStateSelected barMetrics:UIBarMetricsDefault];
|
|
||||||
|
|
||||||
// Change font on UISegmentedControl
|
|
||||||
[[UISegmentedControl appearance] setTitleTextAttributes:[NSDictionary dictionaryWithObjectsAndKeys:
|
|
||||||
[UIColor whiteColor], NSForegroundColorAttributeName,
|
|
||||||
[UIFont fontWithName:@"Roboto-Regular" size:[UIFont systemFontSize]], NSFontAttributeName, nil] forState:UIControlStateNormal];
|
|
||||||
|
|
||||||
return YES;
|
return YES;
|
||||||
}
|
}
|
||||||
@@ -76,18 +58,36 @@ static NSOperationQueue* mainQueue;
|
|||||||
// Saves changes in the application's managed object context before the application terminates.
|
// Saves changes in the application's managed object context before the application terminates.
|
||||||
[self saveContext];
|
[self saveContext];
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
|
||||||
|
// Insert code here to initialize your application
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillTerminate:(NSNotification *)aNotification {
|
||||||
|
// Insert code here to tear down your application
|
||||||
|
[self saveContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
- (void)saveContext
|
- (void)saveContext
|
||||||
{
|
{
|
||||||
NSError *error = nil;
|
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
|
||||||
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
|
|
||||||
if (managedObjectContext != nil) {
|
if (managedObjectContext != nil) {
|
||||||
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
|
[managedObjectContext performBlock:^{
|
||||||
// Replace this implementation with code to handle the error appropriately.
|
if (![managedObjectContext hasChanges]) {
|
||||||
// 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.
|
return;
|
||||||
Log(LOG_E, @"Unresolved error %@, %@", error, [error userInfo]);
|
}
|
||||||
abort();
|
NSError *error = nil;
|
||||||
}
|
if (![managedObjectContext save:&error]) {
|
||||||
|
Log(LOG_E, @"Critical database error: %@, %@", error, [error userInfo]);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
NSData* dbData = [NSData dataWithContentsOfURL:[[[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:DB_NAME]];
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:dbData forKey:DB_NAME];
|
||||||
|
#endif
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ static NSOperationQueue* mainQueue;
|
|||||||
|
|
||||||
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
||||||
if (coordinator != nil) {
|
if (coordinator != nil) {
|
||||||
_managedObjectContext = [[NSManagedObjectContext alloc] init];
|
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||||
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
|
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
|
||||||
}
|
}
|
||||||
return _managedObjectContext;
|
return _managedObjectContext;
|
||||||
@@ -128,39 +128,33 @@ static NSOperationQueue* mainQueue;
|
|||||||
return _persistentStoreCoordinator;
|
return _persistentStoreCoordinator;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSURL *storeURL = [self getStoreURL];
|
|
||||||
|
|
||||||
NSError *error = nil;
|
NSError *error = nil;
|
||||||
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
|
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
|
||||||
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
||||||
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
|
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
|
||||||
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:options error:&error]) {
|
NSString* storeType;
|
||||||
/*
|
|
||||||
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.
|
#if TARGET_OS_TV
|
||||||
|
// Use a binary store for tvOS since we will need exclusive access to the file
|
||||||
|
// to serialize into NSUserDefaults.
|
||||||
|
storeType = NSBinaryStoreType;
|
||||||
|
#else
|
||||||
|
storeType = NSSQLiteStoreType;
|
||||||
|
#endif
|
||||||
|
|
||||||
Typical reasons for an error here include:
|
// We must ensure the persistent store is ready to opened
|
||||||
* The persistent store is not accessible;
|
[self preparePersistentStore];
|
||||||
* 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 (![_persistentStoreCoordinator addPersistentStoreWithType:storeType configuration:nil URL:[self getStoreURL] options:options error:&error]) {
|
||||||
|
// Log the error
|
||||||
|
Log(LOG_E, @"Critical database error: %@, %@", error, [error userInfo]);
|
||||||
|
|
||||||
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.
|
// Drop the database
|
||||||
|
[self dropDatabase];
|
||||||
|
|
||||||
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
|
// Try again
|
||||||
* Simply deleting the existing store:
|
return [self persistentStoreCoordinator];
|
||||||
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
|
|
||||||
|
|
||||||
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
|
|
||||||
@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
|
|
||||||
|
|
||||||
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
|
|
||||||
|
|
||||||
*/
|
|
||||||
Log(LOG_E, @"Unresolved error %@, %@", error, [error userInfo]);
|
|
||||||
abort();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return _persistentStoreCoordinator;
|
return _persistentStoreCoordinator;
|
||||||
@@ -174,8 +168,50 @@ static NSOperationQueue* mainQueue;
|
|||||||
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void) dropDatabase
|
||||||
|
{
|
||||||
|
// Delete the file on disk
|
||||||
|
[[NSFileManager defaultManager] removeItemAtURL:[self getStoreURL] error:nil];
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
// Also delete the copy in the NSUserDefaults on tvOS
|
||||||
|
[[NSUserDefaults standardUserDefaults] removeObjectForKey:DB_NAME];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) preparePersistentStore
|
||||||
|
{
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
// On tvOS, we may need to inflate the DB from NSUserDefaults
|
||||||
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||||
|
NSString *cacheDirectory = [paths objectAtIndex:0];
|
||||||
|
NSString *dbPath = [cacheDirectory stringByAppendingPathComponent:DB_NAME];
|
||||||
|
|
||||||
|
// Always prefer the on disk version
|
||||||
|
if (![[NSFileManager defaultManager] fileExistsAtPath:dbPath]) {
|
||||||
|
// If that is unavailable, inflate it from NSUserDefaults
|
||||||
|
NSData* data = [[NSUserDefaults standardUserDefaults] dataForKey:DB_NAME];
|
||||||
|
if (data != nil) {
|
||||||
|
Log(LOG_I, @"Inflating database from NSUserDefaults");
|
||||||
|
[data writeToFile:dbPath atomically:YES];
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log(LOG_I, @"No database on disk or in NSUserDefaults");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Log(LOG_I, @"Using cached database");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
- (NSURL*) getStoreURL {
|
- (NSURL*) getStoreURL {
|
||||||
return [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Limelight_iOS.sqlite"];
|
#if TARGET_OS_TV
|
||||||
|
// We use the cache folder to store our database on tvOS
|
||||||
|
return [[[[NSFileManager defaultManager] URLsForDirectory:NSCachesDirectory inDomains:NSUserDomainMask] lastObject] URLByAppendingPathComponent:DB_NAME];
|
||||||
|
#else
|
||||||
|
return [[self applicationDocumentsDirectory] URLByAppendingPathComponent:DB_NAME];
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// ComputerScrollView.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface ComputerScrollView : UIScrollView
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// ComputerScrollView.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "ComputerScrollView.h"
|
||||||
|
|
||||||
|
@implementation ComputerScrollView
|
||||||
|
|
||||||
|
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
|
||||||
|
if ([view isKindOfClass:[UIButton class]]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return [super touchesShouldCancelInContentView:view];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Only override drawRect: if you perform custom drawing.
|
||||||
|
// An empty implementation adversely affects performance during animation.
|
||||||
|
- (void)drawRect:(CGRect)rect {
|
||||||
|
// Drawing code
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -1,24 +1,24 @@
|
|||||||
//
|
//
|
||||||
// CryptoManager.h
|
// CryptoManager.h
|
||||||
// Limelight
|
// Moonlight
|
||||||
//
|
//
|
||||||
// Created by Diego Waxemberg on 10/14/14.
|
// 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>
|
|
||||||
|
|
||||||
@interface CryptoManager : NSObject
|
@interface CryptoManager : NSObject
|
||||||
|
|
||||||
+ (void) generateKeyPairUsingSSl;
|
+ (void) generateKeyPairUsingSSL;
|
||||||
+ (NSString*) getUniqueID;
|
|
||||||
+ (NSData*) readCertFromFile;
|
+ (NSData*) readCertFromFile;
|
||||||
+ (NSData*) readKeyFromFile;
|
+ (NSData*) readKeyFromFile;
|
||||||
+ (NSData*) readP12FromFile;
|
+ (NSData*) readP12FromFile;
|
||||||
+ (NSData*) getSignatureFromCert:(NSData*)cert;
|
+ (NSData*) getSignatureFromCert:(NSData*)cert;
|
||||||
|
+ (NSData*) pemToDer:(NSData*)pemCertBytes;
|
||||||
|
|
||||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN;
|
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN;
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN;
|
||||||
- (NSData*) SHA1HashData:(NSData*)data;
|
- (NSData*) SHA1HashData:(NSData*)data;
|
||||||
|
- (NSData*) SHA256HashData:(NSData*)data;
|
||||||
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
|
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
|
||||||
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
|
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
|
||||||
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
|
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
//
|
//
|
||||||
// CryptoManager.m
|
// CryptoManager.m
|
||||||
// Limelight
|
// Moonlight
|
||||||
//
|
//
|
||||||
// Created by Diego Waxemberg on 10/14/14.
|
// 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 "CryptoManager.h"
|
||||||
#import "mkcert.h"
|
#import "mkcert.h"
|
||||||
#import <AdSupport/ASIdentifierManager.h>
|
|
||||||
|
|
||||||
#include <openssl/aes.h>
|
#include <openssl/aes.h>
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
@@ -17,19 +16,31 @@
|
|||||||
#include <openssl/evp.h>
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
@implementation CryptoManager
|
@implementation CryptoManager
|
||||||
static const int SHA1_DIGEST_LENGTH = 20;
|
static const int SHA1_HASH_LENGTH = 20;
|
||||||
|
static const int SHA256_HASH_LENGTH = 32;
|
||||||
static NSData* key = nil;
|
static NSData* key = nil;
|
||||||
static NSData* cert = nil;
|
static NSData* cert = nil;
|
||||||
static NSData* p12 = nil;
|
static NSData* p12 = nil;
|
||||||
|
|
||||||
- (NSData*) createAESKeyFromSalt:(NSData*)saltedPIN {
|
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN {
|
||||||
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN {
|
||||||
|
return [[self SHA256HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||||
|
}
|
||||||
|
|
||||||
- (NSData*) SHA1HashData:(NSData*)data {
|
- (NSData*) SHA1HashData:(NSData*)data {
|
||||||
unsigned char sha1[SHA1_DIGEST_LENGTH];
|
unsigned char sha1[SHA1_HASH_LENGTH];
|
||||||
SHA1([data bytes], [data length], sha1);
|
SHA1([data bytes], [data length], sha1);
|
||||||
NSData* bytes = [NSData dataWithBytes:sha1 length:20];
|
NSData* bytes = [NSData dataWithBytes:sha1 length:sizeof(sha1)];
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSData*) SHA256HashData:(NSData*)data {
|
||||||
|
unsigned char sha256[SHA256_HASH_LENGTH];
|
||||||
|
SHA256([data bytes], [data length], sha256);
|
||||||
|
NSData* bytes = [NSData dataWithBytes:sha256 length:sizeof(sha256)];
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -76,11 +87,28 @@ static NSData* p12 = nil;
|
|||||||
return (((int)[data length] + 15) / 16) * 16;
|
return (((int)[data length] + 15) / 16) * 16;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert {
|
+ (NSData*) pemToDer:(NSData*)pemCertBytes {
|
||||||
const char* buffer = [cert bytes];
|
|
||||||
X509* x509;
|
X509* x509;
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
|
||||||
BIO_puts(bio, buffer);
|
BIO* bio = BIO_new_mem_buf([pemCertBytes bytes], (int)[pemCertBytes length]);
|
||||||
|
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||||
|
BIO_free(bio);
|
||||||
|
|
||||||
|
bio = BIO_new(BIO_s_mem());
|
||||||
|
i2d_X509_bio(bio, x509);
|
||||||
|
|
||||||
|
BUF_MEM* mem;
|
||||||
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
|
|
||||||
|
NSData* ret = [[NSData alloc] initWithBytes:mem->data length:mem->length];
|
||||||
|
BIO_free(bio);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert {
|
||||||
|
X509* x509;
|
||||||
|
BIO* bio = BIO_new_mem_buf([cert bytes], (int)[cert length]);
|
||||||
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||||
|
|
||||||
BIO_free(bio);
|
BIO_free(bio);
|
||||||
@@ -105,9 +133,7 @@ static NSData* p12 = nil;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (NSData *)signData:(NSData *)data withKey:(NSData *)key {
|
- (NSData *)signData:(NSData *)data withKey:(NSData *)key {
|
||||||
const char* buffer = [key bytes];
|
BIO* bio = BIO_new_mem_buf([key bytes], (int)[key length]);
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
|
||||||
BIO_puts(bio, buffer);
|
|
||||||
|
|
||||||
EVP_PKEY* pkey;
|
EVP_PKEY* pkey;
|
||||||
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||||
@@ -142,57 +168,60 @@ static NSData* p12 = nil;
|
|||||||
return signedData;
|
return signedData;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: these three methods are almost identical, fix the copy-pasta
|
+ (NSData*) readCryptoObject:(NSString*)item {
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
return [[NSUserDefaults standardUserDefaults] dataForKey:item];
|
||||||
|
#else
|
||||||
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||||
|
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||||
|
NSString *file = [documentsDirectory stringByAppendingPathComponent:item];
|
||||||
|
return [NSData dataWithContentsOfFile:file];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void) writeCryptoObject:(NSString*)item data:(NSData*)data {
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
[[NSUserDefaults standardUserDefaults] setObject:data forKey:item];
|
||||||
|
#else
|
||||||
|
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||||
|
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||||
|
NSString *file = [documentsDirectory stringByAppendingPathComponent:item];
|
||||||
|
[data writeToFile:file atomically:NO];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
+ (NSData*) readCertFromFile {
|
+ (NSData*) readCertFromFile {
|
||||||
if (cert == nil) {
|
if (cert == nil) {
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
cert = [CryptoManager readCryptoObject:@"client.crt"];
|
||||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
|
||||||
NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"];
|
|
||||||
cert = [NSData dataWithContentsOfFile:certFile];
|
|
||||||
}
|
}
|
||||||
return cert;
|
return cert;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSData*) readP12FromFile {
|
+ (NSData*) readP12FromFile {
|
||||||
if (p12 == nil) {
|
if (p12 == nil) {
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
p12 = [CryptoManager readCryptoObject:@"client.p12"];
|
||||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
|
||||||
NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"];
|
|
||||||
p12 = [NSData dataWithContentsOfFile:p12File];
|
|
||||||
}
|
}
|
||||||
return p12;
|
return p12;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSData*) readKeyFromFile {
|
+ (NSData*) readKeyFromFile {
|
||||||
if (key == nil) {
|
if (key == nil) {
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
key = [CryptoManager readCryptoObject:@"client.key"];
|
||||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
|
||||||
NSString *keyFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"];
|
|
||||||
key = [NSData dataWithContentsOfFile:keyFile];
|
|
||||||
}
|
}
|
||||||
return key;
|
return key;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (bool) keyPairExists {
|
+ (bool) keyPairExists {
|
||||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
bool keyFileExists = [CryptoManager readCryptoObject:@"client.key"] != nil;
|
||||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
bool p12FileExists = [CryptoManager readCryptoObject:@"client.p12"] != nil;
|
||||||
NSString *keyFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"];
|
bool certFileExists = [CryptoManager readCryptoObject:@"client.crt"] != nil;
|
||||||
NSString *p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"];
|
|
||||||
NSString *certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"];
|
|
||||||
|
|
||||||
bool keyFileExists = [[NSFileManager defaultManager] fileExistsAtPath:keyFile];
|
|
||||||
bool p12FileExists = [[NSFileManager defaultManager] fileExistsAtPath:p12File];
|
|
||||||
bool certFileExists = [[NSFileManager defaultManager] fileExistsAtPath:certFile];
|
|
||||||
|
|
||||||
return keyFileExists && p12FileExists && certFileExists;
|
return keyFileExists && p12FileExists && certFileExists;
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSData *)getSignatureFromCert:(NSData *)cert {
|
+ (NSData *)getSignatureFromCert:(NSData *)cert {
|
||||||
const char* buffer = [cert bytes];
|
BIO* bio = BIO_new_mem_buf([cert bytes], (int)[cert length]);
|
||||||
X509* x509;
|
X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||||
BIO* bio = BIO_new(BIO_s_mem());
|
|
||||||
BIO_puts(bio, buffer);
|
|
||||||
x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
|
||||||
|
|
||||||
if (!x509) {
|
if (!x509) {
|
||||||
Log(LOG_E, @"Unable to parse certificate in memory!");
|
Log(LOG_E, @"Unable to parse certificate in memory!");
|
||||||
@@ -201,40 +230,62 @@ static NSData* p12 = nil;
|
|||||||
return [NSData dataWithBytes:x509->signature->data length:x509->signature->length];
|
return [NSData dataWithBytes:x509->signature->data length:x509->signature->length];
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void) generateKeyPairUsingSSl {
|
+ (NSData*)getKeyFromCertKeyPair:(CertKeyPair*)certKeyPair {
|
||||||
|
BIO* bio = BIO_new(BIO_s_mem());
|
||||||
|
|
||||||
|
PEM_write_bio_PrivateKey(bio, certKeyPair->pkey, NULL, NULL, 0, NULL, NULL);
|
||||||
|
|
||||||
|
BUF_MEM* mem;
|
||||||
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
|
NSData* data = [NSData dataWithBytes:mem->data length:mem->length];
|
||||||
|
BIO_free(bio);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData*)getP12FromCertKeyPair:(CertKeyPair*)certKeyPair {
|
||||||
|
BIO* bio = BIO_new(BIO_s_mem());
|
||||||
|
|
||||||
|
i2d_PKCS12_bio(bio, certKeyPair->p12);
|
||||||
|
|
||||||
|
BUF_MEM* mem;
|
||||||
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
|
NSData* data = [NSData dataWithBytes:mem->data length:mem->length];
|
||||||
|
BIO_free(bio);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData*)getCertFromCertKeyPair:(CertKeyPair*)certKeyPair {
|
||||||
|
BIO* bio = BIO_new(BIO_s_mem());
|
||||||
|
|
||||||
|
PEM_write_bio_X509(bio, certKeyPair->x509);
|
||||||
|
|
||||||
|
BUF_MEM* mem;
|
||||||
|
BIO_get_mem_ptr(bio, &mem);
|
||||||
|
NSData* data = [NSData dataWithBytes:mem->data length:mem->length];
|
||||||
|
BIO_free(bio);
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (void) generateKeyPairUsingSSL {
|
||||||
static dispatch_once_t pred;
|
static dispatch_once_t pred;
|
||||||
dispatch_once(&pred, ^{
|
dispatch_once(&pred, ^{
|
||||||
if (![CryptoManager keyPairExists]) {
|
if (![CryptoManager keyPairExists]) {
|
||||||
|
|
||||||
Log(LOG_I, @"Generating Certificate... ");
|
Log(LOG_I, @"Generating Certificate... ");
|
||||||
CertKeyPair certKeyPair = generateCertKeyPair();
|
CertKeyPair certKeyPair = generateCertKeyPair();
|
||||||
|
|
||||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
NSData* certData = [CryptoManager getCertFromCertKeyPair:&certKeyPair];
|
||||||
NSString* documentsDirectory = [paths objectAtIndex:0];
|
NSData* p12Data = [CryptoManager getP12FromCertKeyPair:&certKeyPair];
|
||||||
NSString* certFile = [documentsDirectory stringByAppendingPathComponent:@"client.crt"];
|
NSData* keyData = [CryptoManager getKeyFromCertKeyPair:&certKeyPair];
|
||||||
NSString* keyPairFile = [documentsDirectory stringByAppendingPathComponent:@"client.key"];
|
|
||||||
NSString* p12File = [documentsDirectory stringByAppendingPathComponent:@"client.p12"];
|
|
||||||
|
|
||||||
//Log(LOG_D, @"Writing cert and key to: \n%@\n%@", certFile, keyPairFile);
|
|
||||||
saveCertKeyPair([certFile UTF8String], [p12File UTF8String], [keyPairFile UTF8String], certKeyPair);
|
|
||||||
freeCertKeyPair(certKeyPair);
|
freeCertKeyPair(certKeyPair);
|
||||||
|
|
||||||
|
[CryptoManager writeCryptoObject:@"client.crt" data:certData];
|
||||||
|
[CryptoManager writeCryptoObject:@"client.p12" data:p12Data];
|
||||||
|
[CryptoManager writeCryptoObject:@"client.key" data:keyData];
|
||||||
|
|
||||||
Log(LOG_I, @"Certificate created");
|
Log(LOG_I, @"Certificate created");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (NSString*) getUniqueID {
|
|
||||||
// generate a UUID
|
|
||||||
NSUUID* uuid = [ASIdentifierManager sharedManager].advertisingIdentifier;
|
|
||||||
NSString* idString = [NSString stringWithString:[uuid UUIDString]];
|
|
||||||
|
|
||||||
// we need a 16byte hex-string so we take the last 17 characters
|
|
||||||
// and remove the '-' to get a 16 character string
|
|
||||||
NSMutableString* uniqueId = [NSMutableString stringWithString:[idString substringFromIndex:19]];
|
|
||||||
[uniqueId deleteCharactersInRange:NSMakeRange(4, 1)];
|
|
||||||
|
|
||||||
//Log(LOG_D, @"Unique ID: %@", uniqueId);
|
|
||||||
return [NSString stringWithString:uniqueId];
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// IdManager.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/31/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
@interface IdManager : NSObject
|
||||||
|
|
||||||
|
+ (NSString*) getUniqueId;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
//
|
||||||
|
// IdManager.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/31/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "IdManager.h"
|
||||||
|
#import "DataManager.h"
|
||||||
|
|
||||||
|
@implementation IdManager
|
||||||
|
|
||||||
|
+ (NSString*) getUniqueId {
|
||||||
|
DataManager* dataMan = [[DataManager alloc] init];
|
||||||
|
|
||||||
|
NSString* uniqueId = [dataMan getUniqueId];
|
||||||
|
if (uniqueId == nil) {
|
||||||
|
uniqueId = [IdManager generateUniqueId];
|
||||||
|
[dataMan updateUniqueId:uniqueId];
|
||||||
|
Log(LOG_I, @"No UUID found. Generated new UUID: %@", uniqueId);
|
||||||
|
}
|
||||||
|
|
||||||
|
return uniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSString*) generateUniqueId {
|
||||||
|
UInt64 uuidLong = ((UInt64) arc4random() << 32) | arc4random();
|
||||||
|
return [NSString stringWithFormat:@"%016llx", uuidLong];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -19,7 +19,7 @@ static const int NUM_YEARS = 10;
|
|||||||
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years);
|
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years);
|
||||||
int add_ext(X509 *cert, int nid, char *value);
|
int add_ext(X509 *cert, int nid, char *value);
|
||||||
|
|
||||||
struct CertKeyPair generateCertKeyPair() {
|
struct CertKeyPair generateCertKeyPair(void) {
|
||||||
BIO *bio_err;
|
BIO *bio_err;
|
||||||
X509 *x509 = NULL;
|
X509 *x509 = NULL;
|
||||||
EVP_PKEY *pkey = NULL;
|
EVP_PKEY *pkey = NULL;
|
||||||
@@ -62,21 +62,6 @@ void freeCertKeyPair(struct CertKeyPair certKeyPair) {
|
|||||||
PKCS12_free(certKeyPair.p12);
|
PKCS12_free(certKeyPair.p12);
|
||||||
}
|
}
|
||||||
|
|
||||||
void saveCertKeyPair(const char* certFile, const char* p12File, const char* keyPairFile, CertKeyPair certKeyPair) {
|
|
||||||
FILE* certFilePtr = fopen(certFile, "w");
|
|
||||||
FILE* keyPairFilePtr = fopen(keyPairFile, "w");
|
|
||||||
FILE* p12FilePtr = fopen(p12File, "wb");
|
|
||||||
|
|
||||||
//TODO: error check
|
|
||||||
PEM_write_PrivateKey(keyPairFilePtr, certKeyPair.pkey, NULL, NULL, 0, NULL, NULL);
|
|
||||||
PEM_write_X509(certFilePtr, certKeyPair.x509);
|
|
||||||
i2d_PKCS12_fp(p12FilePtr, certKeyPair.p12);
|
|
||||||
|
|
||||||
fclose(p12FilePtr);
|
|
||||||
fclose(certFilePtr);
|
|
||||||
fclose(keyPairFilePtr);
|
|
||||||
}
|
|
||||||
|
|
||||||
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
||||||
X509 *x;
|
X509 *x;
|
||||||
EVP_PKEY *pk;
|
EVP_PKEY *pk;
|
||||||
@@ -85,7 +70,6 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
|||||||
|
|
||||||
if (*pkeyp == NULL) {
|
if (*pkeyp == NULL) {
|
||||||
if ((pk=EVP_PKEY_new()) == NULL) {
|
if ((pk=EVP_PKEY_new()) == NULL) {
|
||||||
abort();
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -102,7 +86,6 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
|||||||
|
|
||||||
rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
|
rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
|
||||||
if (!EVP_PKEY_assign_RSA(pk, rsa)) {
|
if (!EVP_PKEY_assign_RSA(pk, rsa)) {
|
||||||
abort();
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,13 +107,7 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
|||||||
*/
|
*/
|
||||||
X509_set_issuer_name(x, name);
|
X509_set_issuer_name(x, name);
|
||||||
|
|
||||||
/* Add various extensions: standard extensions */
|
if (!X509_sign(x, pk, EVP_sha256())) {
|
||||||
add_ext(x, NID_basic_constraints, "critical,CA:TRUE");
|
|
||||||
add_ext(x, NID_key_usage, "critical,keyCertSign,cRLSign");
|
|
||||||
|
|
||||||
add_ext(x, NID_subject_key_identifier, "hash");
|
|
||||||
|
|
||||||
if (!X509_sign(x, pk, EVP_sha1())) {
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -141,29 +118,3 @@ int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
|||||||
err:
|
err:
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add extension using V3 code: we can set the config file as NULL
|
|
||||||
* because we wont reference any other sections.
|
|
||||||
*/
|
|
||||||
|
|
||||||
int add_ext(X509 *cert, int nid, char *value)
|
|
||||||
{
|
|
||||||
X509_EXTENSION *ex;
|
|
||||||
X509V3_CTX ctx;
|
|
||||||
/* This sets the 'context' of the extensions. */
|
|
||||||
/* No configuration database */
|
|
||||||
X509V3_set_ctx_nodb(&ctx);
|
|
||||||
/* Issuer and subject certs: both the target since it is self signed,
|
|
||||||
* no request and no CRL
|
|
||||||
*/
|
|
||||||
X509V3_set_ctx(&ctx, cert, cert, NULL, NULL, 0);
|
|
||||||
ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value);
|
|
||||||
if (!ex) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
X509_add_ext(cert, ex, -1);
|
|
||||||
X509_EXTENSION_free(ex);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
//
|
//
|
||||||
// mkcert.h
|
// mkcert.h
|
||||||
// Limelight
|
// Moonlight
|
||||||
//
|
//
|
||||||
// Created by Diego Waxemberg on 10/16/14.
|
// 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
|
#ifndef Limelight_mkcert_h
|
||||||
@@ -18,8 +18,7 @@ typedef struct CertKeyPair {
|
|||||||
PKCS12 *p12;
|
PKCS12 *p12;
|
||||||
} CertKeyPair;
|
} CertKeyPair;
|
||||||
|
|
||||||
struct CertKeyPair generateCertKeyPair();
|
struct CertKeyPair generateCertKeyPair(void);
|
||||||
void freeCertKeyPair(CertKeyPair);
|
void freeCertKeyPair(CertKeyPair);
|
||||||
void saveCertKeyPair(const char* certFile, const char* p12File, const char* keyPairFile, CertKeyPair certKeyPair);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1,25 +1,39 @@
|
|||||||
//
|
//
|
||||||
// DataManager.h
|
// DataManager.h
|
||||||
// Limelight
|
// Moonlight
|
||||||
//
|
//
|
||||||
// Created by Diego Waxemberg on 10/28/14.
|
// 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 "AppDelegate.h"
|
||||||
#import "Host.h"
|
#import "TemporaryHost.h"
|
||||||
|
#import "TemporaryApp.h"
|
||||||
|
#import "TemporarySettings.h"
|
||||||
|
|
||||||
@interface DataManager : NSObject
|
@interface DataManager : NSObject
|
||||||
|
|
||||||
@property (strong, nonatomic) AppDelegate* appDelegate;
|
- (void) saveSettingsWithBitrate:(NSInteger)bitrate
|
||||||
|
framerate:(NSInteger)framerate
|
||||||
|
height:(NSInteger)height
|
||||||
|
width:(NSInteger)width
|
||||||
|
onscreenControls:(NSInteger)onscreenControls
|
||||||
|
remote:(BOOL)streamingRemotely
|
||||||
|
optimizeGames:(BOOL)optimizeGames
|
||||||
|
multiController:(BOOL)multiController
|
||||||
|
audioOnPC:(BOOL)audioOnPC
|
||||||
|
useHevc:(BOOL)useHevc
|
||||||
|
enableHdr:(BOOL)enableHdr;
|
||||||
|
|
||||||
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls;
|
- (NSArray*) getHosts;
|
||||||
- (Settings*) retrieveSettings;
|
- (void) updateHost:(TemporaryHost*)host;
|
||||||
- (NSArray*) retrieveHosts;
|
- (void) updateAppsForExistingHost:(TemporaryHost *)host;
|
||||||
- (void) saveHosts;
|
- (void) removeHost:(TemporaryHost*)host;
|
||||||
- (Host*) createHost;
|
- (void) removeApp:(TemporaryApp*)app;
|
||||||
- (void) removeHost:(Host*)host;
|
|
||||||
|
- (TemporarySettings*) getSettings;
|
||||||
|
|
||||||
|
- (void) updateUniqueId:(NSString*)uniqueId;
|
||||||
|
- (NSString*) getUniqueId;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -1,43 +1,149 @@
|
|||||||
//
|
//
|
||||||
// DataManager.m
|
// DataManager.m
|
||||||
// Limelight
|
// Moonlight
|
||||||
//
|
//
|
||||||
// Created by Diego Waxemberg on 10/28/14.
|
// 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 "DataManager.h"
|
||||||
|
#import "TemporaryApp.h"
|
||||||
|
#import "TemporarySettings.h"
|
||||||
|
|
||||||
@implementation DataManager
|
@implementation DataManager {
|
||||||
|
NSManagedObjectContext *_managedObjectContext;
|
||||||
|
AppDelegate *_appDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
- (id) init {
|
- (id) init {
|
||||||
self = [super init];
|
self = [super init];
|
||||||
self.appDelegate = [[UIApplication sharedApplication] delegate];
|
|
||||||
|
// HACK: Avoid calling [UIApplication delegate] off the UI thread to keep
|
||||||
|
// Main Thread Checker happy.
|
||||||
|
if ([NSThread isMainThread]) {
|
||||||
|
_appDelegate = (AppDelegate *)[[OSApplication sharedApplication] delegate];
|
||||||
|
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||||
|
self->_appDelegate = (AppDelegate *)[[OSApplication sharedApplication] delegate];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
|
||||||
|
[_managedObjectContext setParentContext:[_appDelegate managedObjectContext]];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) saveSettingsWithBitrate:(NSInteger)bitrate framerate:(NSInteger)framerate height:(NSInteger)height width:(NSInteger)width onscreenControls:(NSInteger)onscreenControls {
|
- (void) updateUniqueId:(NSString*)uniqueId {
|
||||||
Settings* settingsToSave = [self retrieveSettings];
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
|
[self retrieveSettings].uniqueId = uniqueId;
|
||||||
// Bitrate is persisted in kbps
|
[self saveData];
|
||||||
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
|
}];
|
||||||
settingsToSave.height = [NSNumber numberWithInteger:height];
|
}
|
||||||
settingsToSave.width = [NSNumber numberWithInteger:width];
|
|
||||||
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
|
|
||||||
|
|
||||||
NSError* error;
|
- (NSString*) getUniqueId {
|
||||||
if (![[self.appDelegate managedObjectContext] save:&error]) {
|
__block NSString *uid;
|
||||||
Log(LOG_E, @"Unable to save settings to database: %@", error);
|
|
||||||
}
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
[self.appDelegate saveContext];
|
uid = [self retrieveSettings].uniqueId;
|
||||||
|
}];
|
||||||
|
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) saveSettingsWithBitrate:(NSInteger)bitrate
|
||||||
|
framerate:(NSInteger)framerate
|
||||||
|
height:(NSInteger)height
|
||||||
|
width:(NSInteger)width
|
||||||
|
onscreenControls:(NSInteger)onscreenControls
|
||||||
|
remote:(BOOL)streamingRemotely
|
||||||
|
optimizeGames:(BOOL)optimizeGames
|
||||||
|
multiController:(BOOL)multiController
|
||||||
|
audioOnPC:(BOOL)audioOnPC
|
||||||
|
useHevc:(BOOL)useHevc
|
||||||
|
enableHdr:(BOOL)enableHdr {
|
||||||
|
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
Settings* settingsToSave = [self retrieveSettings];
|
||||||
|
settingsToSave.framerate = [NSNumber numberWithInteger:framerate];
|
||||||
|
settingsToSave.bitrate = [NSNumber numberWithInteger:bitrate];
|
||||||
|
settingsToSave.height = [NSNumber numberWithInteger:height];
|
||||||
|
settingsToSave.width = [NSNumber numberWithInteger:width];
|
||||||
|
settingsToSave.onscreenControls = [NSNumber numberWithInteger:onscreenControls];
|
||||||
|
settingsToSave.streamingRemotely = streamingRemotely;
|
||||||
|
settingsToSave.optimizeGames = optimizeGames;
|
||||||
|
settingsToSave.multiController = multiController;
|
||||||
|
settingsToSave.playAudioOnPC = audioOnPC;
|
||||||
|
settingsToSave.useHevc = useHevc;
|
||||||
|
settingsToSave.enableHdr = enableHdr;
|
||||||
|
|
||||||
|
[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:self->_managedObjectContext];
|
||||||
|
parent = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:self->_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:self->_managedObjectContext];
|
||||||
|
parentApp = [[App alloc] initWithEntity:entity insertIntoManagedObjectContext:self->_managedObjectContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
[app propagateChangesToParent:parentApp withHost:parent];
|
||||||
|
|
||||||
|
[applist addObject:parentApp];
|
||||||
|
}
|
||||||
|
|
||||||
|
parent.appList = applist;
|
||||||
|
|
||||||
|
[self saveData];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (TemporarySettings*) getSettings {
|
||||||
|
__block TemporarySettings *tempSettings;
|
||||||
|
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
tempSettings = [[TemporarySettings alloc] initFromSettings:[self retrieveSettings]];
|
||||||
|
}];
|
||||||
|
|
||||||
|
return tempSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (Settings*) retrieveSettings {
|
- (Settings*) retrieveSettings {
|
||||||
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
|
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
|
||||||
if (fetchedRecords.count == 0) {
|
if (fetchedRecords.count == 0) {
|
||||||
// create a new settings object with the default values
|
// create a new settings object with the default values
|
||||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:_managedObjectContext];
|
||||||
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
|
||||||
|
|
||||||
return settings;
|
return settings;
|
||||||
} else {
|
} else {
|
||||||
@@ -46,40 +152,84 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (Host*) createHost {
|
- (void) removeApp:(TemporaryApp*)app {
|
||||||
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Host" inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
Host* host = [[Host alloc] initWithEntity:entity insertIntoManagedObjectContext:[self.appDelegate managedObjectContext]];
|
App* managedApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
|
||||||
return host;
|
if (managedApp != nil) {
|
||||||
|
[self->_managedObjectContext deleteObject:managedApp];
|
||||||
|
[self saveData];
|
||||||
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) removeHost:(Host*)host {
|
- (void) removeHost:(TemporaryHost*)host {
|
||||||
[[self.appDelegate managedObjectContext] deleteObject:host];
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
Host* managedHost = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
|
||||||
|
if (managedHost != nil) {
|
||||||
|
[self->_managedObjectContext deleteObject:managedHost];
|
||||||
|
[self saveData];
|
||||||
|
}
|
||||||
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void) saveHosts {
|
- (void) saveData {
|
||||||
NSError* error;
|
NSError* error;
|
||||||
if (![[self.appDelegate managedObjectContext] save:&error]) {
|
if ([_managedObjectContext hasChanges] && ![_managedObjectContext save:&error]) {
|
||||||
Log(LOG_E, @"Unable to save hosts to database: %@", error);
|
Log(LOG_E, @"Unable to save hosts to database: %@", error);
|
||||||
}
|
}
|
||||||
[self.appDelegate saveContext];
|
|
||||||
|
[_appDelegate saveContext];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray*) retrieveHosts {
|
- (NSArray*) getHosts {
|
||||||
return [self fetchRecords:@"Host"];
|
__block NSMutableArray *tempHosts = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
NSArray *hosts = [self fetchRecords:@"Host"];
|
||||||
|
|
||||||
|
for (Host* host in hosts) {
|
||||||
|
[tempHosts addObject:[[TemporaryHost alloc] initFromHost:host]];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
return tempHosts;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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:tempApp.host.uuid]) {
|
||||||
|
return app;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSArray*) fetchRecords:(NSString*)entityName {
|
- (NSArray*) fetchRecords:(NSString*)entityName {
|
||||||
|
NSArray* fetchedRecords;
|
||||||
|
|
||||||
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
|
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
|
||||||
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:[self.appDelegate managedObjectContext]];
|
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];
|
||||||
[fetchRequest setEntity:entity];
|
[fetchRequest setEntity:entity];
|
||||||
[fetchRequest setAffectedStores:[NSArray arrayWithObjects:[[self.appDelegate persistentStoreCoordinator] persistentStoreForURL:[self.appDelegate getStoreURL]], nil]];
|
|
||||||
|
|
||||||
NSError* error;
|
NSError* error;
|
||||||
NSArray* fetchedRecords = [[self.appDelegate managedObjectContext] executeFetchRequest:fetchRequest error:&error];
|
fetchedRecords = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
|
||||||
//TODO: handle errors
|
//TODO: handle errors
|
||||||
|
|
||||||
return fetchedRecords;
|
return fetchedRecords;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|||||||
@@ -1,24 +0,0 @@
|
|||||||
//
|
|
||||||
// Host.h
|
|
||||||
// Limelight
|
|
||||||
//
|
|
||||||
// Created by Diego Waxemberg on 10/28/14.
|
|
||||||
// Copyright (c) 2014 Limelight Stream. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <CoreData/CoreData.h>
|
|
||||||
#import "Utils.h"
|
|
||||||
|
|
||||||
@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
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
//
|
|
||||||
// Host.m
|
|
||||||
// Limelight
|
|
||||||
//
|
|
||||||
// Created by Diego Waxemberg on 10/28/14.
|
|
||||||
// Copyright (c) 2014 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
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
//
|
|
||||||
// Settings.h
|
|
||||||
// Limelight
|
|
||||||
//
|
|
||||||
// Created by Diego Waxemberg on 10/28/14.
|
|
||||||
// Copyright (c) 2014 Limelight Stream. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
|
||||||
#import <CoreData/CoreData.h>
|
|
||||||
|
|
||||||
|
|
||||||
@interface Settings : NSManagedObject
|
|
||||||
|
|
||||||
@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;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
//
|
|
||||||
// Settings.m
|
|
||||||
// Limelight
|
|
||||||
//
|
|
||||||
// Created by Diego Waxemberg on 10/28/14.
|
|
||||||
// Copyright (c) 2014 Limelight Stream. All rights reserved.
|
|
||||||
//
|
|
||||||
|
|
||||||
#import "Settings.h"
|
|
||||||
|
|
||||||
|
|
||||||
@implementation Settings
|
|
||||||
|
|
||||||
@dynamic bitrate;
|
|
||||||
@dynamic framerate;
|
|
||||||
@dynamic height;
|
|
||||||
@dynamic width;
|
|
||||||
@dynamic onscreenControls;
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// TemporaryApp.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "TemporaryHost.h"
|
||||||
|
#import "App+CoreDataClass.h"
|
||||||
|
|
||||||
|
@interface TemporaryApp : NSObject
|
||||||
|
|
||||||
|
@property (nullable, nonatomic, retain) NSString *id;
|
||||||
|
@property (nullable, nonatomic, retain) NSString *name;
|
||||||
|
@property (nullable, nonatomic, retain) NSString *installPath;
|
||||||
|
@property (nonatomic) BOOL hdrSupported;
|
||||||
|
@property (nullable, nonatomic, retain) TemporaryHost *host;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost;
|
||||||
|
|
||||||
|
- (NSComparisonResult)compareName:(TemporaryApp *)other;
|
||||||
|
|
||||||
|
- (void) propagateChangesToParent:(App*)parent withHost:(Host*)host;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,52 @@
|
|||||||
|
//
|
||||||
|
// TemporaryApp.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "TemporaryApp.h"
|
||||||
|
|
||||||
|
@implementation TemporaryApp
|
||||||
|
|
||||||
|
- (id) initFromApp:(App*)app withTempHost:(TemporaryHost*)tempHost {
|
||||||
|
self = [self init];
|
||||||
|
|
||||||
|
self.id = app.id;
|
||||||
|
self.name = app.name;
|
||||||
|
self.hdrSupported = app.hdrSupported;
|
||||||
|
self.host = tempHost;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) propagateChangesToParent:(App*)parent withHost:(Host*)host {
|
||||||
|
parent.id = self.id;
|
||||||
|
parent.name = self.name;
|
||||||
|
parent.hdrSupported = self.hdrSupported;
|
||||||
|
parent.host = host;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSComparisonResult)compareName:(TemporaryApp *)other {
|
||||||
|
return [self.name caseInsensitiveCompare:other.name];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)hash {
|
||||||
|
return [self.host.uuid hash] * 31 + [self.id intValue];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqual:(id)object {
|
||||||
|
if (self == object) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![object isKindOfClass:[App class]]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [self.host.uuid isEqualToString:((App*)object).host.uuid] &&
|
||||||
|
[self.id isEqualToString:((App*)object).id];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
//
|
||||||
|
// TemporaryHost.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 12/1/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "Utils.h"
|
||||||
|
#import "Host+CoreDataClass.h"
|
||||||
|
|
||||||
|
@interface TemporaryHost : NSObject
|
||||||
|
|
||||||
|
@property (nonatomic) State state;
|
||||||
|
@property (nonatomic) PairState pairState;
|
||||||
|
@property (nonatomic, nullable) NSString * activeAddress;
|
||||||
|
@property (nonatomic, nullable) NSString * currentGame;
|
||||||
|
|
||||||
|
@property (nonatomic, nullable, retain) NSData *serverCert;
|
||||||
|
@property (nonatomic, nullable, retain) NSString *address;
|
||||||
|
@property (nonatomic, nullable, retain) NSString *externalAddress;
|
||||||
|
@property (nonatomic, nullable, retain) NSString *localAddress;
|
||||||
|
@property (nonatomic, nullable, retain) NSString *ipv6Address;
|
||||||
|
@property (nonatomic, nullable, retain) NSString *mac;
|
||||||
|
@property (nonatomic) int serverCodecModeSupport;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@property (nonatomic, retain) NSString *name;
|
||||||
|
@property (nonatomic, retain) NSString *uuid;
|
||||||
|
@property (nonatomic, retain) NSMutableSet *appList;
|
||||||
|
|
||||||
|
- (id) initFromHost:(Host*)host;
|
||||||
|
|
||||||
|
- (NSComparisonResult)compareName:(TemporaryHost *)other;
|
||||||
|
|
||||||
|
- (void) propagateChangesToParent:(Host*)host;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
//
|
||||||
|
// 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 "TemporaryApp.h"
|
||||||
|
|
||||||
|
@implementation TemporaryHost
|
||||||
|
|
||||||
|
- (id) init {
|
||||||
|
self = [super init];
|
||||||
|
self.appList = [[NSMutableSet alloc] init];
|
||||||
|
self.currentGame = @"0";
|
||||||
|
self.state = StateUnknown;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initFromHost:(Host*)host {
|
||||||
|
self = [self init];
|
||||||
|
|
||||||
|
self.address = host.address;
|
||||||
|
self.externalAddress = host.externalAddress;
|
||||||
|
self.localAddress = host.localAddress;
|
||||||
|
self.ipv6Address = host.ipv6Address;
|
||||||
|
self.mac = host.mac;
|
||||||
|
self.name = host.name;
|
||||||
|
self.uuid = host.uuid;
|
||||||
|
self.serverCodecModeSupport = host.serverCodecModeSupport;
|
||||||
|
self.serverCert = host.serverCert;
|
||||||
|
|
||||||
|
// Ensure we don't use a stale cached pair state if we haven't pinned the cert yet
|
||||||
|
self.pairState = host.serverCert ? [host.pairState intValue] : PairStateUnpaired;
|
||||||
|
|
||||||
|
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 {
|
||||||
|
// Avoid overwriting existing data with nil if
|
||||||
|
// we don't have everything populated in the temporary
|
||||||
|
// host.
|
||||||
|
if (self.address != nil) {
|
||||||
|
parentHost.address = self.address;
|
||||||
|
}
|
||||||
|
if (self.externalAddress != nil) {
|
||||||
|
parentHost.externalAddress = self.externalAddress;
|
||||||
|
}
|
||||||
|
if (self.localAddress != nil) {
|
||||||
|
parentHost.localAddress = self.localAddress;
|
||||||
|
}
|
||||||
|
if (self.ipv6Address != nil) {
|
||||||
|
parentHost.ipv6Address = self.ipv6Address;
|
||||||
|
}
|
||||||
|
if (self.mac != nil) {
|
||||||
|
parentHost.mac = self.mac;
|
||||||
|
}
|
||||||
|
if (self.serverCert != nil) {
|
||||||
|
parentHost.serverCert = self.serverCert;
|
||||||
|
}
|
||||||
|
parentHost.name = self.name;
|
||||||
|
parentHost.uuid = self.uuid;
|
||||||
|
parentHost.serverCodecModeSupport = self.serverCodecModeSupport;
|
||||||
|
parentHost.pairState = [NSNumber numberWithInt:self.pairState];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSComparisonResult)compareName:(TemporaryHost *)other {
|
||||||
|
return [self.name caseInsensitiveCompare:other.name];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSUInteger)hash {
|
||||||
|
return [self.uuid hash];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isEqual:(id)object {
|
||||||
|
if (self == object) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (![object isKindOfClass:[Host class]]) {
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
return [self.uuid isEqualToString:((Host*)object).uuid];
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
//
|
||||||
|
// TemporarySettings.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 12/1/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "Settings+CoreDataClass.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;
|
||||||
|
@property (nonatomic) BOOL streamingRemotely;
|
||||||
|
@property (nonatomic) BOOL useHevc;
|
||||||
|
@property (nonatomic) BOOL multiController;
|
||||||
|
@property (nonatomic) BOOL playAudioOnPC;
|
||||||
|
@property (nonatomic) BOOL optimizeGames;
|
||||||
|
@property (nonatomic) BOOL enableHdr;
|
||||||
|
|
||||||
|
- (id) initFromSettings:(Settings*)settings;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,76 @@
|
|||||||
|
//
|
||||||
|
// TemporarySettings.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 12/1/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "TemporarySettings.h"
|
||||||
|
#import "OnScreenControls.h"
|
||||||
|
|
||||||
|
@implementation TemporarySettings
|
||||||
|
|
||||||
|
- (id) initFromSettings:(Settings*)settings {
|
||||||
|
self = [self init];
|
||||||
|
|
||||||
|
self.parent = settings;
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
NSInteger _bitrate = [[NSUserDefaults standardUserDefaults] integerForKey:@"bitrate"];
|
||||||
|
NSInteger _framerate = [[NSUserDefaults standardUserDefaults] integerForKey:@"framerate"];
|
||||||
|
|
||||||
|
if (_bitrate) {
|
||||||
|
self.bitrate = [NSNumber numberWithInteger:_bitrate];
|
||||||
|
} else {
|
||||||
|
self.bitrate = [NSNumber numberWithInteger:20000];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_framerate) {
|
||||||
|
self.framerate = [NSNumber numberWithInteger:_framerate];
|
||||||
|
} else {
|
||||||
|
self.framerate = [NSNumber numberWithInteger:60];
|
||||||
|
}
|
||||||
|
|
||||||
|
self.useHevc = [[NSUserDefaults standardUserDefaults] boolForKey:@"useHevc"] || NO;
|
||||||
|
self.playAudioOnPC = [[NSUserDefaults standardUserDefaults] boolForKey:@"audioOnPC"] || NO;
|
||||||
|
self.enableHdr = [[NSUserDefaults standardUserDefaults] boolForKey:@"enableHdr"] || NO;
|
||||||
|
self.optimizeGames = [[NSUserDefaults standardUserDefaults] boolForKey:@"optimizeGames"] || YES;
|
||||||
|
self.multiController = [[NSUserDefaults standardUserDefaults] boolForKey:@"multipleControllers"] || YES;
|
||||||
|
|
||||||
|
NSInteger _screenSize = [[NSUserDefaults standardUserDefaults] integerForKey:@"streamResolution"];
|
||||||
|
switch (_screenSize) {
|
||||||
|
case 0:
|
||||||
|
self.height = [NSNumber numberWithInteger:720];
|
||||||
|
self.width = [NSNumber numberWithInteger:1280];
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
self.height = [NSNumber numberWithInteger:2160];
|
||||||
|
self.width = [NSNumber numberWithInteger:3840];
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
self.height = [NSNumber numberWithInteger:1080];
|
||||||
|
self.width = [NSNumber numberWithInteger:1920];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
self.onscreenControls = [NSNumber numberWithInteger:OnScreenControlsLevelOff];
|
||||||
|
#else
|
||||||
|
self.bitrate = settings.bitrate;
|
||||||
|
self.framerate = settings.framerate;
|
||||||
|
self.height = settings.height;
|
||||||
|
self.width = settings.width;
|
||||||
|
self.useHevc = settings.useHevc;
|
||||||
|
self.playAudioOnPC = settings.playAudioOnPC;
|
||||||
|
self.enableHdr = settings.enableHdr;
|
||||||
|
self.optimizeGames = settings.optimizeGames;
|
||||||
|
self.multiController = settings.multiController;
|
||||||
|
self.onscreenControls = settings.onscreenControls;
|
||||||
|
#endif
|
||||||
|
self.uniqueId = settings.uniqueId;
|
||||||
|
self.streamingRemotely = settings.streamingRemotely;
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
Font data copyright Google 2012
|
|
||||||
|
|
||||||
Apache License
|
|
||||||
Version 2.0, January 2004
|
|
||||||
http://www.apache.org/licenses/
|
|
||||||
|
|
||||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"License" shall mean the terms and conditions for use, reproduction,
|
|
||||||
and distribution as defined by Sections 1 through 9 of this document.
|
|
||||||
|
|
||||||
"Licensor" shall mean the copyright owner or entity authorized by
|
|
||||||
the copyright owner that is granting the License.
|
|
||||||
|
|
||||||
"Legal Entity" shall mean the union of the acting entity and all
|
|
||||||
other entities that control, are controlled by, or are under common
|
|
||||||
control with that entity. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean an individual or Legal Entity
|
|
||||||
exercising permissions granted by this License.
|
|
||||||
|
|
||||||
"Source" form shall mean the preferred form for making modifications,
|
|
||||||
including but not limited to software source code, documentation
|
|
||||||
source, and configuration files.
|
|
||||||
|
|
||||||
"Object" form shall mean any form resulting from mechanical
|
|
||||||
transformation or translation of a Source form, including but
|
|
||||||
not limited to compiled object code, generated documentation,
|
|
||||||
and conversions to other media types.
|
|
||||||
|
|
||||||
"Work" shall mean the work of authorship, whether in Source or
|
|
||||||
Object form, made available under the License, as indicated by a
|
|
||||||
copyright notice that is included in or attached to the work
|
|
||||||
(an example is provided in the Appendix below).
|
|
||||||
|
|
||||||
"Derivative Works" shall mean any work, whether in Source or Object
|
|
||||||
form, that is based on (or derived from) the Work and for which the
|
|
||||||
editorial revisions, annotations, elaborations, or other modifications
|
|
||||||
represent, as a whole, an original work of authorship. For the purposes
|
|
||||||
of this License, Derivative Works shall not include works that remain
|
|
||||||
separable from, or merely link (or bind by name) to the interfaces of,
|
|
||||||
the Work and Derivative Works thereof.
|
|
||||||
|
|
||||||
"Contribution" shall mean any work of authorship, including
|
|
||||||
the original version of the Work and any modifications or additions
|
|
||||||
to that Work or Derivative Works thereof, that is intentionally
|
|
||||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
||||||
or by an individual or Legal Entity authorized to submit on behalf of
|
|
||||||
the copyright owner. For the purposes of this definition, "submitted"
|
|
||||||
means any form of electronic, verbal, or written communication sent
|
|
||||||
to the Licensor or its representatives, including but not limited to
|
|
||||||
communication on electronic mailing lists, source code control systems,
|
|
||||||
and issue tracking systems that are managed by, or on behalf of, the
|
|
||||||
Licensor for the purpose of discussing and improving the Work, but
|
|
||||||
excluding communication that is conspicuously marked or otherwise
|
|
||||||
designated in writing by the copyright owner as "Not a Contribution."
|
|
||||||
|
|
||||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
||||||
on behalf of whom a Contribution has been received by Licensor and
|
|
||||||
subsequently incorporated within the Work.
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare Derivative Works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute the
|
|
||||||
Work and such Derivative Works in Source or Object form.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this License, each Contributor hereby grants to You a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have made,
|
|
||||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
||||||
where such license applies only to those patent claims licensable
|
|
||||||
by such Contributor that are necessarily infringed by their
|
|
||||||
Contribution(s) alone or by combination of their Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If You
|
|
||||||
institute patent litigation against any entity (including a
|
|
||||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
||||||
or a Contribution incorporated within the Work constitutes direct
|
|
||||||
or contributory patent infringement, then any patent licenses
|
|
||||||
granted to You under this License for that Work shall terminate
|
|
||||||
as of the date such litigation is filed.
|
|
||||||
|
|
||||||
4. Redistribution. You may reproduce and distribute copies of the
|
|
||||||
Work or Derivative Works thereof in any medium, with or without
|
|
||||||
modifications, and in Source or Object form, provided that You
|
|
||||||
meet the following conditions:
|
|
||||||
|
|
||||||
(a) You must give any other recipients of the Work or
|
|
||||||
Derivative Works a copy of this License; and
|
|
||||||
|
|
||||||
(b) You must cause any modified files to carry prominent notices
|
|
||||||
stating that You changed the files; and
|
|
||||||
|
|
||||||
(c) You must retain, in the Source form of any Derivative Works
|
|
||||||
that You distribute, all copyright, patent, trademark, and
|
|
||||||
attribution notices from the Source form of the Work,
|
|
||||||
excluding those notices that do not pertain to any part of
|
|
||||||
the Derivative Works; and
|
|
||||||
|
|
||||||
(d) If the Work includes a "NOTICE" text file as part of its
|
|
||||||
distribution, then any Derivative Works that You distribute must
|
|
||||||
include a readable copy of the attribution notices contained
|
|
||||||
within such NOTICE file, excluding those notices that do not
|
|
||||||
pertain to any part of the Derivative Works, in at least one
|
|
||||||
of the following places: within a NOTICE text file distributed
|
|
||||||
as part of the Derivative Works; within the Source form or
|
|
||||||
documentation, if provided along with the Derivative Works; or,
|
|
||||||
within a display generated by the Derivative Works, if and
|
|
||||||
wherever such third-party notices normally appear. The contents
|
|
||||||
of the NOTICE file are for informational purposes only and
|
|
||||||
do not modify the License. You may add Your own attribution
|
|
||||||
notices within Derivative Works that You distribute, alongside
|
|
||||||
or as an addendum to the NOTICE text from the Work, provided
|
|
||||||
that such additional attribution notices cannot be construed
|
|
||||||
as modifying the License.
|
|
||||||
|
|
||||||
You may add Your own copyright statement to Your modifications and
|
|
||||||
may provide additional or different license terms and conditions
|
|
||||||
for use, reproduction, or distribution of Your modifications, or
|
|
||||||
for any such Derivative Works as a whole, provided Your use,
|
|
||||||
reproduction, and distribution of the Work otherwise complies with
|
|
||||||
the conditions stated in this License.
|
|
||||||
|
|
||||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
||||||
any Contribution intentionally submitted for inclusion in the Work
|
|
||||||
by You to the Licensor shall be under the terms and conditions of
|
|
||||||
this License, without any additional terms or conditions.
|
|
||||||
Notwithstanding the above, nothing herein shall supersede or modify
|
|
||||||
the terms of any separate license agreement you may have executed
|
|
||||||
with Licensor regarding such Contributions.
|
|
||||||
|
|
||||||
6. Trademarks. This License does not grant permission to use the trade
|
|
||||||
names, trademarks, service marks, or product names of the Licensor,
|
|
||||||
except as required for reasonable and customary use in describing the
|
|
||||||
origin of the Work and reproducing the content of the NOTICE file.
|
|
||||||
|
|
||||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
||||||
agreed to in writing, Licensor provides the Work (and each
|
|
||||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
||||||
implied, including, without limitation, any warranties or conditions
|
|
||||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
||||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
||||||
appropriateness of using or redistributing the Work and assume any
|
|
||||||
risks associated with Your exercise of permissions under this License.
|
|
||||||
|
|
||||||
8. Limitation of Liability. In no event and under no legal theory,
|
|
||||||
whether in tort (including negligence), contract, or otherwise,
|
|
||||||
unless required by applicable law (such as deliberate and grossly
|
|
||||||
negligent acts) or agreed to in writing, shall any Contributor be
|
|
||||||
liable to You for damages, including any direct, indirect, special,
|
|
||||||
incidental, or consequential damages of any character arising as a
|
|
||||||
result of this License or out of the use or inability to use the
|
|
||||||
Work (including but not limited to damages for loss of goodwill,
|
|
||||||
work stoppage, computer failure or malfunction, or any and all
|
|
||||||
other commercial damages or losses), even if such Contributor
|
|
||||||
has been advised of the possibility of such damages.
|
|
||||||
|
|
||||||
9. Accepting Warranty or Additional Liability. While redistributing
|
|
||||||
the Work or Derivative Works thereof, You may choose to offer,
|
|
||||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
||||||
or other liability obligations and/or rights consistent with this
|
|
||||||
License. However, in accepting such obligations, You may act only
|
|
||||||
on Your own behalf and on Your sole responsibility, not on behalf
|
|
||||||
of any other Contributor, and only if You agree to indemnify,
|
|
||||||
defend, and hold each Contributor harmless for any liability
|
|
||||||
incurred by, or claims asserted against, such Contributor by reason
|
|
||||||
of your accepting any such warranty or additional liability.
|
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
|
||||||
|
|
||||||
APPENDIX: How to apply the Apache License to your work.
|
|
||||||
|
|
||||||
To apply the Apache License to your work, attach the following
|
|
||||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
||||||
replaced with your own identifying information. (Don't include
|
|
||||||
the brackets!) The text should be enclosed in the appropriate
|
|
||||||
comment syntax for the file format. We also recommend that a
|
|
||||||
file or class name and description of purpose be included on the
|
|
||||||
same "printed page" as the copyright notice for easier
|
|
||||||
identification within third-party archives.
|
|
||||||
|
|
||||||
Copyright [yyyy] [name of copyright owner]
|
|
||||||
|
|
||||||
Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
you may not use this file except in compliance with the License.
|
|
||||||
You may obtain a copy of the License at
|
|
||||||
|
|
||||||
http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
|
|
||||||
Unless required by applicable law or agreed to in writing, software
|
|
||||||
distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
See the License for the specific language governing permissions and
|
|
||||||
limitations under the License.
|
|
||||||
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "a_button_80x80@2x.png",
|
||||||
"filename" : "a_button.png"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "a_button_120x120@3x.png",
|
||||||
"filename" : "a_button-1.png"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "a_button-2.png"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
@@ -1,23 +0,0 @@
|
|||||||
{
|
|
||||||
"images" : [
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "1x",
|
|
||||||
"filename" : "limelight_computer_add_icon_1x.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "2x",
|
|
||||||
"filename" : "limelight_computer_add_icon_2x.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "universal",
|
|
||||||
"scale" : "3x",
|
|
||||||
"filename" : "limelight_computer_add_icon_3x.png"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"info" : {
|
|
||||||
"version" : 1,
|
|
||||||
"author" : "xcode"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Before Width: | Height: | Size: 1.5 KiB |
|
Before Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.4 KiB |
@@ -2,18 +2,16 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "add.pdf",
|
||||||
"filename" : "settings_1x.png"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"scale" : "2x"
|
||||||
"filename" : "settings_2x.png"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "settings_3x.png"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
After Width: | Height: | Size: 32 KiB |
@@ -2,79 +2,111 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"scale" : "2x",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-Small@2x.png"
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"scale" : "3x",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-Small@3x.png"
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"scale" : "2x",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-40@2x.png"
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"scale" : "3x",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-40@3x.png"
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "iphone",
|
|
||||||
"size" : "60x60",
|
"size" : "60x60",
|
||||||
"scale" : "2x",
|
|
||||||
"filename" : "Icon-60@2x.png"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"idiom" : "iphone",
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
"size" : "60x60",
|
"size" : "60x60",
|
||||||
"scale" : "3x",
|
"idiom" : "iphone",
|
||||||
"filename" : "Icon-60@3x.png"
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "ipad",
|
"idiom" : "ipad",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"scale" : "1x",
|
"idiom" : "ipad",
|
||||||
"filename" : "Icon-Small.png"
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "ipad",
|
|
||||||
"size" : "29x29",
|
"size" : "29x29",
|
||||||
"scale" : "2x",
|
"idiom" : "ipad",
|
||||||
"filename" : "Icon-Small@2x.png"
|
"filename" : "Icon-App-29x29@2x-1.png",
|
||||||
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "ipad",
|
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"scale" : "1x",
|
"idiom" : "ipad",
|
||||||
"filename" : "Icon-40.png"
|
"filename" : "Icon-App-40x40@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "ipad",
|
|
||||||
"size" : "40x40",
|
"size" : "40x40",
|
||||||
"scale" : "2x",
|
"idiom" : "ipad",
|
||||||
"filename" : "Icon-40@2x.png"
|
"filename" : "Icon-App-40x40@2x-1.png",
|
||||||
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "ipad",
|
|
||||||
"size" : "76x76",
|
"size" : "76x76",
|
||||||
"scale" : "1x",
|
"idiom" : "ipad",
|
||||||
"filename" : "Icon-76.png"
|
"filename" : "Icon-App-76x76@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "ipad",
|
|
||||||
"size" : "76x76",
|
"size" : "76x76",
|
||||||
"scale" : "2x",
|
"idiom" : "ipad",
|
||||||
"filename" : "Icon-76@2x.png"
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "83.5x83.5",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "1024x1024",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"filename" : "1024x icon.png",
|
||||||
|
"scale" : "1x"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
"version" : 1,
|
"version" : 1,
|
||||||
"author" : "makeappicon"
|
"author" : "xcode"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Before Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 14 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 2.1 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 4.0 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 6.4 KiB |
|
Before Width: | Height: | Size: 10 KiB |
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "b_button_80x80@2x.png",
|
||||||
"filename" : "b_button.png"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "b_button_120x120@3x.png",
|
||||||
"filename" : "b_button-1.png"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "b_button-2.png"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.0 KiB |
|
Before Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 6.3 KiB |
@@ -0,0 +1,69 @@
|
|||||||
|
%PDF-1.5
|
||||||
|
%µí®û
|
||||||
|
4 0 obj
|
||||||
|
<< /Length 5 0 R
|
||||||
|
/Filter /FlateDecode
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
xœ]‘]!„ß{Š^ÀÊ”Àâ1<‚Ùøó êý…E␍ »ÛN‡Yp°µƒmª‰×=)´³×•÷§À×7iØ·¸Hbä"‹= ¯3_\W«FÆ!K©%ðÁ½ÛñÎX¤@;$Ú®‹ ”mÊê@Œ¬Ç¿ ‰µµ+¸“!ïd�±ùË}œ#¡TÙ;7_Û«†,ÚLÙ˜EˆMHS~»ì8Ðà—î�$ëô¾±ÍX™F—ØÙ´<òŸ\W¾Í¤MlæÜûþeÓeÇÿÎé¦Lg7
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
212
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/ExtGState <<
|
||||||
|
/a0 << /CA 0.3 /ca 0.3 >>
|
||||||
|
/a1 << /CA 1 /ca 1 >>
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<< /Type /Page % 1
|
||||||
|
/Parent 1 0 R
|
||||||
|
/MediaBox [ 0 0 225 225 ]
|
||||||
|
/Contents 4 0 R
|
||||||
|
/Group <<
|
||||||
|
/Type /Group
|
||||||
|
/S /Transparency
|
||||||
|
/I true
|
||||||
|
/CS /DeviceRGB
|
||||||
|
>>
|
||||||
|
/Resources 3 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
1 0 obj
|
||||||
|
<< /Type /Pages
|
||||||
|
/Kids [ 2 0 R ]
|
||||||
|
/Count 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<< /Producer (cairo 1.16.0 (https://cairographics.org))
|
||||||
|
/CreationDate (D:20190830180928-07'00)
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
7 0 obj
|
||||||
|
<< /Type /Catalog
|
||||||
|
/Pages 1 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
xref
|
||||||
|
0 8
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000648 00000 n
|
||||||
|
0000000430 00000 n
|
||||||
|
0000000326 00000 n
|
||||||
|
0000000015 00000 n
|
||||||
|
0000000304 00000 n
|
||||||
|
0000000713 00000 n
|
||||||
|
0000000829 00000 n
|
||||||
|
trailer
|
||||||
|
<< /Size 8
|
||||||
|
/Root 7 0 R
|
||||||
|
/Info 6 0 R
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
881
|
||||||
|
%%EOF
|
||||||
@@ -2,18 +2,16 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "Computer.pdf",
|
||||||
"filename" : "limelight_computer_1x.png"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"scale" : "2x"
|
||||||
"filename" : "limelight_computer_2x.png"
|
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "limelight_computer_3x.png"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 9.3 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,18 +2,17 @@
|
|||||||
"images" : [
|
"images" : [
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"filename" : "down_61x75@2x.png",
|
||||||
"filename" : "down.png"
|
"scale" : "1x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"filename" : "down_93x114@3x.png",
|
||||||
"filename" : "down-1.png"
|
"scale" : "2x"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x"
|
||||||
"filename" : "down-2.png"
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 455 B |
|
Before Width: | Height: | Size: 455 B |
|
After Width: | Height: | Size: 3.6 KiB |
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "error.pdf",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,68 @@
|
|||||||
|
%PDF-1.5
|
||||||
|
%µí®û
|
||||||
|
4 0 obj
|
||||||
|
<< /Length 5 0 R
|
||||||
|
/Filter /FlateDecode
|
||||||
|
>>
|
||||||
|
stream
|
||||||
|
xœeŒÑ Ã0Dÿ5Å-Uªì(kt„Rhò¤Ýª8µ �t︓Bb�å¯B)öù̸=ó—Œõž1fã¸òä�W˜sW½P’jçjXbó†kG Ý’rî%c?õì=ÓãÍ?ÜðÒ~Óƒ~®L+·
|
||||||
|
endstream
|
||||||
|
endobj
|
||||||
|
5 0 obj
|
||||||
|
115
|
||||||
|
endobj
|
||||||
|
3 0 obj
|
||||||
|
<<
|
||||||
|
/ExtGState <<
|
||||||
|
/a0 << /CA 1 /ca 1 >>
|
||||||
|
>>
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
2 0 obj
|
||||||
|
<< /Type /Page % 1
|
||||||
|
/Parent 1 0 R
|
||||||
|
/MediaBox [ 0 0 75 75 ]
|
||||||
|
/Contents 4 0 R
|
||||||
|
/Group <<
|
||||||
|
/Type /Group
|
||||||
|
/S /Transparency
|
||||||
|
/I true
|
||||||
|
/CS /DeviceRGB
|
||||||
|
>>
|
||||||
|
/Resources 3 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
1 0 obj
|
||||||
|
<< /Type /Pages
|
||||||
|
/Kids [ 2 0 R ]
|
||||||
|
/Count 1
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
6 0 obj
|
||||||
|
<< /Producer (cairo 1.16.0 (https://cairographics.org))
|
||||||
|
/CreationDate (D:20190830180932-07'00)
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
7 0 obj
|
||||||
|
<< /Type /Catalog
|
||||||
|
/Pages 1 0 R
|
||||||
|
>>
|
||||||
|
endobj
|
||||||
|
xref
|
||||||
|
0 8
|
||||||
|
0000000000 65535 f
|
||||||
|
0000000517 00000 n
|
||||||
|
0000000301 00000 n
|
||||||
|
0000000229 00000 n
|
||||||
|
0000000015 00000 n
|
||||||
|
0000000207 00000 n
|
||||||
|
0000000582 00000 n
|
||||||
|
0000000698 00000 n
|
||||||
|
trailer
|
||||||
|
<< /Size 8
|
||||||
|
/Root 7 0 R
|
||||||
|
/Info 6 0 R
|
||||||
|
>>
|
||||||
|
startxref
|
||||||
|
750
|
||||||
|
%%EOF
|
||||||
@@ -3,17 +3,17 @@
|
|||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "1x",
|
"scale" : "1x",
|
||||||
"filename" : "L1-1.png"
|
"filename" : "L1_40x40@1x.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "2x",
|
"scale" : "2x",
|
||||||
"filename" : "L1.png"
|
"filename" : "L1_80x80@2x.png"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"idiom" : "universal",
|
"idiom" : "universal",
|
||||||
"scale" : "3x",
|
"scale" : "3x",
|
||||||
"filename" : "L1-2.png"
|
"filename" : "L1_120x120@3x.png"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"info" : {
|
"info" : {
|
||||||
|
|||||||