Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
65f7e75736 | ||
|
|
3617ea98e2 | ||
|
|
81c84597c8 | ||
|
|
ea231e16b6 | ||
|
|
c205b99080 | ||
|
|
e3dd4e7238 | ||
|
|
0c36754ebe | ||
|
|
e7dc22bb15 | ||
|
|
d4b5ec5764 | ||
|
|
bed8c729f9 | ||
|
|
0a767767fb | ||
|
|
e31df3f44e | ||
|
|
9c9795ab1f | ||
|
|
c7c28a18c5 | ||
|
|
93119f25a6 | ||
|
|
1313429f65 | ||
|
|
11c27baaf8 | ||
|
|
d728e63bb4 | ||
|
|
7d584fb4de | ||
|
|
7d7adb0753 | ||
|
|
337e5e3d9d | ||
|
|
879f304a79 | ||
|
|
75d3f23f0a | ||
|
|
14f30349a3 | ||
|
|
8e721a9c6a | ||
|
|
e3e95c29f6 | ||
|
|
4224d02eae | ||
|
|
f300119d23 | ||
|
|
ed1dc4c0ff | ||
|
|
4b4aec0006 | ||
|
|
c44e03c945 | ||
|
|
179110508c | ||
|
|
514d5d13a0 | ||
|
|
3190c61a0a | ||
|
|
1b629bc55d | ||
|
|
ae6ff4b442 | ||
|
|
25d815dcd7 | ||
|
|
3e85f13e08 | ||
|
|
01902536ab | ||
|
|
0a4fa5fc6c | ||
|
|
106ba15245 | ||
|
|
a535f908c7 | ||
|
|
de4ed222cd | ||
|
|
d92edc19df | ||
|
|
f7fdd7cb45 | ||
|
|
c1a1dbe881 | ||
|
|
c368012e84 | ||
|
|
650eca829b | ||
|
|
4aac38e514 | ||
|
|
5ef91f2fc0 | ||
|
|
3da1d5e511 | ||
|
|
64c60976f7 | ||
|
|
61401b3e7b | ||
|
|
b7ccf57a2d | ||
|
|
600560d9e3 | ||
|
|
cdaf98398c | ||
|
|
6f9c16a548 | ||
|
|
9e054973c8 | ||
|
|
afb7e930ee | ||
|
|
684aaf8cb2 | ||
|
|
8fc81b9563 | ||
|
|
903395b273 | ||
|
|
6977684045 | ||
|
|
abb0d5b8ba | ||
|
|
60cba0399d | ||
|
|
b7fcce08d6 | ||
|
|
ec39c27498 | ||
|
|
ccd8b3332e | ||
|
|
7cf521272a | ||
|
|
f0abd599d1 | ||
|
|
a754b55753 | ||
|
|
fe131af464 | ||
|
|
b89515089f | ||
|
|
e9c449bbf4 | ||
|
|
55e9d2daeb | ||
|
|
132a90a865 | ||
|
|
fe64d70577 | ||
|
|
94d399e275 | ||
|
|
89ac394891 | ||
|
|
bb03148b85 | ||
|
|
d162bdbbc2 | ||
|
|
ce3f046ae8 | ||
|
|
d4cd8d3bba | ||
|
|
021283e6ef | ||
|
|
84a314adb4 | ||
|
|
fcd3af5bcc | ||
|
|
514d79fde9 | ||
|
|
e325ee1c27 | ||
|
|
aaeef1d6bb | ||
|
|
57bf748877 | ||
|
|
d134ff83d6 | ||
|
|
f0b145c01a | ||
|
|
5aeedb894a | ||
|
|
ee61dc9a59 | ||
|
|
a52b20ee52 | ||
|
|
f209670c1a | ||
|
|
168eac17eb | ||
|
|
417f1e02bc | ||
|
|
3eee684961 | ||
|
|
e8c8f4f8e9 | ||
|
|
0e2765ad86 | ||
|
|
40d6ab91cf | ||
|
|
c96a77f1aa | ||
|
|
ece113787d | ||
|
|
cb93486bb0 | ||
|
|
809a660506 | ||
|
|
7b0a383ad0 | ||
|
|
2cb1acc611 | ||
|
|
d6d30f021d | ||
|
|
4a08288d0d | ||
|
|
5c488cf4aa | ||
|
|
c7b6011806 | ||
|
|
af4a833806 | ||
|
|
87a6d2f656 | ||
|
|
0ee9b87742 | ||
|
|
5968d511b2 | ||
|
|
20561ae64f | ||
|
|
600e71223c | ||
|
|
d5c12a3eb6 | ||
|
|
35dc4a7de3 | ||
|
|
582dda5727 | ||
|
|
c05949c43b | ||
|
|
e913d26ca6 | ||
|
|
427e8f67fc | ||
|
|
79e51defe1 | ||
|
|
5f800b7901 | ||
|
|
c3b44a32d5 | ||
|
|
539e120167 | ||
|
|
a924d63750 | ||
|
|
1affb03b89 | ||
|
|
dae484445b | ||
|
|
99d3ac45c3 | ||
|
|
33d6306359 | ||
|
|
5ee9e285e7 | ||
|
|
1be97e1c8a | ||
|
|
8d360d2266 | ||
|
|
2a49f8901f | ||
|
|
d8020a367f | ||
|
|
88c917c103 | ||
|
|
77b6d304f7 | ||
|
|
6273f2bb29 | ||
|
|
412c5c2516 | ||
|
|
6fbc55f193 | ||
|
|
fac48ecf42 | ||
|
|
b5bf26bb2d | ||
|
|
00fab87b4c | ||
|
|
3554b40962 | ||
|
|
aa3752a905 | ||
|
|
c0a3ae9371 | ||
|
|
47850cd658 | ||
|
|
1b98870b41 | ||
|
|
ef98976ebf | ||
|
|
ba022da665 | ||
|
|
ae9abf2911 | ||
|
|
99e7f59df4 | ||
|
|
8273173080 | ||
|
|
3357b3882b | ||
|
|
b7510717c8 | ||
|
|
5434542877 | ||
|
|
4c2f6b269a | ||
|
|
0ccf046c69 | ||
|
|
f0b6602b99 | ||
|
|
72e0da4319 | ||
|
|
d2ad8b12ce | ||
|
|
6ef492662b | ||
|
|
3c7f33a80c | ||
|
|
eeec1f1cf5 | ||
|
|
45545e8f9b | ||
|
|
85b65d7112 | ||
|
|
26f7a27117 | ||
|
|
ea78cbc47e | ||
|
|
ea24b39fbe | ||
|
|
01a2853032 | ||
|
|
bfca061694 | ||
|
|
4a9bb00e0d | ||
|
|
72271a0c74 | ||
|
|
1ca787822b | ||
|
|
39186a4edf | ||
|
|
528b44f2f2 | ||
|
|
dfe2addca2 | ||
|
|
44bbba805f | ||
|
|
f756451001 | ||
|
|
b2236b5dad | ||
|
|
8dd62a8645 | ||
|
|
29f676a6d1 | ||
|
|
d83ac48a73 | ||
|
|
bf6a2e571f | ||
|
|
1f19d4de9d | ||
|
|
f4f3d7df50 | ||
|
|
a3f7aa41a1 | ||
|
|
101096ad80 | ||
|
|
34d871403c | ||
|
|
05e969221a | ||
|
|
c36fb14b15 | ||
|
|
c5dc7001f8 | ||
|
|
cd709000d7 | ||
|
|
a359aee36c | ||
|
|
185a4334ca | ||
|
|
6b10497e3e | ||
|
|
97f968fb0d | ||
|
|
127c53e341 | ||
|
|
3178f87707 | ||
|
|
9e8903402b | ||
|
|
af43539015 | ||
|
|
ca2fe9b0a3 | ||
|
|
84316166eb | ||
|
|
613f82b0ac | ||
|
|
f2ae32c45c | ||
|
|
4c646e36c7 | ||
|
|
85ee4f6518 | ||
|
|
37428c8c77 | ||
|
|
283a386b9c | ||
|
|
4d7715565a | ||
|
|
5ffdc1d2bd | ||
|
|
35e2ca1e00 | ||
|
|
b1938610dd | ||
|
|
f14a2a66dd | ||
|
|
44a7494823 | ||
|
|
f909371a90 | ||
|
|
f3b3d2bd08 | ||
|
|
e56923a71d | ||
|
|
f133f293b8 | ||
|
|
42773241c1 | ||
|
|
b8d256b73d | ||
|
|
0cb4c31d1e | ||
|
|
02fbd5f1d2 | ||
|
|
70f3a91dfb | ||
|
|
93063f5606 | ||
|
|
13f39e30f6 | ||
|
|
8ae0e4a547 | ||
|
|
3a6472eb0b | ||
|
|
037df87585 | ||
|
|
9b6865a53b | ||
|
|
4c3bc16593 | ||
|
|
440631fe2f | ||
|
|
374caee973 | ||
|
|
6225af1e76 | ||
|
|
2062c4c3e9 | ||
|
|
fbc3d1aa73 | ||
|
|
ec6166c232 | ||
|
|
ee21c612d5 | ||
|
|
9226a05ad8 | ||
|
|
31d57de339 | ||
|
|
bd91d74de8 | ||
|
|
fba676c405 | ||
|
|
1b6a558a7c | ||
|
|
92d32922ef | ||
|
|
00072a55f9 | ||
|
|
fec330b76e | ||
|
|
8b0514d73d | ||
|
|
f578ee4963 | ||
|
|
b828d5426b | ||
|
|
80a4b493ab | ||
|
|
6eed8cb962 | ||
|
|
8722d14048 | ||
|
|
0987ef0fa8 | ||
|
|
592e5dbe44 | ||
|
|
764f051318 | ||
|
|
457b6b13cc | ||
|
|
55e0c3c7bf | ||
|
|
26492c5783 | ||
|
|
4c6a3b2e43 | ||
|
|
45b9f5411e | ||
|
|
1e76b550e8 | ||
|
|
ef6909da88 | ||
|
|
01f11fc095 | ||
|
|
4b9e68950a | ||
|
|
e0cf044d60 | ||
|
|
9387211ce8 | ||
|
|
1ef314d3bd | ||
|
|
72ed023645 | ||
|
|
f97fe7fce2 | ||
|
|
029d3b0a97 | ||
|
|
87d8d117c1 | ||
|
|
d7a703828a | ||
|
|
8fdc5ad97b | ||
|
|
70510f8410 |
@@ -1,55 +0,0 @@
|
|||||||
---
|
|
||||||
name: Bug report
|
|
||||||
about: Follow the troubleshooting guide before reporting a bug
|
|
||||||
|
|
||||||
---
|
|
||||||
**READ ME FIRST!**
|
|
||||||
If you're here because something basic is not working (like gamepad input, video, or similar), it's probably something specific to your setup, so make sure you've gone through the Troubleshooting Guide first: https://github.com/moonlight-stream/moonlight-docs/wiki/Troubleshooting
|
|
||||||
|
|
||||||
If you still have trouble with basic functionality after following the guide, join our Discord server where there are many other volunteers who can help (or direct you back here if it looks like a Moonlight bug after all). https://moonlight-stream.org/discord
|
|
||||||
|
|
||||||
**Describe the bug**
|
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
|
||||||
**Steps to reproduce**
|
|
||||||
Any special steps that are required for the bug to appear.
|
|
||||||
|
|
||||||
**Screenshots**
|
|
||||||
If applicable, add screenshots to help explain your problem. If the issue is related to video glitching or poor quality, please include screenshots.
|
|
||||||
|
|
||||||
**Affected games**
|
|
||||||
List the games you've tried that exhibit the issue. To see if the issue is game-specific, try streaming Steam Big Picture with Moonlight and see if the issue persists there.
|
|
||||||
|
|
||||||
**Other Moonlight clients**
|
|
||||||
- Does the issue occur when using Moonlight on iOS or Android?
|
|
||||||
|
|
||||||
**Moonlight settings (please complete the following information)**
|
|
||||||
- Have any settings been adjusted from defaults?
|
|
||||||
- If so, which settings have been changed?
|
|
||||||
- Does the problem still occur after reverting settings back to default?
|
|
||||||
|
|
||||||
**Gamepad-related issues (please complete if problem is gamepad-related)**
|
|
||||||
- Do you have any gamepads connected to your host PC directly?
|
|
||||||
- Does the problem still remain if you stream the desktop and use https://html5gamepad.com to test your gamepad?
|
|
||||||
- Instructions for streaming the desktop can be found here: https://github.com/moonlight-stream/moonlight-docs/wiki/Setup-Guide
|
|
||||||
|
|
||||||
**Client PC details (please complete the following information)**
|
|
||||||
- OS: [e.g. Windows 10 1809]
|
|
||||||
- Moonlight Version: [e.g. v0.9.0]
|
|
||||||
- GPU: [e.g. Intel HD Graphics 520]
|
|
||||||
- Linux package type (if applicable): [e.g. Flatpak]
|
|
||||||
|
|
||||||
**Server PC details (please complete the following information)**
|
|
||||||
- OS: [e.g. Windows 10 1809]
|
|
||||||
- Sunshine or GeForce Experience version: [e.g. Sunshine v0.21.0]
|
|
||||||
- GPU: [e.g. AMD Radeon RX 7900 XT]
|
|
||||||
- GPU driver: [e.g. 24.1.1]
|
|
||||||
|
|
||||||
**Moonlight Logs (please attach)**
|
|
||||||
- On Windows, `Moonlight-###.log` files can be found in `%TEMP%`. Simply type that into the File Explorer path field to navigate there.
|
|
||||||
- On macOS, `Moonlight-###.log` files can be found in `/tmp`. In Finder, press Cmd+Shift+G, then type `/tmp` to navigate there.
|
|
||||||
- On Linux with the Flatpak, logs print to the terminal when running with the command: `flatpak run com.moonlight_stream.Moonlight`
|
|
||||||
- On Linux with the Snap, logs print to the terminal when running with the command: `moonlight`
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Anything else you think may be relevant to the issue
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
blank_issues_enabled: false
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
---
|
|
||||||
name: Feature request
|
|
||||||
about: Suggest an idea for this project
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
**Is your feature request related to a problem? Please describe.**
|
|
||||||
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
|
||||||
|
|
||||||
**Describe the solution you'd like**
|
|
||||||
A clear and concise description of what you want to happen.
|
|
||||||
|
|
||||||
**Describe alternatives you've considered**
|
|
||||||
A clear and concise description of any alternative solutions or features you've considered.
|
|
||||||
|
|
||||||
**Additional context**
|
|
||||||
Add any other context or screenshots about the feature request here.
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
issuesOpened: >
|
|
||||||
If this is a question about Moonlight or you need help troubleshooting a streaming problem, please use the help channels on our [Discord server](https://moonlight-stream.org/discord) instead of GitHub issues. There are many more people available on Discord to help you and answer your questions.<br /><br />
|
|
||||||
This issue tracker should only be used for specific bugs or feature requests.<br /><br />
|
|
||||||
Thank you, and happy streaming!
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
# Please see the documentation for all configuration options:
|
|
||||||
# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file
|
|
||||||
|
|
||||||
version: 2
|
|
||||||
updates:
|
|
||||||
- package-ecosystem: "gitsubmodule"
|
|
||||||
directory: "/"
|
|
||||||
schedule:
|
|
||||||
interval: "daily"
|
|
||||||
@@ -1,164 +0,0 @@
|
|||||||
---
|
|
||||||
name: Build - Linux AppImage
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
ci_version:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
env:
|
|
||||||
CI_VERSION: ${{ inputs.ci_version }}
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
submodules: 'recursive'
|
|
||||||
fetch-depth: 1
|
|
||||||
|
|
||||||
- name: Setup environment
|
|
||||||
run: |
|
|
||||||
wget -qO - https://packages.lunarg.com/lunarg-signing-key-pub.asc | sudo apt-key add -
|
|
||||||
sudo wget -qO /etc/apt/sources.list.d/lunarg-vulkan-1.4.313-jammy.list https://packages.lunarg.com/vulkan/1.4.313/lunarg-vulkan-1.4.313-jammy.list
|
|
||||||
sudo apt update
|
|
||||||
sudo apt install -y qt6-base-dev qt6-declarative-dev libqt6svg6-dev qt6-wayland qml6-module-qtquick-controls qml6-module-qtquick-templates qml6-module-qtquick-layouts \
|
|
||||||
qml6-module-qtqml-workerscript qml6-module-qtquick-window qml6-module-qtquick python3-pip nasm libgbm-dev libdrm-dev libfreetype-dev libasound2-dev \
|
|
||||||
libdbus-1-dev libegl1-mesa-dev libgl1-mesa-dev libgles2-mesa-dev libglu1-mesa-dev libibus-1.0-dev libpulse-dev libudev-dev libx11-dev libxcursor-dev \
|
|
||||||
libxext-dev libxi-dev libxinerama-dev libxkbcommon-dev libxrandr-dev libxss-dev libxt-dev libxv-dev libxxf86vm-dev libxcb-dri3-dev libx11-xcb-dev \
|
|
||||||
libxfixes-dev libxtst-dev wayland-protocols libopus-dev libvdpau-dev libgl-dev libpipewire-0.3-dev liburing-dev vulkan-sdk cmake
|
|
||||||
sudo pip3 install meson
|
|
||||||
mkdir -p dep_root/{bin,include,lib}
|
|
||||||
echo "DEP_ROOT=$PWD/dep_root" >> "${GITHUB_ENV}"
|
|
||||||
echo "$PWD/dep_root/bin" >> "${GITHUB_PATH}"
|
|
||||||
|
|
||||||
- name: Checkout SDL3
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
repository: libsdl-org/SDL
|
|
||||||
ref: release-3.4.8
|
|
||||||
path: deps/SDL
|
|
||||||
|
|
||||||
- name: Build SDL3
|
|
||||||
working-directory: deps/SDL
|
|
||||||
run: |
|
|
||||||
cmake -DSDL_TEST_LIBRARY=OFF -DSDL_INSTALL_DOCS=OFF -S . -B build
|
|
||||||
cmake --build build -j
|
|
||||||
sudo cmake --install build
|
|
||||||
|
|
||||||
- name: Checkout sdl2-compat
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
repository: libsdl-org/sdl2-compat
|
|
||||||
ref: release-2.32.68
|
|
||||||
path: deps/sdl2-compat
|
|
||||||
|
|
||||||
- name: Build sdl2-compat
|
|
||||||
working-directory: deps/sdl2-compat
|
|
||||||
run: |
|
|
||||||
cmake -DSDL2COMPAT_TESTS=OFF -S . -B build
|
|
||||||
cmake --build build -j
|
|
||||||
sudo cmake --install build
|
|
||||||
|
|
||||||
- name: Checkout SDL_ttf
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
repository: libsdl-org/SDL_ttf
|
|
||||||
ref: a883e490e30fb44a5336ea3dcb990c6982c5216f
|
|
||||||
path: deps/SDL_ttf
|
|
||||||
submodules: 'recursive'
|
|
||||||
|
|
||||||
- name: Build SDL_ttf
|
|
||||||
working-directory: deps/SDL_ttf
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure
|
|
||||||
make -j$(nproc)
|
|
||||||
sudo make install
|
|
||||||
|
|
||||||
- name: Checkout libva
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
repository: intel/libva
|
|
||||||
ref: 2.23.0
|
|
||||||
path: deps/libva
|
|
||||||
|
|
||||||
- name: Build libva
|
|
||||||
working-directory: deps/libva
|
|
||||||
run: |
|
|
||||||
./autogen.sh
|
|
||||||
./configure --enable-x11
|
|
||||||
make -j$(nproc)
|
|
||||||
sudo make install
|
|
||||||
|
|
||||||
- name: Checkout libplacebo
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
repository: haasn/libplacebo
|
|
||||||
ref: v7.360.1
|
|
||||||
path: deps/libplacebo
|
|
||||||
submodules: 'recursive'
|
|
||||||
|
|
||||||
- name: Build libplacebo
|
|
||||||
working-directory: deps/libplacebo
|
|
||||||
run: |
|
|
||||||
meson setup build -Dvulkan=enabled -Dopengl=disabled -Ddemos=false
|
|
||||||
ninja -C build
|
|
||||||
sudo ninja install -C build
|
|
||||||
|
|
||||||
- name: Build dav1d
|
|
||||||
working-directory: deps
|
|
||||||
env:
|
|
||||||
DAV1D_VER: 1.5.3
|
|
||||||
run: |
|
|
||||||
git clone --branch $DAV1D_VER --depth 1 https://code.videolan.org/videolan/dav1d.git
|
|
||||||
pushd dav1d
|
|
||||||
meson setup build -Ddefault_library=static -Dbuildtype=release -Denable_tools=false -Denable_tests=false
|
|
||||||
ninja -C build
|
|
||||||
sudo ninja install -C build
|
|
||||||
popd
|
|
||||||
|
|
||||||
- name: Checkout FFmpeg
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
repository: FFmpeg/FFmpeg
|
|
||||||
ref: n8.1.1
|
|
||||||
path: deps/FFmpeg
|
|
||||||
|
|
||||||
- name: Build FFmpeg
|
|
||||||
working-directory: deps/FFmpeg
|
|
||||||
run: |
|
|
||||||
./configure --enable-pic --disable-static --enable-shared --disable-all --disable-autodetect --enable-avcodec --enable-avformat --enable-swscale \
|
|
||||||
--enable-decoder=h264 --enable-decoder=hevc --enable-decoder=av1 \
|
|
||||||
--enable-vaapi --enable-hwaccel=h264_vaapi --enable-hwaccel=hevc_vaapi --enable-hwaccel=av1_vaapi \
|
|
||||||
--enable-vdpau --enable-hwaccel=h264_vdpau --enable-hwaccel=hevc_vdpau --enable-hwaccel=av1_vdpau \
|
|
||||||
--enable-libdrm --enable-vulkan --enable-hwaccel=h264_vulkan --enable-hwaccel=hevc_vulkan --enable-hwaccel=av1_vulkan \
|
|
||||||
--enable-libdav1d --enable-decoder=libdav1d
|
|
||||||
make -j$(nproc)
|
|
||||||
sudo make install
|
|
||||||
|
|
||||||
- name: Install linuxdeploy
|
|
||||||
working-directory: dep_root/bin
|
|
||||||
run: |
|
|
||||||
wget https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage
|
|
||||||
wget https://github.com/linuxdeploy/linuxdeploy-plugin-qt/releases/download/continuous/linuxdeploy-plugin-qt-x86_64.AppImage
|
|
||||||
chmod +x linuxdeploy*.AppImage
|
|
||||||
|
|
||||||
- name: Build Binaries
|
|
||||||
run: |
|
|
||||||
sudo ldconfig
|
|
||||||
scripts/build-appimage.sh
|
|
||||||
|
|
||||||
- name: Upload Binaries
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: Moonlight-LinuxAppImage-${{ env.CI_VERSION }}
|
|
||||||
path: build/installer-release/Moonlight-${{ env.CI_VERSION }}-x86_64.AppImage
|
|
||||||
compression-level: 0
|
|
||||||
if-no-files-found: error
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
---
|
|
||||||
name: Build - Steam Link
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
ci_version:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
env:
|
|
||||||
CI_VERSION: ${{ inputs.ci_version }}
|
|
||||||
runs-on: ubuntu-22.04
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
submodules: 'recursive'
|
|
||||||
fetch-depth: 1
|
|
||||||
|
|
||||||
- name: Checkout Steam Link SDK
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
repository: ValveSoftware/steamlink-sdk
|
|
||||||
path: steamlink-sdk
|
|
||||||
fetch-depth: 1
|
|
||||||
|
|
||||||
- name: Build binaries
|
|
||||||
run: STEAMLINK_SDK_PATH=$PWD/steamlink-sdk scripts/build-steamlink-app.sh
|
|
||||||
|
|
||||||
- name: Upload Binaries
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: Moonlight-SteamLink-${{ env.CI_VERSION }}
|
|
||||||
path: build/deploy-release/*
|
|
||||||
if-no-files-found: error
|
|
||||||
@@ -1,125 +0,0 @@
|
|||||||
---
|
|
||||||
name: Build - Windows and macOS
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
on:
|
|
||||||
workflow_call:
|
|
||||||
inputs:
|
|
||||||
ci_version:
|
|
||||||
required: true
|
|
||||||
type: string
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
env:
|
|
||||||
CI_VERSION: ${{ inputs.ci_version }}
|
|
||||||
strategy:
|
|
||||||
fail-fast: false
|
|
||||||
matrix:
|
|
||||||
include:
|
|
||||||
# Windows
|
|
||||||
- os: windows-2025
|
|
||||||
qt_version: 6.11.0
|
|
||||||
# macOS
|
|
||||||
- os: macos-15
|
|
||||||
qt_version: 6.11.0
|
|
||||||
|
|
||||||
runs-on: ${{ matrix.os }}
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v5
|
|
||||||
with:
|
|
||||||
submodules: 'recursive'
|
|
||||||
fetch-depth: 1
|
|
||||||
|
|
||||||
- name: Download dependencies (Windows)
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
run: powershell ./setup-deps.ps1
|
|
||||||
|
|
||||||
- name: Install create-dmg (macOS)
|
|
||||||
if: runner.os == 'macOS'
|
|
||||||
run: |
|
|
||||||
brew install node
|
|
||||||
npm install --global create-dmg
|
|
||||||
|
|
||||||
- name: Install Qt
|
|
||||||
uses: jurplel/install-qt-action@v4
|
|
||||||
with:
|
|
||||||
cache: true
|
|
||||||
set-env: ${{ runner.os != 'Windows' }}
|
|
||||||
add-tools-to-path: ${{ runner.os != 'Windows' }}
|
|
||||||
version: ${{ matrix.qt_version }}
|
|
||||||
aqtsource: 'git+https://github.com/miurahr/aqtinstall.git@073e34d7c2ab4ae6961ed7cca690b3abd5ba5a7e'
|
|
||||||
|
|
||||||
- name: Install Qt ARM64 (Windows)
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
uses: jurplel/install-qt-action@v4
|
|
||||||
with:
|
|
||||||
cache: true
|
|
||||||
set-env: false
|
|
||||||
add-tools-to-path: false
|
|
||||||
arch: win64_msvc2022_arm64_cross_compiled
|
|
||||||
version: ${{ matrix.qt_version }}
|
|
||||||
|
|
||||||
- name: Build x64 binaries (Windows)
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
set "PATH=%QT_PATH%;%PATH%"
|
|
||||||
scripts\build-arch.bat Release x64
|
|
||||||
env:
|
|
||||||
QT_PATH: ${{ runner.workspace }}\Qt\${{ matrix.qt_version }}\msvc2022_64\bin
|
|
||||||
|
|
||||||
- name: Build ARM64 binaries (Windows)
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
shell: cmd
|
|
||||||
run: |
|
|
||||||
set "PATH=%QT_PATH%;%PATH%"
|
|
||||||
scripts\build-arch.bat Release arm64
|
|
||||||
env:
|
|
||||||
QT_PATH: ${{ runner.workspace }}\Qt\${{ matrix.qt_version }}\msvc2022_arm64\bin
|
|
||||||
|
|
||||||
- name: Build Package
|
|
||||||
shell: pwsh
|
|
||||||
run: |
|
|
||||||
if ($Env:RUNNER_OS -eq "Windows") {
|
|
||||||
cmd /c scripts\generate-bundle.bat Release
|
|
||||||
} else {
|
|
||||||
bash scripts/generate-dmg.sh Release
|
|
||||||
}
|
|
||||||
|
|
||||||
- name: Upload Binaries (Windows x64)
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
with:
|
|
||||||
name: Moonlight-${{ runner.os }}-x64-${{ env.CI_VERSION }}
|
|
||||||
path: build/deploy-x64-release/*
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload Binaries (Windows arm64)
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
if: runner.os == 'Windows'
|
|
||||||
with:
|
|
||||||
name: Moonlight-${{ runner.os }}-arm64-${{ env.CI_VERSION }}
|
|
||||||
path: build/deploy-arm64-release/*
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload Binaries (macOS)
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
if: runner.os == 'macOS'
|
|
||||||
with:
|
|
||||||
name: Moonlight-${{ runner.os }}-${{ env.CI_VERSION }}
|
|
||||||
path: build/installer-Release/*.dmg
|
|
||||||
compression-level: 0
|
|
||||||
if-no-files-found: error
|
|
||||||
|
|
||||||
- name: Upload Symbols
|
|
||||||
uses: actions/upload-artifact@v6
|
|
||||||
with:
|
|
||||||
name: zDevDbgSyms-${{ runner.os }}-${{ env.CI_VERSION }}
|
|
||||||
path: |
|
|
||||||
build/installer-*/*.dsym/*
|
|
||||||
build/symbols-*/*.pdb
|
|
||||||
if-no-files-found: error
|
|
||||||
@@ -1,45 +0,0 @@
|
|||||||
---
|
|
||||||
name: Build
|
|
||||||
permissions:
|
|
||||||
contents: read
|
|
||||||
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
pull_request:
|
|
||||||
branches:
|
|
||||||
- master
|
|
||||||
|
|
||||||
concurrency:
|
|
||||||
group: build-${{ github.ref }}
|
|
||||||
cancel-in-progress: true
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
setup:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
outputs:
|
|
||||||
ci_version: ${{ steps.set-ci-version.outputs.ci_version }}
|
|
||||||
steps:
|
|
||||||
- name: Set CI version
|
|
||||||
id: set-ci-version
|
|
||||||
shell: bash
|
|
||||||
run: |
|
|
||||||
CI_VERSION=`echo ${GITHUB_SHA} | cut -c1-6`
|
|
||||||
echo "ci_version=${CI_VERSION}" >> "${GITHUB_OUTPUT}"
|
|
||||||
|
|
||||||
build-appimage:
|
|
||||||
needs: setup
|
|
||||||
uses: ./.github/workflows/build-appimage.yml
|
|
||||||
with:
|
|
||||||
ci_version: ${{ needs.setup.outputs.ci_version }}
|
|
||||||
|
|
||||||
build-steamlink:
|
|
||||||
needs: setup
|
|
||||||
uses: ./.github/workflows/build-steamlink.yml
|
|
||||||
with:
|
|
||||||
ci_version: ${{ needs.setup.outputs.ci_version }}
|
|
||||||
|
|
||||||
build-windows-macos:
|
|
||||||
needs: setup
|
|
||||||
uses: ./.github/workflows/build-win-mac.yml
|
|
||||||
with:
|
|
||||||
ci_version: ${{ needs.setup.outputs.ci_version }}
|
|
||||||
@@ -1,9 +1,4 @@
|
|||||||
*pro.user
|
**/xcuserdata/
|
||||||
|
**/Moonlight.xcscmblueprint
|
||||||
|
Build
|
||||||
**/.vs/
|
DerivedData
|
||||||
.vscode/
|
|
||||||
build/
|
|
||||||
libs/
|
|
||||||
config.tests/*/.qmake.stash
|
|
||||||
config.tests/*/Makefile
|
|
||||||
|
|||||||
@@ -1,12 +1,3 @@
|
|||||||
[submodule "moonlight-common-c/moonlight-common-c"]
|
[submodule "moonlight-common/moonlight-common-c"]
|
||||||
path = moonlight-common-c/moonlight-common-c
|
path = moonlight-common/moonlight-common-c
|
||||||
url = https://github.com/moonlight-stream/moonlight-common-c.git
|
url = https://github.com/moonlight-stream/moonlight-common-c.git
|
||||||
[submodule "qmdnsengine/qmdnsengine"]
|
|
||||||
path = qmdnsengine/qmdnsengine
|
|
||||||
url = https://github.com/cgutman/qmdnsengine.git
|
|
||||||
[submodule "app/SDL_GameControllerDB"]
|
|
||||||
path = app/SDL_GameControllerDB
|
|
||||||
url = https://github.com/gabomdq/SDL_GameControllerDB.git
|
|
||||||
[submodule "h264bitstream/h264bitstream"]
|
|
||||||
path = h264bitstream/h264bitstream
|
|
||||||
url = https://github.com/aizvorski/h264bitstream.git
|
|
||||||
|
|||||||
@@ -1,22 +0,0 @@
|
|||||||
QT -= core gui
|
|
||||||
|
|
||||||
TARGET = AntiHooking
|
|
||||||
TEMPLATE = lib
|
|
||||||
|
|
||||||
include(../globaldefs.pri)
|
|
||||||
|
|
||||||
INCLUDEPATH += $$PWD/../libs/windows/include
|
|
||||||
contains(QT_ARCH, i386) {
|
|
||||||
LIBS += -L$$PWD/../libs/windows/lib/x86
|
|
||||||
}
|
|
||||||
contains(QT_ARCH, x86_64) {
|
|
||||||
LIBS += -L$$PWD/../libs/windows/lib/x64
|
|
||||||
}
|
|
||||||
contains(QT_ARCH, arm64) {
|
|
||||||
LIBS += -L$$PWD/../libs/windows/lib/arm64
|
|
||||||
}
|
|
||||||
|
|
||||||
LIBS += -ldetours
|
|
||||||
DEFINES += ANTIHOOKING_LIBRARY
|
|
||||||
SOURCES += antihookingprotection.cpp
|
|
||||||
HEADERS += antihookingprotection.h
|
|
||||||
@@ -1,266 +0,0 @@
|
|||||||
#include "antihookingprotection.h"
|
|
||||||
|
|
||||||
#define WIN32_LEAN_AND_MEAN
|
|
||||||
#include <Windows.h>
|
|
||||||
|
|
||||||
#include <detours.h>
|
|
||||||
|
|
||||||
typedef HMODULE (WINAPI *LoadLibraryAFunc)(LPCSTR lpLibFileName);
|
|
||||||
typedef HMODULE (WINAPI *LoadLibraryWFunc)(LPCWSTR lpLibFileName);
|
|
||||||
typedef HMODULE (WINAPI *LoadLibraryExAFunc)(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
|
||||||
typedef HMODULE (WINAPI *LoadLibraryExWFunc)(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags);
|
|
||||||
|
|
||||||
class AntiHookingProtection
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void enable()
|
|
||||||
{
|
|
||||||
DetourTransactionBegin();
|
|
||||||
DetourUpdateThread(GetCurrentThread());
|
|
||||||
|
|
||||||
s_RealLoadLibraryA = LoadLibraryA;
|
|
||||||
DetourAttach(&(PVOID&)s_RealLoadLibraryA, LoadLibraryAHook);
|
|
||||||
|
|
||||||
s_RealLoadLibraryW = LoadLibraryW;
|
|
||||||
DetourAttach(&(PVOID&)s_RealLoadLibraryW, LoadLibraryWHook);
|
|
||||||
|
|
||||||
s_RealLoadLibraryExA = LoadLibraryExA;
|
|
||||||
DetourAttach(&(PVOID&)s_RealLoadLibraryExA, LoadLibraryExAHook);
|
|
||||||
|
|
||||||
s_RealLoadLibraryExW = LoadLibraryExW;
|
|
||||||
DetourAttach(&(PVOID&)s_RealLoadLibraryExW, LoadLibraryExWHook);
|
|
||||||
|
|
||||||
DetourTransactionCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
static void disable()
|
|
||||||
{
|
|
||||||
DetourTransactionBegin();
|
|
||||||
DetourUpdateThread(GetCurrentThread());
|
|
||||||
|
|
||||||
DetourDetach(&(PVOID&)s_RealLoadLibraryA, LoadLibraryAHook);
|
|
||||||
DetourDetach(&(PVOID&)s_RealLoadLibraryW, LoadLibraryWHook);
|
|
||||||
DetourDetach(&(PVOID&)s_RealLoadLibraryExA, LoadLibraryExAHook);
|
|
||||||
DetourDetach(&(PVOID&)s_RealLoadLibraryExW, LoadLibraryExWHook);
|
|
||||||
|
|
||||||
DetourTransactionCommit();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static bool isImageBlacklistedW(LPCWSTR lpLibFileName)
|
|
||||||
{
|
|
||||||
LPCWSTR dllName;
|
|
||||||
|
|
||||||
// If the library has a path prefixed, remove it
|
|
||||||
dllName = wcsrchr(lpLibFileName, '\\');
|
|
||||||
if (!dllName) {
|
|
||||||
// No prefix, so use the full name
|
|
||||||
dllName = lpLibFileName;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Advance past the backslash
|
|
||||||
dllName++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: We don't currently handle LoadLibrary calls where the
|
|
||||||
// library name does not include a file extension and the loader
|
|
||||||
// automatically assumes .dll.
|
|
||||||
|
|
||||||
for (int i = 0; i < ARRAYSIZE(k_BlacklistedDlls); i++) {
|
|
||||||
if (_wcsicmp(dllName, k_BlacklistedDlls[i]) == 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool isImageBlacklistedA(LPCSTR lpLibFileName)
|
|
||||||
{
|
|
||||||
int uniChars = MultiByteToWideChar(CP_THREAD_ACP, 0, lpLibFileName, -1, nullptr, 0);
|
|
||||||
if (uniChars > 0) {
|
|
||||||
PWCHAR wideBuffer = new WCHAR[uniChars];
|
|
||||||
uniChars = MultiByteToWideChar(CP_THREAD_ACP, 0,
|
|
||||||
lpLibFileName, -1,
|
|
||||||
wideBuffer, uniChars * sizeof(WCHAR));
|
|
||||||
if (uniChars > 0) {
|
|
||||||
bool ret = isImageBlacklistedW(wideBuffer);
|
|
||||||
delete[] wideBuffer;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
delete[] wideBuffer;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Error path
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static HMODULE WINAPI LoadLibraryAHook(LPCSTR lpLibFileName)
|
|
||||||
{
|
|
||||||
if (lpLibFileName && isImageBlacklistedA(lpLibFileName)) {
|
|
||||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_RealLoadLibraryA(lpLibFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HMODULE WINAPI LoadLibraryWHook(LPCWSTR lpLibFileName)
|
|
||||||
{
|
|
||||||
if (lpLibFileName && isImageBlacklistedW(lpLibFileName)) {
|
|
||||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_RealLoadLibraryW(lpLibFileName);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HMODULE WINAPI LoadLibraryExAHook(LPCSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
|
||||||
{
|
|
||||||
if (lpLibFileName && isImageBlacklistedA(lpLibFileName)) {
|
|
||||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_RealLoadLibraryExA(lpLibFileName, hFile, dwFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static HMODULE WINAPI LoadLibraryExWHook(LPCWSTR lpLibFileName, HANDLE hFile, DWORD dwFlags)
|
|
||||||
{
|
|
||||||
if (lpLibFileName && isImageBlacklistedW(lpLibFileName)) {
|
|
||||||
SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY);
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
return s_RealLoadLibraryExW(lpLibFileName, hFile, dwFlags);
|
|
||||||
}
|
|
||||||
|
|
||||||
static LoadLibraryAFunc s_RealLoadLibraryA;
|
|
||||||
static LoadLibraryWFunc s_RealLoadLibraryW;
|
|
||||||
static LoadLibraryExAFunc s_RealLoadLibraryExA;
|
|
||||||
static LoadLibraryExWFunc s_RealLoadLibraryExW;
|
|
||||||
|
|
||||||
static constexpr LPCWSTR k_BlacklistedDlls[] = {
|
|
||||||
// These A-Volute DLLs shipped with various audio driver packages improperly handle
|
|
||||||
// D3D9 exclusive fullscreen in a way that causes CreateDeviceEx() to deadlock.
|
|
||||||
// https://github.com/moonlight-stream/moonlight-qt/issues/102
|
|
||||||
L"NahimicOSD.dll", // ASUS Sonic Radar 3
|
|
||||||
L"SSAudioOSD.dll", // SteelSeries headsets
|
|
||||||
L"SS2OSD.dll", // ASUS Sonic Studio 2
|
|
||||||
L"Nahimic2OSD.dll",
|
|
||||||
L"NahimicMSIOSD.dll",
|
|
||||||
L"nhAsusPhoebusOSD.dll", // ASUS Phoebus
|
|
||||||
|
|
||||||
// This DLL has been seen in several crash reports. Some Googling
|
|
||||||
// suggests it's highly unstable and causes issues in many games.
|
|
||||||
L"EZFRD32.dll",
|
|
||||||
L"EZFRD64.dll",
|
|
||||||
|
|
||||||
// These are the older dList/AppInit DLLs for Optimus hybrid graphics DDI.
|
|
||||||
// https://docs.microsoft.com/en-us/windows-hardware/drivers/display/hybrid-system-ddi
|
|
||||||
//
|
|
||||||
// These seem to cause a crash in PresentEx() in full-screen exclusive mode.
|
|
||||||
// This block will prevent Optimus from ever using the dGPU even if the user has requested it.
|
|
||||||
// https://github.com/moonlight-stream/moonlight-qt/issues/386
|
|
||||||
//
|
|
||||||
// d3d9!CSwapChain::BltToHybridPrimary+0x200:
|
|
||||||
// 00007ffa`23f37e58 488b01 mov rax,qword ptr [rcx] ds:00000000`00000038=????????????????
|
|
||||||
// 00 0000004e`496ff4e0 00007ffa`23f39e2c d3d9!CSwapChain::BltToHybridPrimary+0x200
|
|
||||||
// 01 0000004e`496ff880 00007ffa`23ee39ce d3d9!CSwapChain::FlipToSurface+0x15c
|
|
||||||
// 02 0000004e`496ff900 00007ffa`23f4dd75 d3d9!CSwapChain::PresentMain+0x3e13e
|
|
||||||
// 03 0000004e`496ffab0 00007ffa`23f4dccd d3d9!CBaseDevice::PresentMain+0x9d
|
|
||||||
// 04 0000004e`496ffb00 00007ff7`8e31016f d3d9!CBaseDevice::PresentEx+0xbd
|
|
||||||
// 05 0000004e`496ffb50 00007ff7`8e30df1e Moonlight!DXVA2Renderer::renderFrame+0x61f [C:\moonlight-qt\app\streaming\video\ffmpeg-renderers\dxva2.cpp @ 1035]
|
|
||||||
// 06 0000004e`496ffd50 00007ff7`8e30e46a Moonlight!Pacer::renderFrame+0x3e [C:\moonlight-qt\app\streaming\video\ffmpeg-renderers\pacer\pacer.cpp @ 265]
|
|
||||||
// 07 (Inline Function) --------`-------- Moonlight!Pacer::renderLastFrameAndUnlock+0x197 [C:\moonlight-qt\app\streaming\video\ffmpeg-renderers\pacer\pacer.cpp @ 156]
|
|
||||||
// 08 0000004e`496ffda0 00007ffa`14476978 Moonlight!Pacer::renderThread+0x1ca [C:\moonlight-qt\app\streaming\video\ffmpeg-renderers\pacer\pacer.cpp @ 88]
|
|
||||||
// 09 0000004e`496ffde0 00007ffa`14476ee2 SDL2!SDL_RunThread+0x38 [C:\Users\camer\SDL\src\thread\SDL_thread.c @ 276]
|
|
||||||
// 0a 0000004e`496ffe10 00007ffa`2aae0e82 SDL2!RunThread+0x12 [C:\Users\camer\SDL\src\thread\windows\SDL_systhread.c @ 83]
|
|
||||||
// 0b 0000004e`496ffe40 00007ffa`2d627bd4 ucrtbase!thread_start<unsigned int (__cdecl*)(void *),1>+0x42
|
|
||||||
// 0c 0000004e`496ffe70 00007ffa`2da4ce51 kernel32!BaseThreadInitThunk+0x14
|
|
||||||
// 0d 0000004e`496ffea0 00000000`00000000 ntdll!RtlUserThreadStart+0x21
|
|
||||||
//
|
|
||||||
L"nvinit.dll",
|
|
||||||
L"nvinitx.dll",
|
|
||||||
|
|
||||||
// In some unknown circumstances, RTSS tries to hook in the middle of an instruction, leaving garbage
|
|
||||||
// code inside d3d9.dll that causes a crash when executed:
|
|
||||||
//
|
|
||||||
// 0:000> u
|
|
||||||
// d3d9!D3D9GetCurrentOwnershipMode+0x5d:
|
|
||||||
// 00007ff8`95b95861 9b wait
|
|
||||||
// 00007ff8`95b95862 a7 cmps dword ptr [rsi],dword ptr [rdi] <--- crash happens here
|
|
||||||
// 00007ff8`95b95863 ff ???
|
|
||||||
// 00007ff8`95b95864 bfe8ca8a00 mov edi,8ACAE8h
|
|
||||||
// 00007ff8`95b95869 00eb add bl,ch
|
|
||||||
// 00007ff8`95b9586b f1 ???
|
|
||||||
// 00007ff8`95b9586c b808000000 mov eax,8
|
|
||||||
// 00007ff8`95b95871 ebe6 jmp d3d9!D3D9GetCurrentOwnershipMode+0x55 (00007ff8`95b95859)
|
|
||||||
//
|
|
||||||
// Disassembling starting at the exact address of the attempted hook yields the intended jmp instruction
|
|
||||||
//
|
|
||||||
// 0:000> u d3d9!D3D9GetCurrentOwnershipMode+0x5c:
|
|
||||||
// 00007ff8`95b95860 e99ba7ffbf jmp 00007ff8`55b90000
|
|
||||||
//
|
|
||||||
// Since the RTSS OSD doesn't even work with DXVA2, we'll just block the hooks entirely.
|
|
||||||
L"RTSSHooks.dll",
|
|
||||||
L"RTSSHooks64.dll",
|
|
||||||
|
|
||||||
// Bandicam's Vulkan layer DLL crashes during destruction of the Vulkan swapchain
|
|
||||||
// bdcamvk64+0x10b73:
|
|
||||||
// 00007ffa`be3b0b73 498b5630 mov rdx,qword ptr [r14+30h] ds:00000000`00000030=????????????????
|
|
||||||
//
|
|
||||||
// bdcamvk64+0x10b73
|
|
||||||
// libplacebo_357!vk_sw_destroy+0x14f [D:\a\moonlight-deps\moonlight-deps\libplacebo\src\vulkan\swapchain.c @ 460]
|
|
||||||
// libplacebo_357!pl_swapchain_destroy+0x1a [D:\a\moonlight-deps\moonlight-deps\libplacebo\src\swapchain.c @ 30]
|
|
||||||
// Moonlight!PlVkRenderer::~PlVkRenderer+0x159 [D:\a\moonlight-qt\app\streaming\video\ffmpeg-renderers\plvk.cpp @ 140]
|
|
||||||
// Moonlight!PlVkRenderer::`scalar deleting destructor'+0x17
|
|
||||||
// Moonlight!FFmpegVideoDecoder::reset+0x203 [D:\a\moonlight-qt\app\streaming\video\ffmpeg.cpp @ 301]
|
|
||||||
// Moonlight!FFmpegVideoDecoder::~FFmpegVideoDecoder+0x22 [D:\a\moonlight-qt\app\streaming\video\ffmpeg.cpp @ 257]
|
|
||||||
// Moonlight!FFmpegVideoDecoder::`scalar deleting destructor'+0x17
|
|
||||||
// Moonlight!Session::getDecoderInfo+0x19a [D:\a\moonlight-qt\app\streaming\session.cpp @ 415]
|
|
||||||
// Moonlight!SystemProperties::querySdlVideoInfoInternal+0x134 [D:\a\moonlight-qt\app\backend\systemproperties.cpp @ 161]
|
|
||||||
// Moonlight!SystemProperties::querySdlVideoInfo+0x97 [D:\a\moonlight-qt\app\backend\systemproperties.cpp @ 123]
|
|
||||||
// Moonlight!SystemProperties::SystemProperties+0x4bf [D:\a\moonlight-qt\app\backend\systemproperties.cpp @ 75]
|
|
||||||
//
|
|
||||||
// https://github.com/moonlight-stream/moonlight-qt/issues/1425
|
|
||||||
// https://github.com/moonlight-stream/moonlight-qt/issues/1579
|
|
||||||
L"bdcamvk32.dll",
|
|
||||||
L"bdcamvk64.dll",
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
LoadLibraryAFunc AntiHookingProtection::s_RealLoadLibraryA;
|
|
||||||
LoadLibraryWFunc AntiHookingProtection::s_RealLoadLibraryW;
|
|
||||||
LoadLibraryExAFunc AntiHookingProtection::s_RealLoadLibraryExA;
|
|
||||||
LoadLibraryExWFunc AntiHookingProtection::s_RealLoadLibraryExW;
|
|
||||||
|
|
||||||
AH_EXPORT void AntiHookingDummyImport() {}
|
|
||||||
|
|
||||||
extern "C"
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|
||||||
{
|
|
||||||
if (DetourIsHelperProcess()) {
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (fdwReason)
|
|
||||||
{
|
|
||||||
case DLL_PROCESS_ATTACH:
|
|
||||||
DetourRestoreAfterWith();
|
|
||||||
AntiHookingProtection::enable();
|
|
||||||
DisableThreadLibraryCalls(hinstDLL);
|
|
||||||
break;
|
|
||||||
case DLL_PROCESS_DETACH:
|
|
||||||
// Ignore DLL_PROCESS_DETACH on process exit. No need to waste time
|
|
||||||
// unhooking everything if the whole process is being destroyed.
|
|
||||||
if (lpvReserved == NULL) {
|
|
||||||
AntiHookingProtection::disable();
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return TRUE;
|
|
||||||
};
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
#ifdef ANTIHOOKING_LIBRARY
|
|
||||||
#define AH_EXPORT extern "C" __declspec(dllexport)
|
|
||||||
#else
|
|
||||||
#define AH_EXPORT extern "C" __declspec(dllimport)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
AH_EXPORT void AntiHookingDummyImport();
|
|
||||||
|
|
||||||
@@ -0,0 +1,144 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source config.sh
|
||||||
|
|
||||||
|
# Number of CPUs (for make -j)
|
||||||
|
NCPU=`sysctl -n hw.ncpu`
|
||||||
|
if test x$NJOB = x; then
|
||||||
|
NJOB=$NCPU
|
||||||
|
fi
|
||||||
|
|
||||||
|
PLATFORMBASE=$(xcode-select -print-path)"/Platforms"
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( (cd -P $(dirname $0) && pwd) )
|
||||||
|
DIST_DIR_BASE=${DIST_DIR_BASE:="$SCRIPT_DIR/dist"}
|
||||||
|
|
||||||
|
if [ ! -d opus ]
|
||||||
|
then
|
||||||
|
echo "opus source directory does not exist, run sync.sh"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# PATH=${SCRIPT_DIR}/gas-preprocessor/:$PATH
|
||||||
|
|
||||||
|
for ARCH in $ARCHS
|
||||||
|
do
|
||||||
|
OPUS_DIR=opus-$ARCH
|
||||||
|
if [ ! -d $OPUS_DIR ]
|
||||||
|
then
|
||||||
|
echo "Directory $OPUS_DIR does not exist, run sync.sh"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
echo "Compiling source for $ARCH in directory $OPUS_DIR"
|
||||||
|
echo "cd $OPUS_DIR"
|
||||||
|
cd $OPUS_DIR
|
||||||
|
|
||||||
|
DIST_DIR=$DIST_DIR_BASE-$ARCH
|
||||||
|
echo "mkdir -p $DIST_DIR"
|
||||||
|
mkdir -p $DIST_DIR
|
||||||
|
CFLAGS_ARCH=$ARCH
|
||||||
|
case $ARCH in
|
||||||
|
armv7)
|
||||||
|
EXTRA_FLAGS="--with-pic --enable-fixed-point"
|
||||||
|
EXTRA_CFLAGS="-mcpu=cortex-a8 -mfpu=neon -miphoneos-version-min=7.1"
|
||||||
|
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
|
||||||
|
IOSSDK=iPhoneOS
|
||||||
|
;;
|
||||||
|
armv7s)
|
||||||
|
EXTRA_FLAGS="--with-pic --enable-fixed-point"
|
||||||
|
EXTRA_CFLAGS="-mcpu=cortex-a9 -mfpu=neon -miphoneos-version-min=7.1"
|
||||||
|
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
|
||||||
|
IOSSDK=iPhoneOS
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
CFLAGS_ARCH="arm64"
|
||||||
|
EXTRA_FLAGS="--with-pic --enable-fixed-point"
|
||||||
|
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
||||||
|
PLATFORM="${PLATFORMBASE}/iPhoneOS.platform"
|
||||||
|
IOSSDK=iPhoneOS
|
||||||
|
;;
|
||||||
|
x86_64)
|
||||||
|
EXTRA_FLAGS="--with-pic"
|
||||||
|
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
||||||
|
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
|
||||||
|
IOSSDK=iPhoneSimulator
|
||||||
|
;;
|
||||||
|
i386)
|
||||||
|
EXTRA_FLAGS="--with-pic"
|
||||||
|
EXTRA_CFLAGS="-miphoneos-version-min=7.1"
|
||||||
|
PLATFORM="${PLATFORMBASE}/iPhoneSimulator.platform"
|
||||||
|
IOSSDK=iPhoneSimulator
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "Unsupported architecture ${ARCH}"
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
echo "Configuring opus for $ARCH..."
|
||||||
|
echo "./autogen.sh"
|
||||||
|
./autogen.sh
|
||||||
|
|
||||||
|
CFLAGS="-g -O2 -pipe -arch ${CFLAGS_ARCH} \
|
||||||
|
-isysroot ${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
|
||||||
|
-I${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk/usr/include \
|
||||||
|
${EXTRA_CFLAGS}"
|
||||||
|
LDFLAGS="-arch ${CFLAGS_ARCH} \
|
||||||
|
-isysroot ${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
|
||||||
|
-L${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk/usr/lib"
|
||||||
|
|
||||||
|
echo "CFLAGS=$CFLAGS"
|
||||||
|
echo "LDFLAGS=$LDFLAGS"
|
||||||
|
|
||||||
|
export CFLAGS
|
||||||
|
export LDFLAGS
|
||||||
|
|
||||||
|
export CXXCPP="/usr/bin/cpp"
|
||||||
|
export CPP="$CXXCPP"
|
||||||
|
export CXX="/usr/bin/gcc"
|
||||||
|
export CC="/usr/bin/gcc"
|
||||||
|
export LD="/usr/bin/ld"
|
||||||
|
export AR="/usr/bin/ar"
|
||||||
|
export AS="/usr/bin/ls"
|
||||||
|
export NM="/usr/bin/nm"
|
||||||
|
export RANLIB="/usr/bin/ranlib"
|
||||||
|
export STRIP="/usr/bin/strip"
|
||||||
|
echo "./configure \
|
||||||
|
--prefix=$DIST_DIR \
|
||||||
|
--host=${ARCH}-apple-darwin \
|
||||||
|
--with-sysroot=${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
|
||||||
|
--enable-static=yes \
|
||||||
|
--enable-shared=no \
|
||||||
|
--disable-doc \
|
||||||
|
${EXTRA_FLAGS}"
|
||||||
|
|
||||||
|
./configure \
|
||||||
|
--prefix=$DIST_DIR \
|
||||||
|
--host=${ARCH}-apple-darwin \
|
||||||
|
--with-sysroot=${PLATFORM}/Developer/SDKs/${IOSSDK}.sdk \
|
||||||
|
--enable-static=yes \
|
||||||
|
--enable-shared=no \
|
||||||
|
--disable-doc \
|
||||||
|
${EXTRA_FLAGS}
|
||||||
|
|
||||||
|
echo "Installing opus for $ARCH..."
|
||||||
|
echo "make clean"
|
||||||
|
make clean
|
||||||
|
echo "make -j$NJOB V=1"
|
||||||
|
make -j$NJOB V=1
|
||||||
|
echo "make install"
|
||||||
|
make install
|
||||||
|
|
||||||
|
echo "cd $SCRIPT_DIR"
|
||||||
|
cd $SCRIPT_DIR
|
||||||
|
|
||||||
|
if [ -d $DIST_DIR/bin ]
|
||||||
|
then
|
||||||
|
rm -rf $DIST_DIR/bin
|
||||||
|
fi
|
||||||
|
if [ -d $DIST_DIR/share ]
|
||||||
|
then
|
||||||
|
rm -rf $DIST_DIR/share
|
||||||
|
fi
|
||||||
|
done
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source config.sh
|
||||||
|
|
||||||
|
for ARCH in $ARCHS
|
||||||
|
do
|
||||||
|
|
||||||
|
if [ -d dist-$ARCH ]
|
||||||
|
then
|
||||||
|
MAIN_ARCH=$ARCH
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ -z "$MAIN_ARCH" ]
|
||||||
|
then
|
||||||
|
echo "Please compile an architecture"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
OUTPUT_DIR="dist-uarch"
|
||||||
|
rm -rf $OUTPUT_DIR
|
||||||
|
|
||||||
|
mkdir -p $OUTPUT_DIR/lib $OUTPUT_DIR/include
|
||||||
|
|
||||||
|
for LIB in dist-$MAIN_ARCH/lib/*.a
|
||||||
|
do
|
||||||
|
LIB=`basename $LIB`
|
||||||
|
LIPO_CREATE=""
|
||||||
|
for ARCH in $ARCHS
|
||||||
|
do
|
||||||
|
LIPO_ARCH=$ARCH
|
||||||
|
if [ "$ARCH" = "aarch64" ];
|
||||||
|
then
|
||||||
|
LIPO_ARCH="arm64"
|
||||||
|
fi
|
||||||
|
if [ -d dist-$ARCH ]
|
||||||
|
then
|
||||||
|
LIPO_CREATE="$LIPO_CREATE-arch $LIPO_ARCH dist-$ARCH/lib/$LIB "
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
OUTPUT="$OUTPUT_DIR/lib/$LIB"
|
||||||
|
echo "Creating: $OUTPUT"
|
||||||
|
xcrun -sdk iphoneos lipo -create $LIPO_CREATE -output $OUTPUT
|
||||||
|
xcrun -sdk iphoneos lipo -info $OUTPUT
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "Copying headers from dist-$MAIN_ARCH..."
|
||||||
|
cp -R dist-$MAIN_ARCH/include/* $OUTPUT_DIR/include
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
OPUS_DIR="opus"
|
||||||
|
IOSSDK_VER=8.1
|
||||||
|
ARCHS="armv7 armv7s aarch64 i386 x86_64"
|
||||||
|
|
||||||
|
remove_arch() {
|
||||||
|
OLD_ARCHS="$ARCHS"
|
||||||
|
NEW_ARCHS=""
|
||||||
|
REMOVAL="$1"
|
||||||
|
|
||||||
|
for ARCH in $OLD_ARCHS; do
|
||||||
|
if [ "$ARCH" != "$REMOVAL" ] ; then
|
||||||
|
NEW_ARCHS="$NEW_ARCHS $ARCH"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
ARCHS=$NEW_ARCHS
|
||||||
|
}
|
||||||
|
|
||||||
|
# armv7s is only supported in iOS 6.0+
|
||||||
|
CHECK=`echo $IOSSDK_VER '>= 6.0' | bc -l`
|
||||||
|
if [ "$CHECK" = "0" ] ; then
|
||||||
|
remove_arch "armv7s"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# armv6 is not supported any more since iOS 6.0
|
||||||
|
CHECK=`echo $IOSSDK_VER '< 6.0' | bc -l`
|
||||||
|
if [ "$CHECK" = "0" ] ; then
|
||||||
|
remove_arch "armv6"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo 'Architectures to build:' $ARCHS
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
source config.sh
|
||||||
|
|
||||||
|
SCRIPT_DIR=$( (cd -P $(dirname $0) && pwd) )
|
||||||
|
DIST_DIR_BASE=${DIST_DIR_BASE:="$SCRIPT_DIR/dist"}
|
||||||
|
|
||||||
|
cd opus
|
||||||
|
git checkout master
|
||||||
|
git pull origin master
|
||||||
|
cd ..
|
||||||
|
|
||||||
|
for ARCH in $ARCHS
|
||||||
|
do
|
||||||
|
OPUS_DIR=opus-$ARCH
|
||||||
|
echo "Syncing source for $ARCH to directory $OPUS_DIR"
|
||||||
|
rsync opus/ $OPUS_DIR/ --exclude '.*' -a --delete
|
||||||
|
done
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
SYSROOT_iPHONE="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk"
|
||||||
|
SYSROOT_SIMULATOR="/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk"
|
||||||
|
CC_IPHONE="xcrun -sdk iphoneos clang"
|
||||||
|
CC_SIMULATOR="xcrun -sdk iphonesimulator clang"
|
||||||
|
function build_one {
|
||||||
|
./configure \
|
||||||
|
--prefix=$PREFIX \
|
||||||
|
--disable-ffmpeg \
|
||||||
|
--disable-ffplay \
|
||||||
|
--disable-ffprobe \
|
||||||
|
--disable-ffserver \
|
||||||
|
--disable-armv5te \
|
||||||
|
--disable-armv6 \
|
||||||
|
--disable-doc \
|
||||||
|
--disable-everything \
|
||||||
|
--disable-debug \
|
||||||
|
--enable-decoder=h264 \
|
||||||
|
--enable-avresample \
|
||||||
|
--enable-cross-compile \
|
||||||
|
--sysroot=$SYSROOT \
|
||||||
|
--target-os=darwin \
|
||||||
|
--cc="$CC" \
|
||||||
|
--extra-cflags="$CFLAGS" \
|
||||||
|
--extra-ldflags="$LDFLAGS" \
|
||||||
|
--enable-pic \
|
||||||
|
$ADDI_FLAGS
|
||||||
|
make clean && make -j4 && make install
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# armv7
|
||||||
|
function build_armv7 {
|
||||||
|
PREFIX="armv7"
|
||||||
|
SYSROOT=$SYSROOT_iPHONE
|
||||||
|
CC=$CC_IPHONE
|
||||||
|
CFLAGS="-arch armv7 -mfpu=neon -miphoneos-version-min=7.1 -fpic"
|
||||||
|
LDFLAGS="-arch armv7 -isysroot $SYSROOT_iPHONE -miphoneos-version-min=7.1"
|
||||||
|
ADDI_FLAGS="--arch=arm --cpu=cortex-a9"
|
||||||
|
build_one
|
||||||
|
}
|
||||||
|
|
||||||
|
# armv7s
|
||||||
|
function build_armv7s {
|
||||||
|
PREFIX="armv7s"
|
||||||
|
SYSROOT=$SYSROOT_iPHONE
|
||||||
|
CC=$CC_IPHONE
|
||||||
|
CFLAGS="-arch armv7s -mfpu=neon -miphoneos-version-min=7.1"
|
||||||
|
LDFLAGS="-arch armv7s -isysroot $SYSROOT_iPHONE -miphoneos-version-min=7.1"
|
||||||
|
ADDI_FLAGS="--arch=arm --cpu=cortex-a9"
|
||||||
|
build_one
|
||||||
|
}
|
||||||
|
|
||||||
|
# i386
|
||||||
|
function build_i386 {
|
||||||
|
PREFIX="i386"
|
||||||
|
SYSROOT=$SYSROOT_SIMULATOR
|
||||||
|
CC=$CC_SIMULATOR
|
||||||
|
CFLAGS="-arch i386"
|
||||||
|
LDFLAGS="-arch i386 -isysroot $SYSROOT_SIMULATOR -mios-simulator-version-min=7.1"
|
||||||
|
ADDI_FLAGS="--arch=i386 --cpu=i386 --disable-asm"
|
||||||
|
build_one
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# create fat library
|
||||||
|
function build_universal {
|
||||||
|
cd armv7/lib
|
||||||
|
for file in *.a
|
||||||
|
do
|
||||||
|
cd ../..
|
||||||
|
xcrun -sdk iphoneos lipo -output universal/lib/$file -create \
|
||||||
|
-arch armv7 armv7/lib/$file \
|
||||||
|
-arch armv7s armv7s/lib/$file \
|
||||||
|
-arch i386 i386/lib/$file
|
||||||
|
echo "Universal $file created."
|
||||||
|
cd -
|
||||||
|
done
|
||||||
|
cd ../..
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "FFmpeg directory?"
|
||||||
|
read SOURCE
|
||||||
|
|
||||||
|
cd $SOURCE
|
||||||
|
|
||||||
|
if [ "$1" = "clean" ]
|
||||||
|
then
|
||||||
|
rm -r armv7 armv7s i386 universal
|
||||||
|
make clean
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
mkdir armv7
|
||||||
|
mkdir armv7s
|
||||||
|
mkdir i386
|
||||||
|
mkdir -p universal/lib
|
||||||
|
|
||||||
|
build_armv7
|
||||||
|
build_armv7s
|
||||||
|
build_i386
|
||||||
|
build_universal
|
||||||
|
echo "Ouput files in $SOURCE/armv7 $SOURCE/armv7s $SOURCE/i386 $SOURCE/universal"
|
||||||
|
|
||||||
@@ -0,0 +1,124 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# Yay shell scripting! This script builds a static version of
|
||||||
|
# OpenSSL ${OPENSSL_VERSION} for iOS 7.0 that contains code for
|
||||||
|
# armv6, armv7, arm7s and i386.
|
||||||
|
|
||||||
|
#set -x
|
||||||
|
|
||||||
|
# Setup paths to stuff we need
|
||||||
|
|
||||||
|
OPENSSL_VERSION="1.0.1h"
|
||||||
|
|
||||||
|
DEVELOPER="/Applications/Xcode.app/Contents/Developer"
|
||||||
|
|
||||||
|
SDK_VERSION="7.1"
|
||||||
|
MIN_VERSION="7.1"
|
||||||
|
|
||||||
|
IPHONEOS_PLATFORM="${DEVELOPER}/Platforms/iPhoneOS.platform"
|
||||||
|
IPHONEOS_SDK="${IPHONEOS_PLATFORM}/Developer/SDKs/iPhoneOS.sdk"
|
||||||
|
IPHONEOS_GCC="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
|
||||||
|
|
||||||
|
IPHONESIMULATOR_PLATFORM="${DEVELOPER}/Platforms/iPhoneSimulator.platform"
|
||||||
|
IPHONESIMULATOR_SDK="${IPHONESIMULATOR_PLATFORM}/Developer/SDKs/iPhoneSimulator.sdk"
|
||||||
|
IPHONESIMULATOR_GCC="/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang"
|
||||||
|
|
||||||
|
# Make sure things actually exist
|
||||||
|
|
||||||
|
if [ ! -d "$IPHONEOS_PLATFORM" ]; then
|
||||||
|
echo "Cannot find $IPHONEOS_PLATFORM"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$IPHONEOS_SDK" ]; then
|
||||||
|
echo "Cannot find $IPHONEOS_SDK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$IPHONEOS_GCC" ]; then
|
||||||
|
echo "Cannot find $IPHONEOS_GCC"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$IPHONESIMULATOR_PLATFORM" ]; then
|
||||||
|
echo "Cannot find $IPHONESIMULATOR_PLATFORM"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -d "$IPHONESIMULATOR_SDK" ]; then
|
||||||
|
echo "Cannot find $IPHONESIMULATOR_SDK"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$IPHONESIMULATOR_GCC" ]; then
|
||||||
|
echo "Cannot find $IPHONESIMULATOR_GCC"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Clean up whatever was left from our previous build
|
||||||
|
|
||||||
|
rm -rf include lib
|
||||||
|
rm -rf /tmp/openssl-${OPENSSL_VERSION}-*
|
||||||
|
rm -rf /tmp/openssl-${OPENSSL_VERSION}-*.*-log
|
||||||
|
|
||||||
|
build()
|
||||||
|
{
|
||||||
|
TARGET=$1
|
||||||
|
ARCH=$2
|
||||||
|
GCC=$3
|
||||||
|
SDK=$4
|
||||||
|
EXTRA=$5
|
||||||
|
rm -rf "openssl-${OPENSSL_VERSION}"
|
||||||
|
tar xfz "openssl-${OPENSSL_VERSION}.tar.gz"
|
||||||
|
pushd .
|
||||||
|
cd "openssl-${OPENSSL_VERSION}"
|
||||||
|
./Configure ${TARGET} --openssldir="/tmp/openssl-${OPENSSL_VERSION}-${ARCH}" ${EXTRA} &> "/tmp/openssl-${OPENSSL_VERSION}-${ARCH}.log"
|
||||||
|
perl -i -pe 's|static volatile sig_atomic_t intr_signal|static volatile int intr_signal|' crypto/ui/ui_openssl.c
|
||||||
|
perl -i -pe "s|^CC= gcc|CC= ${GCC} -arch ${ARCH} -miphoneos-version-min=${MIN_VERSION}|g" Makefile
|
||||||
|
perl -i -pe "s|^CFLAG= (.*)|CFLAG= -isysroot ${SDK} \$1|g" Makefile
|
||||||
|
make &> "/tmp/openssl-${OPENSSL_VERSION}-${ARCH}.build-log"
|
||||||
|
make install &> "/tmp/openssl-${OPENSSL_VERSION}-${ARCH}.install-log"
|
||||||
|
popd
|
||||||
|
rm -rf "openssl-${OPENSSL_VERSION}"
|
||||||
|
}
|
||||||
|
|
||||||
|
mkdir openssl
|
||||||
|
cd openssl
|
||||||
|
if [ ! -e ${OPENSSL_VERSION}.tar.gz ]; then
|
||||||
|
echo "Downloading ${OPENSSL_VERSION}.tar.gz"
|
||||||
|
curl -O http://www.openssl.org/source/openssl-${OPENSSL_VERSION}.tar.gz
|
||||||
|
else
|
||||||
|
echo "Using ${OPENSSL_VERSION}.tar.gz"
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
build "BSD-generic32" "armv7" "${IPHONEOS_GCC}" "${IPHONEOS_SDK}" ""
|
||||||
|
build "BSD-generic32" "armv7s" "${IPHONEOS_GCC}" "${IPHONEOS_SDK}" ""
|
||||||
|
build "BSD-generic64" "arm64" "${IPHONEOS_GCC}" "${IPHONEOS_SDK}" ""
|
||||||
|
build "BSD-generic32" "i386" "${IPHONESIMULATOR_GCC}" "${IPHONESIMULATOR_SDK}" ""
|
||||||
|
build "BSD-generic64" "x86_64" "${IPHONESIMULATOR_GCC}" "${IPHONESIMULATOR_SDK}" "-DOPENSSL_NO_ASM"
|
||||||
|
|
||||||
|
#
|
||||||
|
|
||||||
|
mkdir include
|
||||||
|
cp -r /tmp/openssl-${OPENSSL_VERSION}-i386/include/openssl include/
|
||||||
|
|
||||||
|
mkdir lib
|
||||||
|
lipo \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-armv7/lib/libcrypto.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-armv7s/lib/libcrypto.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-arm64/lib/libcrypto.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-i386/lib/libcrypto.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-x86_64/lib/libcrypto.a" \
|
||||||
|
-create -output lib/libcrypto.a
|
||||||
|
lipo \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-armv7/lib/libssl.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-armv7s/lib/libssl.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-arm64/lib/libssl.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-i386/lib/libssl.a" \
|
||||||
|
"/tmp/openssl-${OPENSSL_VERSION}-x86_64/lib/libssl.a" \
|
||||||
|
-create -output lib/libssl.a
|
||||||
|
|
||||||
|
rm -rf "/tmp/openssl-${OPENSSL_VERSION}-*"
|
||||||
|
rm -rf "/tmp/openssl-${OPENSSL_VERSION}-*.*-log"
|
||||||
|
|
||||||
@@ -631,8 +631,8 @@ to attach them to the start of each source file to most effectively
|
|||||||
state the exclusion of warranty; and each file should have at least
|
state the exclusion of warranty; and each file should have at least
|
||||||
the "copyright" line and a pointer to where the full notice is found.
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
{one line to give the program's name and a brief idea of what it does.}
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
Copyright (C) {year} {name of author}
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
@@ -652,7 +652,7 @@ Also add information on how to contact you by electronic and paper mail.
|
|||||||
If the program does terminal interaction, make it output a short
|
If the program does terminal interaction, make it output a short
|
||||||
notice like this when it starts in an interactive mode:
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
{project} Copyright (C) {year} {fullname}
|
<program> Copyright (C) <year> <name of author>
|
||||||
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
This is free software, and you are welcome to redistribute it
|
This is free software, and you are welcome to redistribute it
|
||||||
under certain conditions; type `show c' for details.
|
under certain conditions; type `show c' for details.
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||||
|
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="8191" systemVersion="15A279b" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
|
||||||
|
<dependencies>
|
||||||
|
<deployment identifier="iOS"/>
|
||||||
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="8154"/>
|
||||||
|
</dependencies>
|
||||||
|
<objects>
|
||||||
|
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||||
|
<navigationController id="vV9-32-ww6">
|
||||||
|
<simulatedOrientationMetrics key="simulatedOrientationMetrics" orientation="landscapeRight"/>
|
||||||
|
<navigationBar key="navigationBar" contentMode="scaleToFill" id="y2P-aE-Haa">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="320" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<animations/>
|
||||||
|
<color key="barTintColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
</navigationBar>
|
||||||
|
<viewControllers>
|
||||||
|
<viewController id="l6V-ue-5Om">
|
||||||
|
<layoutGuides>
|
||||||
|
<viewControllerLayoutGuide type="top" id="rEZ-vx-akr"/>
|
||||||
|
<viewControllerLayoutGuide type="bottom" id="gBD-cy-cth"/>
|
||||||
|
</layoutGuides>
|
||||||
|
<view key="view" contentMode="scaleToFill" id="6lF-fc-kpK">
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<animations/>
|
||||||
|
<color key="backgroundColor" white="0.33333333333333331" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
</view>
|
||||||
|
<navigationItem key="navigationItem" id="rW0-BH-s7l">
|
||||||
|
<barButtonItem key="leftBarButtonItem" enabled="NO" id="d9R-Zo-Uml">
|
||||||
|
<button key="customView" opaque="NO" contentMode="center" contentHorizontalAlignment="center" contentVerticalAlignment="center" adjustsImageWhenDisabled="NO" lineBreakMode="middleTruncation" id="9JC-B5-BAE">
|
||||||
|
<rect key="frame" x="20" y="-1" width="109" height="46"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<animations/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="16"/>
|
||||||
|
<state key="normal" title="Moonlight" image="Logo">
|
||||||
|
<color key="titleColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
<color key="titleShadowColor" white="0.66666666666666663" alpha="1" colorSpace="calibratedWhite"/>
|
||||||
|
</state>
|
||||||
|
<variation key="widthClass=regular" preservesSuperviewLayoutMargins="NO"/>
|
||||||
|
</button>
|
||||||
|
</barButtonItem>
|
||||||
|
</navigationItem>
|
||||||
|
</viewController>
|
||||||
|
</viewControllers>
|
||||||
|
</navigationController>
|
||||||
|
</objects>
|
||||||
|
<resources>
|
||||||
|
<image name="Logo" width="32" height="32"/>
|
||||||
|
</resources>
|
||||||
|
</document>
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
//
|
||||||
|
// AppCollectionView.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppCollectionView : UICollectionView
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
//
|
||||||
|
// AppCollectionView.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 9/30/15.
|
||||||
|
// Copyright © 2015 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppCollectionView.h"
|
||||||
|
|
||||||
|
@implementation AppCollectionView
|
||||||
|
|
||||||
|
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
|
||||||
|
if ([view isKindOfClass:[UIButton class]]) {
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
return [super touchesShouldCancelInContentView:view];
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Only override drawRect: if you perform custom drawing.
|
||||||
|
// An empty implementation adversely affects performance during animation.
|
||||||
|
- (void)drawRect:(CGRect)rect {
|
||||||
|
// Drawing code
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 1/17/14.
|
||||||
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#if TARGET_OS_IPHONE
|
||||||
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
|
@interface AppDelegate : UIResponder <UIApplicationDelegate>
|
||||||
|
|
||||||
|
@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) NSManagedObjectModel *managedObjectModel;
|
||||||
|
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
|
||||||
|
|
||||||
|
- (void)saveContext;
|
||||||
|
- (NSURL *)applicationDocumentsDirectory;
|
||||||
|
- (NSURL*) getStoreURL;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,217 @@
|
|||||||
|
//
|
||||||
|
// AppDelegate.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 1/17/14.
|
||||||
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
|
||||||
|
@implementation AppDelegate
|
||||||
|
|
||||||
|
@synthesize managedObjectContext = _managedObjectContext;
|
||||||
|
@synthesize managedObjectModel = _managedObjectModel;
|
||||||
|
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
|
||||||
|
|
||||||
|
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
|
||||||
|
{
|
||||||
|
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillResignActive:(UIApplication *)application
|
||||||
|
{
|
||||||
|
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
|
||||||
|
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidEnterBackground:(UIApplication *)application
|
||||||
|
{
|
||||||
|
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
|
||||||
|
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillEnterForeground:(UIApplication *)application
|
||||||
|
{
|
||||||
|
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationDidBecomeActive:(UIApplication *)application
|
||||||
|
{
|
||||||
|
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)applicationWillTerminate:(UIApplication *)application
|
||||||
|
{
|
||||||
|
// Saves changes in the application's managed object context before the application terminates.
|
||||||
|
[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
|
||||||
|
{
|
||||||
|
NSManagedObjectContext *managedObjectContext = [self managedObjectContext];
|
||||||
|
if (managedObjectContext != nil) {
|
||||||
|
[managedObjectContext performBlock:^{
|
||||||
|
if (![managedObjectContext hasChanges]) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
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
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Core Data stack
|
||||||
|
|
||||||
|
// Returns the managed object context for the application.
|
||||||
|
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
|
||||||
|
- (NSManagedObjectContext *)managedObjectContext
|
||||||
|
{
|
||||||
|
if (_managedObjectContext != nil) {
|
||||||
|
return _managedObjectContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
|
||||||
|
if (coordinator != nil) {
|
||||||
|
_managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
|
||||||
|
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
|
||||||
|
}
|
||||||
|
return _managedObjectContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the managed object model for the application.
|
||||||
|
// If the model doesn't already exist, it is created from the application's model.
|
||||||
|
- (NSManagedObjectModel *)managedObjectModel
|
||||||
|
{
|
||||||
|
if (_managedObjectModel != nil) {
|
||||||
|
return _managedObjectModel;
|
||||||
|
}
|
||||||
|
_managedObjectModel = [NSManagedObjectModel mergedModelFromBundles:nil];
|
||||||
|
return _managedObjectModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the persistent store coordinator for the application.
|
||||||
|
// If the coordinator doesn't already exist, it is created and the application's store added to it.
|
||||||
|
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
|
||||||
|
{
|
||||||
|
if (_persistentStoreCoordinator != nil) {
|
||||||
|
return _persistentStoreCoordinator;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSError *error = nil;
|
||||||
|
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
|
||||||
|
NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
|
||||||
|
[NSNumber numberWithBool:YES], NSMigratePersistentStoresAutomaticallyOption,
|
||||||
|
[NSNumber numberWithBool:YES], NSInferMappingModelAutomaticallyOption, nil];
|
||||||
|
NSString* storeType;
|
||||||
|
|
||||||
|
#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
|
||||||
|
|
||||||
|
// We must ensure the persistent store is ready to opened
|
||||||
|
[self preparePersistentStore];
|
||||||
|
|
||||||
|
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]);
|
||||||
|
|
||||||
|
// Drop the database
|
||||||
|
[self dropDatabase];
|
||||||
|
|
||||||
|
// Try again
|
||||||
|
return [self persistentStoreCoordinator];
|
||||||
|
}
|
||||||
|
|
||||||
|
return _persistentStoreCoordinator;
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark - Application's Documents directory
|
||||||
|
|
||||||
|
// Returns the URL to the application's Documents directory.
|
||||||
|
- (NSURL *)applicationDocumentsDirectory
|
||||||
|
{
|
||||||
|
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 {
|
||||||
|
#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
|
||||||
@@ -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
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
//
|
||||||
|
// CryptoManager.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/14/14.
|
||||||
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
@interface CryptoManager : NSObject
|
||||||
|
|
||||||
|
+ (void) generateKeyPairUsingSSL;
|
||||||
|
+ (NSData*) readCertFromFile;
|
||||||
|
+ (NSData*) readKeyFromFile;
|
||||||
|
+ (NSData*) readP12FromFile;
|
||||||
|
+ (NSData*) getSignatureFromCert:(NSData*)cert;
|
||||||
|
+ (NSData*) pemToDer:(NSData*)pemCertBytes;
|
||||||
|
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN;
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN;
|
||||||
|
- (NSData*) SHA1HashData:(NSData*)data;
|
||||||
|
- (NSData*) SHA256HashData:(NSData*)data;
|
||||||
|
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key;
|
||||||
|
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key;
|
||||||
|
- (bool) verifySignature:(NSData *)data withSignature:(NSData*)signature andCert:(NSData*)cert;
|
||||||
|
- (NSData*) signData:(NSData*)data withKey:(NSData*)key;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,291 @@
|
|||||||
|
//
|
||||||
|
// CryptoManager.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/14/14.
|
||||||
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "CryptoManager.h"
|
||||||
|
#import "mkcert.h"
|
||||||
|
|
||||||
|
#include <openssl/aes.h>
|
||||||
|
#include <openssl/sha.h>
|
||||||
|
#include <openssl/x509.h>
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
|
||||||
|
@implementation CryptoManager
|
||||||
|
static const int SHA1_HASH_LENGTH = 20;
|
||||||
|
static const int SHA256_HASH_LENGTH = 32;
|
||||||
|
static NSData* key = nil;
|
||||||
|
static NSData* cert = nil;
|
||||||
|
static NSData* p12 = nil;
|
||||||
|
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA1:(NSData*)saltedPIN {
|
||||||
|
return [[self SHA1HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSData*) createAESKeyFromSaltSHA256:(NSData*)saltedPIN {
|
||||||
|
return [[self SHA256HashData:saltedPIN] subdataWithRange:NSMakeRange(0, 16)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSData*) SHA1HashData:(NSData*)data {
|
||||||
|
unsigned char sha1[SHA1_HASH_LENGTH];
|
||||||
|
SHA1([data bytes], [data length], sha1);
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSData*) aesEncrypt:(NSData*)data withKey:(NSData*)key {
|
||||||
|
AES_KEY aesKey;
|
||||||
|
AES_set_encrypt_key([key bytes], 128, &aesKey);
|
||||||
|
int size = [self getEncryptSize:data];
|
||||||
|
unsigned char* buffer = malloc(size);
|
||||||
|
unsigned char* blockRoundedBuffer = calloc(1, size);
|
||||||
|
memcpy(blockRoundedBuffer, [data bytes], [data length]);
|
||||||
|
|
||||||
|
// AES_encrypt only encrypts the first 16 bytes so iterate the entire buffer
|
||||||
|
int blockOffset = 0;
|
||||||
|
while (blockOffset < size) {
|
||||||
|
AES_encrypt(blockRoundedBuffer + blockOffset, buffer + blockOffset, &aesKey);
|
||||||
|
blockOffset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSData* encryptedData = [NSData dataWithBytes:buffer length:size];
|
||||||
|
free(buffer);
|
||||||
|
free(blockRoundedBuffer);
|
||||||
|
return encryptedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSData*) aesDecrypt:(NSData*)data withKey:(NSData*)key {
|
||||||
|
AES_KEY aesKey;
|
||||||
|
AES_set_decrypt_key([key bytes], 128, &aesKey);
|
||||||
|
unsigned char* buffer = malloc([data length]);
|
||||||
|
|
||||||
|
// AES_decrypt only decrypts the first 16 bytes so iterate the entire buffer
|
||||||
|
int blockOffset = 0;
|
||||||
|
while (blockOffset < [data length]) {
|
||||||
|
AES_decrypt([data bytes] + blockOffset, buffer + blockOffset, &aesKey);
|
||||||
|
blockOffset += 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSData* decryptedData = [NSData dataWithBytes:buffer length:[data length]];
|
||||||
|
free(buffer);
|
||||||
|
return decryptedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (int) getEncryptSize:(NSData*)data {
|
||||||
|
// the size is the length of the data ceiling to the nearest 16 bytes
|
||||||
|
return (((int)[data length] + 15) / 16) * 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData*) pemToDer:(NSData*)pemCertBytes {
|
||||||
|
X509* x509;
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
BIO_free(bio);
|
||||||
|
|
||||||
|
if (!x509) {
|
||||||
|
Log(LOG_E, @"Unable to parse certificate in memory");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_PKEY* pubKey = X509_get_pubkey(x509);
|
||||||
|
EVP_MD_CTX *mdctx = NULL;
|
||||||
|
mdctx = EVP_MD_CTX_create();
|
||||||
|
EVP_DigestVerifyInit(mdctx, NULL, EVP_sha256(), NULL, pubKey);
|
||||||
|
EVP_DigestVerifyUpdate(mdctx, [data bytes], [data length]);
|
||||||
|
int result = EVP_DigestVerifyFinal(mdctx, (unsigned char*)[signature bytes], [signature length]);
|
||||||
|
|
||||||
|
X509_free(x509);
|
||||||
|
EVP_PKEY_free(pubKey);
|
||||||
|
EVP_MD_CTX_destroy(mdctx);
|
||||||
|
|
||||||
|
return result > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSData *)signData:(NSData *)data withKey:(NSData *)key {
|
||||||
|
BIO* bio = BIO_new_mem_buf([key bytes], (int)[key length]);
|
||||||
|
|
||||||
|
EVP_PKEY* pkey;
|
||||||
|
pkey = PEM_read_bio_PrivateKey(bio, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
BIO_free(bio);
|
||||||
|
|
||||||
|
if (!pkey) {
|
||||||
|
Log(LOG_E, @"Unable to parse private key in memory!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
EVP_MD_CTX *mdctx = NULL;
|
||||||
|
mdctx = EVP_MD_CTX_create();
|
||||||
|
EVP_DigestSignInit(mdctx, NULL, EVP_sha256(), NULL, pkey);
|
||||||
|
EVP_DigestSignUpdate(mdctx, [data bytes], [data length]);
|
||||||
|
size_t slen;
|
||||||
|
EVP_DigestSignFinal(mdctx, NULL, &slen);
|
||||||
|
unsigned char* signature = malloc(slen);
|
||||||
|
int result = EVP_DigestSignFinal(mdctx, signature, &slen);
|
||||||
|
|
||||||
|
EVP_PKEY_free(pkey);
|
||||||
|
EVP_MD_CTX_destroy(mdctx);
|
||||||
|
|
||||||
|
if (result <= 0) {
|
||||||
|
free(signature);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NSData* signedData = [NSData dataWithBytes:signature length:slen];
|
||||||
|
free(signature);
|
||||||
|
|
||||||
|
return signedData;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (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 {
|
||||||
|
if (cert == nil) {
|
||||||
|
cert = [CryptoManager readCryptoObject:@"client.crt"];
|
||||||
|
}
|
||||||
|
return cert;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData*) readP12FromFile {
|
||||||
|
if (p12 == nil) {
|
||||||
|
p12 = [CryptoManager readCryptoObject:@"client.p12"];
|
||||||
|
}
|
||||||
|
return p12;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData*) readKeyFromFile {
|
||||||
|
if (key == nil) {
|
||||||
|
key = [CryptoManager readCryptoObject:@"client.key"];
|
||||||
|
}
|
||||||
|
return key;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (bool) keyPairExists {
|
||||||
|
bool keyFileExists = [CryptoManager readCryptoObject:@"client.key"] != nil;
|
||||||
|
bool p12FileExists = [CryptoManager readCryptoObject:@"client.p12"] != nil;
|
||||||
|
bool certFileExists = [CryptoManager readCryptoObject:@"client.crt"] != nil;
|
||||||
|
|
||||||
|
return keyFileExists && p12FileExists && certFileExists;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (NSData *)getSignatureFromCert:(NSData *)cert {
|
||||||
|
BIO* bio = BIO_new_mem_buf([cert bytes], (int)[cert length]);
|
||||||
|
X509* x509 = PEM_read_bio_X509(bio, NULL, NULL, NULL);
|
||||||
|
|
||||||
|
if (!x509) {
|
||||||
|
Log(LOG_E, @"Unable to parse certificate in memory!");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return [NSData dataWithBytes:x509->signature->data length:x509->signature->length];
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (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;
|
||||||
|
dispatch_once(&pred, ^{
|
||||||
|
if (![CryptoManager keyPairExists]) {
|
||||||
|
Log(LOG_I, @"Generating Certificate... ");
|
||||||
|
CertKeyPair certKeyPair = generateCertKeyPair();
|
||||||
|
|
||||||
|
NSData* certData = [CryptoManager getCertFromCertKeyPair:&certKeyPair];
|
||||||
|
NSData* p12Data = [CryptoManager getP12FromCertKeyPair:&certKeyPair];
|
||||||
|
NSData* keyData = [CryptoManager getKeyFromCertKeyPair:&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");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@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
|
||||||
@@ -0,0 +1,152 @@
|
|||||||
|
|
||||||
|
#include "mkcert.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include <openssl/pem.h>
|
||||||
|
#include <openssl/conf.h>
|
||||||
|
#include <openssl/pkcs12.h>
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
#include <openssl/engine.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static const int NUM_BITS = 2048;
|
||||||
|
static const int SERIAL = 0;
|
||||||
|
static const int NUM_YEARS = 10;
|
||||||
|
|
||||||
|
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years);
|
||||||
|
int add_ext(X509 *cert, int nid, char *value);
|
||||||
|
|
||||||
|
struct CertKeyPair generateCertKeyPair(void) {
|
||||||
|
BIO *bio_err;
|
||||||
|
X509 *x509 = NULL;
|
||||||
|
EVP_PKEY *pkey = NULL;
|
||||||
|
PKCS12 *p12 = NULL;
|
||||||
|
|
||||||
|
CRYPTO_mem_ctrl(CRYPTO_MEM_CHECK_ON);
|
||||||
|
bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
|
||||||
|
|
||||||
|
SSLeay_add_all_algorithms();
|
||||||
|
ERR_load_crypto_strings();
|
||||||
|
|
||||||
|
mkcert(&x509, &pkey, NUM_BITS, SERIAL, NUM_YEARS);
|
||||||
|
|
||||||
|
p12 = PKCS12_create("limelight", "GameStream", pkey, x509, NULL, 0, 0, 0, 0, 0);
|
||||||
|
if (p12 == NULL) {
|
||||||
|
printf("Error generating a valid PKCS12 certificate.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Debug Print statements
|
||||||
|
//RSA_print_fp(stdout, pkey->pkey.rsa, 0);
|
||||||
|
//X509_print_fp(stdout, x509);
|
||||||
|
//PEM_write_PUBKEY(stdout, pkey);
|
||||||
|
//PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL, NULL);
|
||||||
|
//PEM_write_X509(stdout, x509);
|
||||||
|
|
||||||
|
#ifndef OPENSSL_NO_ENGINE
|
||||||
|
ENGINE_cleanup();
|
||||||
|
#endif
|
||||||
|
CRYPTO_cleanup_all_ex_data();
|
||||||
|
|
||||||
|
CRYPTO_mem_leaks(bio_err);
|
||||||
|
BIO_free(bio_err);
|
||||||
|
|
||||||
|
return (CertKeyPair){x509, pkey, p12};
|
||||||
|
}
|
||||||
|
|
||||||
|
void freeCertKeyPair(struct CertKeyPair certKeyPair) {
|
||||||
|
X509_free(certKeyPair.x509);
|
||||||
|
EVP_PKEY_free(certKeyPair.pkey);
|
||||||
|
PKCS12_free(certKeyPair.p12);
|
||||||
|
}
|
||||||
|
|
||||||
|
int mkcert(X509 **x509p, EVP_PKEY **pkeyp, int bits, int serial, int years) {
|
||||||
|
X509 *x;
|
||||||
|
EVP_PKEY *pk;
|
||||||
|
RSA *rsa;
|
||||||
|
X509_NAME *name = NULL;
|
||||||
|
|
||||||
|
if (*pkeyp == NULL) {
|
||||||
|
if ((pk=EVP_PKEY_new()) == NULL) {
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
pk = *pkeyp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*x509p == NULL) {
|
||||||
|
if ((x = X509_new()) == NULL) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
x = *x509p;
|
||||||
|
}
|
||||||
|
|
||||||
|
rsa = RSA_generate_key(bits, RSA_F4, NULL, NULL);
|
||||||
|
if (!EVP_PKEY_assign_RSA(pk, rsa)) {
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
X509_set_version(x, 2);
|
||||||
|
ASN1_INTEGER_set(X509_get_serialNumber(x), serial);
|
||||||
|
X509_gmtime_adj(X509_get_notBefore(x), 0);
|
||||||
|
X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*365*years);
|
||||||
|
X509_set_pubkey(x, pk);
|
||||||
|
|
||||||
|
name = X509_get_subject_name(x);
|
||||||
|
|
||||||
|
/* This function creates and adds the entry, working out the
|
||||||
|
* correct string type and performing checks on its length.
|
||||||
|
*/
|
||||||
|
X509_NAME_add_entry_by_txt(name,"CN", MBSTRING_ASC, (unsigned char*)"NVIDIA GameStream Client", -1, -1, 0);
|
||||||
|
|
||||||
|
/* Its self signed so set the issuer name to be the same as the
|
||||||
|
* subject.
|
||||||
|
*/
|
||||||
|
X509_set_issuer_name(x, name);
|
||||||
|
|
||||||
|
/* Add various extensions: standard extensions */
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
*x509p = x;
|
||||||
|
*pkeyp = pk;
|
||||||
|
|
||||||
|
return(1);
|
||||||
|
err:
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
//
|
||||||
|
// mkcert.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/16/14.
|
||||||
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef Limelight_mkcert_h
|
||||||
|
#define Limelight_mkcert_h
|
||||||
|
|
||||||
|
#include <openssl/x509v3.h>
|
||||||
|
#include <openssl/pkcs12.h>
|
||||||
|
|
||||||
|
typedef struct CertKeyPair {
|
||||||
|
X509 *x509;
|
||||||
|
EVP_PKEY *pkey;
|
||||||
|
PKCS12 *p12;
|
||||||
|
} CertKeyPair;
|
||||||
|
|
||||||
|
struct CertKeyPair generateCertKeyPair(void);
|
||||||
|
void freeCertKeyPair(CertKeyPair);
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// DataManager.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/28/14.
|
||||||
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "AppDelegate.h"
|
||||||
|
#import "TemporaryHost.h"
|
||||||
|
#import "TemporaryApp.h"
|
||||||
|
#import "TemporarySettings.h"
|
||||||
|
|
||||||
|
@interface DataManager : NSObject
|
||||||
|
|
||||||
|
- (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;
|
||||||
|
|
||||||
|
- (NSArray*) getHosts;
|
||||||
|
- (void) updateHost:(TemporaryHost*)host;
|
||||||
|
- (void) updateAppsForExistingHost:(TemporaryHost *)host;
|
||||||
|
- (void) removeHost:(TemporaryHost*)host;
|
||||||
|
- (void) removeApp:(TemporaryApp*)app;
|
||||||
|
|
||||||
|
- (TemporarySettings*) getSettings;
|
||||||
|
|
||||||
|
- (void) updateUniqueId:(NSString*)uniqueId;
|
||||||
|
- (NSString*) getUniqueId;
|
||||||
|
|
||||||
|
@end
|
||||||
@@ -0,0 +1,236 @@
|
|||||||
|
//
|
||||||
|
// DataManager.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Diego Waxemberg on 10/28/14.
|
||||||
|
// Copyright (c) 2014 Moonlight Stream. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "DataManager.h"
|
||||||
|
#import "TemporaryApp.h"
|
||||||
|
#import "TemporarySettings.h"
|
||||||
|
|
||||||
|
@implementation DataManager {
|
||||||
|
NSManagedObjectContext *_managedObjectContext;
|
||||||
|
AppDelegate *_appDelegate;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) init {
|
||||||
|
self = [super init];
|
||||||
|
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) updateUniqueId:(NSString*)uniqueId {
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
[self retrieveSettings].uniqueId = uniqueId;
|
||||||
|
[self saveData];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSString*) getUniqueId {
|
||||||
|
__block NSString *uid;
|
||||||
|
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
uid = [self retrieveSettings].uniqueId;
|
||||||
|
}];
|
||||||
|
|
||||||
|
return uid;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) saveSettingsWithBitrate:(NSInteger)bitrate
|
||||||
|
framerate:(NSInteger)framerate
|
||||||
|
height:(NSInteger)height
|
||||||
|
width:(NSInteger)width
|
||||||
|
onscreenControls:(NSInteger)onscreenControls
|
||||||
|
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 {
|
||||||
|
NSArray* fetchedRecords = [self fetchRecords:@"Settings"];
|
||||||
|
if (fetchedRecords.count == 0) {
|
||||||
|
// create a new settings object with the default values
|
||||||
|
NSEntityDescription* entity = [NSEntityDescription entityForName:@"Settings" inManagedObjectContext:_managedObjectContext];
|
||||||
|
Settings* settings = [[Settings alloc] initWithEntity:entity insertIntoManagedObjectContext:_managedObjectContext];
|
||||||
|
|
||||||
|
return settings;
|
||||||
|
} else {
|
||||||
|
// we should only ever have 1 settings object stored
|
||||||
|
return [fetchedRecords objectAtIndex:0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) removeApp:(TemporaryApp*)app {
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
App* managedApp = [self getAppForTemporaryApp:app withAppRecords:[self fetchRecords:@"App"]];
|
||||||
|
if (managedApp != nil) {
|
||||||
|
[self->_managedObjectContext deleteObject:managedApp];
|
||||||
|
[self saveData];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) removeHost:(TemporaryHost*)host {
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
Host* managedHost = [self getHostForTemporaryHost:host withHostRecords:[self fetchRecords:@"Host"]];
|
||||||
|
if (managedHost != nil) {
|
||||||
|
[self->_managedObjectContext deleteObject:managedHost];
|
||||||
|
[self saveData];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void) saveData {
|
||||||
|
NSError* error;
|
||||||
|
if ([_managedObjectContext hasChanges] && ![_managedObjectContext save:&error]) {
|
||||||
|
Log(LOG_E, @"Unable to save hosts to database: %@", error);
|
||||||
|
}
|
||||||
|
|
||||||
|
[_appDelegate saveContext];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray*) getHosts {
|
||||||
|
__block NSMutableArray *tempHosts = [[NSMutableArray alloc] init];
|
||||||
|
|
||||||
|
[_managedObjectContext performBlockAndWait:^{
|
||||||
|
NSArray *hosts = [self fetchRecords:@"Host"];
|
||||||
|
|
||||||
|
for (Host* host in hosts) {
|
||||||
|
[tempHosts addObject:[[TemporaryHost alloc] initFromHost:host]];
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
|
||||||
|
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* fetchedRecords;
|
||||||
|
|
||||||
|
NSFetchRequest* fetchRequest = [[NSFetchRequest alloc] init];
|
||||||
|
NSEntityDescription* entity = [NSEntityDescription entityForName:entityName inManagedObjectContext:_managedObjectContext];
|
||||||
|
[fetchRequest setEntity:entity];
|
||||||
|
|
||||||
|
NSError* error;
|
||||||
|
fetchedRecords = [_managedObjectContext executeFetchRequest:fetchRequest error:&error];
|
||||||
|
//TODO: handle errors
|
||||||
|
|
||||||
|
return fetchedRecords;
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// 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 (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,40 @@
|
|||||||
|
//
|
||||||
|
// 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) BOOL online;
|
||||||
|
@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 *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,95 @@
|
|||||||
|
//
|
||||||
|
// 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";
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id) initFromHost:(Host*)host {
|
||||||
|
self = [self init];
|
||||||
|
|
||||||
|
self.address = host.address;
|
||||||
|
self.externalAddress = host.externalAddress;
|
||||||
|
self.localAddress = host.localAddress;
|
||||||
|
self.mac = host.mac;
|
||||||
|
self.name = host.name;
|
||||||
|
self.uuid = host.uuid;
|
||||||
|
self.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.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 = (NSInteger)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
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "a_button_80x80@2x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "a_button_120x120@3x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.5 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 32 KiB |
@@ -0,0 +1,112 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "60x60",
|
||||||
|
"idiom" : "iphone",
|
||||||
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
|
"scale" : "3x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"size" : "20x20",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "29x29",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-29x29@2x-1.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "40x40",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-40x40@2x-1.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"filename" : "Icon-App-76x76@1x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"size" : "76x76",
|
||||||
|
"idiom" : "ipad",
|
||||||
|
"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" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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 |
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "b_button_80x80@2x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "b_button_120x120@3x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.3 KiB |
|
After Width: | Height: | Size: 1.0 KiB |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x",
|
||||||
|
"filename" : "limelight_computer_1x.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x",
|
||||||
|
"filename" : "limelight_computer_2x.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x",
|
||||||
|
"filename" : "limelight_computer_3x.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 9.3 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 22 KiB |
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "down_61x75@2x.png",
|
||||||
|
"scale" : "1x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"filename" : "down_93x114@3x.png",
|
||||||
|
"scale" : "2x"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 455 B |
|
After Width: | Height: | Size: 3.6 KiB |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "1x",
|
||||||
|
"filename" : "L1_40x40@1x.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "2x",
|
||||||
|
"filename" : "L1_80x80@2x.png"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"idiom" : "universal",
|
||||||
|
"scale" : "3x",
|
||||||
|
"filename" : "L1_120x120@3x.png"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"version" : 1,
|
||||||
|
"author" : "xcode"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 6.3 KiB |