Compare commits
1992 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2ab6c40ff1 | ||
|
|
68bb738af2 | ||
|
|
6b968beede | ||
|
|
f68dd1bffb | ||
|
|
f92b71ca99 | ||
|
|
2b79fe2d6a | ||
|
|
44dd9af276 | ||
|
|
d3013d4f8c | ||
|
|
678524ad21 | ||
|
|
32a64481f2 | ||
|
|
1776015c6c | ||
|
|
f1c71a26e3 | ||
|
|
e78ab767d3 | ||
|
|
f01eb2f95d | ||
|
|
1450e45d97 | ||
|
|
ec8cba369c | ||
|
|
f4c248f406 | ||
|
|
f3b2a58646 | ||
|
|
c6f89c42b2 | ||
|
|
5e93cfdd9e | ||
|
|
d91d5a3ab5 | ||
|
|
907c045f33 | ||
|
|
90f189eb54 | ||
|
|
4abd5b2112 | ||
|
|
df9a665994 | ||
|
|
7a098ca0ed | ||
|
|
33716732a1 | ||
|
|
97ae594375 | ||
|
|
3f321ae9a0 | ||
|
|
161d32a7e7 | ||
|
|
d7137586a9 | ||
|
|
cd0c06ba6e | ||
|
|
899ab63d91 | ||
|
|
1097820a5a | ||
|
|
39114f91a7 | ||
|
|
4f01387edf | ||
|
|
de3e0585f1 | ||
|
|
f85f25ba82 | ||
|
|
10a2c179f9 | ||
|
|
6eea56861b | ||
|
|
21fd2064ae | ||
|
|
dcbab8e37a | ||
|
|
5677278251 | ||
|
|
a83bee993d | ||
|
|
96a31f554a | ||
|
|
d14ec6aea5 | ||
|
|
917cedf893 | ||
|
|
193dd71600 | ||
|
|
6c293a3d7f | ||
|
|
e847ddf011 | ||
|
|
7e8b448985 | ||
|
|
d1f3a87c08 | ||
|
|
9f8145e590 | ||
|
|
791efc171a | ||
|
|
144312a525 | ||
|
|
92684112ed | ||
|
|
ef114ee6cb | ||
|
|
667f209742 | ||
|
|
4ad0747c78 | ||
|
|
c5cf66402c | ||
|
|
05417049eb | ||
|
|
c7b0c46d9f | ||
|
|
df578c91ad | ||
|
|
70008c47c9 | ||
|
|
938affef32 | ||
|
|
a3c33000ee | ||
|
|
1e54b7b294 | ||
|
|
cc0dbcf3f4 | ||
|
|
c5a2cadccc | ||
|
|
9aa43416b6 | ||
|
|
8364029db8 | ||
|
|
d842d21be0 | ||
|
|
3514fd2433 | ||
|
|
6778ff27ea | ||
|
|
f32315d699 | ||
|
|
8b754b24b6 | ||
|
|
b1bee9ff38 | ||
|
|
569be2d402 | ||
|
|
78a73eac53 | ||
|
|
533cb99c33 | ||
|
|
79726940dc | ||
|
|
27c7891169 | ||
|
|
7a3a793a12 | ||
|
|
8088469eca | ||
|
|
3dcb082015 | ||
|
|
bece023028 | ||
|
|
9c4df66925 | ||
|
|
2b43ceb6c6 | ||
|
|
c143adba91 | ||
|
|
142fdc8d86 | ||
|
|
67778dcd3d | ||
|
|
ed80863eac | ||
|
|
c3fc84de12 | ||
|
|
904f83cd85 | ||
|
|
28bf100a50 | ||
|
|
accbd4e82a | ||
|
|
d7f478c154 | ||
|
|
8f7f13fea4 | ||
|
|
c82b03a74c | ||
|
|
58fb36bdb9 | ||
|
|
4297a7b0a4 | ||
|
|
1bab6d0dd7 | ||
|
|
13b85edbe2 | ||
|
|
dc53098e43 | ||
|
|
3c66feff5a | ||
|
|
218c3bc0d5 | ||
|
|
9f5eddcd13 | ||
|
|
3cba76552b | ||
|
|
e98a8b624b | ||
|
|
6c6947b01f | ||
|
|
78c91e9e5b | ||
|
|
44493ca0c4 | ||
|
|
42acf78b09 | ||
|
|
3aa9f8af18 | ||
|
|
8a32ee30a5 | ||
|
|
981dc0626b | ||
|
|
8986d14e98 | ||
|
|
5163b1a624 | ||
|
|
860aa9d6d0 | ||
|
|
64dc5212f9 | ||
|
|
6cff3214f3 | ||
|
|
fd910bd5e9 | ||
|
|
c6086bed41 | ||
|
|
1a9dfdfab8 | ||
|
|
5284cd11a9 | ||
|
|
d1a47cffad | ||
|
|
f469595eee | ||
|
|
9cfc52f114 | ||
|
|
30bfb756c2 | ||
|
|
711f85445e | ||
|
|
8aae9766e5 | ||
|
|
288b98ccbf | ||
|
|
bde50b1be8 | ||
|
|
a34dfd55be | ||
|
|
609c1d4d4c | ||
|
|
c12fe09969 | ||
|
|
bd14afe347 | ||
|
|
f445a13051 | ||
|
|
8ddf607d9f | ||
|
|
5900253b85 | ||
|
|
ccec94925f | ||
|
|
4504a9d0b5 | ||
|
|
057f98ad45 | ||
|
|
3b1c9aa026 | ||
|
|
658397dc38 | ||
|
|
0cd1c8e23e | ||
|
|
0345c1e6f8 | ||
|
|
f6c4cda0d4 | ||
|
|
39fd713b91 | ||
|
|
31d77ec580 | ||
|
|
06116382ee | ||
|
|
d2046de193 | ||
|
|
4397fe3a13 | ||
|
|
534e1fa6eb | ||
|
|
3e8cc2c670 | ||
|
|
3c565baf9d | ||
|
|
2e182e84c3 | ||
|
|
a42021655c | ||
|
|
2498a2b0bd | ||
|
|
4484411a77 | ||
|
|
61a151c803 | ||
|
|
5149c950aa | ||
|
|
18f4d846c9 | ||
|
|
db95aa250d | ||
|
|
982d1bf662 | ||
|
|
a0393e9ddf | ||
|
|
a8d6328bd4 | ||
|
|
13dab13319 | ||
|
|
c623aa0f06 | ||
|
|
79403afbe6 | ||
|
|
4c650e87fa | ||
|
|
3dde62befe | ||
|
|
8bfabbe265 | ||
|
|
e334b16aaa | ||
|
|
5626ace245 | ||
|
|
52652cb609 | ||
|
|
256f40d4f5 | ||
|
|
ef9acc54ec | ||
|
|
a9f2d25957 | ||
|
|
6fc47fbb69 | ||
|
|
9c11184238 | ||
|
|
a421c1dbfb | ||
|
|
7ec707927d | ||
|
|
837134daef | ||
|
|
4011899846 | ||
|
|
28e743ba70 | ||
|
|
a161d404ad | ||
|
|
cd607cb280 | ||
|
|
4e60ab7f53 | ||
|
|
71e7d32b08 | ||
|
|
d5e422970c | ||
|
|
871ba5a488 | ||
|
|
249e8d59cb | ||
|
|
8f4769d2ac | ||
|
|
a3ca9963a5 | ||
|
|
2d3c23876c | ||
|
|
bd8d8eef3e | ||
|
|
e786207cc2 | ||
|
|
b042095ac2 | ||
|
|
3413d1bf23 | ||
|
|
018c5ef731 | ||
|
|
fdb136f1fa | ||
|
|
9e33074735 | ||
|
|
d6d465cdf4 | ||
|
|
e76573cc1a | ||
|
|
3fa6dc71e2 | ||
|
|
6fec269844 | ||
|
|
b6004b6837 | ||
|
|
86d3b25aec | ||
|
|
8a407bfbb0 | ||
|
|
d30a590d9e | ||
|
|
f95e404be1 | ||
|
|
ffb8b4fc68 | ||
|
|
f86d6b0162 | ||
|
|
71c72ed072 | ||
|
|
a8d343e07b | ||
|
|
d020172181 | ||
|
|
e5c9f6c1fe | ||
|
|
176dc11748 | ||
|
|
c2abd02b9b | ||
|
|
12ecfdd423 | ||
|
|
67cfbfc2f3 | ||
|
|
fc83d38e67 | ||
|
|
7063c423eb | ||
|
|
36b93993cf | ||
|
|
ceffc5aa72 | ||
|
|
ccb45b6f6e | ||
|
|
d2e47e014a | ||
|
|
a5b8d7917f | ||
|
|
d0e735ee4b | ||
|
|
ece5971027 | ||
|
|
7c6b0d5c31 | ||
|
|
03151310cf | ||
|
|
baa2bc0c38 | ||
|
|
7e1b53480e | ||
|
|
6425b4f9f5 | ||
|
|
fb907f5f76 | ||
|
|
b107a1583f | ||
|
|
ced3f320eb | ||
|
|
a9d7293818 | ||
|
|
add42e9edf | ||
|
|
265ad4b96a | ||
|
|
92eeb4969f | ||
|
|
6fcddaf8fa | ||
|
|
41fd583fbc | ||
|
|
ceba6816de | ||
|
|
093cb475bb | ||
|
|
d44790b35f | ||
|
|
f8164a3dd1 | ||
|
|
c20126598f | ||
|
|
6c818bb37a | ||
|
|
8cb160b1f8 | ||
|
|
df91f3738a | ||
|
|
b5b268f606 | ||
|
|
ce6b8c94a2 | ||
|
|
6e643fe58b | ||
|
|
2bf91a0487 | ||
|
|
2775d747ac | ||
|
|
99659e4cf9 | ||
|
|
3bbcda917c | ||
|
|
7e43fb79af | ||
|
|
eb2b567da6 | ||
|
|
ab332d7b2e | ||
|
|
53e22b81ef | ||
|
|
3fc9d50adb | ||
|
|
c2da6dd45b | ||
|
|
7146f825b2 | ||
|
|
f61a5f5200 | ||
|
|
dc05dd7ca1 | ||
|
|
57dd344f3b | ||
|
|
f7f59df8aa | ||
|
|
0525a6f90f | ||
|
|
7b4305d81b | ||
|
|
94e9e93fa4 | ||
|
|
d2a1294e9a | ||
|
|
3d897f18cd | ||
|
|
68c14d1e53 | ||
|
|
48089394a5 | ||
|
|
30bd190b41 | ||
|
|
cf93cd9307 | ||
|
|
f40816e063 | ||
|
|
3759f29852 | ||
|
|
bc5555933f | ||
|
|
ead7ae8504 | ||
|
|
ad5abba8c6 | ||
|
|
61296cedd2 | ||
|
|
d9c29a2c4f | ||
|
|
f5172e6b84 | ||
|
|
544bcbe903 | ||
|
|
f35dab1b56 | ||
|
|
caee420087 | ||
|
|
e8c374113e | ||
|
|
98a241a730 | ||
|
|
be8297d6f6 | ||
|
|
09da80e9f4 | ||
|
|
df4ecf63a8 | ||
|
|
b4d1937857 | ||
|
|
0be5fbdc35 | ||
|
|
ae7e25ea65 | ||
|
|
fef45d469c | ||
|
|
e7353ec7e7 | ||
|
|
e3237f057d | ||
|
|
54d5d9d1cc | ||
|
|
31d9aebf0b | ||
|
|
5013de6770 | ||
|
|
301abac0c1 | ||
|
|
9614c48e4c | ||
|
|
c6e1ca1c22 | ||
|
|
30dc473697 | ||
|
|
65974ceabc | ||
|
|
6caf53d1c2 | ||
|
|
dee6e498d9 | ||
|
|
b3723274f7 | ||
|
|
9fb7cc796b | ||
|
|
3472208c05 | ||
|
|
fc30e1d559 | ||
|
|
cd4bb444ff | ||
|
|
e443513996 | ||
|
|
3d16f22135 | ||
|
|
6cc1ff5eeb | ||
|
|
3000b9dcde | ||
|
|
3b867462a3 | ||
|
|
b8aa9348b9 | ||
|
|
513e3a3d21 | ||
|
|
bfb0897b54 | ||
|
|
86e8b8c10d | ||
|
|
ee57c3490a | ||
|
|
77c1f54876 | ||
|
|
dc5984d0e0 | ||
|
|
7afbd4800f | ||
|
|
0720702c91 | ||
|
|
5f396e824f | ||
|
|
4f229c254c | ||
|
|
25e58df5e0 | ||
|
|
1261327fa6 | ||
|
|
09c3cc58e4 | ||
|
|
7ef31f84a7 | ||
|
|
85c2b396ce | ||
|
|
0759d72108 | ||
|
|
9b9144f25d | ||
|
|
b677e891b4 | ||
|
|
509f62f68d | ||
|
|
868bf752f3 | ||
|
|
051cdc9670 | ||
|
|
4de5c216ff | ||
|
|
ad2c7304ea | ||
|
|
4dd1309c3f | ||
|
|
541da2740d | ||
|
|
95e2bec215 | ||
|
|
72c96052b4 | ||
|
|
2ab168735f | ||
|
|
85cdf05890 | ||
|
|
bf78b7f815 | ||
|
|
ffb9874d84 | ||
|
|
228cdbe6af | ||
|
|
a303639c9e | ||
|
|
c5133f6088 | ||
|
|
27d368d48d | ||
|
|
085b599f84 | ||
|
|
3b84eb3b70 | ||
|
|
aa877a29d7 | ||
|
|
0abee77e62 | ||
|
|
114fcee2ae | ||
|
|
b488204093 | ||
|
|
322bfbaf57 | ||
|
|
2718f4c333 | ||
|
|
8c342a764b | ||
|
|
697c3f8cb9 | ||
|
|
bb292f501d | ||
|
|
723e54f74e | ||
|
|
1a8c96a3f0 | ||
|
|
a88040e4d5 | ||
|
|
47a0f46ce8 | ||
|
|
66fb352cca | ||
|
|
fd77acc217 | ||
|
|
595d1942cb | ||
|
|
b905933999 | ||
|
|
219a756abc | ||
|
|
2f76f9da89 | ||
|
|
b0b8f573bc | ||
|
|
746aa6cc0f | ||
|
|
fac610d47b | ||
|
|
93209da176 | ||
|
|
35a2a48c47 | ||
|
|
7019f6bea4 | ||
|
|
8bde47280a | ||
|
|
521c6da830 | ||
|
|
5c3e55b5b1 | ||
|
|
22dcca9832 | ||
|
|
db6c0d54cf | ||
|
|
a17abc5557 | ||
|
|
741c6f1179 | ||
|
|
43b285ef7a | ||
|
|
f4bb18b05e | ||
|
|
14885f25b4 | ||
|
|
4e16ea0f0a | ||
|
|
42a696873b | ||
|
|
cfd51db229 | ||
|
|
12f11c97ae | ||
|
|
6a78d11127 | ||
|
|
256ee7a8c7 | ||
|
|
07a51957ee | ||
|
|
37c4470f10 | ||
|
|
4dc7d1c0cd | ||
|
|
f6a85f0b0b | ||
|
|
5b8b660bd0 | ||
|
|
d9cb85df83 | ||
|
|
445e82be75 | ||
|
|
98a12c49dd | ||
|
|
b78cc7e48a | ||
|
|
ac9ce0b3ad | ||
|
|
cf2b814629 | ||
|
|
bbe7a37359 | ||
|
|
d0aa154ea6 | ||
|
|
df4616ae4a | ||
|
|
10f62db9fd | ||
|
|
5c075210d6 | ||
|
|
0cf85b0771 | ||
|
|
fa90047e52 | ||
|
|
b9f64fe19b | ||
|
|
dd072912e8 | ||
|
|
9dbdc75689 | ||
|
|
dce211dbba | ||
|
|
b4e5fa5c1b | ||
|
|
f12fa7e20a | ||
|
|
96f8f1da0c | ||
|
|
db7eec042e | ||
|
|
52aed3f8a1 | ||
|
|
cadd186f1b | ||
|
|
dd9ab16d67 | ||
|
|
d8b6aff23a | ||
|
|
b8aac3f8fc | ||
|
|
4aab97ccb1 | ||
|
|
4cd21f1e07 | ||
|
|
403f0f8c64 | ||
|
|
8c4246f2ad | ||
|
|
1859ba5ec8 | ||
|
|
54d5184255 | ||
|
|
0c5b986fc4 | ||
|
|
7b2cdd618e | ||
|
|
30bb3f1fcb | ||
|
|
b45ea66175 | ||
|
|
543c5034af | ||
|
|
c8aa7afdc6 | ||
|
|
b35bb1b50c | ||
|
|
6341be9cdf | ||
|
|
93a14a93f9 | ||
|
|
d6559e2ac9 | ||
|
|
65e6755b8b | ||
|
|
6ead9750f4 | ||
|
|
6532c7e089 | ||
|
|
8b3d934230 | ||
|
|
e2b7c30811 | ||
|
|
c8bb3c0b71 | ||
|
|
9990e8473c | ||
|
|
d765182bbb | ||
|
|
5a63d1d5a4 | ||
|
|
6d409d27ca | ||
|
|
e9c2885f34 | ||
|
|
ecb8f7362b | ||
|
|
17ccfec358 | ||
|
|
a55bb28069 | ||
|
|
a2e3dc0592 | ||
|
|
df142d4f61 | ||
|
|
fac8edd47a | ||
|
|
9a9da7b077 | ||
|
|
131441846b | ||
|
|
3ff728ab02 | ||
|
|
78bf4ef5fa | ||
|
|
318d0b3976 | ||
|
|
90a14e14f4 | ||
|
|
dea46e8d5a | ||
|
|
7e5ce623fe | ||
|
|
e17805f208 | ||
|
|
d8bcdca55a | ||
|
|
f6f2a3b366 | ||
|
|
d52c7e7a1b | ||
|
|
c4acccac14 | ||
|
|
13001c018c | ||
|
|
1b39efb694 | ||
|
|
0c343cb1c3 | ||
|
|
aead221184 | ||
|
|
16d1c9f5d6 | ||
|
|
0c464b24ad | ||
|
|
a249a630c0 | ||
|
|
f39823eac0 | ||
|
|
69de99636f | ||
|
|
afcff1fa77 | ||
|
|
9b5bae049c | ||
|
|
7a3415166e | ||
|
|
5b2b4bf13c | ||
|
|
4bd67bc298 | ||
|
|
1560749579 | ||
|
|
ed68fd4ab3 | ||
|
|
e9a9dabb49 | ||
|
|
31faafea9d | ||
|
|
6961bd61ca | ||
|
|
726fc53e62 | ||
|
|
c598686bd9 | ||
|
|
cab87e9398 | ||
|
|
680037927d | ||
|
|
ee026386e5 | ||
|
|
60f72f0ff9 | ||
|
|
debc855806 | ||
|
|
49c04ccfc7 | ||
|
|
11ba44870b | ||
|
|
f9a64d24bf | ||
|
|
e1a8dcfcc8 | ||
|
|
1ee0e29974 | ||
|
|
10e32454ef | ||
|
|
8d41e9658f | ||
|
|
086652dd50 | ||
|
|
77a9940461 | ||
|
|
9c1c180ae0 | ||
|
|
06682bd2a9 | ||
|
|
6135f0763b | ||
|
|
307964d874 | ||
|
|
f3dd50de87 | ||
|
|
c776bcc5f6 | ||
|
|
4bbc43d91a | ||
|
|
db8b5dc698 | ||
|
|
2f56c61b47 | ||
|
|
1d340e7664 | ||
|
|
ea62bc0bb2 | ||
|
|
8380c3be02 | ||
|
|
6470bcda19 | ||
|
|
2d51349d1d | ||
|
|
2f2b394d72 | ||
|
|
ba181ae9df | ||
|
|
f62546ec79 | ||
|
|
7c251fe190 | ||
|
|
1c155a0d03 | ||
|
|
8f196db778 | ||
|
|
a85455fb3f | ||
|
|
d0302d1bbe | ||
|
|
d73267df5e | ||
|
|
8bbfb5cda1 | ||
|
|
1e17d5b1cc | ||
|
|
f881917d2f | ||
|
|
99244f51b0 | ||
|
|
606d029ed9 | ||
|
|
e4b9d679fb | ||
|
|
2bf2bd8932 | ||
|
|
4a8a33ea85 | ||
|
|
ac4b83046a | ||
|
|
2a2ac35b98 | ||
|
|
8c744efd56 | ||
|
|
597e59f10d | ||
|
|
3cd07d0b54 | ||
|
|
13259225c2 | ||
|
|
7acd91331c | ||
|
|
0fdaca17a2 | ||
|
|
539c0ed171 | ||
|
|
553365b942 | ||
|
|
100308db02 | ||
|
|
ab967462e6 | ||
|
|
1bc553ea62 | ||
|
|
687ea53616 | ||
|
|
220d9528a3 | ||
|
|
fc7d3f64c0 | ||
|
|
63ab7767a3 | ||
|
|
20894d1c5e | ||
|
|
2f03d2234a | ||
|
|
dadf3d846b | ||
|
|
941a9284b9 | ||
|
|
4ee3820bd6 | ||
|
|
c155df5d79 | ||
|
|
33b70567c8 | ||
|
|
720bf51ba6 | ||
|
|
26bdb72428 | ||
|
|
90c8a1b1cf | ||
|
|
3143dbf3dc | ||
|
|
38d587aaeb | ||
|
|
fe9bafa741 | ||
|
|
8092e18158 | ||
|
|
6ed77f2a27 | ||
|
|
a73688a2be | ||
|
|
e7d327226a | ||
|
|
ae1eb9ccde | ||
|
|
860064c812 | ||
|
|
845901ab01 | ||
|
|
25f7360264 | ||
|
|
78ec7d0fe1 | ||
|
|
a1e9678b69 | ||
|
|
be5d629c13 | ||
|
|
957b399e90 | ||
|
|
5e6c164b9f | ||
|
|
5d9a889190 | ||
|
|
a9acc9c971 | ||
|
|
308010794a | ||
|
|
0ce72cbf9d | ||
|
|
6e52ab285a | ||
|
|
3da4648112 | ||
|
|
1897409476 | ||
|
|
c60d65dd8f | ||
|
|
f29949e14d | ||
|
|
75aa98ddaa | ||
|
|
06909f4f00 | ||
|
|
aca081557a | ||
|
|
a71efacd1e | ||
|
|
871063dab7 | ||
|
|
135662d6b0 | ||
|
|
a69c3c1848 | ||
|
|
50e5244e25 | ||
|
|
1c07f197de | ||
|
|
13c32111a0 | ||
|
|
28c6975732 | ||
|
|
12091fcfb1 | ||
|
|
5598826eaf | ||
|
|
3fea624cca | ||
|
|
9007dd9ab7 | ||
|
|
08166cf330 | ||
|
|
e51b6a6233 | ||
|
|
3887465d80 | ||
|
|
d84f96a571 | ||
|
|
f600e226da | ||
|
|
d775f13a03 | ||
|
|
b630afdeda | ||
|
|
c39c259078 | ||
|
|
a571c4ba33 | ||
|
|
889be6e29d | ||
|
|
d15f64ae5d | ||
|
|
a07117ea55 | ||
|
|
d0dae177cf | ||
|
|
d4db873716 | ||
|
|
de0752fd56 | ||
|
|
4204d4928b | ||
|
|
e2f6cc9c9f | ||
|
|
05de0ecec3 | ||
|
|
b05beb000f | ||
|
|
093abaad29 | ||
|
|
e84e4169f9 | ||
|
|
cd6c5cfd4c | ||
|
|
b855f2fcc2 | ||
|
|
ba69ade024 | ||
|
|
8748b2dc3f | ||
|
|
5f66af3712 | ||
|
|
31ae50b137 | ||
|
|
87e0459fcc | ||
|
|
07e58ae64f | ||
|
|
a88d18148c | ||
|
|
1cf43a9dc9 | ||
|
|
196ce8426b | ||
|
|
6a95c34a81 | ||
|
|
ea0e6d9824 | ||
|
|
14d3da0e18 | ||
|
|
b6b8fb7d73 | ||
|
|
2bca3cd247 | ||
|
|
22a353b8e3 | ||
|
|
743fa73a01 | ||
|
|
a546bfe7d9 | ||
|
|
25deae6cc7 | ||
|
|
62000670e3 | ||
|
|
ac49043fbb | ||
|
|
37a7ca7f14 | ||
|
|
4d6192adcd | ||
|
|
9f1ada898e | ||
|
|
5617521380 | ||
|
|
9835a2545d | ||
|
|
c28cefeeb0 | ||
|
|
afd5b750dc | ||
|
|
2b97b124bd | ||
|
|
d042ab87da | ||
|
|
588303b78d | ||
|
|
36704c5e18 | ||
|
|
21d747cd36 | ||
|
|
ef3494f160 | ||
|
|
2dc6c4a496 | ||
|
|
5834843b8a | ||
|
|
2777a23672 | ||
|
|
32afd92d30 | ||
|
|
762f3afb9d | ||
|
|
7fb2f15a1a | ||
|
|
7456dccd3a | ||
|
|
245f41bb7e | ||
|
|
9bfb844cfa | ||
|
|
d790d3ba3c | ||
|
|
c3dbc92766 | ||
|
|
0bd25f1e17 | ||
|
|
a4cd7411e8 | ||
|
|
bf276f6235 | ||
|
|
d916890a8f | ||
|
|
071cacc9a4 | ||
|
|
33f33323af | ||
|
|
388fae2c47 | ||
|
|
9f878b77e9 | ||
|
|
a547d2aaba | ||
|
|
c013026821 | ||
|
|
96b48a2404 | ||
|
|
9612975c2c | ||
|
|
41bfd45a2e | ||
|
|
bbdcbd1f08 | ||
|
|
6b3c525a9d | ||
|
|
83aed7051c | ||
|
|
77c6e45e65 | ||
|
|
8825393660 | ||
|
|
2b9246c6ad | ||
|
|
a9edb4de28 | ||
|
|
a076ddf38c | ||
|
|
0c809fbb40 | ||
|
|
cafc266e0b | ||
|
|
a3d020eff9 | ||
|
|
8412d94d05 | ||
|
|
d1c5bb956a | ||
|
|
70986bc120 | ||
|
|
f31fe8b865 | ||
|
|
142a9fe530 | ||
|
|
4dd2ad9b27 | ||
|
|
62f7375804 | ||
|
|
543296b5ba | ||
|
|
5fee130d00 | ||
|
|
073facea70 | ||
|
|
dbe3b6eee4 | ||
|
|
df97049647 | ||
|
|
42c5f68362 | ||
|
|
cc19e760cf | ||
|
|
0ff22a16fa | ||
|
|
47360ec906 | ||
|
|
087a9938d2 | ||
|
|
26d8e41a6b | ||
|
|
750ae1d3f3 | ||
|
|
f8a9a7a108 | ||
|
|
eb192137d6 | ||
|
|
c25b464f37 | ||
|
|
710b48d410 | ||
|
|
5e77a8199d | ||
|
|
6637db086b | ||
|
|
a271a55da7 | ||
|
|
6eeec6cbfa | ||
|
|
5e3f3b0400 | ||
|
|
923c402f69 | ||
|
|
4fed0b991c | ||
|
|
ad80acb22a | ||
|
|
bd8414f8ea | ||
|
|
2eb467c788 | ||
|
|
c436e29b89 | ||
|
|
44219d5e91 | ||
|
|
b9de3270f6 | ||
|
|
590d6faeb0 | ||
|
|
62e96e9a58 | ||
|
|
1c818ef0a0 | ||
|
|
d6ce2e3671 | ||
|
|
85b6a52662 | ||
|
|
0246082b9b | ||
|
|
3b031c6ba5 | ||
|
|
74740ca50b | ||
|
|
631baa7120 | ||
|
|
657d6edff7 | ||
|
|
737c5a9549 | ||
|
|
c5fb56f90f | ||
|
|
4cd9abe632 | ||
|
|
b67e7df38e | ||
|
|
f28c746b6b | ||
|
|
ab95027fc6 | ||
|
|
ed3bc4ab63 | ||
|
|
68064f1aa6 | ||
|
|
475ac76a5f | ||
|
|
79d4f8674c | ||
|
|
e42eed4d4c | ||
|
|
4a7042e847 | ||
|
|
7f36923eb4 | ||
|
|
2ca8d69126 | ||
|
|
70367d70c8 | ||
|
|
e068d62ac6 | ||
|
|
e6389ff5a1 | ||
|
|
b46cf57d98 | ||
|
|
6f59d71e07 | ||
|
|
f9130f42a2 | ||
|
|
faf2eeaa99 | ||
|
|
1c7de0b4ac | ||
|
|
58487e484f | ||
|
|
104075f3e0 | ||
|
|
b8097eaf2e | ||
|
|
5eb0cbc887 | ||
|
|
1a4a6f3807 | ||
|
|
a012b25335 | ||
|
|
46e8b137e9 | ||
|
|
4b25c5e8d6 | ||
|
|
2fdbae3e1f | ||
|
|
87e06793c2 | ||
|
|
8cc451a2e2 | ||
|
|
723c2c7fa9 | ||
|
|
4dd2c5cdd5 | ||
|
|
bdc257b40e | ||
|
|
4728f7c697 | ||
|
|
1c4c0fe8a1 | ||
|
|
360274a6e9 | ||
|
|
07228ff56a | ||
|
|
a61f153df7 | ||
|
|
34e91850d9 | ||
|
|
ba8e579e9b | ||
|
|
072e39c9cf | ||
|
|
8dc3f3b21a | ||
|
|
3a21241248 | ||
|
|
5c75096bcd | ||
|
|
a43b0f5253 | ||
|
|
d93271e86d | ||
|
|
4a6df9f961 | ||
|
|
a43ae2369b | ||
|
|
9a049de859 | ||
|
|
58b8398aa0 | ||
|
|
645751f680 | ||
|
|
2d3b6879f5 | ||
|
|
26c0924461 | ||
|
|
d4f801a8e9 | ||
|
|
cb1082c58c | ||
|
|
8406864963 | ||
|
|
85ef034fd0 | ||
|
|
59141f62bb | ||
|
|
d68cadba7b | ||
|
|
1207fd1f16 | ||
|
|
8aa61e230c | ||
|
|
2c7bda8a3b | ||
|
|
d58c5dd398 | ||
|
|
171da7a347 | ||
|
|
3fd70a769a | ||
|
|
4280f84535 | ||
|
|
c3d9c32615 | ||
|
|
a938b609b9 | ||
|
|
d3c7fac606 | ||
|
|
fea3f6cc72 | ||
|
|
aee5966e1c | ||
|
|
95e53ac0a0 | ||
|
|
5d11759f7d | ||
|
|
829616534e | ||
|
|
863f4d8366 | ||
|
|
bdd0c3686d | ||
|
|
91769d536d | ||
|
|
9500343d85 | ||
|
|
ef053035d0 | ||
|
|
35faafb32c | ||
|
|
f9fd868b99 | ||
|
|
8b903626c2 | ||
|
|
faf0c950fe | ||
|
|
4ecd325371 | ||
|
|
021519f295 | ||
|
|
e83685d667 | ||
|
|
81a198a76a | ||
|
|
5771d67202 | ||
|
|
b2b7974ba0 | ||
|
|
f59ca94416 | ||
|
|
22ff0d80ce | ||
|
|
5a22a0c27d | ||
|
|
287ef181ba | ||
|
|
bc63810ebd | ||
|
|
92cdea123e | ||
|
|
e4c7e343c8 | ||
|
|
6b75be183d | ||
|
|
718f6d9cef | ||
|
|
2ee43c403c | ||
|
|
24fa3f5e7b | ||
|
|
bbbda7f812 | ||
|
|
e958900380 | ||
|
|
74926c1dd3 | ||
|
|
2654888782 | ||
|
|
49597b0e9c | ||
|
|
b5ecfb4c9a | ||
|
|
07fa3764ef | ||
|
|
5acc77a163 | ||
|
|
0709878b4c | ||
|
|
662e477028 | ||
|
|
b7b7c381ee | ||
|
|
995cd95474 | ||
|
|
fe8a13f76f | ||
|
|
9252432bc0 | ||
|
|
f057f6768f | ||
|
|
806bf0be8d | ||
|
|
958506a108 | ||
|
|
e8fd771b91 | ||
|
|
fa4178fefa | ||
|
|
1af59d31b9 | ||
|
|
20758cef30 | ||
|
|
272938529d | ||
|
|
a67b7266ed | ||
|
|
75c8aecffa | ||
|
|
f26159a0e3 | ||
|
|
675e8667c2 | ||
|
|
a1a26b70bc | ||
|
|
34a7f86a07 | ||
|
|
e7311ac2f3 | ||
|
|
8d9ecc0c62 | ||
|
|
f01b991108 | ||
|
|
f80736c3d7 | ||
|
|
2c7f69cf85 | ||
|
|
348ecc1118 | ||
|
|
a9678f0ae0 | ||
|
|
461f298d2c | ||
|
|
068de7cf40 | ||
|
|
d04eb87c4f | ||
|
|
8af68db965 | ||
|
|
1cf632e98b | ||
|
|
58c11c3128 | ||
|
|
efcda95dda | ||
|
|
80d2028bac | ||
|
|
215213fc2c | ||
|
|
99d32dc0b4 | ||
|
|
0998097253 | ||
|
|
c17be5af6b | ||
|
|
b376536a3b | ||
|
|
e7edc02647 | ||
|
|
69bf835059 | ||
|
|
b97ffddfe8 | ||
|
|
6407b7c591 | ||
|
|
e14cd92d59 | ||
|
|
73cadd1798 | ||
|
|
fb9840f1f8 | ||
|
|
492aaa3375 | ||
|
|
33c5da700d | ||
|
|
48d3af7d9a | ||
|
|
9b3470eabd | ||
|
|
86a505b4f3 | ||
|
|
ed6c6296eb | ||
|
|
b27a41812f | ||
|
|
6c933d2b77 | ||
|
|
fb5610f9bd | ||
|
|
7adbd00811 | ||
|
|
1c91d19163 | ||
|
|
f491135318 | ||
|
|
a7ced00520 | ||
|
|
be3359fc67 | ||
|
|
69ed35ed71 | ||
|
|
280d35a053 | ||
|
|
eca6b9f0af | ||
|
|
aa5d05eaa4 | ||
|
|
15735552f4 | ||
|
|
d6d9dc9d95 | ||
|
|
dc57966dc3 | ||
|
|
cc9345e703 | ||
|
|
3fb8f3ec95 | ||
|
|
04ed50fb0f | ||
|
|
c9553411bb | ||
|
|
62221adf55 | ||
|
|
a6bf4746c6 | ||
|
|
72637d00e8 | ||
|
|
27d4b15925 | ||
|
|
7a77767e66 | ||
|
|
1b26621860 | ||
|
|
3db5f4d0aa | ||
|
|
b2a6e327bf | ||
|
|
9aec5fe907 | ||
|
|
fc3e0dfcd1 | ||
|
|
6513ff92a7 | ||
|
|
a0eb6d0976 | ||
|
|
7530770842 | ||
|
|
11ea72e240 | ||
|
|
c98330909a | ||
|
|
bec6fa4ad7 | ||
|
|
ac7ce73526 | ||
|
|
4c6619e6c5 | ||
|
|
e8121fdc11 | ||
|
|
21f17270a1 | ||
|
|
423cd5900e | ||
|
|
b9f535cd49 | ||
|
|
c731a82b71 | ||
|
|
e6fad97edc | ||
|
|
e228144159 | ||
|
|
9431a7b022 | ||
|
|
cd041f8574 | ||
|
|
8ba3378096 | ||
|
|
225984822d | ||
|
|
01b68db30e | ||
|
|
33fdaa5b6d | ||
|
|
70495aada1 | ||
|
|
f243f615ef | ||
|
|
6a1f5667f9 | ||
|
|
fab5f58ee0 | ||
|
|
55be8e6f52 | ||
|
|
c75b9b0d12 | ||
|
|
9b85446808 | ||
|
|
fd5d42836f | ||
|
|
4eaa82fd22 | ||
|
|
a497cc46f9 | ||
|
|
178f737971 | ||
|
|
74963bce9d | ||
|
|
33a4dbe1e5 | ||
|
|
60f32d0bce | ||
|
|
dce36d3e55 | ||
|
|
807c72b2f1 | ||
|
|
4f393553f4 | ||
|
|
91afc7b23c | ||
|
|
36d158e13e | ||
|
|
02a97b5985 | ||
|
|
b980545012 | ||
|
|
8aad152b23 | ||
|
|
74dbaade6f | ||
|
|
2deb5b7fec | ||
|
|
53677172f2 | ||
|
|
bef0ccf42a | ||
|
|
2fd5182608 | ||
|
|
7ad7caa2ae | ||
|
|
6d1710c74f | ||
|
|
233b8d0129 | ||
|
|
f55bdf07d3 | ||
|
|
6c2b532ae3 | ||
|
|
2539f294e4 | ||
|
|
b6a3ce9305 | ||
|
|
b07495aae9 | ||
|
|
686a53215d | ||
|
|
6190da1300 | ||
|
|
6fd7d8191e | ||
|
|
2ccd1cc9f0 | ||
|
|
8167bdd978 | ||
|
|
dfb3e34f7b | ||
|
|
45ee75055e | ||
|
|
5da4e321c0 | ||
|
|
e8519fecb4 | ||
|
|
ff35aa07dc | ||
|
|
06c172838c | ||
|
|
1543dd85b5 | ||
|
|
f37a1026f9 | ||
|
|
91fb7fa3d8 | ||
|
|
7b70153068 | ||
|
|
7e096ee2c5 | ||
|
|
86a90daf1b | ||
|
|
42f7df9681 | ||
|
|
2edad38c7c | ||
|
|
296ee4961e | ||
|
|
b1becddf11 | ||
|
|
667edcd9d0 | ||
|
|
b4e75bedf0 | ||
|
|
5482ef5451 | ||
|
|
a3afd5178c | ||
|
|
f1285a6dfd | ||
|
|
cf7c1afb93 | ||
|
|
f254831aa6 | ||
|
|
bd40c8649c | ||
|
|
7c53df2ed1 | ||
|
|
5ca6026787 | ||
|
|
483daa5882 | ||
|
|
e2bc92d128 | ||
|
|
5ffe3773d4 | ||
|
|
a7c68018a2 | ||
|
|
5ffb82993e | ||
|
|
07add0bd91 | ||
|
|
9a9b6fa326 | ||
|
|
ba43ec5759 | ||
|
|
008a9560fe | ||
|
|
6ff01cc72c | ||
|
|
e140a28073 | ||
|
|
de61c3b962 | ||
|
|
c46fc4531b | ||
|
|
065a9ed10f | ||
|
|
e44c0254f7 | ||
|
|
13f9f0315f | ||
|
|
1532ffe215 | ||
|
|
b24cbc68ba | ||
|
|
976fdd76c1 | ||
|
|
bbda335e02 | ||
|
|
031410c72b | ||
|
|
710def8e38 | ||
|
|
c0bda1b103 | ||
|
|
0e87ce4680 | ||
|
|
b4d594eeff | ||
|
|
ce09379bae | ||
|
|
b27fb64317 | ||
|
|
099455db25 | ||
|
|
3146bf51e6 | ||
|
|
b24a5e0662 | ||
|
|
e52ac0b187 | ||
|
|
eaa1590866 | ||
|
|
071af004bd | ||
|
|
23ab4e5e5f | ||
|
|
8e563cbccd | ||
|
|
1aee89f5ea | ||
|
|
d2dd6f7c70 | ||
|
|
e9a544fa98 | ||
|
|
fb547260d1 | ||
|
|
2065e32904 | ||
|
|
ac15581c56 | ||
|
|
9e2e882157 | ||
|
|
99ded56047 | ||
|
|
65386f52f0 | ||
|
|
5b8dce7456 | ||
|
|
de938eb621 | ||
|
|
83cc6c0835 | ||
|
|
304d78a4c8 | ||
|
|
347590751c | ||
|
|
fe4b1f96f1 | ||
|
|
9de984f7f8 | ||
|
|
b6cb9b853a | ||
|
|
50b930f283 | ||
|
|
cbeb809798 | ||
|
|
ea626368a0 | ||
|
|
c81747dd15 | ||
|
|
f8810d7caf | ||
|
|
92f54f0b59 | ||
|
|
ddce544b53 | ||
|
|
21fb7eea82 | ||
|
|
fd7eb43366 | ||
|
|
7d0ca894a4 | ||
|
|
a1add27c4c | ||
|
|
fc8194ee1e | ||
|
|
8ffcdb73e8 | ||
|
|
111528e51c | ||
|
|
5628dcf47e | ||
|
|
fb4f02cd38 | ||
|
|
d1be643c0d | ||
|
|
c9761bf6af | ||
|
|
4a47265224 | ||
|
|
f0f3017a76 | ||
|
|
d3f0b62348 | ||
|
|
6a53fb33da | ||
|
|
dcaf299864 | ||
|
|
ab2e00bc38 | ||
|
|
48d02bef15 | ||
|
|
1d67aa7bf2 | ||
|
|
e56066f721 | ||
|
|
5e3844ac13 | ||
|
|
cb4f5d454b | ||
|
|
e5c6fe1bb2 | ||
|
|
bf65a9732c | ||
|
|
1388b3219a | ||
|
|
d9e8ce22cb | ||
|
|
c85ba73371 | ||
|
|
224944528f | ||
|
|
cdcd3e77b3 | ||
|
|
ed5058a363 | ||
|
|
a670ff6d3e | ||
|
|
32f6d34904 | ||
|
|
d3ae05506d | ||
|
|
96f4394dce | ||
|
|
35567e6507 | ||
|
|
ae37e25452 | ||
|
|
c4537fe6f6 | ||
|
|
677334f5a9 | ||
|
|
3d9652ae35 | ||
|
|
a9130cb99c | ||
|
|
b1d60b5c85 | ||
|
|
99a05c56ad | ||
|
|
cfc65397b3 | ||
|
|
cd8fd1ef42 | ||
|
|
6350089e51 | ||
|
|
79f2f8cddc | ||
|
|
39fa949345 | ||
|
|
e1d7a5cbf5 | ||
|
|
f3cefaf043 | ||
|
|
b3460f3f54 | ||
|
|
8e5a67ed9f | ||
|
|
cccbcf510a | ||
|
|
a1e680fec7 | ||
|
|
1b58bd64ff | ||
|
|
196de8c758 | ||
|
|
222b777552 | ||
|
|
b5c206d3ae | ||
|
|
17ace95268 | ||
|
|
779d73f94b | ||
|
|
73307bf2e7 | ||
|
|
7623c1c5cb | ||
|
|
de568c84c2 | ||
|
|
1f5b9c6185 | ||
|
|
a5f8fd774d | ||
|
|
cc5443c38e | ||
|
|
8a86460b8f | ||
|
|
7ae9e49f51 | ||
|
|
c682d087d9 | ||
|
|
57da5c0841 | ||
|
|
a224722ae2 | ||
|
|
283ef5b163 | ||
|
|
09a188bfd9 | ||
|
|
10f086854b | ||
|
|
d67c6c37e3 | ||
|
|
136725dfb1 | ||
|
|
438895842c | ||
|
|
82b8f4f1ce | ||
|
|
0705f42cf8 | ||
|
|
cadc67ea40 | ||
|
|
054e9ecaae | ||
|
|
84fe3bfa87 | ||
|
|
2ef8403bfa | ||
|
|
1d3b2baee7 | ||
|
|
86de876b24 | ||
|
|
8a9f04f7fe | ||
|
|
98bd4dfe04 | ||
|
|
8e0e4d7c04 | ||
|
|
a5e8269c72 | ||
|
|
0acc88cde5 | ||
|
|
1e0ad1f6bf | ||
|
|
4abcb08cc9 | ||
|
|
81e7833711 | ||
|
|
3392cbbd91 | ||
|
|
e7b211f2c0 | ||
|
|
6c5bc9b4a3 | ||
|
|
cd2f65aafc | ||
|
|
3ee5093b03 | ||
|
|
6e2ad6860f | ||
|
|
8610eb84c6 | ||
|
|
a2e008347c | ||
|
|
a1ef0159e3 | ||
|
|
1c5f76635a | ||
|
|
e2a0fd7a28 | ||
|
|
5869a4ba2d | ||
|
|
ac9a93261b | ||
|
|
4b79f0047d | ||
|
|
6a789b660a | ||
|
|
0d8e44a079 | ||
|
|
f097952b42 | ||
|
|
224d511616 | ||
|
|
050c6cc4b0 | ||
|
|
bc2d23ff0d | ||
|
|
2939fadd6a | ||
|
|
ef260377c3 | ||
|
|
b9213df64b | ||
|
|
aa7694047b | ||
|
|
e2bc63217a | ||
|
|
6c5b8bcf9d | ||
|
|
e425fe3f97 | ||
|
|
6507993972 | ||
|
|
f081696f62 | ||
|
|
09157c3130 | ||
|
|
00626b1633 | ||
|
|
7e0cdbe502 | ||
|
|
ca08902d71 | ||
|
|
fad0e834d5 | ||
|
|
dc76eb6139 | ||
|
|
55e113c7a7 | ||
|
|
b62f5e079e | ||
|
|
ac1eaff6ec | ||
|
|
45f6129ae7 | ||
|
|
f3503e0026 | ||
|
|
826a654c95 | ||
|
|
08754e6ce7 | ||
|
|
3843972b05 | ||
|
|
37862f0f20 | ||
|
|
1f184f4aec | ||
|
|
db5a691693 | ||
|
|
48693250a4 | ||
|
|
570dcb6309 | ||
|
|
19e43087a8 | ||
|
|
fe0b6a1117 | ||
|
|
72851647ca | ||
|
|
1c90400081 | ||
|
|
672e18cac9 | ||
|
|
e939d667d9 | ||
|
|
8bb5a565cd | ||
|
|
7562c5751c | ||
|
|
e6e7d6dbd6 | ||
|
|
fe60c52c70 | ||
|
|
93f4590453 | ||
|
|
1098d271b8 | ||
|
|
51168169e7 | ||
|
|
d256a0e98f | ||
|
|
6717325c3f | ||
|
|
c4a0571e7a | ||
|
|
e4a06da14e | ||
|
|
36d6ead65c | ||
|
|
7eae3bc8c5 | ||
|
|
24b2198668 | ||
|
|
d29be0f460 | ||
|
|
8f93c36466 | ||
|
|
3092e5a8a5 | ||
|
|
55f95b3ac9 | ||
|
|
16218c8680 | ||
|
|
c11345c4d9 | ||
|
|
e31f0b8b0c | ||
|
|
7dd3b72a8c | ||
|
|
aeccccb33d | ||
|
|
b46a27c554 | ||
|
|
13bc15c05d | ||
|
|
cb1e644230 | ||
|
|
9bc0fada5c | ||
|
|
019aea3d63 | ||
|
|
21439108ed | ||
|
|
754b30a7a6 | ||
|
|
89d5d480d7 | ||
|
|
fbcacb590b | ||
|
|
f97ad2b2ee | ||
|
|
e70f7141be | ||
|
|
7a08ce7ece | ||
|
|
86486336ec | ||
|
|
ec2a2522aa | ||
|
|
556f9ee39c | ||
|
|
7dad662d69 | ||
|
|
2daa3eb61f | ||
|
|
3079aa1f9d | ||
|
|
28f9a0a900 | ||
|
|
a6bb3cf60a | ||
|
|
004da5d385 | ||
|
|
0368282486 | ||
|
|
4404f20cf4 | ||
|
|
faca8bc02a | ||
|
|
5e93c05095 | ||
|
|
0f4f04eaa4 | ||
|
|
2e55d561d3 | ||
|
|
76a9049739 | ||
|
|
27bfcda20d | ||
|
|
c6d1d360a3 | ||
|
|
afc1236b06 | ||
|
|
bedd5f00f8 | ||
|
|
36239895bd | ||
|
|
738583e3d4 | ||
|
|
c513478c31 | ||
|
|
a944927b56 | ||
|
|
b9a8b0d146 | ||
|
|
4d15db0134 | ||
|
|
0d1a54262c | ||
|
|
e7ef7f5159 | ||
|
|
3dc989bccb | ||
|
|
75d46efd23 | ||
|
|
b83392cb04 | ||
|
|
7640d333f4 | ||
|
|
c880099deb | ||
|
|
42f5ecd4a1 | ||
|
|
733989a284 | ||
|
|
493f74d94d | ||
|
|
3b71e2abef | ||
|
|
30cad0c5f1 | ||
|
|
3a387643b3 | ||
|
|
e6b37703da | ||
|
|
990f473bb3 | ||
|
|
cf1de78205 | ||
|
|
ccea6dd74b | ||
|
|
166b490eed | ||
|
|
efd871ad2f | ||
|
|
b78896d64e | ||
|
|
e753c924ef | ||
|
|
9dc7b5a6d9 | ||
|
|
f5d21c9cdb | ||
|
|
6ce13646da | ||
|
|
151653dd98 | ||
|
|
619cfe6a1c | ||
|
|
8acf996d90 | ||
|
|
15e432204e | ||
|
|
4b1630e1ec | ||
|
|
41e63031b0 | ||
|
|
bb86f27fdf | ||
|
|
5cf4f62610 | ||
|
|
8e10a14866 | ||
|
|
94f850a588 | ||
|
|
3882c11450 | ||
|
|
08f77c2b60 | ||
|
|
6269abbcc8 | ||
|
|
22ebe0e58f | ||
|
|
f072cbbba7 | ||
|
|
1a5b66b78d | ||
|
|
bea5973e0c | ||
|
|
0366dcf604 | ||
|
|
8211d4a1c2 | ||
|
|
fc2154ee92 | ||
|
|
76f85e6f7b | ||
|
|
81ce684b35 | ||
|
|
42bd888946 | ||
|
|
6bea346c41 | ||
|
|
8d23706354 | ||
|
|
62bfb1a273 | ||
|
|
38e86af75c | ||
|
|
607c2c5ba2 | ||
|
|
85f58eb082 | ||
|
|
54383b017e | ||
|
|
438b7b7bd0 | ||
|
|
27a40a9843 | ||
|
|
c7b0e9b05b | ||
|
|
356c829b76 | ||
|
|
ffbb5c48ed | ||
|
|
6b6c7b0920 | ||
|
|
de332a16d1 | ||
|
|
84ab3ee3af | ||
|
|
ce0d896492 | ||
|
|
eae9cb4afe | ||
|
|
459a812a54 | ||
|
|
7743647460 | ||
|
|
352ec364f0 | ||
|
|
54f684b7b3 | ||
|
|
1943b158fe | ||
|
|
a36eeb5261 | ||
|
|
a8b00faba1 | ||
|
|
bf73d0f905 | ||
|
|
193ffa06d9 | ||
|
|
9d176e35d4 | ||
|
|
cd2e8c6ef1 | ||
|
|
8461d71b52 | ||
|
|
e31cdf0df9 | ||
|
|
6f41791ea6 | ||
|
|
0bacbcd04e | ||
|
|
ffe689363f | ||
|
|
48d7fedbc0 | ||
|
|
75dff64450 | ||
|
|
f0b58c6f24 | ||
|
|
f3661b19c0 | ||
|
|
2f5106c97f | ||
|
|
0c19418e84 | ||
|
|
60c077c790 | ||
|
|
7aaa4dda22 | ||
|
|
109b3700b5 | ||
|
|
71fecf4d1f | ||
|
|
0f75c79665 | ||
|
|
9bcb01a75e | ||
|
|
4f29034f11 | ||
|
|
567bf445bf | ||
|
|
28a0c46ca7 | ||
|
|
7cc33d0f27 | ||
|
|
5fba8d773c | ||
|
|
36cd73df51 | ||
|
|
6f20889f00 | ||
|
|
8e408725e9 | ||
|
|
d053797340 | ||
|
|
c8d0f947d2 | ||
|
|
86e036c393 | ||
|
|
7652a2986b | ||
|
|
b1480167be | ||
|
|
e118e958f7 | ||
|
|
ee61dfe087 | ||
|
|
9231f420c1 | ||
|
|
0f92d021a1 | ||
|
|
cbdc3194cc | ||
|
|
993df0fd28 | ||
|
|
4294fdb0b2 | ||
|
|
082523bcea | ||
|
|
5d13c13821 | ||
|
|
21ef656e24 | ||
|
|
3c4fe8cc04 | ||
|
|
95ebd57b25 | ||
|
|
84e09aa8dd | ||
|
|
6cce3d2996 | ||
|
|
77b34fa961 | ||
|
|
024d978ae5 | ||
|
|
e0f55b9295 | ||
|
|
ccd83748f7 | ||
|
|
291ee9f86a | ||
|
|
59e4d7f0f5 | ||
|
|
4647448399 | ||
|
|
7dfe841876 | ||
|
|
34db35c36d | ||
|
|
3e9738dc66 | ||
|
|
2ecf57cdd9 | ||
|
|
c8b602038e | ||
|
|
e384fa226e | ||
|
|
cbb595ba83 | ||
|
|
fdeec0307e | ||
|
|
f084bbbf35 | ||
|
|
20d69b957f | ||
|
|
7de0a621e3 | ||
|
|
3441ea9844 | ||
|
|
83752e9349 | ||
|
|
8fdfe85b5f | ||
|
|
d4d9a85ad8 | ||
|
|
6f22452b54 | ||
|
|
a4a37d7a19 | ||
|
|
d1b1a8e490 | ||
|
|
104fe124df | ||
|
|
5bdbd74d59 | ||
|
|
e621c24270 | ||
|
|
554888318a | ||
|
|
49aaf98a7f | ||
|
|
ccdb94b06c | ||
|
|
6f7bfa71a9 | ||
|
|
fb3564fbe7 | ||
|
|
e1e365e16e | ||
|
|
5b5a18db2a | ||
|
|
3fa4dad418 | ||
|
|
0756607e32 | ||
|
|
a03be5a8a6 | ||
|
|
39c5bb95d2 | ||
|
|
4d33b089da | ||
|
|
58996b841a | ||
|
|
df03a7b3f8 | ||
|
|
ac03871174 | ||
|
|
2a086d20c6 | ||
|
|
d5cfa6d4dc | ||
|
|
f415167e59 | ||
|
|
9477db2363 | ||
|
|
8d11577ff2 | ||
|
|
037d1d9ad1 | ||
|
|
619ef2b341 | ||
|
|
f06fe76d35 | ||
|
|
eb86fdfbea | ||
|
|
c7712e2ef0 | ||
|
|
61fa770644 | ||
|
|
334bd73792 | ||
|
|
090ce262c4 | ||
|
|
d551d40886 | ||
|
|
aecfcaa8a2 | ||
|
|
61a3028788 | ||
|
|
11d048b8e3 | ||
|
|
d814a01f2a | ||
|
|
4c0916df79 | ||
|
|
e4844b9936 | ||
|
|
60aa8c527b | ||
|
|
9f7c3b8ea6 | ||
|
|
9f4f1bab39 | ||
|
|
73bd6af0f9 | ||
|
|
2aa54c5365 | ||
|
|
bc8542503d | ||
|
|
a6aea4ba58 | ||
|
|
0b41faec89 | ||
|
|
e12bd00b47 | ||
|
|
50eac9b49e | ||
|
|
e0405f1781 | ||
|
|
680d03e4d6 | ||
|
|
b4fc2e38ab | ||
|
|
16639f9d71 | ||
|
|
22f2605e25 | ||
|
|
69476b4f21 | ||
|
|
fdf92c5f3b | ||
|
|
5e22c83baa | ||
|
|
eed1a3c239 | ||
|
|
94c037821b | ||
|
|
e38e8eb636 | ||
|
|
bef8c83388 | ||
|
|
2e98324486 | ||
|
|
6e2d7445c5 | ||
|
|
90e7ace980 | ||
|
|
2b0a127fa5 | ||
|
|
07c5d3277f | ||
|
|
d1d44a4fde | ||
|
|
6837a67234 | ||
|
|
d6eb74262a | ||
|
|
403aa8c5a1 | ||
|
|
cd1148c6aa | ||
|
|
cfd26f53f0 | ||
|
|
69ad5671ed | ||
|
|
f9e0f0d257 | ||
|
|
98f3135ad3 | ||
|
|
8c9c3a91e6 | ||
|
|
7f3518333d | ||
|
|
f1f871f103 | ||
|
|
6387b52896 | ||
|
|
077e95da85 | ||
|
|
7f6e1fbc8d | ||
|
|
06827cfcf1 | ||
|
|
6dc3097998 | ||
|
|
cd35271698 | ||
|
|
7b575f61d0 | ||
|
|
400e3ea649 | ||
|
|
622d871587 | ||
|
|
63d04645c7 | ||
|
|
3f4908c363 | ||
|
|
dd0f1d9d2d | ||
|
|
b31d171ae8 | ||
|
|
085f06594c | ||
|
|
ce3d41052c | ||
|
|
44f3df697f | ||
|
|
28c75b2283 | ||
|
|
b6e56119c4 | ||
|
|
a0e29b5435 | ||
|
|
65ff72cdf8 | ||
|
|
1da0956331 | ||
|
|
983078992d | ||
|
|
81059f80d8 | ||
|
|
a261442279 | ||
|
|
2f41eba100 | ||
|
|
91a6fb81c1 | ||
|
|
c95f0820bc | ||
|
|
830a1bd130 | ||
|
|
5c5ea8a254 | ||
|
|
5222c684d3 | ||
|
|
5798faa13b | ||
|
|
a062693875 | ||
|
|
6887d5d347 | ||
|
|
39c9669445 | ||
|
|
44565e22a0 | ||
|
|
ddec10d494 | ||
|
|
758e969cb6 | ||
|
|
a9a6a5041b | ||
|
|
59dd8ffbc6 | ||
|
|
8f9fe1b11a | ||
|
|
9ed0152cf2 | ||
|
|
250332a8d5 | ||
|
|
39825c6622 | ||
|
|
cee3070ca4 | ||
|
|
cd08e5c7da | ||
|
|
dd4beea44c | ||
|
|
5b48d59769 | ||
|
|
4dec12fcfc | ||
|
|
57ad3aca8e | ||
|
|
f677f42be7 | ||
|
|
a5760670ef | ||
|
|
f04a3ec201 | ||
|
|
f402c5fe3c | ||
|
|
9352e25392 | ||
|
|
1c90b0c19d | ||
|
|
cd776ff1a8 | ||
|
|
40a587bbaf | ||
|
|
818d729d8b | ||
|
|
dd5daa0767 | ||
|
|
ef5090c397 | ||
|
|
cf073de36c | ||
|
|
f16054639b | ||
|
|
b0983e8708 | ||
|
|
0febb218ed | ||
|
|
dfcfeeb550 | ||
|
|
820debf45a | ||
|
|
c19292c036 | ||
|
|
4ee81e6a3d | ||
|
|
87a8a3e22f | ||
|
|
e9125ef8e4 | ||
|
|
6ff394bcc9 | ||
|
|
7ce96585f5 | ||
|
|
41cc31c124 | ||
|
|
605af61a0f | ||
|
|
77e163e5b8 | ||
|
|
0e00b9009d | ||
|
|
a6dd998d31 | ||
|
|
cdd0ccc67a | ||
|
|
a918821868 | ||
|
|
c637b96f10 | ||
|
|
44b9197354 | ||
|
|
7a8f96b1dd | ||
|
|
f4f21f462d | ||
|
|
d09b8b5bd7 | ||
|
|
ee327db517 | ||
|
|
90a61b6bab | ||
|
|
00583bc4a8 | ||
|
|
2d06a8e880 | ||
|
|
e1a434edbc | ||
|
|
6b3b1cbd99 | ||
|
|
4dd861ee23 | ||
|
|
4f0f81a047 | ||
|
|
e3908c8de6 | ||
|
|
81c49fba03 | ||
|
|
eb174d5ba3 | ||
|
|
4c899e9c5a | ||
|
|
00b0f6ad51 | ||
|
|
fe1e467a49 | ||
|
|
73cb538d72 | ||
|
|
64b9e7fd48 | ||
|
|
12de22d3bb | ||
|
|
821bc6d777 | ||
|
|
6e66a5b77b | ||
|
|
cf5c10bbe6 | ||
|
|
4e30e74739 | ||
|
|
42890b9acf | ||
|
|
33a27379f9 | ||
|
|
0cf57cc7ca | ||
|
|
68fcbaf4c8 | ||
|
|
9c83d3c78c | ||
|
|
676dfabc91 | ||
|
|
60e6d1d61b | ||
|
|
975e275030 | ||
|
|
afcd5670e3 | ||
|
|
b17b53955c | ||
|
|
ff2b427cc1 | ||
|
|
a62fe30546 | ||
|
|
25ebb427da | ||
|
|
c5bde10b4f | ||
|
|
e582e893cc | ||
|
|
833ec3d3cd | ||
|
|
3d446d3266 | ||
|
|
e660229c40 | ||
|
|
ee6e0e16cb | ||
|
|
eb1733609a | ||
|
|
e2e66404d5 | ||
|
|
3ecb19d0f1 | ||
|
|
fd02c87fa2 | ||
|
|
63ac81c8f5 | ||
|
|
557bee61d5 | ||
|
|
8bfb88840b | ||
|
|
593bb5a8a7 | ||
|
|
822ac7b100 | ||
|
|
cc70c5c67d | ||
|
|
ae7e1a22cb | ||
|
|
16944b5397 | ||
|
|
72e44d596f | ||
|
|
8f2ca8f085 | ||
|
|
6725c2afa1 | ||
|
|
e9d4b73cc3 | ||
|
|
929ec70512 | ||
|
|
6cd5d73607 | ||
|
|
80a7e1ea7d | ||
|
|
0d3b26b3aa | ||
|
|
52acea7b1f | ||
|
|
e9b49a43e2 | ||
|
|
4fa5538e2b | ||
|
|
84e74173de | ||
|
|
6cdb2a4896 | ||
|
|
d8bef3270d | ||
|
|
a33db8fe6f | ||
|
|
1c3f5517fa | ||
|
|
10972da060 | ||
|
|
a38f02541d | ||
|
|
fdba76ba47 | ||
|
|
f900ab0121 | ||
|
|
f80ab6a7a2 | ||
|
|
6ed209bbf3 | ||
|
|
fe85fa3bea | ||
|
|
76b7882f33 | ||
|
|
bf0ab2d44c | ||
|
|
bcbfa560e9 | ||
|
|
8b366f0795 | ||
|
|
aa08f9692c | ||
|
|
288ba84939 | ||
|
|
4c74016b1a | ||
|
|
1d8544ef3b | ||
|
|
91a12f76cd | ||
|
|
f4627acc48 | ||
|
|
2b1194d574 | ||
|
|
e8debd2e45 | ||
|
|
1caa41a623 | ||
|
|
bf59635280 | ||
|
|
5d6f75aaef | ||
|
|
eaf0662b75 | ||
|
|
6e8ea2a2cb | ||
|
|
b043b2a761 | ||
|
|
ac7e0dfb77 | ||
|
|
05d47bb09a | ||
|
|
575a5bd0b8 | ||
|
|
ae4c189e19 | ||
|
|
362a6e6d46 | ||
|
|
c76c7c68ff | ||
|
|
59ac9d39d5 | ||
|
|
ec41caade4 | ||
|
|
06ec06cdd7 | ||
|
|
b7acf86408 | ||
|
|
58c4db925b | ||
|
|
fe0c4ff3c2 | ||
|
|
7a2af0fbf4 | ||
|
|
d83127722f | ||
|
|
dc03ad05be | ||
|
|
a62df3cb8f | ||
|
|
18e32abda9 | ||
|
|
15d29da43b | ||
|
|
8b217d5313 | ||
|
|
ac62586bad | ||
|
|
c150fd9a1c | ||
|
|
674d14879f | ||
|
|
81df45a893 | ||
|
|
c1f0708a5d | ||
|
|
153f5854e2 | ||
|
|
f532964fde | ||
|
|
efea609dc3 | ||
|
|
f3a160038d | ||
|
|
f016eef48a | ||
|
|
f649514183 | ||
|
|
afd31677dd | ||
|
|
b28710b08c | ||
|
|
712ed555e6 | ||
|
|
11fb5bc3d0 | ||
|
|
2a5feb225b | ||
|
|
970e338847 | ||
|
|
0b9f650fe2 | ||
|
|
977834179a | ||
|
|
b42732743d | ||
|
|
99e6409a67 | ||
|
|
6a0a5f9693 | ||
|
|
fe9db8b369 | ||
|
|
ca035d0e8d | ||
|
|
84c9260dc4 | ||
|
|
987c02e946 | ||
|
|
5c0bc612fe | ||
|
|
0e28b53242 | ||
|
|
5fc0ce80fc | ||
|
|
af9092df39 | ||
|
|
58a5da33c2 | ||
|
|
7077eac589 | ||
|
|
b3435ae432 | ||
|
|
a31129333c | ||
|
|
2983c2a24f | ||
|
|
412bedb697 | ||
|
|
d37811f177 | ||
|
|
d4ca853fd3 | ||
|
|
5a8d2e8057 | ||
|
|
687fc358fd | ||
|
|
c4c2da06b7 | ||
|
|
8928cd53bf | ||
|
|
ca88fc4ed3 | ||
|
|
b83a1d79b7 | ||
|
|
cec2a837cf | ||
|
|
cff47262da | ||
|
|
da83eae754 | ||
|
|
c5409d52f5 | ||
|
|
54fc8f0e8c | ||
|
|
2ea633a2f7 | ||
|
|
9a52043fad | ||
|
|
39a5be2df9 | ||
|
|
96560e317a | ||
|
|
adb27903eb | ||
|
|
51150faa39 | ||
|
|
ea96919b80 | ||
|
|
5835afb849 | ||
|
|
7f3fecbdf5 | ||
|
|
a2c6d5e148 | ||
|
|
373706c92b | ||
|
|
7afe63aa06 | ||
|
|
8fab855099 | ||
|
|
062fef36f9 | ||
|
|
fefe2df3ee | ||
|
|
90b91ead72 | ||
|
|
1e98e41381 | ||
|
|
7030e8f050 | ||
|
|
74bb514a8c | ||
|
|
46914e486c | ||
|
|
f9abc561fb | ||
|
|
2e22ff2e36 | ||
|
|
8c3be4a5f0 | ||
|
|
3fe2f7337c | ||
|
|
ec24eb1d8e | ||
|
|
ffcaf85609 | ||
|
|
d0c481e44e | ||
|
|
67e2d9f9e1 | ||
|
|
dd5aa2b483 | ||
|
|
806494a254 | ||
|
|
5c3afd020a | ||
|
|
190cdfc326 | ||
|
|
13b954c765 | ||
|
|
49f6b50ed3 | ||
|
|
0f2a304d34 | ||
|
|
a142f93dca | ||
|
|
2dfe2fb22c | ||
|
|
e8564b4c90 | ||
|
|
2fd81b4932 | ||
|
|
0cf4c6ffea | ||
|
|
25f89afbfb | ||
|
|
43f3cdcd24 | ||
|
|
3454fed324 | ||
|
|
a64ffda688 | ||
|
|
8400da9934 | ||
|
|
ae8bdd473c | ||
|
|
adfc5db3d2 | ||
|
|
3f32a6b607 | ||
|
|
21aa1631a4 | ||
|
|
49968541fd | ||
|
|
cc143105b8 | ||
|
|
fed44e95b3 | ||
|
|
71ece56470 | ||
|
|
204a1de3fd | ||
|
|
80ddf4aecf | ||
|
|
12b4a666bc | ||
|
|
cfdbaf331e | ||
|
|
052d350b19 | ||
|
|
2ca18a7ee5 | ||
|
|
7dbe5f4640 | ||
|
|
432ecd1b6a | ||
|
|
7d9aa5b716 | ||
|
|
43267dc892 | ||
|
|
3ec6c26e6c | ||
|
|
7de684668b | ||
|
|
4741d7bfe2 | ||
|
|
aea99a1222 | ||
|
|
7c8038e2da | ||
|
|
673336297d | ||
|
|
ee4b7042ce | ||
|
|
310ab7d41b | ||
|
|
fc1796f3e8 | ||
|
|
d8926ea5eb | ||
|
|
0c1e428c7d | ||
|
|
bcd97f5887 | ||
|
|
0faf86c2b9 | ||
|
|
b30957c89c | ||
|
|
dbbcbc3616 | ||
|
|
1889150013 | ||
|
|
14f9cdde6b | ||
|
|
3ab0691eec | ||
|
|
1e073a196f | ||
|
|
7b60e3916c | ||
|
|
c486c5bf5b | ||
|
|
fc0b6d143a | ||
|
|
5f4252bcd2 | ||
|
|
a588aef921 | ||
|
|
b70df57f7b | ||
|
|
e813c93e08 | ||
|
|
900c4977cc | ||
|
|
bb39fffab9 | ||
|
|
f52aefb341 | ||
|
|
aecb5630cb | ||
|
|
0f0245625a | ||
|
|
8583689fa4 | ||
|
|
7a1e026bb5 | ||
|
|
64f04ee6db | ||
|
|
5c6f538b85 | ||
|
|
00aa83a498 | ||
|
|
e44848f8c4 | ||
|
|
5ea8950a13 | ||
|
|
184557bfed | ||
|
|
b4253210d2 | ||
|
|
8e1585aa8a | ||
|
|
dee49d7488 | ||
|
|
1ecde309e4 | ||
|
|
d62a738460 | ||
|
|
0f1b1bb44d | ||
|
|
16f870aa41 | ||
|
|
16f729eb22 | ||
|
|
36f0bd432c | ||
|
|
457ab8b2ce | ||
|
|
1ebf5f3bcb | ||
|
|
a928a9640f | ||
|
|
cb302476b4 | ||
|
|
31726737df | ||
|
|
082be33cbd | ||
|
|
9aada2ef19 | ||
|
|
4066b2767b | ||
|
|
de43bddc1a | ||
|
|
6edfc56c9d | ||
|
|
5837a63942 | ||
|
|
3a28f456b1 | ||
|
|
4f6fc2675c | ||
|
|
c7da1821c3 | ||
|
|
1a8c3271da | ||
|
|
bd49e8e76f | ||
|
|
533699abe7 | ||
|
|
267ccc98d3 | ||
|
|
cd3c2fdb49 | ||
|
|
5cbc319e96 | ||
|
|
d435dcdca4 | ||
|
|
e5ab456df3 | ||
|
|
08bf4f74a9 | ||
|
|
a838a03412 | ||
|
|
ad4e597f74 | ||
|
|
ee3610a2d2 | ||
|
|
88b75b57d0 | ||
|
|
aa4c7055f8 | ||
|
|
4b70f9d213 | ||
|
|
79d2d1c201 | ||
|
|
406bda9b95 | ||
|
|
405f1dd027 | ||
|
|
51f349d504 | ||
|
|
4f201d1e85 | ||
|
|
03cfef100f | ||
|
|
ff89b491dd | ||
|
|
7552dff0e5 | ||
|
|
110589c0f3 | ||
|
|
3400398230 | ||
|
|
5c244e9a8c | ||
|
|
4e2f4e2091 | ||
|
|
e69bef3ce3 | ||
|
|
c1c0fc79bc | ||
|
|
02a77f6797 | ||
|
|
77b316cdfb | ||
|
|
2abfc7b87b | ||
|
|
050f0c3d8f | ||
|
|
90e6c727da | ||
|
|
d3d9a04e62 | ||
|
|
a66051216f | ||
|
|
0debba0f6e | ||
|
|
f2bd2c318c | ||
|
|
21c42819c7 | ||
|
|
5899a272ef | ||
|
|
27b4c62bc1 | ||
|
|
b227fddec7 | ||
|
|
2c1f1de33c | ||
|
|
c26622cf8f | ||
|
|
9e91873428 | ||
|
|
7363d50a1e | ||
|
|
15213a041d | ||
|
|
fb70a34c80 | ||
|
|
fbf76c6d21 | ||
|
|
bc00c38f9d | ||
|
|
4658bd8208 | ||
|
|
6eb1caa417 | ||
|
|
41efc1376e | ||
|
|
0f35016773 | ||
|
|
c641ca90a9 | ||
|
|
87c88fcb27 | ||
|
|
4f80a129f1 | ||
|
|
6987f2ba82 | ||
|
|
563db580ae | ||
|
|
125daea16a | ||
|
|
fd2c6b8a4b | ||
|
|
5b1db917bc | ||
|
|
849b0563ce | ||
|
|
16a99ad515 | ||
|
|
d93172bee8 | ||
|
|
25429af122 | ||
|
|
4bfd104a23 | ||
|
|
7745067d99 | ||
|
|
b19d3629b9 | ||
|
|
84c519df09 | ||
|
|
737a56a030 | ||
|
|
12b6959ea2 | ||
|
|
7519768cb1 | ||
|
|
9af470c92d | ||
|
|
ac8c1d0a01 | ||
|
|
921d01b59d | ||
|
|
8aa4a66ba0 | ||
|
|
2e7153d8d6 | ||
|
|
70b5a81a29 | ||
|
|
83fd822e8b | ||
|
|
dd3752956a | ||
|
|
bf15cac980 | ||
|
|
1a61b01315 | ||
|
|
c643b6ff16 | ||
|
|
b3f5b4932c | ||
|
|
b3f5f2f75f | ||
|
|
62288907dd | ||
|
|
cdbdcec715 | ||
|
|
ccf78448aa | ||
|
|
ed001e0cfb | ||
|
|
26382713c2 | ||
|
|
f37481f843 | ||
|
|
c3f6502be2 | ||
|
|
0120f396ac | ||
|
|
231fffe594 | ||
|
|
e67afc35b8 | ||
|
|
5e73007b1d | ||
|
|
2d9876a261 | ||
|
|
303d67aed2 | ||
|
|
575fbad254 | ||
|
|
fa0aa91bf9 | ||
|
|
3e641e2147 | ||
|
|
de7e4f0db7 | ||
|
|
a1cb1d78bd | ||
|
|
1178f2c1ab | ||
|
|
76f277eeb4 | ||
|
|
4000390dcd |
5
.gitignore
vendored
5
.gitignore
vendored
@@ -35,7 +35,8 @@ tags
|
|||||||
/mkinstalldirs
|
/mkinstalldirs
|
||||||
/build
|
/build
|
||||||
/src/mpd
|
/src/mpd
|
||||||
/systemd/mpd.service
|
/systemd/system/mpd.service
|
||||||
|
/systemd/user/mpd.service
|
||||||
/stamp-h1
|
/stamp-h1
|
||||||
|
|
||||||
/src/dsd2pcm/dsd2pcm
|
/src/dsd2pcm/dsd2pcm
|
||||||
@@ -83,3 +84,5 @@ tags
|
|||||||
/*.tar.bz2
|
/*.tar.bz2
|
||||||
/*.tar.xz
|
/*.tar.xz
|
||||||
/mpd-*/
|
/mpd-*/
|
||||||
|
|
||||||
|
__pycache__/
|
||||||
|
|||||||
5
AUTHORS
5
AUTHORS
@@ -1,11 +1,11 @@
|
|||||||
Music Player Daemon - http://www.musicpd.org
|
Music Player Daemon - http://www.musicpd.org
|
||||||
Copyright (C) 2003-2014 The Music Player Daemon Project
|
Copyright 2003-2017 The Music Player Daemon Project
|
||||||
|
|
||||||
The following people have contributed code to MPD:
|
The following people have contributed code to MPD:
|
||||||
|
|
||||||
Warren Dukes <warren.dukes@gmail.com>
|
Warren Dukes <warren.dukes@gmail.com>
|
||||||
Avuton Olrich <avuton@gmail.com>
|
Avuton Olrich <avuton@gmail.com>
|
||||||
Max Kellermann <max@duempel.org>
|
Max Kellermann <max.kellermann@gmail.com>
|
||||||
Laszlo Ashin <kodest@gmail.com>
|
Laszlo Ashin <kodest@gmail.com>
|
||||||
Viliam Mateicka <viliam.mateicka@gmail.com>
|
Viliam Mateicka <viliam.mateicka@gmail.com>
|
||||||
Eric Wollesen <encoded@xmtp.net>
|
Eric Wollesen <encoded@xmtp.net>
|
||||||
@@ -29,3 +29,4 @@ The following people have contributed code to MPD:
|
|||||||
Denis Krjuchkov <denis@crazydev.net>
|
Denis Krjuchkov <denis@crazydev.net>
|
||||||
Jurgen Kramer <gtmkramer@xs4all.nl>
|
Jurgen Kramer <gtmkramer@xs4all.nl>
|
||||||
Jean-Francois Dockes <jf@dockes.org>
|
Jean-Francois Dockes <jf@dockes.org>
|
||||||
|
Yue Wang <yuleopen@gmail.com>
|
||||||
|
|||||||
5
INSTALL
5
INSTALL
@@ -12,15 +12,12 @@ install MPD. If more information is desired, read the user manual:
|
|||||||
Dependencies
|
Dependencies
|
||||||
------------
|
------------
|
||||||
|
|
||||||
gcc 4.6 or later - http://gcc.gnu.org/
|
gcc 4.7 or later - http://gcc.gnu.org/
|
||||||
clang 3.2 or later - http://clang.llvm.org/
|
clang 3.2 or later - http://clang.llvm.org/
|
||||||
Any other C++11 compliant compiler should also work.
|
Any other C++11 compliant compiler should also work.
|
||||||
|
|
||||||
Boost 1.46 - http://www.boost.org/
|
Boost 1.46 - http://www.boost.org/
|
||||||
|
|
||||||
GLib 2.28 - http://www.gtk.org/
|
|
||||||
General-purpose utility library.
|
|
||||||
|
|
||||||
|
|
||||||
Optional Output Dependencies
|
Optional Output Dependencies
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|||||||
734
Makefile.am
734
Makefile.am
File diff suppressed because it is too large
Load Diff
192
NEWS
192
NEWS
@@ -1,3 +1,195 @@
|
|||||||
|
ver 0.20.3 (2017/01/25)
|
||||||
|
* protocol
|
||||||
|
- "playlistadd" creates new playlist if it does not exist, as documented
|
||||||
|
* database
|
||||||
|
- proxy: fix error "terminate called after throwing ..."
|
||||||
|
- proxy: make connect errors during startup non-fatal
|
||||||
|
* neighbor
|
||||||
|
- upnp: fix premature expiry
|
||||||
|
* replay gain: don't reset ReplayGain levels when unpausing playback
|
||||||
|
* silence surround channels when converting from stereo
|
||||||
|
* use shortcuts such as "dsd64" in log messages
|
||||||
|
|
||||||
|
ver 0.20.2 (2017/01/15)
|
||||||
|
* input
|
||||||
|
- alsa: fix crash bug
|
||||||
|
- alsa: fix buffer overruns
|
||||||
|
* decoder
|
||||||
|
- flac: add options "probesize" and "analyzeduration"
|
||||||
|
* resampler
|
||||||
|
- libsamplerate: reset state after seeking
|
||||||
|
* output
|
||||||
|
- fix static noise after changing to a different audio format
|
||||||
|
- alsa: fix the DSD_U32 sample rate
|
||||||
|
- alsa: fix the DSD_U32 byte order
|
||||||
|
- alsa: support DSD_U16
|
||||||
|
- recorder: fix error "Failed to create : No such file or directory"
|
||||||
|
* playlist
|
||||||
|
- cue: fix skipping songs
|
||||||
|
|
||||||
|
ver 0.20.1 (2017/01/09)
|
||||||
|
* input
|
||||||
|
- curl: fix crash bug
|
||||||
|
- curl: fix freeze bug
|
||||||
|
* decoder
|
||||||
|
- wavpack: fix crash bug
|
||||||
|
* storage
|
||||||
|
- curl: new storage plugin for WebDAV (work in progress)
|
||||||
|
* mixer
|
||||||
|
- alsa: normalize displayed volume according to human perception
|
||||||
|
* fix crash with volume_normalization enabled
|
||||||
|
|
||||||
|
ver 0.20 (2017/01/04)
|
||||||
|
* protocol
|
||||||
|
- "commands" returns playlist commands only if playlist_directory configured
|
||||||
|
- "search"/"find" have a "window" parameter
|
||||||
|
- report song duration with milliseconds precision
|
||||||
|
- "sticker find" can match sticker values
|
||||||
|
- drop the "file:///" prefix for absolute file paths
|
||||||
|
- add range parameter to command "plchanges" and "plchangesposid"
|
||||||
|
- send verbose error message to client
|
||||||
|
* input
|
||||||
|
- curl: fix memory leak
|
||||||
|
* tags
|
||||||
|
- ape, ogg: drop support for non-standard tag "album artist"
|
||||||
|
affected filetypes: vorbis, flac, opus & all files with ape2 tags
|
||||||
|
(most importantly some mp3s)
|
||||||
|
- id3: remove the "id3v1_encoding" setting; by definition, all ID3v1 tags
|
||||||
|
are ISO-Latin-1
|
||||||
|
- ape: support APE replay gain on remote files
|
||||||
|
- read ID3 tags from NFS/SMB
|
||||||
|
* decoder
|
||||||
|
- improved error logging
|
||||||
|
- report I/O errors to clients
|
||||||
|
- ffmpeg: support ReplayGain and MixRamp
|
||||||
|
- ffmpeg: support stream tags
|
||||||
|
- gme: add option "accuracy"
|
||||||
|
- gme: provide the TRACK tag
|
||||||
|
- gme: faster scanning
|
||||||
|
- mad: reduce memory usage while scanning tags
|
||||||
|
- mpcdec: read the bit rate
|
||||||
|
- pcm: support audio/L16 (RFC 2586) and audio/x-mpd-float
|
||||||
|
- sidplay: faster scanning
|
||||||
|
- wavpack: large file support
|
||||||
|
- wavpack: support DSD (WavPack 5)
|
||||||
|
- wavpack: archive support
|
||||||
|
* playlist
|
||||||
|
- cue: don't skip pregap
|
||||||
|
- embcue: fix last track
|
||||||
|
- flac: new plugin which reads the "CUESHEET" metadata block
|
||||||
|
* output
|
||||||
|
- alsa: fix multi-channel order
|
||||||
|
- alsa: remove option "use_mmap"
|
||||||
|
- alsa: support DSD_U32
|
||||||
|
- alsa: disable DoP if it fails
|
||||||
|
- jack: reduce CPU usage
|
||||||
|
- pulse: set channel map to WAVE-EX
|
||||||
|
- recorder: record tags
|
||||||
|
- recorder: allow dynamic file names
|
||||||
|
- sndio: new output plugin
|
||||||
|
* mixer
|
||||||
|
- null: new plugin
|
||||||
|
* resampler
|
||||||
|
- new block "resampler" in configuration file
|
||||||
|
replacing the old "samplerate_converter" setting
|
||||||
|
- soxr: allow multi-threaded resampling
|
||||||
|
* player
|
||||||
|
- reset song priority on playback
|
||||||
|
- reduce xruns
|
||||||
|
* write database and state file atomically
|
||||||
|
* always write UTF-8 to the log file.
|
||||||
|
* remove dependency on GLib
|
||||||
|
* support libsystemd (instead of the older libsystemd-daemon)
|
||||||
|
* database
|
||||||
|
- proxy: add TCP keepalive option
|
||||||
|
* update
|
||||||
|
- apply .mpdignore matches to subdirectories
|
||||||
|
* switch the code base to C++14
|
||||||
|
- GCC 4.9 or clang 3.4 (or newer) recommended
|
||||||
|
|
||||||
|
ver 0.19.21 (2016/12/13)
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: fix crash bug
|
||||||
|
* fix unit test failure after recent "setprio" change
|
||||||
|
* systemd: add user unit
|
||||||
|
|
||||||
|
ver 0.19.20 (2016/12/09)
|
||||||
|
* protocol
|
||||||
|
- "setprio" re-enqueues old song if priority has been raised
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: ignore empty packets
|
||||||
|
- pcm: fix corruption bug with partial frames (after short read)
|
||||||
|
- sidplay: fix playback speed with libsidplayfp
|
||||||
|
* output
|
||||||
|
- winmm: fix 8 bit playback
|
||||||
|
* fix gcc 7.0 -Wimplicit-fallthrough
|
||||||
|
* systemd: paranoid security settings
|
||||||
|
|
||||||
|
ver 0.19.19 (2016/08/23)
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: bug fix for FFmpeg 3.1 support
|
||||||
|
- wildmidi: support libWildMidi 0.4
|
||||||
|
* output
|
||||||
|
- pulse: support 32 bit, 24 bit and floating point playback
|
||||||
|
* support non-x86 NetBSD
|
||||||
|
* fix clang 3.9 warnings
|
||||||
|
|
||||||
|
ver 0.19.18 (2016/08/05)
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: fix crash with older FFmpeg versions (< 3.0)
|
||||||
|
- ffmpeg: log detailed error message
|
||||||
|
- ffmpeg: support FFmpeg 3.1
|
||||||
|
- sidplay: detect libsidplay2 with pkg-config
|
||||||
|
- sidplay: log detailed error message
|
||||||
|
- sidplay: read the "date" tag
|
||||||
|
- sidplay: allow building with libsidplayfp instead of libsidplay2
|
||||||
|
* output
|
||||||
|
- shout: recognize setting "encoder" instead of "encoding"
|
||||||
|
* fix memory leak after stream failure
|
||||||
|
* fix build failure with Boost 1.61
|
||||||
|
* require gcc 4.7 or newer
|
||||||
|
|
||||||
|
ver 0.19.17 (2016/07/09)
|
||||||
|
* decoder
|
||||||
|
- flac: fix assertion failure while seeking
|
||||||
|
- flac: fix stream duration indicator
|
||||||
|
- fix seek problems in several plugins
|
||||||
|
* fix spurious seek error "Failed to allocate silence buffer"
|
||||||
|
* replay gain: fix "replay_gain_handler mixer" setting
|
||||||
|
* DSD: use 0x69 as silence pattern
|
||||||
|
* fix use-after-free bug on "close" and "kill"
|
||||||
|
|
||||||
|
ver 0.19.16 (2016/06/13)
|
||||||
|
* faster seeking
|
||||||
|
* fix system include path order
|
||||||
|
* add missing DocBook file to tarball
|
||||||
|
|
||||||
|
ver 0.19.15 (2016/04/30)
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: support FFmpeg 3.0
|
||||||
|
- ffmpeg: use as fallback instead of "mad" if no plugin matches
|
||||||
|
- opus: support bigger OpusTags packets
|
||||||
|
* fix more build failures on non-glibc builds due to constexpr Mutex
|
||||||
|
* fix build failure due to missing include
|
||||||
|
* fix unit test on Alpha
|
||||||
|
|
||||||
|
ver 0.19.14 (2016/03/18)
|
||||||
|
* decoder
|
||||||
|
- dsdiff: fix off-by-one buffer overflow
|
||||||
|
- opus: limit tag size to 64 kB
|
||||||
|
* archive
|
||||||
|
- iso9660: fix buffer overflow
|
||||||
|
* fix quadratic runtime bug in the tag pool
|
||||||
|
* fix build failures on non-glibc builds due to constexpr Mutex
|
||||||
|
|
||||||
|
ver 0.19.13 (2016/02/23)
|
||||||
|
* tags
|
||||||
|
- aiff, riff: fix ID3 chunk padding
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: support the TAK codec
|
||||||
|
* fix disappearing duration of remote songs during playback
|
||||||
|
* initialize supplementary groups with glibc 2.19+
|
||||||
|
|
||||||
ver 0.19.12 (2015/12/15)
|
ver 0.19.12 (2015/12/15)
|
||||||
* fix assertion failure on malformed UTF-8 tag
|
* fix assertion failure on malformed UTF-8 tag
|
||||||
* fix build failure on non-Linux systems
|
* fix build failure on non-Linux systems
|
||||||
|
|||||||
17
README
17
README
@@ -1,17 +0,0 @@
|
|||||||
|
|
||||||
Music Player Daemon (MPD)
|
|
||||||
http://www.musicpd.org
|
|
||||||
|
|
||||||
A daemon for playing music of various formats. Music is played through the
|
|
||||||
server's audio device. The daemon stores info about all available music,
|
|
||||||
and this info can be easily searched and retrieved. Player control, info
|
|
||||||
retrieval, and playlist management can all be managed remotely.
|
|
||||||
|
|
||||||
For basic installation information see the INSTALL file.
|
|
||||||
|
|
||||||
MPD is released under the GNU General Public License version 2, which is
|
|
||||||
distributed in the COPYING file.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU General Public License along with
|
|
||||||
this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
28
README.md
Normal file
28
README.md
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
# Music Player Daemon
|
||||||
|
|
||||||
|
http://www.musicpd.org
|
||||||
|
|
||||||
|
A daemon for playing music of various formats. Music is played through the
|
||||||
|
server's audio device. The daemon stores info about all available music,
|
||||||
|
and this info can be easily searched and retrieved. Player control, info
|
||||||
|
retrieval, and playlist management can all be managed remotely.
|
||||||
|
|
||||||
|
For basic installation information see the INSTALL file.
|
||||||
|
|
||||||
|
# Users
|
||||||
|
|
||||||
|
- [Manual](http://www.musicpd.org/doc/user/)
|
||||||
|
- [Forum](http://forum.musicpd.org/)
|
||||||
|
- [IRC](irc://chat.freenode.net/#mpd)
|
||||||
|
- [Bug tracker](http://bugs.musicpd.org/)
|
||||||
|
|
||||||
|
# Developers
|
||||||
|
|
||||||
|
- [Protocol specification](http://www.musicpd.org/doc/protocol/)
|
||||||
|
- [Developer manual](http://www.musicpd.org/doc/developer/)
|
||||||
|
|
||||||
|
# Legal
|
||||||
|
|
||||||
|
MPD is released under the
|
||||||
|
[GNU General Public License version 2](https://www.gnu.org/licenses/gpl-2.0.txt),
|
||||||
|
which is distributed in the COPYING file.
|
||||||
464
android/build.py
464
android/build.py
@@ -1,10 +1,7 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
|
|
||||||
import os, os.path
|
import os, os.path
|
||||||
import sys, shutil, subprocess
|
import sys, subprocess
|
||||||
import urllib.request
|
|
||||||
import hashlib
|
|
||||||
import re
|
|
||||||
|
|
||||||
if len(sys.argv) < 3:
|
if len(sys.argv) < 3:
|
||||||
print("Usage: build.py SDK_PATH NDK_PATH [configure_args...]", file=sys.stderr)
|
print("Usage: build.py SDK_PATH NDK_PATH [configure_args...]", file=sys.stderr)
|
||||||
@@ -22,412 +19,135 @@ if not os.path.isdir(ndk_path):
|
|||||||
print("NDK not found in", ndk_path, file=sys.stderr)
|
print("NDK not found in", ndk_path, file=sys.stderr)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
|
# select the NDK target
|
||||||
|
arch = 'arm-linux-androideabi'
|
||||||
|
|
||||||
# the path to the MPD sources
|
# the path to the MPD sources
|
||||||
mpd_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]) or '.', '..'))
|
mpd_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[0]) or '.', '..'))
|
||||||
|
sys.path[0] = os.path.join(mpd_path, 'python')
|
||||||
|
|
||||||
# output directories
|
# output directories
|
||||||
lib_path = os.path.abspath('lib')
|
from build.dirs import lib_path, tarball_path, src_path
|
||||||
tarball_path = lib_path
|
|
||||||
src_path = os.path.join(lib_path, 'src')
|
arch_path = os.path.join(lib_path, arch)
|
||||||
build_path = os.path.join(lib_path, 'build')
|
build_path = os.path.join(arch_path, 'build')
|
||||||
root_path = os.path.join(lib_path, 'root')
|
|
||||||
|
|
||||||
# build host configuration
|
# build host configuration
|
||||||
build_arch = 'linux-x86_64'
|
build_arch = 'linux-x86_64'
|
||||||
|
|
||||||
# redirect pkg-config to use our root directory instead of the default
|
|
||||||
# one on the build host
|
|
||||||
os.environ['PKG_CONFIG_LIBDIR'] = os.path.join(root_path, 'lib/pkgconfig')
|
|
||||||
|
|
||||||
# select the NDK compiler
|
|
||||||
gcc_version = '4.9'
|
|
||||||
llvm_version = '3.5'
|
|
||||||
|
|
||||||
# select the NDK target
|
|
||||||
ndk_arch = 'arm'
|
|
||||||
host_arch = 'arm-linux-androideabi'
|
|
||||||
android_abi = 'armeabi-v7a'
|
|
||||||
ndk_platform = 'android-14'
|
|
||||||
|
|
||||||
# set up the NDK toolchain
|
# set up the NDK toolchain
|
||||||
|
|
||||||
gcc_toolchain = os.path.join(ndk_path, 'toolchains', host_arch + '-' + gcc_version, 'prebuilt', build_arch)
|
class AndroidNdkToolchain:
|
||||||
llvm_toolchain = os.path.join(ndk_path, 'toolchains', 'llvm-' + llvm_version, 'prebuilt', build_arch)
|
def __init__(self, tarball_path, src_path, build_path,
|
||||||
ndk_platform_path = os.path.join(ndk_path, 'platforms', ndk_platform)
|
use_cxx):
|
||||||
target_root = os.path.join(ndk_platform_path, 'arch-' + ndk_arch)
|
self.tarball_path = tarball_path
|
||||||
|
self.src_path = src_path
|
||||||
|
self.build_path = build_path
|
||||||
|
|
||||||
llvm_triple = 'armv7-none-linux-androideabi'
|
self.ndk_arch = 'arm'
|
||||||
|
android_abi = 'armeabi-v7a'
|
||||||
|
ndk_platform = 'android-14'
|
||||||
|
|
||||||
def select_toolchain(use_cxx, use_clang):
|
# select the NDK compiler
|
||||||
global cc, cxx, ar, strip, cflags, cxxflags, cppflags, ldflags, libs
|
gcc_version = '4.9'
|
||||||
|
|
||||||
target_arch = '-march=armv7-a -mfloat-abi=softfp'
|
ndk_platform_path = os.path.join(ndk_path, 'platforms', ndk_platform)
|
||||||
if use_clang:
|
sysroot = os.path.join(ndk_platform_path, 'arch-' + self.ndk_arch)
|
||||||
cc = os.path.join(llvm_toolchain, 'bin/clang')
|
|
||||||
cxx = os.path.join(llvm_toolchain, 'bin/clang++')
|
install_prefix = os.path.join(arch_path, 'root')
|
||||||
target_arch += ' -target ' + llvm_triple + ' -integrated-as -gcc-toolchain ' + gcc_toolchain
|
|
||||||
else:
|
self.arch = arch
|
||||||
cc = os.path.join(gcc_toolchain, 'bin', host_arch + '-gcc')
|
self.install_prefix = install_prefix
|
||||||
cxx = os.path.join(gcc_toolchain, 'bin', host_arch + '-g++')
|
self.sysroot = sysroot
|
||||||
ar = os.path.join(gcc_toolchain, 'bin', host_arch + '-ar')
|
|
||||||
strip = os.path.join(gcc_toolchain, 'bin', host_arch + '-strip')
|
toolchain_path = os.path.join(ndk_path, 'toolchains', arch + '-' + gcc_version, 'prebuilt', build_arch)
|
||||||
|
llvm_path = os.path.join(ndk_path, 'toolchains', 'llvm', 'prebuilt', build_arch)
|
||||||
|
llvm_triple = 'armv7-none-linux-androideabi'
|
||||||
|
|
||||||
|
common_flags = '-march=armv7-a -mfloat-abi=softfp'
|
||||||
|
|
||||||
|
toolchain_bin = os.path.join(toolchain_path, 'bin')
|
||||||
|
llvm_bin = os.path.join(llvm_path, 'bin')
|
||||||
|
self.cc = os.path.join(llvm_bin, 'clang')
|
||||||
|
self.cxx = os.path.join(llvm_bin, 'clang++')
|
||||||
|
common_flags += ' -target ' + llvm_triple + ' -integrated-as -gcc-toolchain ' + toolchain_path
|
||||||
|
|
||||||
|
self.ar = os.path.join(toolchain_bin, arch + '-ar')
|
||||||
|
self.ranlib = os.path.join(toolchain_bin, arch + '-ranlib')
|
||||||
|
self.nm = os.path.join(toolchain_bin, arch + '-nm')
|
||||||
|
self.strip = os.path.join(toolchain_bin, arch + '-strip')
|
||||||
|
|
||||||
|
self.cflags = '-Os -g ' + common_flags
|
||||||
|
self.cxxflags = '-Os -g ' + common_flags
|
||||||
|
self.cppflags = '--sysroot=' + self.sysroot + ' -isystem ' + os.path.join(install_prefix, 'include')
|
||||||
|
self.ldflags = '--sysroot=' + self.sysroot + ' ' + common_flags + ' -L' + os.path.join(install_prefix, 'lib')
|
||||||
|
self.libs = ''
|
||||||
|
|
||||||
|
self.is_arm = self.ndk_arch == 'arm'
|
||||||
|
self.is_armv7 = self.is_arm and 'armv7' in self.cflags
|
||||||
|
self.is_windows = False
|
||||||
|
|
||||||
libstdcxx_path = os.path.join(ndk_path, 'sources/cxx-stl/gnu-libstdc++', gcc_version)
|
libstdcxx_path = os.path.join(ndk_path, 'sources/cxx-stl/gnu-libstdc++', gcc_version)
|
||||||
libstdcxx_cppflags = '-isystem ' + os.path.join(libstdcxx_path, 'include') + ' -isystem ' + os.path.join(libstdcxx_path, 'libs', android_abi, 'include')
|
libstdcxx_cppflags = '-isystem ' + os.path.join(libstdcxx_path, 'include') + ' -isystem ' + os.path.join(libstdcxx_path, 'libs', android_abi, 'include')
|
||||||
if use_clang:
|
|
||||||
libstdcxx_cppflags += ' -D__STRICT_ANSI__'
|
|
||||||
libstdcxx_ldadd = os.path.join(libstdcxx_path, 'libs', android_abi, 'libgnustl_static.a')
|
libstdcxx_ldadd = os.path.join(libstdcxx_path, 'libs', android_abi, 'libgnustl_static.a')
|
||||||
|
|
||||||
cflags = '-Os -g ' + target_arch
|
|
||||||
cxxflags = '-Os -g ' + target_arch
|
|
||||||
cppflags = '--sysroot=' + target_root + ' -I' + root_path + '/include'
|
|
||||||
ldflags = '--sysroot=' + target_root + ' -L' + root_path + '/lib'
|
|
||||||
libs = ''
|
|
||||||
|
|
||||||
if use_cxx:
|
if use_cxx:
|
||||||
libs += ' ' + libstdcxx_ldadd
|
self.libs += ' ' + libstdcxx_ldadd
|
||||||
cppflags += ' ' + libstdcxx_cppflags
|
self.cppflags += ' ' + libstdcxx_cppflags
|
||||||
|
|
||||||
def file_md5(path):
|
self.env = dict(os.environ)
|
||||||
"""Calculate the MD5 checksum of a file and return it in hexadecimal notation."""
|
|
||||||
|
|
||||||
with open(path, 'rb') as f:
|
# redirect pkg-config to use our root directory instead of the
|
||||||
m = hashlib.md5()
|
# default one on the build host
|
||||||
while True:
|
self.env['PKG_CONFIG_LIBDIR'] = os.path.join(install_prefix, 'lib/pkgconfig')
|
||||||
data = f.read(65536)
|
|
||||||
if len(data) == 0:
|
|
||||||
# end of file
|
|
||||||
return m.hexdigest()
|
|
||||||
m.update(data)
|
|
||||||
|
|
||||||
def download_tarball(url, md5):
|
|
||||||
"""Download a tarball, verify its MD5 checksum and return the local path."""
|
|
||||||
|
|
||||||
global tarball_path
|
|
||||||
os.makedirs(tarball_path, exist_ok=True)
|
|
||||||
path = os.path.join(tarball_path, os.path.basename(url))
|
|
||||||
|
|
||||||
try:
|
|
||||||
calculated_md5 = file_md5(path)
|
|
||||||
if md5 == calculated_md5: return path
|
|
||||||
os.unlink(path)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
tmp_path = path + '.tmp'
|
|
||||||
|
|
||||||
print("download", url)
|
|
||||||
urllib.request.urlretrieve(url, tmp_path)
|
|
||||||
calculated_md5 = file_md5(tmp_path)
|
|
||||||
if calculated_md5 != md5:
|
|
||||||
os.unlink(tmp_path)
|
|
||||||
raise "MD5 mismatch"
|
|
||||||
|
|
||||||
os.rename(tmp_path, path)
|
|
||||||
return path
|
|
||||||
|
|
||||||
class Project:
|
|
||||||
def __init__(self, url, md5, installed, name=None, version=None,
|
|
||||||
base=None,
|
|
||||||
use_cxx=False, use_clang=False):
|
|
||||||
if base is None:
|
|
||||||
basename = os.path.basename(url)
|
|
||||||
m = re.match(r'^(.+)\.(tar(\.(gz|bz2|xz|lzma))?|zip)$', basename)
|
|
||||||
if not m: raise
|
|
||||||
self.base = m.group(1)
|
|
||||||
else:
|
|
||||||
self.base = base
|
|
||||||
|
|
||||||
if name is None or version is None:
|
|
||||||
m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?)$', self.base)
|
|
||||||
if name is None: name = m.group(1)
|
|
||||||
if version is None: version = m.group(2)
|
|
||||||
|
|
||||||
self.name = name
|
|
||||||
self.version = version
|
|
||||||
|
|
||||||
self.url = url
|
|
||||||
self.md5 = md5
|
|
||||||
self.installed = installed
|
|
||||||
|
|
||||||
self.use_cxx = use_cxx
|
|
||||||
self.use_clang = use_clang
|
|
||||||
|
|
||||||
def download(self):
|
|
||||||
return download_tarball(self.url, self.md5)
|
|
||||||
|
|
||||||
def is_installed(self):
|
|
||||||
global root_path
|
|
||||||
tarball = self.download()
|
|
||||||
installed = os.path.join(root_path, self.installed)
|
|
||||||
tarball_mtime = os.path.getmtime(tarball)
|
|
||||||
try:
|
|
||||||
return os.path.getmtime(installed) >= tarball_mtime
|
|
||||||
except FileNotFoundError:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def unpack(self):
|
|
||||||
global src_path
|
|
||||||
tarball = self.download()
|
|
||||||
path = os.path.join(src_path, self.base)
|
|
||||||
try:
|
|
||||||
shutil.rmtree(path)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
os.makedirs(src_path, exist_ok=True)
|
|
||||||
subprocess.check_call(['/bin/tar', 'xfC', tarball, src_path])
|
|
||||||
return path
|
|
||||||
|
|
||||||
def make_build_path(self):
|
|
||||||
path = os.path.join(build_path, self.base)
|
|
||||||
try:
|
|
||||||
shutil.rmtree(path)
|
|
||||||
except FileNotFoundError:
|
|
||||||
pass
|
|
||||||
os.makedirs(path, exist_ok=True)
|
|
||||||
return path
|
|
||||||
|
|
||||||
class AutotoolsProject(Project):
|
|
||||||
def __init__(self, url, md5, installed, configure_args=[],
|
|
||||||
autogen=False,
|
|
||||||
cppflags='',
|
|
||||||
**kwargs):
|
|
||||||
Project.__init__(self, url, md5, installed, **kwargs)
|
|
||||||
self.configure_args = configure_args
|
|
||||||
self.autogen = autogen
|
|
||||||
self.cppflags = cppflags
|
|
||||||
|
|
||||||
def build(self):
|
|
||||||
src = self.unpack()
|
|
||||||
if self.autogen:
|
|
||||||
subprocess.check_call(['/usr/bin/aclocal'], cwd=src)
|
|
||||||
subprocess.check_call(['/usr/bin/automake', '--add-missing', '--force-missing', '--foreign'], cwd=src)
|
|
||||||
subprocess.check_call(['/usr/bin/autoconf'], cwd=src)
|
|
||||||
subprocess.check_call(['/usr/bin/libtoolize', '--force'], cwd=src)
|
|
||||||
|
|
||||||
build = self.make_build_path()
|
|
||||||
|
|
||||||
select_toolchain(use_cxx=self.use_cxx, use_clang=self.use_clang)
|
|
||||||
configure = [
|
|
||||||
os.path.join(src, 'configure'),
|
|
||||||
'CC=' + cc,
|
|
||||||
'CXX=' + cxx,
|
|
||||||
'CFLAGS=' + cflags,
|
|
||||||
'CXXFLAGS=' + cxxflags,
|
|
||||||
'CPPFLAGS=' + cppflags + ' ' + self.cppflags,
|
|
||||||
'LDFLAGS=' + ldflags,
|
|
||||||
'LIBS=' + libs,
|
|
||||||
'AR=' + ar,
|
|
||||||
'STRIP=' + strip,
|
|
||||||
'--host=' + host_arch,
|
|
||||||
'--prefix=' + root_path,
|
|
||||||
'--with-sysroot=' + target_root,
|
|
||||||
'--enable-silent-rules',
|
|
||||||
] + self.configure_args
|
|
||||||
|
|
||||||
subprocess.check_call(configure, cwd=build)
|
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], cwd=build)
|
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet', 'install'], cwd=build)
|
|
||||||
|
|
||||||
class FfmpegProject(Project):
|
|
||||||
def __init__(self, url, md5, installed, configure_args=[],
|
|
||||||
cppflags='',
|
|
||||||
**kwargs):
|
|
||||||
Project.__init__(self, url, md5, installed, **kwargs)
|
|
||||||
self.configure_args = configure_args
|
|
||||||
self.cppflags = cppflags
|
|
||||||
|
|
||||||
def build(self):
|
|
||||||
src = self.unpack()
|
|
||||||
build = self.make_build_path()
|
|
||||||
|
|
||||||
select_toolchain(use_cxx=self.use_cxx, use_clang=self.use_clang)
|
|
||||||
configure = [
|
|
||||||
os.path.join(src, 'configure'),
|
|
||||||
'--cc=' + cc,
|
|
||||||
'--cxx=' + cxx,
|
|
||||||
'--extra-cflags=' + cflags + ' ' + cppflags + ' ' + self.cppflags,
|
|
||||||
'--extra-cxxflags=' + cxxflags + ' ' + cppflags + ' ' + self.cppflags,
|
|
||||||
'--extra-ldflags=' + ldflags,
|
|
||||||
'--extra-libs=' + libs,
|
|
||||||
'--ar=' + ar,
|
|
||||||
'--enable-cross-compile',
|
|
||||||
'--target-os=linux',
|
|
||||||
'--arch=' + ndk_arch,
|
|
||||||
'--cpu=cortex-a8',
|
|
||||||
'--prefix=' + root_path,
|
|
||||||
] + self.configure_args
|
|
||||||
|
|
||||||
subprocess.check_call(configure, cwd=build)
|
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], cwd=build)
|
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet', 'install'], cwd=build)
|
|
||||||
|
|
||||||
class BoostProject(Project):
|
|
||||||
def __init__(self, url, md5, installed,
|
|
||||||
**kwargs):
|
|
||||||
m = re.match(r'.*/boost_(\d+)_(\d+)_(\d+)\.tar\.bz2$', url)
|
|
||||||
version = "%s.%s.%s" % (m.group(1), m.group(2), m.group(3))
|
|
||||||
Project.__init__(self, url, md5, installed,
|
|
||||||
name='boost', version=version,
|
|
||||||
**kwargs)
|
|
||||||
|
|
||||||
def build(self):
|
|
||||||
src = self.unpack()
|
|
||||||
|
|
||||||
# install the headers manually; don't build any library
|
|
||||||
# (because right now, we only use header-only libraries)
|
|
||||||
includedir = os.path.join(root_path, 'include')
|
|
||||||
for dirpath, dirnames, filenames in os.walk(os.path.join(src, 'boost')):
|
|
||||||
relpath = dirpath[len(src)+1:]
|
|
||||||
destdir = os.path.join(includedir, relpath)
|
|
||||||
try:
|
|
||||||
os.mkdir(destdir)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
for name in filenames:
|
|
||||||
if name[-4:] == '.hpp':
|
|
||||||
shutil.copyfile(os.path.join(dirpath, name),
|
|
||||||
os.path.join(destdir, name))
|
|
||||||
|
|
||||||
# a list of third-party libraries to be used by MPD on Android
|
# a list of third-party libraries to be used by MPD on Android
|
||||||
|
from build.libs import *
|
||||||
thirdparty_libs = [
|
thirdparty_libs = [
|
||||||
AutotoolsProject(
|
libogg,
|
||||||
'http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.xz',
|
libvorbis,
|
||||||
'5c3a34309d8b98640827e5d0991a4015',
|
opus,
|
||||||
'lib/libogg.a',
|
flac,
|
||||||
['--disable-shared', '--enable-static'],
|
libid3tag,
|
||||||
),
|
libmad,
|
||||||
|
ffmpeg,
|
||||||
AutotoolsProject(
|
curl,
|
||||||
'http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.4.tar.xz',
|
boost,
|
||||||
'55f2288055e44754275a17c9a2497391',
|
|
||||||
'lib/libvorbis.a',
|
|
||||||
['--disable-shared', '--enable-static'],
|
|
||||||
),
|
|
||||||
|
|
||||||
AutotoolsProject(
|
|
||||||
'http://downloads.xiph.org/releases/opus/opus-1.1.tar.gz',
|
|
||||||
'c5a8cf7c0b066759542bc4ca46817ac6',
|
|
||||||
'lib/libopus.a',
|
|
||||||
['--disable-shared', '--enable-static'],
|
|
||||||
use_clang=True,
|
|
||||||
),
|
|
||||||
|
|
||||||
AutotoolsProject(
|
|
||||||
'http://downloads.xiph.org/releases/flac/flac-1.3.1.tar.xz',
|
|
||||||
'b9922c9a0378c88d3e901b234f852698',
|
|
||||||
'lib/libFLAC.a',
|
|
||||||
[
|
|
||||||
'--disable-shared', '--enable-static',
|
|
||||||
'--disable-xmms-plugin', '--disable-cpplibs',
|
|
||||||
],
|
|
||||||
use_clang=True,
|
|
||||||
),
|
|
||||||
|
|
||||||
AutotoolsProject(
|
|
||||||
'ftp://ftp.mars.org/pub/mpeg/libid3tag-0.15.1b.tar.gz',
|
|
||||||
'e5808ad997ba32c498803822078748c3',
|
|
||||||
'lib/libid3tag.a',
|
|
||||||
['--disable-shared', '--enable-static'],
|
|
||||||
autogen=True,
|
|
||||||
),
|
|
||||||
|
|
||||||
AutotoolsProject(
|
|
||||||
'ftp://ftp.mars.org/pub/mpeg/libmad-0.15.1b.tar.gz',
|
|
||||||
'1be543bc30c56fb6bea1d7bf6a64e66c',
|
|
||||||
'lib/libmad.a',
|
|
||||||
['--disable-shared', '--enable-static'],
|
|
||||||
autogen=True,
|
|
||||||
),
|
|
||||||
|
|
||||||
FfmpegProject(
|
|
||||||
'http://ffmpeg.org/releases/ffmpeg-2.5.tar.bz2',
|
|
||||||
'4346fe710cc6bdd981f6534d2420d1ab',
|
|
||||||
'lib/libavcodec.a',
|
|
||||||
[
|
|
||||||
'--disable-shared', '--enable-static',
|
|
||||||
'--enable-gpl',
|
|
||||||
'--enable-small',
|
|
||||||
'--disable-pthreads',
|
|
||||||
'--disable-runtime-cpudetect',
|
|
||||||
'--disable-programs',
|
|
||||||
'--disable-doc',
|
|
||||||
'--disable-avdevice',
|
|
||||||
'--disable-swresample',
|
|
||||||
'--disable-swscale',
|
|
||||||
'--disable-postproc',
|
|
||||||
'--disable-avfilter',
|
|
||||||
'--disable-network',
|
|
||||||
'--disable-encoders',
|
|
||||||
'--disable-protocols',
|
|
||||||
'--disable-outdevs',
|
|
||||||
'--disable-filters',
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
AutotoolsProject(
|
|
||||||
'http://curl.haxx.se/download/curl-7.39.0.tar.lzma',
|
|
||||||
'e9aa6dec29920eba8ef706ea5823bad7',
|
|
||||||
'lib/libcurl.a',
|
|
||||||
[
|
|
||||||
'--disable-shared', '--enable-static',
|
|
||||||
'--disable-debug',
|
|
||||||
'--enable-http',
|
|
||||||
'--enable-ipv6',
|
|
||||||
'--disable-ftp', '--disable-file',
|
|
||||||
'--disable-ldap', '--disable-ldaps',
|
|
||||||
'--disable-rtsp', '--disable-proxy', '--disable-dict', '--disable-telnet',
|
|
||||||
'--disable-tftp', '--disable-pop3', '--disable-imap', '--disable-smtp',
|
|
||||||
'--disable-gopher',
|
|
||||||
'--disable-manual',
|
|
||||||
'--disable-threaded-resolver', '--disable-verbose', '--disable-sspi',
|
|
||||||
'--disable-crypto-auth', '--disable-ntlm-wb', '--disable-tls-srp', '--disable-cookies',
|
|
||||||
'--without-ssl', '--without-gnutls', '--without-nss', '--without-libssh2',
|
|
||||||
],
|
|
||||||
use_clang=True,
|
|
||||||
),
|
|
||||||
|
|
||||||
BoostProject(
|
|
||||||
'http://netcologne.dl.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2',
|
|
||||||
'd6eef4b4cacb2183f2bf265a5a03a354',
|
|
||||||
'include/boost/version.hpp',
|
|
||||||
),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
# build the third-party libraries
|
# build the third-party libraries
|
||||||
for x in thirdparty_libs:
|
for x in thirdparty_libs:
|
||||||
if not x.is_installed():
|
toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
|
||||||
x.build()
|
use_cxx=x.use_cxx)
|
||||||
|
if not x.is_installed(toolchain):
|
||||||
|
x.build(toolchain)
|
||||||
|
|
||||||
# configure and build MPD
|
# configure and build MPD
|
||||||
select_toolchain(use_cxx=True, use_clang=True)
|
toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
|
||||||
|
use_cxx=True)
|
||||||
|
|
||||||
configure = [
|
configure = [
|
||||||
os.path.join(mpd_path, 'configure'),
|
os.path.join(mpd_path, 'configure'),
|
||||||
'CC=' + cc,
|
'CC=' + toolchain.cc,
|
||||||
'CXX=' + cxx,
|
'CXX=' + toolchain.cxx,
|
||||||
'CFLAGS=' + cflags,
|
'CFLAGS=' + toolchain.cflags,
|
||||||
'CXXFLAGS=' + cxxflags,
|
'CXXFLAGS=' + toolchain.cxxflags,
|
||||||
'CPPFLAGS=' + cppflags,
|
'CPPFLAGS=' + toolchain.cppflags,
|
||||||
'LDFLAGS=' + ldflags,
|
'LDFLAGS=' + toolchain.ldflags,
|
||||||
'LIBS=' + libs,
|
'LIBS=' + toolchain.libs,
|
||||||
'AR=' + ar,
|
'AR=' + toolchain.ar,
|
||||||
'STRIP=' + strip,
|
'RANLIB=' + toolchain.ranlib,
|
||||||
'--host=' + host_arch,
|
'STRIP=' + toolchain.strip,
|
||||||
'--prefix=' + root_path,
|
'--host=' + toolchain.arch,
|
||||||
'--with-sysroot=' + target_root,
|
'--prefix=' + toolchain.install_prefix,
|
||||||
|
'--with-sysroot=' + toolchain.sysroot,
|
||||||
'--with-android-sdk=' + sdk_path,
|
'--with-android-sdk=' + sdk_path,
|
||||||
|
|
||||||
'--enable-silent-rules',
|
'--enable-silent-rules',
|
||||||
|
|
||||||
'--disable-glib',
|
|
||||||
'--disable-icu',
|
'--disable-icu',
|
||||||
|
|
||||||
# disabled for now because these features require GLib:
|
|
||||||
'--disable-httpd-output',
|
|
||||||
'--disable-vorbis-encoder',
|
|
||||||
|
|
||||||
] + configure_args
|
] + configure_args
|
||||||
|
|
||||||
subprocess.check_call(configure)
|
subprocess.check_call(configure, env=toolchain.env)
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'])
|
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], env=toolchain.env)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
968
configure.ac
968
configure.ac
File diff suppressed because it is too large
Load Diff
@@ -1,10 +1,11 @@
|
|||||||
<?xml version='1.0' encoding="utf-8"?>
|
<?xml version='1.0' encoding="utf-8"?>
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
"docbook/dtd/xml/4.2/docbookx.dtd">
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
|
||||||
<book>
|
<book>
|
||||||
<title>The Music Player Daemon - Developer's Manual</title>
|
<title>The Music Player Daemon - Developer's Manual</title>
|
||||||
|
|
||||||
<chapter>
|
<chapter id="introduction">
|
||||||
<title>Introduction</title>
|
<title>Introduction</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -20,7 +21,7 @@
|
|||||||
</para>
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter>
|
<chapter id="code_style">
|
||||||
<title>Code Style</title>
|
<title>Code Style</title>
|
||||||
|
|
||||||
<itemizedlist>
|
<itemizedlist>
|
||||||
@@ -39,9 +40,35 @@
|
|||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
the code should be C++11 compliant, and must compile with
|
comment your code, document your APIs
|
||||||
<application>GCC</application> 4.6 and
|
</para>
|
||||||
<application>clang</application> 3.2
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
the code should be C++14 compliant, and must compile with
|
||||||
|
<application>GCC</application> 4.9 and
|
||||||
|
<application>clang</application> 3.4
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
report error conditions with C++ exceptions, preferable
|
||||||
|
derived from <varname>std::runtime_error</varname>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
all code must be exception-safe
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
classes and functions names use CamelCase; variables are
|
||||||
|
lower-case with words separated by underscore
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
@@ -51,9 +78,9 @@
|
|||||||
</para>
|
</para>
|
||||||
|
|
||||||
<programlisting lang="C">static inline int
|
<programlisting lang="C">static inline int
|
||||||
foo(const char *abc, int xyz)
|
Foo(const char *abc, int xyz)
|
||||||
{
|
{
|
||||||
if (abc == NULL) {
|
if (abc == nullptr) {
|
||||||
LogWarning("Foo happened!");
|
LogWarning("Foo happened!");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@@ -65,7 +92,7 @@ foo(const char *abc, int xyz)
|
|||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter>
|
<chapter id="hacking">
|
||||||
<title>Hacking The Source</title>
|
<title>Hacking The Source</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -150,7 +177,7 @@ foo(const char *abc, int xyz)
|
|||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter>
|
<chapter id="submitting_patches">
|
||||||
<title>Submitting Patches</title>
|
<title>Submitting Patches</title>
|
||||||
|
|
||||||
<para>
|
<para>
|
||||||
@@ -166,9 +193,16 @@ foo(const char *abc, int xyz)
|
|||||||
url="http://git.musicpd.org/account-policy.html">an account on
|
url="http://git.musicpd.org/account-policy.html">an account on
|
||||||
git.musicpd.org</ulink>, but any public git repository will do.
|
git.musicpd.org</ulink>, but any public git repository will do.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
There is <ulink url="https://github.com/MaxKellermann/MPD">a
|
||||||
|
mirror of the <application>MPD</application> git repository on
|
||||||
|
GitHub</ulink>, and you can use that as well to submit pull
|
||||||
|
requests.
|
||||||
|
</para>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter>
|
<chapter id="tools">
|
||||||
<title>Development Tools</title>
|
<title>Development Tools</title>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|||||||
2473
doc/doxygen.conf.in
2473
doc/doxygen.conf.in
File diff suppressed because it is too large
Load Diff
154
doc/include/tags.xml
Normal file
154
doc/include/tags.xml
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<?xml version='1.0' encoding="utf-8"?>
|
||||||
|
<!DOCTYPE itemizedlist PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
|
||||||
|
<itemizedlist>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>artist</varname>: the artist name. Its meaning is not
|
||||||
|
well-defined; see <varname>composer</varname> and
|
||||||
|
<varname>performer</varname> for more specific tags.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>artistsort</varname>: same as
|
||||||
|
<varname>artist</varname>, but for sorting. This usually omits
|
||||||
|
prefixes such as "The".
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>album</varname>: the album name.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>albumsort</varname>: same as <varname>album</varname>,
|
||||||
|
but for sorting.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>albumartist</varname>: on multi-artist albums, this is
|
||||||
|
the artist name which shall be used for the whole album. The
|
||||||
|
exact meaning of this tag is not well-defined.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>albumartistsort</varname>: same as
|
||||||
|
<varname>albumartist</varname>, but for sorting.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>title</varname>: the song title.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>track</varname>: the track number within the album.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>name</varname>: a name for this song. This is not the
|
||||||
|
song title. The exact meaning of this tag is not well-defined.
|
||||||
|
It is often used by badly configured internet radio stations
|
||||||
|
with broken tags to squeeze both the artist name and the song
|
||||||
|
title in one tag.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>genre</varname>: the music genre.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>date</varname>: the song's release date. This is
|
||||||
|
usually a 4-digit year.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>composer</varname>: the artist who composed the song.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>performer</varname>: the artist who performed the song.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>comment</varname>: a human-readable comment about this
|
||||||
|
song. The exact meaning of this tag is not well-defined.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>disc</varname>: the disc number in a multi-disc album.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>musicbrainz_artistid</varname>: the artist id in the
|
||||||
|
<ulink
|
||||||
|
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
|
||||||
|
database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>musicbrainz_albumid</varname>: the album id in the
|
||||||
|
<ulink
|
||||||
|
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
|
||||||
|
database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>musicbrainz_albumartistid</varname>: the album artist
|
||||||
|
id in the <ulink
|
||||||
|
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
|
||||||
|
database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>musicbrainz_trackid</varname>: the track id in the
|
||||||
|
<ulink
|
||||||
|
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
|
||||||
|
database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>musicbrainz_releasetrackid</varname>: the release track
|
||||||
|
id in the <ulink
|
||||||
|
url="http://musicbrainz.org/doc/MusicBrainzTag">MusicBrainz</ulink>
|
||||||
|
database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</itemizedlist>
|
||||||
@@ -50,6 +50,6 @@ If you find a bug, please report it at
|
|||||||
.br
|
.br
|
||||||
<\fBhttp://bugs.musicpd.org/bug_report_page.php\fP>.
|
<\fBhttp://bugs.musicpd.org/bug_report_page.php\fP>.
|
||||||
.SH AUTHORS
|
.SH AUTHORS
|
||||||
Max Kellermann <max@duempel.org>
|
Max Kellermann <max.kellermann@gmail.com>
|
||||||
|
|
||||||
Special thanks to all the people that provided feedback and patches.
|
Special thanks to all the people that provided feedback and patches.
|
||||||
|
|||||||
@@ -156,12 +156,6 @@ This specifies the character set used for the filesystem. A list of supported
|
|||||||
character sets can be obtained by running "iconv \-l". The default is
|
character sets can be obtained by running "iconv \-l". The default is
|
||||||
determined from the locale when the db was originally created.
|
determined from the locale when the db was originally created.
|
||||||
.TP
|
.TP
|
||||||
.B id3v1_encoding <charset>
|
|
||||||
This specifies the character set which ID3v1 tags are encoded in. A list of
|
|
||||||
supported character sets can be obtained by running "iconv \-l". The default is
|
|
||||||
to let libid3tag convert them (from ISO-8859-1, as the standard specifies) and
|
|
||||||
do no additional conversion.
|
|
||||||
.TP
|
|
||||||
.B gapless_mp3_playback <yes or no>
|
.B gapless_mp3_playback <yes or no>
|
||||||
This specifies whether to support gapless playback of MP3s which have the
|
This specifies whether to support gapless playback of MP3s which have the
|
||||||
necessary headers. Useful if your MP3s have headers with incorrect
|
necessary headers. Useful if your MP3s have headers with incorrect
|
||||||
@@ -174,18 +168,6 @@ MP3 playback.
|
|||||||
This specifies whether relative or absolute paths for song filenames are used
|
This specifies whether relative or absolute paths for song filenames are used
|
||||||
when saving playlists. The default is "no".
|
when saving playlists. The default is "no".
|
||||||
.TP
|
.TP
|
||||||
.B metadata_to_use <tags>
|
|
||||||
This specifies the tag types that will be scanned for and made available to
|
|
||||||
clients. Note that you must recreate (not update) your database for changes to
|
|
||||||
this parameter to take effect. Possible values are artist, album, title,
|
|
||||||
track, name, genre, date, composer, performer, comment, disc,
|
|
||||||
musicbrainz_artistid, musicbrainz_albumid, musicbrainz_albumartistid,
|
|
||||||
musicbrainz_releasetrackid, musicbrainz_trackid. Multiple tags may be specified
|
|
||||||
as a comma separated list.
|
|
||||||
An example value is "artist,album,title,track". The special value "none" may
|
|
||||||
be used alone to disable all metadata. The default is to use all known tag
|
|
||||||
types except for comments and those starting with "musicbrainz".
|
|
||||||
.TP
|
|
||||||
.B auto_update <yes or no>
|
.B auto_update <yes or no>
|
||||||
This specifies the whether to support automatic update of music database when
|
This specifies the whether to support automatic update of music database when
|
||||||
files are changed in music_directory. The default is to disable autoupdate
|
files are changed in music_directory. The default is to disable autoupdate
|
||||||
@@ -244,11 +226,6 @@ probably only useful if your alsa device has more than one
|
|||||||
identically\-named mixer control. The default is "0". Use "amixer
|
identically\-named mixer control. The default is "0". Use "amixer
|
||||||
scontrols" to see the list of controls with their indexes.
|
scontrols" to see the list of controls with their indexes.
|
||||||
.TP
|
.TP
|
||||||
.B use_mmap <yes or no>
|
|
||||||
Setting this allows you to use memory-mapped I/O. Certain hardware setups may
|
|
||||||
benefit from this, but most do not. Most users do not need to set this. The
|
|
||||||
default is to not use memory-mapped I/O.
|
|
||||||
.TP
|
|
||||||
.B auto_resample <yes or no>
|
.B auto_resample <yes or no>
|
||||||
Setting this to "no" disables ALSA's software resampling, if the
|
Setting this to "no" disables ALSA's software resampling, if the
|
||||||
hardware does not support a specific sample rate. This lets MPD do
|
hardware does not support a specific sample rate. This lets MPD do
|
||||||
|
|||||||
@@ -75,7 +75,8 @@
|
|||||||
#
|
#
|
||||||
# This setting sets the address for the daemon to listen on. Careful attention
|
# This setting sets the address for the daemon to listen on. Careful attention
|
||||||
# should be paid if this is assigned to anything other then the default, any.
|
# should be paid if this is assigned to anything other then the default, any.
|
||||||
# This setting can deny access to control of the daemon.
|
# This setting can deny access to control of the daemon. Not effective if
|
||||||
|
# systemd socket activiation is in use.
|
||||||
#
|
#
|
||||||
# For network
|
# For network
|
||||||
#bind_to_address "any"
|
#bind_to_address "any"
|
||||||
@@ -115,7 +116,7 @@
|
|||||||
#
|
#
|
||||||
# This setting defines a list of tag types that will be extracted during the
|
# This setting defines a list of tag types that will be extracted during the
|
||||||
# audio file discovery process. The complete list of possible values can be
|
# audio file discovery process. The complete list of possible values can be
|
||||||
# found in the mpd.conf man page.
|
# found in the user manual.
|
||||||
#metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc"
|
#metadata_to_use "artist,album,title,track,name,genre,date,composer,performer,disc"
|
||||||
#
|
#
|
||||||
# This setting enables automatic update of MPD's database when files in
|
# This setting enables automatic update of MPD's database when files in
|
||||||
@@ -164,7 +165,7 @@
|
|||||||
# Permissions #################################################################
|
# Permissions #################################################################
|
||||||
#
|
#
|
||||||
# If this setting is set, MPD will require password authorization. The password
|
# If this setting is set, MPD will require password authorization. The password
|
||||||
# can setting can be specified multiple times for different password profiles.
|
# setting can be specified multiple times for different password profiles.
|
||||||
#
|
#
|
||||||
#password "password@read,add,control,admin"
|
#password "password@read,add,control,admin"
|
||||||
#
|
#
|
||||||
@@ -231,7 +232,7 @@ input {
|
|||||||
#
|
#
|
||||||
#audio_output {
|
#audio_output {
|
||||||
# type "shout"
|
# type "shout"
|
||||||
# encoding "ogg" # optional
|
# encoder "vorbis" # optional
|
||||||
# name "My Shout Stream"
|
# name "My Shout Stream"
|
||||||
# host "localhost"
|
# host "localhost"
|
||||||
# port "8000"
|
# port "8000"
|
||||||
@@ -304,6 +305,23 @@ input {
|
|||||||
## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional
|
## device "Digital Audio (S/PDIF) (High Definition Audio Device)" # optional
|
||||||
#}
|
#}
|
||||||
#
|
#
|
||||||
|
# An example of an sndio output.
|
||||||
|
#
|
||||||
|
#audio_output {
|
||||||
|
# type "sndio"
|
||||||
|
# name "sndio output"
|
||||||
|
# mixer_type "software"
|
||||||
|
#}
|
||||||
|
#
|
||||||
|
# An example of an OS X output:
|
||||||
|
#
|
||||||
|
#audio_output {
|
||||||
|
# type "osx"
|
||||||
|
# name "My OS X Device"
|
||||||
|
## device "Built-in Output" # optional
|
||||||
|
## channel_map "-1,-1,0,1" # optional
|
||||||
|
#}
|
||||||
|
#
|
||||||
## Example "pipe" output:
|
## Example "pipe" output:
|
||||||
#
|
#
|
||||||
#audio_output {
|
#audio_output {
|
||||||
@@ -325,13 +343,6 @@ input {
|
|||||||
# mixer_type "none" # optional
|
# mixer_type "none" # optional
|
||||||
#}
|
#}
|
||||||
#
|
#
|
||||||
# If MPD has been compiled with libsamplerate support, this setting specifies
|
|
||||||
# the sample rate converter to use. Possible values can be found in the
|
|
||||||
# mpd.conf man page or the libsamplerate documentation. By default, this is
|
|
||||||
# setting is disabled.
|
|
||||||
#
|
|
||||||
#samplerate_converter "Fastest Sinc Interpolator"
|
|
||||||
#
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
@@ -380,34 +391,4 @@ input {
|
|||||||
#
|
#
|
||||||
#filesystem_charset "UTF-8"
|
#filesystem_charset "UTF-8"
|
||||||
#
|
#
|
||||||
# This setting controls the encoding that ID3v1 tags should be converted from.
|
|
||||||
#
|
|
||||||
#id3v1_encoding "ISO-8859-1"
|
|
||||||
#
|
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
|
||||||
# SIDPlay decoder #############################################################
|
|
||||||
#
|
|
||||||
# songlength_database:
|
|
||||||
# Location of your songlengths file, as distributed with the HVSC.
|
|
||||||
# The sidplay plugin checks this for matching MD5 fingerprints.
|
|
||||||
# See http://www.c64.org/HVSC/DOCUMENTS/Songlengths.faq
|
|
||||||
#
|
|
||||||
# default_songlength:
|
|
||||||
# This is the default playing time in seconds for songs not in the
|
|
||||||
# songlength database, or in case you're not using a database.
|
|
||||||
# A value of 0 means play indefinitely.
|
|
||||||
#
|
|
||||||
# filter:
|
|
||||||
# Turns the SID filter emulation on or off.
|
|
||||||
#
|
|
||||||
#decoder {
|
|
||||||
# plugin "sidplay"
|
|
||||||
# songlength_database "/media/C64Music/DOCUMENTS/Songlengths.txt"
|
|
||||||
# default_songlength "120"
|
|
||||||
# filter "true"
|
|
||||||
#}
|
|
||||||
#
|
|
||||||
###############################################################################
|
|
||||||
|
|
||||||
|
|||||||
103
doc/protocol.xml
103
doc/protocol.xml
@@ -1,6 +1,7 @@
|
|||||||
<?xml version='1.0' encoding="utf-8"?>
|
<?xml version='1.0' encoding="utf-8"?>
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
|
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
||||||
"docbook/dtd/xml/4.2/docbookx.dtd">
|
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
||||||
|
|
||||||
<book>
|
<book>
|
||||||
<title>The Music Player Daemon protocol</title>
|
<title>The Music Player Daemon protocol</title>
|
||||||
|
|
||||||
@@ -65,8 +66,8 @@
|
|||||||
<function>strcpy</function> just fine with UTF-8 encoded
|
<function>strcpy</function> just fine with UTF-8 encoded
|
||||||
strings. For example: <returnvalue>OK</returnvalue> encoded in
|
strings. For example: <returnvalue>OK</returnvalue> encoded in
|
||||||
UTF-8 is simply <returnvalue>OK</returnvalue>. For more
|
UTF-8 is simply <returnvalue>OK</returnvalue>. For more
|
||||||
information on UTF=8:
|
information on UTF-8:
|
||||||
http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8)
|
<ulink url="http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8"/>)
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
@@ -201,6 +202,25 @@
|
|||||||
omitted, then the maximum possible value is assumed.
|
omitted, then the maximum possible value is assumed.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="tags">
|
||||||
|
<title>Tags</title>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
The following tags are supported by
|
||||||
|
<application>MPD</application>:
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<xi:include href="include/tags.xml"
|
||||||
|
xmlns:xi="http://www.w3.org/2001/XInclude"/>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
There can be multiple values for some of these tags. For
|
||||||
|
example, <application>MPD</application> may return multiple
|
||||||
|
lines with a <varname>performer</varname> tag. A tag value is
|
||||||
|
a UTF-8 string.
|
||||||
|
</para>
|
||||||
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
|
|
||||||
<chapter id="recipes">
|
<chapter id="recipes">
|
||||||
@@ -238,9 +258,10 @@
|
|||||||
"before" the current song in that sequence) will only be
|
"before" the current song in that sequence) will only be
|
||||||
scheduled for repeated playback if its priority has become
|
scheduled for repeated playback if its priority has become
|
||||||
bigger than the priority of the current song. Decreasing the
|
bigger than the priority of the current song. Decreasing the
|
||||||
priority of a song will moved it farther to the end of the
|
priority of a song will move it farther to the end of the
|
||||||
sequence. Changing the priority of the current song has no
|
sequence. Changing the priority of the current song has no
|
||||||
effect on the sequence.
|
effect on the sequence. During playback, a song's priority is
|
||||||
|
reset to zero.
|
||||||
</para>
|
</para>
|
||||||
</section>
|
</section>
|
||||||
</chapter>
|
</chapter>
|
||||||
@@ -515,6 +536,15 @@
|
|||||||
</returnvalue>
|
</returnvalue>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>duration</varname>:
|
||||||
|
<footnote id="since_0_20"><simpara>Introduced with <application>MPD</application> 0.20</simpara></footnote>
|
||||||
|
<returnvalue>
|
||||||
|
Duration of the current song in seconds.
|
||||||
|
</returnvalue>
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<varname>bitrate</varname>:
|
<varname>bitrate</varname>:
|
||||||
@@ -543,7 +573,12 @@
|
|||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
<varname>audio</varname>:
|
<varname>audio</varname>:
|
||||||
<returnvalue>sampleRate:bits:channels</returnvalue>
|
<returnvalue>
|
||||||
|
The format emitted by the decoder plugin during
|
||||||
|
playback, format:
|
||||||
|
"<replaceable>samplerate:bits:channels</replaceable>".
|
||||||
|
Check the user manual for a detailed explanation.
|
||||||
|
</returnvalue>
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
<listitem>
|
<listitem>
|
||||||
@@ -1151,12 +1186,15 @@ OK
|
|||||||
<cmdsynopsis>
|
<cmdsynopsis>
|
||||||
<command>plchanges</command>
|
<command>plchanges</command>
|
||||||
<arg choice="req"><replaceable>VERSION</replaceable></arg>
|
<arg choice="req"><replaceable>VERSION</replaceable></arg>
|
||||||
|
<arg><replaceable>START:END</replaceable></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Displays changed songs currently in the playlist since
|
Displays changed songs currently in the playlist since
|
||||||
<varname>VERSION</varname>.
|
<varname>VERSION</varname>. Start and end positions may
|
||||||
|
be given to limit the output to changes in the given
|
||||||
|
range.
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
To detect songs that were deleted at the end of the
|
To detect songs that were deleted at the end of the
|
||||||
@@ -1169,6 +1207,7 @@ OK
|
|||||||
<cmdsynopsis>
|
<cmdsynopsis>
|
||||||
<command>plchangesposid</command>
|
<command>plchangesposid</command>
|
||||||
<arg choice="req"><replaceable>VERSION</replaceable></arg>
|
<arg choice="req"><replaceable>VERSION</replaceable></arg>
|
||||||
|
<arg><replaceable>START:END</replaceable></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@@ -1465,15 +1504,15 @@ OK
|
|||||||
<cmdsynopsis>
|
<cmdsynopsis>
|
||||||
<command>playlistmove</command>
|
<command>playlistmove</command>
|
||||||
<arg choice="req"><replaceable>NAME</replaceable></arg>
|
<arg choice="req"><replaceable>NAME</replaceable></arg>
|
||||||
<arg choice="req"><replaceable>SONGID</replaceable></arg>
|
<arg choice="req"><replaceable>FROM</replaceable></arg>
|
||||||
<arg choice="req"><replaceable>SONGPOS</replaceable></arg>
|
<arg choice="req"><replaceable>TO</replaceable></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>
|
<para>
|
||||||
Moves <varname>SONGID</varname> in the playlist
|
Moves the song at position <varname>FROM</varname> in
|
||||||
<filename>NAME.m3u</filename> to the position
|
the playlist <filename>NAME.m3u</filename> to the
|
||||||
<varname>SONGPOS</varname>.
|
position <varname>TO</varname>.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -1559,6 +1598,7 @@ OK
|
|||||||
<arg choice="req"><replaceable>TYPE</replaceable></arg>
|
<arg choice="req"><replaceable>TYPE</replaceable></arg>
|
||||||
<arg choice="req"><replaceable>WHAT</replaceable></arg>
|
<arg choice="req"><replaceable>WHAT</replaceable></arg>
|
||||||
<arg choice="opt"><replaceable>...</replaceable></arg>
|
<arg choice="opt"><replaceable>...</replaceable></arg>
|
||||||
|
<arg choice="opt">window <replaceable>START</replaceable>:<replaceable>END</replaceable></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@@ -1603,6 +1643,13 @@ OK
|
|||||||
<para>
|
<para>
|
||||||
<varname>WHAT</varname> is what to find.
|
<varname>WHAT</varname> is what to find.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
<varname>window</varname> can be used to query only a
|
||||||
|
portion of the real response. The parameter is two
|
||||||
|
zero-based record numbers; a start number and an end
|
||||||
|
number.
|
||||||
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
<varlistentry id="command_findadd">
|
<varlistentry id="command_findadd">
|
||||||
@@ -1754,7 +1801,7 @@ OK
|
|||||||
<para>
|
<para>
|
||||||
Clients that are connected via UNIX domain socket may
|
Clients that are connected via UNIX domain socket may
|
||||||
use this command to read the tags of an arbitrary local
|
use this command to read the tags of an arbitrary local
|
||||||
file (URI beginning with "file:///").
|
file (URI is an absolute path).
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
@@ -1769,8 +1816,7 @@ OK
|
|||||||
<para>
|
<para>
|
||||||
Read "comments" (i.e. key-value pairs) from the file
|
Read "comments" (i.e. key-value pairs) from the file
|
||||||
specified by "URI". This "URI" can be a path relative
|
specified by "URI". This "URI" can be a path relative
|
||||||
to the music directory or a URL in the form
|
to the music directory or an absolute path.
|
||||||
"file:///foo/bar.ogg".
|
|
||||||
</para>
|
</para>
|
||||||
<para>
|
<para>
|
||||||
This command may be used to list metadata of remote
|
This command may be used to list metadata of remote
|
||||||
@@ -1795,6 +1841,7 @@ OK
|
|||||||
<arg choice="req"><replaceable>TYPE</replaceable></arg>
|
<arg choice="req"><replaceable>TYPE</replaceable></arg>
|
||||||
<arg choice="req"><replaceable>WHAT</replaceable></arg>
|
<arg choice="req"><replaceable>WHAT</replaceable></arg>
|
||||||
<arg choice="opt"><replaceable>...</replaceable></arg>
|
<arg choice="opt"><replaceable>...</replaceable></arg>
|
||||||
|
<arg choice="opt">window <replaceable>START</replaceable>:<replaceable>END</replaceable></arg>
|
||||||
</cmdsynopsis>
|
</cmdsynopsis>
|
||||||
</term>
|
</term>
|
||||||
<listitem>
|
<listitem>
|
||||||
@@ -2119,6 +2166,30 @@ OK
|
|||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
</varlistentry>
|
</varlistentry>
|
||||||
|
|
||||||
|
<varlistentry id="command_sticker_find_equals">
|
||||||
|
<term>
|
||||||
|
<cmdsynopsis>
|
||||||
|
<command>sticker</command>
|
||||||
|
<arg choice="plain">find</arg>
|
||||||
|
<arg choice="req"><replaceable>TYPE</replaceable></arg>
|
||||||
|
<arg choice="req"><replaceable>URI</replaceable></arg>
|
||||||
|
<arg choice="req"><replaceable>NAME</replaceable></arg>
|
||||||
|
<arg choice="plain">=</arg>
|
||||||
|
<arg choice="req"><replaceable>VALUE</replaceable></arg>
|
||||||
|
</cmdsynopsis>
|
||||||
|
</term>
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
Searches for stickers with the given value.
|
||||||
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
Other supported operators are:
|
||||||
|
"<function><</function>", "<function>></function>"
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
|
</varlistentry>
|
||||||
</variablelist>
|
</variablelist>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
1446
doc/user.xml
1446
doc/user.xml
File diff suppressed because it is too large
Load Diff
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS])
|
# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
|
||||||
#
|
#
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
#
|
#
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
# the flags: "CFLAGS EXTRA-FLAGS FLAG". This can for example be used to
|
||||||
# force the compiler to issue an error when a bad flag is given.
|
# force the compiler to issue an error when a bad flag is given.
|
||||||
#
|
#
|
||||||
|
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
||||||
|
#
|
||||||
# NOTE: This macro depends on the AX_APPEND_FLAG and
|
# NOTE: This macro depends on the AX_APPEND_FLAG and
|
||||||
# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
|
# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
|
||||||
# AX_APPEND_LINK_FLAGS.
|
# AX_APPEND_LINK_FLAGS.
|
||||||
@@ -54,12 +56,12 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 4
|
#serial 5
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
|
AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
|
||||||
[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
|
[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
|
||||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
||||||
for flag in $1; do
|
for flag in $1; do
|
||||||
AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3])
|
AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
|
||||||
done
|
done
|
||||||
])dnl AX_APPEND_COMPILE_FLAGS
|
])dnl AX_APPEND_COMPILE_FLAGS
|
||||||
|
|||||||
@@ -49,21 +49,23 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 2
|
#serial 6
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_FLAG],
|
AC_DEFUN([AX_APPEND_FLAG],
|
||||||
[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
|
[dnl
|
||||||
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])dnl
|
AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
|
||||||
AS_VAR_SET_IF(FLAGS,
|
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
|
||||||
[case " AS_VAR_GET(FLAGS) " in
|
AS_VAR_SET_IF(FLAGS,[
|
||||||
*" $1 "*)
|
AS_CASE([" AS_VAR_GET(FLAGS) "],
|
||||||
AC_RUN_LOG([: FLAGS already contains $1])
|
[*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
|
||||||
;;
|
[
|
||||||
*)
|
AS_VAR_APPEND(FLAGS,[" $1"])
|
||||||
AC_RUN_LOG([: FLAGS="$FLAGS $1"])
|
AC_RUN_LOG([: FLAGS="$FLAGS"])
|
||||||
AS_VAR_SET(FLAGS, ["AS_VAR_GET(FLAGS) $1"])
|
])
|
||||||
;;
|
],
|
||||||
esac],
|
[
|
||||||
[AS_VAR_SET(FLAGS,["$1"])])
|
AS_VAR_SET(FLAGS,[$1])
|
||||||
|
AC_RUN_LOG([: FLAGS="$FLAGS"])
|
||||||
|
])
|
||||||
AS_VAR_POPDEF([FLAGS])dnl
|
AS_VAR_POPDEF([FLAGS])dnl
|
||||||
])dnl AX_APPEND_FLAG
|
])dnl AX_APPEND_FLAG
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
#
|
#
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
#
|
#
|
||||||
# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS])
|
# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
|
||||||
#
|
#
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
#
|
#
|
||||||
@@ -19,6 +19,8 @@
|
|||||||
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
|
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
|
||||||
# issue an error when a bad flag is given.
|
# issue an error when a bad flag is given.
|
||||||
#
|
#
|
||||||
|
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
||||||
|
#
|
||||||
# NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG.
|
# NOTE: This macro depends on the AX_APPEND_FLAG and AX_CHECK_LINK_FLAG.
|
||||||
# Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
|
# Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
|
||||||
#
|
#
|
||||||
@@ -52,12 +54,12 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 4
|
#serial 5
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_LINK_FLAGS],
|
AC_DEFUN([AX_APPEND_LINK_FLAGS],
|
||||||
[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
||||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
||||||
for flag in $1; do
|
for flag in $1; do
|
||||||
AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3])
|
AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4])
|
||||||
done
|
done
|
||||||
])dnl AX_APPEND_LINK_FLAGS
|
])dnl AX_APPEND_LINK_FLAGS
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
# and this notice are preserved. This file is offered as-is, without any
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
# warranty.
|
# warranty.
|
||||||
|
|
||||||
#serial 23
|
#serial 27
|
||||||
|
|
||||||
AC_DEFUN([AX_BOOST_BASE],
|
AC_DEFUN([AX_BOOST_BASE],
|
||||||
[
|
[
|
||||||
@@ -92,7 +92,10 @@ if test "x$want_boost" = "xyes"; then
|
|||||||
libsubdirs="lib"
|
libsubdirs="lib"
|
||||||
ax_arch=`uname -m`
|
ax_arch=`uname -m`
|
||||||
case $ax_arch in
|
case $ax_arch in
|
||||||
x86_64|ppc64|s390x|sparc64|aarch64)
|
x86_64)
|
||||||
|
libsubdirs="lib64 libx32 lib lib64"
|
||||||
|
;;
|
||||||
|
ppc64|s390x|sparc64|aarch64|ppc64le)
|
||||||
libsubdirs="lib64 lib lib64"
|
libsubdirs="lib64 lib lib64"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -170,6 +173,10 @@ if test "x$want_boost" = "xyes"; then
|
|||||||
dnl if we found no boost with system layout we search for boost libraries
|
dnl if we found no boost with system layout we search for boost libraries
|
||||||
dnl built and installed without the --layout=system option or for a staged(not installed) version
|
dnl built and installed without the --layout=system option or for a staged(not installed) version
|
||||||
if test "x$succeeded" != "xyes"; then
|
if test "x$succeeded" != "xyes"; then
|
||||||
|
CPPFLAGS="$CPPFLAGS_SAVED"
|
||||||
|
LDFLAGS="$LDFLAGS_SAVED"
|
||||||
|
BOOST_CPPFLAGS=
|
||||||
|
BOOST_LDFLAGS=
|
||||||
_version=0
|
_version=0
|
||||||
if test "$ac_boost_path" != ""; then
|
if test "$ac_boost_path" != ""; then
|
||||||
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
||||||
@@ -182,6 +189,12 @@ if test "x$want_boost" = "xyes"; then
|
|||||||
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
||||||
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
|
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
|
||||||
done
|
done
|
||||||
|
dnl if nothing found search for layout used in Windows distributions
|
||||||
|
if test -z "$BOOST_CPPFLAGS"; then
|
||||||
|
if test -d "$ac_boost_path/boost" && test -r "$ac_boost_path/boost"; then
|
||||||
|
BOOST_CPPFLAGS="-I$ac_boost_path"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if test "$cross_compiling" != yes; then
|
if test "$cross_compiling" != yes; then
|
||||||
|
|||||||
@@ -55,10 +55,10 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 3
|
#serial 4
|
||||||
|
|
||||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
||||||
[AC_PREREQ(2.59)dnl for _AC_LANG_PREFIX
|
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
||||||
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_[]_AC_LANG_ABBREV[]flags_$4_$1])dnl
|
||||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
||||||
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
||||||
@@ -67,7 +67,7 @@ AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
|||||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
[AS_VAR_SET(CACHEVAR,[yes])],
|
||||||
[AS_VAR_SET(CACHEVAR,[no])])
|
[AS_VAR_SET(CACHEVAR,[no])])
|
||||||
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
||||||
AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
|
AS_VAR_IF(CACHEVAR,yes,
|
||||||
[m4_default([$2], :)],
|
[m4_default([$2], :)],
|
||||||
[m4_default([$3], :)])
|
[m4_default([$3], :)])
|
||||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
AS_VAR_POPDEF([CACHEVAR])dnl
|
||||||
|
|||||||
@@ -55,10 +55,11 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 3
|
#serial 4
|
||||||
|
|
||||||
AC_DEFUN([AX_CHECK_LINK_FLAG],
|
AC_DEFUN([AX_CHECK_LINK_FLAG],
|
||||||
[AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
|
[AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_IF
|
||||||
|
AS_VAR_PUSHDEF([CACHEVAR],[ax_cv_check_ldflags_$4_$1])dnl
|
||||||
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
|
AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
|
||||||
ax_check_save_flags=$LDFLAGS
|
ax_check_save_flags=$LDFLAGS
|
||||||
LDFLAGS="$LDFLAGS $4 $1"
|
LDFLAGS="$LDFLAGS $4 $1"
|
||||||
@@ -66,7 +67,7 @@ AC_CACHE_CHECK([whether the linker accepts $1], CACHEVAR, [
|
|||||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
[AS_VAR_SET(CACHEVAR,[yes])],
|
||||||
[AS_VAR_SET(CACHEVAR,[no])])
|
[AS_VAR_SET(CACHEVAR,[no])])
|
||||||
LDFLAGS=$ax_check_save_flags])
|
LDFLAGS=$ax_check_save_flags])
|
||||||
AS_IF([test x"AS_VAR_GET(CACHEVAR)" = xyes],
|
AS_VAR_IF(CACHEVAR,yes,
|
||||||
[m4_default([$2], :)],
|
[m4_default([$2], :)],
|
||||||
[m4_default([$3], :)])
|
[m4_default([$3], :)])
|
||||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
AS_VAR_POPDEF([CACHEVAR])dnl
|
||||||
|
|||||||
564
m4/ax_cxx_compile_stdcxx.m4
Normal file
564
m4/ax_cxx_compile_stdcxx.m4
Normal file
@@ -0,0 +1,564 @@
|
|||||||
|
# ===========================================================================
|
||||||
|
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
|
||||||
|
# ===========================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the specified
|
||||||
|
# version of the C++ standard. If necessary, add switches to CXX and
|
||||||
|
# CXXCPP to enable support. VERSION may be '11' (for the C++11 standard)
|
||||||
|
# or '14' (for the C++14 standard).
|
||||||
|
#
|
||||||
|
# The second argument, if specified, indicates whether you insist on an
|
||||||
|
# extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
|
||||||
|
# -std=c++11). If neither is specified, you get whatever works, with
|
||||||
|
# preference for an extended mode.
|
||||||
|
#
|
||||||
|
# The third argument, if specified 'mandatory' or if left unspecified,
|
||||||
|
# indicates that baseline support for the specified C++ standard is
|
||||||
|
# required and that the macro should error out if no mode with that
|
||||||
|
# support is found. If specified 'optional', then configuration proceeds
|
||||||
|
# regardless, after defining HAVE_CXX${VERSION} if and only if a
|
||||||
|
# supporting mode is found.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
||||||
|
# Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
|
||||||
|
# Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
|
||||||
|
# Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
|
||||||
|
# Copyright (c) 2015 Paul Norman <penorman@mac.com>
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 4
|
||||||
|
|
||||||
|
dnl This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
|
||||||
|
dnl (serial version number 13).
|
||||||
|
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
|
||||||
|
m4_if([$1], [11], [],
|
||||||
|
[$1], [14], [],
|
||||||
|
[$1], [17], [m4_fatal([support for C++17 not yet implemented in AX_CXX_COMPILE_STDCXX])],
|
||||||
|
[m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$2], [], [],
|
||||||
|
[$2], [ext], [],
|
||||||
|
[$2], [noext], [],
|
||||||
|
[m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
|
||||||
|
m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
|
||||||
|
[$3], [optional], [ax_cxx_compile_cxx$1_required=false],
|
||||||
|
[m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
|
||||||
|
AC_LANG_PUSH([C++])dnl
|
||||||
|
ac_success=no
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
|
||||||
|
ax_cv_cxx_compile_cxx$1,
|
||||||
|
[AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=yes],
|
||||||
|
[ax_cv_cxx_compile_cxx$1=no])])
|
||||||
|
if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
|
||||||
|
ac_success=yes
|
||||||
|
fi
|
||||||
|
|
||||||
|
m4_if([$2], [noext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
for switch in -std=gnu++$1 -std=gnu++0x; do
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
|
||||||
|
m4_if([$2], [ext], [], [dnl
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
dnl HP's aCC needs +std=c++11 according to:
|
||||||
|
dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
|
||||||
|
dnl Cray's crayCC needs "-h std=c++11"
|
||||||
|
for switch in -std=c++$1 -std=c++0x +std=c++$1 "-h std=c++$1"; do
|
||||||
|
cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
|
||||||
|
AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
|
||||||
|
$cachevar,
|
||||||
|
[ac_save_CXX="$CXX"
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
|
||||||
|
[eval $cachevar=yes],
|
||||||
|
[eval $cachevar=no])
|
||||||
|
CXX="$ac_save_CXX"])
|
||||||
|
if eval test x\$$cachevar = xyes; then
|
||||||
|
CXX="$CXX $switch"
|
||||||
|
if test -n "$CXXCPP" ; then
|
||||||
|
CXXCPP="$CXXCPP $switch"
|
||||||
|
fi
|
||||||
|
ac_success=yes
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi])
|
||||||
|
AC_LANG_POP([C++])
|
||||||
|
if test x$ax_cxx_compile_cxx$1_required = xtrue; then
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if test x$ac_success = xno; then
|
||||||
|
HAVE_CXX$1=0
|
||||||
|
AC_MSG_NOTICE([No compiler with C++$1 support was found])
|
||||||
|
else
|
||||||
|
HAVE_CXX$1=1
|
||||||
|
AC_DEFINE(HAVE_CXX$1,1,
|
||||||
|
[define if the compiler supports basic C++$1 syntax])
|
||||||
|
fi
|
||||||
|
AC_SUBST(HAVE_CXX$1)
|
||||||
|
])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++11 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dnl Test body for checking C++14 support
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_11
|
||||||
|
_AX_CXX_COMPILE_STDCXX_testbody_new_in_14
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++11
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++11, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201103L
|
||||||
|
|
||||||
|
#error "This is not a C++11 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx11
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_static_assert
|
||||||
|
{
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct check
|
||||||
|
{
|
||||||
|
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_final_override
|
||||||
|
{
|
||||||
|
|
||||||
|
struct Base
|
||||||
|
{
|
||||||
|
virtual void f() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Derived : public Base
|
||||||
|
{
|
||||||
|
virtual void f() override {}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_double_right_angle_brackets
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct check {};
|
||||||
|
|
||||||
|
typedef check<void> single_type;
|
||||||
|
typedef check<check<void>> double_type;
|
||||||
|
typedef check<check<check<void>>> triple_type;
|
||||||
|
typedef check<check<check<check<void>>>> quadruple_type;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_decltype
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
f()
|
||||||
|
{
|
||||||
|
int a = 1;
|
||||||
|
decltype(a) b = 2;
|
||||||
|
return a + b;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static const bool value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static const bool value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
auto
|
||||||
|
add(T1 a1, T2 a2) -> decltype(a1 + a2)
|
||||||
|
{
|
||||||
|
return a1 + a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test(const int c, volatile int v)
|
||||||
|
{
|
||||||
|
static_assert(is_same<int, decltype(0)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(c)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(v)>::value == false, "");
|
||||||
|
auto ac = c;
|
||||||
|
auto av = v;
|
||||||
|
auto sumi = ac + av + 'x';
|
||||||
|
auto sumf = ac + av + 1.0;
|
||||||
|
static_assert(is_same<int, decltype(ac)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(av)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumi)>::value == true, "");
|
||||||
|
static_assert(is_same<int, decltype(sumf)>::value == false, "");
|
||||||
|
static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
|
||||||
|
return (sumf > 0.0) ? sumi : add(c, v);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_noexcept
|
||||||
|
{
|
||||||
|
|
||||||
|
int f() { return 0; }
|
||||||
|
int g() noexcept { return 0; }
|
||||||
|
|
||||||
|
static_assert(noexcept(f()) == false, "");
|
||||||
|
static_assert(noexcept(g()) == true, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
|
||||||
|
{
|
||||||
|
return *s ? strlen_c_r(s + 1, acc + 1) : acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
unsigned long constexpr
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
return strlen_c_r(s, 0UL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("1") == 1UL, "");
|
||||||
|
static_assert(strlen_c("example") == 7UL, "");
|
||||||
|
static_assert(strlen_c("another\0example") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_rvalue_references
|
||||||
|
{
|
||||||
|
|
||||||
|
template < int N >
|
||||||
|
struct answer
|
||||||
|
{
|
||||||
|
static constexpr int value = N;
|
||||||
|
};
|
||||||
|
|
||||||
|
answer<1> f(int&) { return answer<1>(); }
|
||||||
|
answer<2> f(const int&) { return answer<2>(); }
|
||||||
|
answer<3> f(int&&) { return answer<3>(); }
|
||||||
|
|
||||||
|
void
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
int i = 0;
|
||||||
|
const int c = 0;
|
||||||
|
static_assert(decltype(f(i))::value == 1, "");
|
||||||
|
static_assert(decltype(f(c))::value == 2, "");
|
||||||
|
static_assert(decltype(f(0))::value == 3, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_uniform_initialization
|
||||||
|
{
|
||||||
|
|
||||||
|
struct test
|
||||||
|
{
|
||||||
|
static const int zero {};
|
||||||
|
static const int one {1};
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(test::zero == 0, "");
|
||||||
|
static_assert(test::one == 1, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
void
|
||||||
|
test1()
|
||||||
|
{
|
||||||
|
auto lambda1 = [](){};
|
||||||
|
auto lambda2 = lambda1;
|
||||||
|
lambda1();
|
||||||
|
lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test2()
|
||||||
|
{
|
||||||
|
auto a = [](int i, int j){ return i + j; }(1, 2);
|
||||||
|
auto b = []() -> int { return '0'; }();
|
||||||
|
auto c = [=](){ return a + b; }();
|
||||||
|
auto d = [&](){ return c; }();
|
||||||
|
auto e = [a, &b](int x) mutable {
|
||||||
|
const auto identity = [](int y){ return y; };
|
||||||
|
for (auto i = 0; i < a; ++i)
|
||||||
|
a += b--;
|
||||||
|
return x + identity(a + b);
|
||||||
|
}(0);
|
||||||
|
return a + b + c + d + e;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
test3()
|
||||||
|
{
|
||||||
|
const auto nullary = [](){ return 0; };
|
||||||
|
const auto unary = [](int x){ return x; };
|
||||||
|
using nullary_t = decltype(nullary);
|
||||||
|
using unary_t = decltype(unary);
|
||||||
|
const auto higher1st = [](nullary_t f){ return f(); };
|
||||||
|
const auto higher2nd = [unary](nullary_t f1){
|
||||||
|
return [unary, f1](unary_t f2){ return f2(unary(f1())); };
|
||||||
|
};
|
||||||
|
return higher1st(nullary) + higher2nd(nullary)(unary);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_variadic_templates
|
||||||
|
{
|
||||||
|
|
||||||
|
template <int...>
|
||||||
|
struct sum;
|
||||||
|
|
||||||
|
template <int N0, int... N1toN>
|
||||||
|
struct sum<N0, N1toN...>
|
||||||
|
{
|
||||||
|
static constexpr auto value = N0 + sum<N1toN...>::value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct sum<>
|
||||||
|
{
|
||||||
|
static constexpr auto value = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
static_assert(sum<>::value == 0, "");
|
||||||
|
static_assert(sum<1>::value == 1, "");
|
||||||
|
static_assert(sum<23>::value == 23, "");
|
||||||
|
static_assert(sum<1, 2>::value == 3, "");
|
||||||
|
static_assert(sum<5, 5, 11>::value == 21, "");
|
||||||
|
static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
|
||||||
|
// Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
|
||||||
|
// because of this.
|
||||||
|
namespace test_template_alias_sfinae
|
||||||
|
{
|
||||||
|
|
||||||
|
struct foo {};
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
using member = typename T::member_type;
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(...) {}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
void func(member<T>*) {}
|
||||||
|
|
||||||
|
void test();
|
||||||
|
|
||||||
|
void test() { func<foo>(0); }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx11
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201103L
|
||||||
|
|
||||||
|
]])
|
||||||
|
|
||||||
|
|
||||||
|
dnl Tests for new features in C++14
|
||||||
|
|
||||||
|
m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
|
||||||
|
|
||||||
|
// If the compiler admits that it is not ready for C++14, why torture it?
|
||||||
|
// Hopefully, this will speed up the test.
|
||||||
|
|
||||||
|
#ifndef __cplusplus
|
||||||
|
|
||||||
|
#error "This is not a C++ compiler"
|
||||||
|
|
||||||
|
#elif __cplusplus < 201300L
|
||||||
|
|
||||||
|
#error "This is not a C++14 compiler"
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
namespace cxx14
|
||||||
|
{
|
||||||
|
|
||||||
|
namespace test_polymorphic_lambdas
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
const auto lambda = [](auto&&... args){
|
||||||
|
const auto istiny = [](auto x){
|
||||||
|
return (sizeof(x) == 1UL) ? 1 : 0;
|
||||||
|
};
|
||||||
|
const int aretiny[] = { istiny(args)... };
|
||||||
|
return aretiny[0];
|
||||||
|
};
|
||||||
|
return lambda(1, 1L, 1.0f, '1');
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_binary_literals
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ivii = 0b0000000000101010;
|
||||||
|
static_assert(ivii == 42, "wrong value");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef DISALLOW_GCC48
|
||||||
|
namespace test_generalized_constexpr
|
||||||
|
{
|
||||||
|
|
||||||
|
template < typename CharT >
|
||||||
|
constexpr unsigned long
|
||||||
|
strlen_c(const CharT *const s) noexcept
|
||||||
|
{
|
||||||
|
auto length = 0UL;
|
||||||
|
for (auto p = s; *p; ++p)
|
||||||
|
++length;
|
||||||
|
return length;
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(strlen_c("") == 0UL, "");
|
||||||
|
static_assert(strlen_c("x") == 1UL, "");
|
||||||
|
static_assert(strlen_c("test") == 4UL, "");
|
||||||
|
static_assert(strlen_c("another\0test") == 7UL, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace test_lambda_init_capture
|
||||||
|
{
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
const auto lambda1 = [a = x](int b){ return a + b; };
|
||||||
|
const auto lambda2 = [a = lambda1(x)](){ return a; };
|
||||||
|
return lambda2();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_digit_seperators
|
||||||
|
{
|
||||||
|
|
||||||
|
constexpr auto ten_million = 100'000'000;
|
||||||
|
static_assert(ten_million == 100000000, "");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace test_return_type_deduction
|
||||||
|
{
|
||||||
|
|
||||||
|
auto f(int& x) { return x; }
|
||||||
|
decltype(auto) g(int& x) { return x; }
|
||||||
|
|
||||||
|
template < typename T1, typename T2 >
|
||||||
|
struct is_same
|
||||||
|
{
|
||||||
|
static constexpr auto value = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
template < typename T >
|
||||||
|
struct is_same<T, T>
|
||||||
|
{
|
||||||
|
static constexpr auto value = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
int
|
||||||
|
test()
|
||||||
|
{
|
||||||
|
auto x = 0;
|
||||||
|
static_assert(is_same<int, decltype(f(x))>::value, "");
|
||||||
|
static_assert(is_same<int&, decltype(g(x))>::value, "");
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace cxx14
|
||||||
|
|
||||||
|
#endif // __cplusplus >= 201402L
|
||||||
|
|
||||||
|
]])
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_0x.html
|
|
||||||
# ============================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_CXX_COMPILE_STDCXX_0X
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Check for baseline language coverage in the compiler for the C++0x
|
|
||||||
# standard.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
|
|
||||||
#
|
|
||||||
# Copying and distribution of this file, with or without modification, are
|
|
||||||
# permitted in any medium without royalty provided the copyright notice
|
|
||||||
# and this notice are preserved. This file is offered as-is, without any
|
|
||||||
# warranty.
|
|
||||||
|
|
||||||
#serial 7
|
|
||||||
|
|
||||||
AU_ALIAS([AC_CXX_COMPILE_STDCXX_0X], [AX_CXX_COMPILE_STDCXX_0X])
|
|
||||||
AC_DEFUN([AX_CXX_COMPILE_STDCXX_0X], [
|
|
||||||
AC_CACHE_CHECK(if g++ supports C++0x features without additional flags,
|
|
||||||
ax_cv_cxx_compile_cxx0x_native,
|
|
||||||
[AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
AC_TRY_COMPILE([
|
|
||||||
template <typename T>
|
|
||||||
struct check
|
|
||||||
{
|
|
||||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef check<check<bool>> right_angle_brackets;
|
|
||||||
|
|
||||||
int a;
|
|
||||||
decltype(a) b;
|
|
||||||
|
|
||||||
typedef check<int> check_type;
|
|
||||||
check_type c;
|
|
||||||
check_type&& cr = static_cast<check_type&&>(c);],,
|
|
||||||
ax_cv_cxx_compile_cxx0x_native=yes, ax_cv_cxx_compile_cxx0x_native=no)
|
|
||||||
AC_LANG_RESTORE
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK(if g++ supports C++0x features with -std=c++0x,
|
|
||||||
ax_cv_cxx_compile_cxx0x_cxx,
|
|
||||||
[AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
ac_save_CXXFLAGS="$CXXFLAGS"
|
|
||||||
CXXFLAGS="$CXXFLAGS -std=c++0x"
|
|
||||||
AC_TRY_COMPILE([
|
|
||||||
template <typename T>
|
|
||||||
struct check
|
|
||||||
{
|
|
||||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef check<check<bool>> right_angle_brackets;
|
|
||||||
|
|
||||||
int a;
|
|
||||||
decltype(a) b;
|
|
||||||
|
|
||||||
typedef check<int> check_type;
|
|
||||||
check_type c;
|
|
||||||
check_type&& cr = static_cast<check_type&&>(c);],,
|
|
||||||
ax_cv_cxx_compile_cxx0x_cxx=yes, ax_cv_cxx_compile_cxx0x_cxx=no)
|
|
||||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
|
||||||
AC_LANG_RESTORE
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK(if g++ supports C++0x features with -std=gnu++0x,
|
|
||||||
ax_cv_cxx_compile_cxx0x_gxx,
|
|
||||||
[AC_LANG_SAVE
|
|
||||||
AC_LANG_CPLUSPLUS
|
|
||||||
ac_save_CXXFLAGS="$CXXFLAGS"
|
|
||||||
CXXFLAGS="$CXXFLAGS -std=gnu++0x"
|
|
||||||
AC_TRY_COMPILE([
|
|
||||||
template <typename T>
|
|
||||||
struct check
|
|
||||||
{
|
|
||||||
static_assert(sizeof(int) <= sizeof(T), "not big enough");
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef check<check<bool>> right_angle_brackets;
|
|
||||||
|
|
||||||
int a;
|
|
||||||
decltype(a) b;
|
|
||||||
|
|
||||||
typedef check<int> check_type;
|
|
||||||
check_type c;
|
|
||||||
check_type&& cr = static_cast<check_type&&>(c);],,
|
|
||||||
ax_cv_cxx_compile_cxx0x_gxx=yes, ax_cv_cxx_compile_cxx0x_gxx=no)
|
|
||||||
CXXFLAGS="$ac_save_CXXFLAGS"
|
|
||||||
AC_LANG_RESTORE
|
|
||||||
])
|
|
||||||
|
|
||||||
if test "$ax_cv_cxx_compile_cxx0x_native" = yes ||
|
|
||||||
test "$ax_cv_cxx_compile_cxx0x_cxx" = yes ||
|
|
||||||
test "$ax_cv_cxx_compile_cxx0x_gxx" = yes; then
|
|
||||||
AC_DEFINE(HAVE_STDCXX_0X,,[Define if g++ supports C++0x features. ])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
34
m4/ax_cxx_compile_stdcxx_14.m4
Normal file
34
m4/ax_cxx_compile_stdcxx_14.m4
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
# ============================================================================
|
||||||
|
# http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx_14.html
|
||||||
|
# ============================================================================
|
||||||
|
#
|
||||||
|
# SYNOPSIS
|
||||||
|
#
|
||||||
|
# AX_CXX_COMPILE_STDCXX_14([ext|noext], [mandatory|optional])
|
||||||
|
#
|
||||||
|
# DESCRIPTION
|
||||||
|
#
|
||||||
|
# Check for baseline language coverage in the compiler for the C++14
|
||||||
|
# standard; if necessary, add switches to CXX and CXXCPP to enable
|
||||||
|
# support.
|
||||||
|
#
|
||||||
|
# This macro is a convenience alias for calling the AX_CXX_COMPILE_STDCXX
|
||||||
|
# macro with the version set to C++14. The two optional arguments are
|
||||||
|
# forwarded literally as the second and third argument respectively.
|
||||||
|
# Please see the documentation for the AX_CXX_COMPILE_STDCXX macro for
|
||||||
|
# more information. If you want to use this macro, you also need to
|
||||||
|
# download the ax_cxx_compile_stdcxx.m4 file.
|
||||||
|
#
|
||||||
|
# LICENSE
|
||||||
|
#
|
||||||
|
# Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
|
||||||
|
#
|
||||||
|
# Copying and distribution of this file, with or without modification, are
|
||||||
|
# permitted in any medium without royalty provided the copyright notice
|
||||||
|
# and this notice are preserved. This file is offered as-is, without any
|
||||||
|
# warranty.
|
||||||
|
|
||||||
|
#serial 4
|
||||||
|
|
||||||
|
AX_REQUIRE_DEFINED([AX_CXX_COMPILE_STDCXX])
|
||||||
|
AC_DEFUN([AX_CXX_COMPILE_STDCXX_14], [AX_CXX_COMPILE_STDCXX([14], [$1], [$2])])
|
||||||
349
m4/ax_pthread.m4
349
m4/ax_pthread.m4
@@ -19,10 +19,10 @@
|
|||||||
# is necessary on AIX to use the special cc_r compiler alias.)
|
# is necessary on AIX to use the special cc_r compiler alias.)
|
||||||
#
|
#
|
||||||
# NOTE: You are assumed to not only compile your program with these flags,
|
# NOTE: You are assumed to not only compile your program with these flags,
|
||||||
# but also link it with them as well. e.g. you should link with
|
# but also to link with them as well. For example, you might link with
|
||||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
||||||
#
|
#
|
||||||
# If you are only building threads programs, you may wish to use these
|
# If you are only building threaded programs, you may wish to use these
|
||||||
# variables in your default LIBS, CFLAGS, and CC:
|
# variables in your default LIBS, CFLAGS, and CC:
|
||||||
#
|
#
|
||||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
# LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
@@ -30,8 +30,8 @@
|
|||||||
# CC="$PTHREAD_CC"
|
# CC="$PTHREAD_CC"
|
||||||
#
|
#
|
||||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
||||||
# has a nonstandard name, defines PTHREAD_CREATE_JOINABLE to that name
|
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
||||||
# (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
||||||
#
|
#
|
||||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
||||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
||||||
@@ -82,35 +82,40 @@
|
|||||||
# modified version of the Autoconf Macro, you may extend this special
|
# modified version of the Autoconf Macro, you may extend this special
|
||||||
# exception to the GPL to apply to your modified version as well.
|
# exception to the GPL to apply to your modified version as well.
|
||||||
|
|
||||||
#serial 21
|
#serial 23
|
||||||
|
|
||||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
||||||
AC_DEFUN([AX_PTHREAD], [
|
AC_DEFUN([AX_PTHREAD], [
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
AC_REQUIRE([AC_CANONICAL_HOST])
|
||||||
|
AC_REQUIRE([AC_PROG_CC])
|
||||||
|
AC_REQUIRE([AC_PROG_SED])
|
||||||
AC_LANG_PUSH([C])
|
AC_LANG_PUSH([C])
|
||||||
ax_pthread_ok=no
|
ax_pthread_ok=no
|
||||||
|
|
||||||
# We used to check for pthread.h first, but this fails if pthread.h
|
# We used to check for pthread.h first, but this fails if pthread.h
|
||||||
# requires special compiler flags (e.g. on True64 or Sequent).
|
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
||||||
# It gets checked for in the link test anyway.
|
# It gets checked for in the link test anyway.
|
||||||
|
|
||||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
||||||
# etcetera environment variables, and if threads linking works using
|
# etcetera environment variables, and if threads linking works using
|
||||||
# them:
|
# them:
|
||||||
if test x"$PTHREAD_LIBS$PTHREAD_CFLAGS" != x; then
|
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
||||||
save_CFLAGS="$CFLAGS"
|
ax_pthread_save_CC="$CC"
|
||||||
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
|
ax_pthread_save_LIBS="$LIBS"
|
||||||
|
AS_IF([test "x$PTHREAD_CC" != "x"], [CC="$PTHREAD_CC"])
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
save_LIBS="$LIBS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
AC_MSG_CHECKING([for pthread_join in LIBS=$PTHREAD_LIBS with CFLAGS=$PTHREAD_CFLAGS])
|
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
||||||
AC_TRY_LINK_FUNC([pthread_join], [ax_pthread_ok=yes])
|
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
AC_MSG_RESULT([$ax_pthread_ok])
|
||||||
if test x"$ax_pthread_ok" = xno; then
|
if test "x$ax_pthread_ok" = "xno"; then
|
||||||
PTHREAD_LIBS=""
|
PTHREAD_LIBS=""
|
||||||
PTHREAD_CFLAGS=""
|
PTHREAD_CFLAGS=""
|
||||||
fi
|
fi
|
||||||
LIBS="$save_LIBS"
|
CC="$ax_pthread_save_CC"
|
||||||
CFLAGS="$save_CFLAGS"
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
|
LIBS="$ax_pthread_save_LIBS"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# We must check for the threads library under a number of different
|
# We must check for the threads library under a number of different
|
||||||
@@ -123,7 +128,7 @@ fi
|
|||||||
# which indicates that we try without any flags at all, and "pthread-config"
|
# which indicates that we try without any flags at all, and "pthread-config"
|
||||||
# which is a program returning the flags for the Pth emulation library.
|
# which is a program returning the flags for the Pth emulation library.
|
||||||
|
|
||||||
ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
||||||
|
|
||||||
# The ordering *is* (sometimes) important. Some notes on the
|
# The ordering *is* (sometimes) important. Some notes on the
|
||||||
# individual items follow:
|
# individual items follow:
|
||||||
@@ -132,82 +137,225 @@ ax_pthread_flags="pthreads none -Kthread -kthread lthread -pthread -pthreads -mt
|
|||||||
# none: in case threads are in libc; should be tried before -Kthread and
|
# none: in case threads are in libc; should be tried before -Kthread and
|
||||||
# other compiler flags to prevent continual compiler warnings
|
# other compiler flags to prevent continual compiler warnings
|
||||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
||||||
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
||||||
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
# (Note: HP C rejects this with "bad form for `-t' option")
|
||||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads)
|
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
||||||
# -pthreads: Solaris/gcc
|
|
||||||
# -mthreads: Mingw32/gcc, Lynx/gcc
|
|
||||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
||||||
# doesn't hurt to check since this sometimes defines pthreads too;
|
# doesn't hurt to check since this sometimes defines pthreads and
|
||||||
# also defines -D_REENTRANT)
|
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
||||||
# ... -mt is also the pthreads flag for HP/aCC
|
# is present but should not be used directly; and before -mthreads,
|
||||||
|
# because the compiler interprets this as "-mt" + "-hreads")
|
||||||
|
# -mthreads: Mingw32/gcc, Lynx/gcc
|
||||||
# pthread: Linux, etcetera
|
# pthread: Linux, etcetera
|
||||||
# --thread-safe: KAI C++
|
# --thread-safe: KAI C++
|
||||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
# pthread-config: use pthread-config program (for GNU Pth library)
|
||||||
|
|
||||||
case ${host_os} in
|
case $host_os in
|
||||||
|
|
||||||
|
freebsd*)
|
||||||
|
|
||||||
|
# -kthread: FreeBSD kernel threads (preferred to -pthread since SMP-able)
|
||||||
|
# lthread: LinuxThreads port on FreeBSD (also preferred to -pthread)
|
||||||
|
|
||||||
|
ax_pthread_flags="-kthread lthread $ax_pthread_flags"
|
||||||
|
;;
|
||||||
|
|
||||||
|
hpux*)
|
||||||
|
|
||||||
|
# From the cc(1) man page: "[-mt] Sets various -D flags to enable
|
||||||
|
# multi-threading and also sets -lpthread."
|
||||||
|
|
||||||
|
ax_pthread_flags="-mt -pthread pthread $ax_pthread_flags"
|
||||||
|
;;
|
||||||
|
|
||||||
|
openedition*)
|
||||||
|
|
||||||
|
# IBM z/OS requires a feature-test macro to be defined in order to
|
||||||
|
# enable POSIX threads at all, so give the user a hint if this is
|
||||||
|
# not set. (We don't define these ourselves, as they can affect
|
||||||
|
# other portions of the system API in unpredictable ways.)
|
||||||
|
|
||||||
|
AC_EGREP_CPP([AX_PTHREAD_ZOS_MISSING],
|
||||||
|
[
|
||||||
|
# if !defined(_OPEN_THREADS) && !defined(_UNIX03_THREADS)
|
||||||
|
AX_PTHREAD_ZOS_MISSING
|
||||||
|
# endif
|
||||||
|
],
|
||||||
|
[AC_MSG_WARN([IBM z/OS requires -D_OPEN_THREADS or -D_UNIX03_THREADS to enable pthreads support.])])
|
||||||
|
;;
|
||||||
|
|
||||||
solaris*)
|
solaris*)
|
||||||
|
|
||||||
# On Solaris (at least, for some versions), libc contains stubbed
|
# On Solaris (at least, for some versions), libc contains stubbed
|
||||||
# (non-functional) versions of the pthreads routines, so link-based
|
# (non-functional) versions of the pthreads routines, so link-based
|
||||||
# tests will erroneously succeed. (We need to link with -pthreads/-mt/
|
# tests will erroneously succeed. (N.B.: The stubs are missing
|
||||||
# -lpthread.) (The stubs are missing pthread_cleanup_push, or rather
|
# pthread_cleanup_push, or rather a function called by this macro,
|
||||||
# a function called by this macro, so we could check for that, but
|
# so we could check for that, but who knows whether they'll stub
|
||||||
# who knows whether they'll stub that too in a future libc.) So,
|
# that too in a future libc.) So we'll check first for the
|
||||||
# we'll just look for -pthreads and -lpthread first:
|
# standard Solaris way of linking pthreads (-mt -lpthread).
|
||||||
|
|
||||||
ax_pthread_flags="-pthreads pthread -mt -pthread $ax_pthread_flags"
|
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
|
||||||
;;
|
|
||||||
|
|
||||||
darwin*)
|
|
||||||
ax_pthread_flags="-pthread $ax_pthread_flags"
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
# Clang doesn't consider unrecognized options an error unless we specify
|
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
||||||
# -Werror. We throw in some extra Clang-specific options to ensure that
|
|
||||||
# this doesn't happen for GCC, which also accepts -Werror.
|
|
||||||
|
|
||||||
AC_MSG_CHECKING([if compiler needs -Werror to reject unknown flags])
|
AS_IF([test "x$GCC" = "xyes"],
|
||||||
save_CFLAGS="$CFLAGS"
|
[ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
|
||||||
ax_pthread_extra_flags="-Werror"
|
|
||||||
CFLAGS="$CFLAGS $ax_pthread_extra_flags -Wunknown-warning-option -Wsizeof-array-argument"
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([int foo(void);],[foo()])],
|
|
||||||
[AC_MSG_RESULT([yes])],
|
|
||||||
[ax_pthread_extra_flags=
|
|
||||||
AC_MSG_RESULT([no])])
|
|
||||||
CFLAGS="$save_CFLAGS"
|
|
||||||
|
|
||||||
if test x"$ax_pthread_ok" = xno; then
|
# The presence of a feature test macro requesting re-entrant function
|
||||||
for flag in $ax_pthread_flags; do
|
# definitions is, on some systems, a strong hint that pthreads support is
|
||||||
|
# correctly enabled
|
||||||
|
|
||||||
case $flag in
|
case $host_os in
|
||||||
|
darwin* | hpux* | linux* | osf* | solaris*)
|
||||||
|
ax_pthread_check_macro="_REENTRANT"
|
||||||
|
;;
|
||||||
|
|
||||||
|
aix*)
|
||||||
|
ax_pthread_check_macro="_THREAD_SAFE"
|
||||||
|
;;
|
||||||
|
|
||||||
|
*)
|
||||||
|
ax_pthread_check_macro="--"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
AS_IF([test "x$ax_pthread_check_macro" = "x--"],
|
||||||
|
[ax_pthread_check_cond=0],
|
||||||
|
[ax_pthread_check_cond="!defined($ax_pthread_check_macro)"])
|
||||||
|
|
||||||
|
# Are we compiling with Clang?
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([whether $CC is Clang],
|
||||||
|
[ax_cv_PTHREAD_CLANG],
|
||||||
|
[ax_cv_PTHREAD_CLANG=no
|
||||||
|
# Note that Autoconf sets GCC=yes for Clang as well as GCC
|
||||||
|
if test "x$GCC" = "xyes"; then
|
||||||
|
AC_EGREP_CPP([AX_PTHREAD_CC_IS_CLANG],
|
||||||
|
[/* Note: Clang 2.7 lacks __clang_[a-z]+__ */
|
||||||
|
# if defined(__clang__) && defined(__llvm__)
|
||||||
|
AX_PTHREAD_CC_IS_CLANG
|
||||||
|
# endif
|
||||||
|
],
|
||||||
|
[ax_cv_PTHREAD_CLANG=yes])
|
||||||
|
fi
|
||||||
|
])
|
||||||
|
ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
|
||||||
|
|
||||||
|
ax_pthread_clang_warning=no
|
||||||
|
|
||||||
|
# Clang needs special handling, because older versions handle the -pthread
|
||||||
|
# option in a rather... idiosyncratic way
|
||||||
|
|
||||||
|
if test "x$ax_pthread_clang" = "xyes"; then
|
||||||
|
|
||||||
|
# Clang takes -pthread; it has never supported any other flag
|
||||||
|
|
||||||
|
# (Note 1: This will need to be revisited if a system that Clang
|
||||||
|
# supports has POSIX threads in a separate library. This tends not
|
||||||
|
# to be the way of modern systems, but it's conceivable.)
|
||||||
|
|
||||||
|
# (Note 2: On some systems, notably Darwin, -pthread is not needed
|
||||||
|
# to get POSIX threads support; the API is always present and
|
||||||
|
# active. We could reasonably leave PTHREAD_CFLAGS empty. But
|
||||||
|
# -pthread does define _REENTRANT, and while the Darwin headers
|
||||||
|
# ignore this macro, third-party headers might not.)
|
||||||
|
|
||||||
|
PTHREAD_CFLAGS="-pthread"
|
||||||
|
PTHREAD_LIBS=
|
||||||
|
|
||||||
|
ax_pthread_ok=yes
|
||||||
|
|
||||||
|
# However, older versions of Clang make a point of warning the user
|
||||||
|
# that, in an invocation where only linking and no compilation is
|
||||||
|
# taking place, the -pthread option has no effect ("argument unused
|
||||||
|
# during compilation"). They expect -pthread to be passed in only
|
||||||
|
# when source code is being compiled.
|
||||||
|
#
|
||||||
|
# Problem is, this is at odds with the way Automake and most other
|
||||||
|
# C build frameworks function, which is that the same flags used in
|
||||||
|
# compilation (CFLAGS) are also used in linking. Many systems
|
||||||
|
# supported by AX_PTHREAD require exactly this for POSIX threads
|
||||||
|
# support, and in fact it is often not straightforward to specify a
|
||||||
|
# flag that is used only in the compilation phase and not in
|
||||||
|
# linking. Such a scenario is extremely rare in practice.
|
||||||
|
#
|
||||||
|
# Even though use of the -pthread flag in linking would only print
|
||||||
|
# a warning, this can be a nuisance for well-run software projects
|
||||||
|
# that build with -Werror. So if the active version of Clang has
|
||||||
|
# this misfeature, we search for an option to squash it.
|
||||||
|
|
||||||
|
AC_CACHE_CHECK([whether Clang needs flag to prevent "argument unused" warning when linking with -pthread],
|
||||||
|
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG],
|
||||||
|
[ax_cv_PTHREAD_CLANG_NO_WARN_FLAG=unknown
|
||||||
|
# Create an alternate version of $ac_link that compiles and
|
||||||
|
# links in two steps (.c -> .o, .o -> exe) instead of one
|
||||||
|
# (.c -> exe), because the warning occurs only in the second
|
||||||
|
# step
|
||||||
|
ax_pthread_save_ac_link="$ac_link"
|
||||||
|
ax_pthread_sed='s/conftest\.\$ac_ext/conftest.$ac_objext/g'
|
||||||
|
ax_pthread_link_step=`$as_echo "$ac_link" | sed "$ax_pthread_sed"`
|
||||||
|
ax_pthread_2step_ac_link="($ac_compile) && (echo ==== >&5) && ($ax_pthread_link_step)"
|
||||||
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
|
for ax_pthread_try in '' -Qunused-arguments -Wno-unused-command-line-argument unknown; do
|
||||||
|
AS_IF([test "x$ax_pthread_try" = "xunknown"], [break])
|
||||||
|
CFLAGS="-Werror -Wunknown-warning-option $ax_pthread_try -pthread $ax_pthread_save_CFLAGS"
|
||||||
|
ac_link="$ax_pthread_save_ac_link"
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||||
|
[ac_link="$ax_pthread_2step_ac_link"
|
||||||
|
AC_LINK_IFELSE([AC_LANG_SOURCE([[int main(void){return 0;}]])],
|
||||||
|
[break])
|
||||||
|
])
|
||||||
|
done
|
||||||
|
ac_link="$ax_pthread_save_ac_link"
|
||||||
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
|
AS_IF([test "x$ax_pthread_try" = "x"], [ax_pthread_try=no])
|
||||||
|
ax_cv_PTHREAD_CLANG_NO_WARN_FLAG="$ax_pthread_try"
|
||||||
|
])
|
||||||
|
|
||||||
|
case "$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG" in
|
||||||
|
no | unknown) ;;
|
||||||
|
*) PTHREAD_CFLAGS="$ax_cv_PTHREAD_CLANG_NO_WARN_FLAG $PTHREAD_CFLAGS" ;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
fi # $ax_pthread_clang = yes
|
||||||
|
|
||||||
|
if test "x$ax_pthread_ok" = "xno"; then
|
||||||
|
for ax_pthread_try_flag in $ax_pthread_flags; do
|
||||||
|
|
||||||
|
case $ax_pthread_try_flag in
|
||||||
none)
|
none)
|
||||||
AC_MSG_CHECKING([whether pthreads work without any flags])
|
AC_MSG_CHECKING([whether pthreads work without any flags])
|
||||||
;;
|
;;
|
||||||
|
|
||||||
|
-mt,pthread)
|
||||||
|
AC_MSG_CHECKING([whether pthreads work with -mt -lpthread])
|
||||||
|
PTHREAD_CFLAGS="-mt"
|
||||||
|
PTHREAD_LIBS="-lpthread"
|
||||||
|
;;
|
||||||
|
|
||||||
-*)
|
-*)
|
||||||
AC_MSG_CHECKING([whether pthreads work with $flag])
|
AC_MSG_CHECKING([whether pthreads work with $ax_pthread_try_flag])
|
||||||
PTHREAD_CFLAGS="$flag"
|
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
pthread-config)
|
pthread-config)
|
||||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
||||||
if test x"$ax_pthread_config" = xno; then continue; fi
|
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
||||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
||||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
||||||
;;
|
;;
|
||||||
|
|
||||||
*)
|
*)
|
||||||
AC_MSG_CHECKING([for the pthreads library -l$flag])
|
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
||||||
PTHREAD_LIBS="-l$flag"
|
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
|
|
||||||
save_LIBS="$LIBS"
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
save_CFLAGS="$CFLAGS"
|
ax_pthread_save_LIBS="$LIBS"
|
||||||
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS $ax_pthread_extra_flags"
|
|
||||||
|
|
||||||
# Check for various functions. We must include pthread.h,
|
# Check for various functions. We must include pthread.h,
|
||||||
# since some functions may be macros. (On the Sequent, we
|
# since some functions may be macros. (On the Sequent, we
|
||||||
@@ -218,7 +366,11 @@ for flag in $ax_pthread_flags; do
|
|||||||
# pthread_cleanup_push because it is one of the few pthread
|
# pthread_cleanup_push because it is one of the few pthread
|
||||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
# functions on Solaris that doesn't have a non-functional libc stub.
|
||||||
# We try pthread_create on general principles.
|
# We try pthread_create on general principles.
|
||||||
|
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>
|
||||||
|
# if $ax_pthread_check_cond
|
||||||
|
# error "$ax_pthread_check_macro must be defined"
|
||||||
|
# endif
|
||||||
static void routine(void *a) { a = 0; }
|
static void routine(void *a) { a = 0; }
|
||||||
static void *start_routine(void *a) { return a; }],
|
static void *start_routine(void *a) { return a; }],
|
||||||
[pthread_t th; pthread_attr_t attr;
|
[pthread_t th; pthread_attr_t attr;
|
||||||
@@ -230,13 +382,11 @@ for flag in $ax_pthread_flags; do
|
|||||||
[ax_pthread_ok=yes],
|
[ax_pthread_ok=yes],
|
||||||
[])
|
[])
|
||||||
|
|
||||||
LIBS="$save_LIBS"
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
CFLAGS="$save_CFLAGS"
|
LIBS="$ax_pthread_save_LIBS"
|
||||||
|
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
AC_MSG_RESULT([$ax_pthread_ok])
|
||||||
if test "x$ax_pthread_ok" = xyes; then
|
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
||||||
break;
|
|
||||||
fi
|
|
||||||
|
|
||||||
PTHREAD_LIBS=""
|
PTHREAD_LIBS=""
|
||||||
PTHREAD_CFLAGS=""
|
PTHREAD_CFLAGS=""
|
||||||
@@ -244,62 +394,65 @@ done
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
# Various other checks:
|
# Various other checks:
|
||||||
if test "x$ax_pthread_ok" = xyes; then
|
if test "x$ax_pthread_ok" = "xyes"; then
|
||||||
save_LIBS="$LIBS"
|
ax_pthread_save_CFLAGS="$CFLAGS"
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
ax_pthread_save_LIBS="$LIBS"
|
||||||
save_CFLAGS="$CFLAGS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
||||||
|
LIBS="$PTHREAD_LIBS $LIBS"
|
||||||
|
|
||||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
||||||
AC_MSG_CHECKING([for joinable pthread attribute])
|
AC_CACHE_CHECK([for joinable pthread attribute],
|
||||||
attr_name=unknown
|
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||||
for attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
[ax_cv_PTHREAD_JOINABLE_ATTR=unknown
|
||||||
|
for ax_pthread_attr in PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_UNDETACHED; do
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
AC_LINK_IFELSE([AC_LANG_PROGRAM([#include <pthread.h>],
|
||||||
[int attr = $attr; return attr /* ; */])],
|
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
||||||
[attr_name=$attr; break],
|
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
||||||
[])
|
[])
|
||||||
done
|
done
|
||||||
AC_MSG_RESULT([$attr_name])
|
])
|
||||||
if test "$attr_name" != PTHREAD_CREATE_JOINABLE; then
|
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
||||||
AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE], [$attr_name],
|
test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xPTHREAD_CREATE_JOINABLE" && \
|
||||||
|
test "x$ax_pthread_joinable_attr_defined" != "xyes"],
|
||||||
|
[AC_DEFINE_UNQUOTED([PTHREAD_CREATE_JOINABLE],
|
||||||
|
[$ax_cv_PTHREAD_JOINABLE_ATTR],
|
||||||
[Define to necessary symbol if this constant
|
[Define to necessary symbol if this constant
|
||||||
uses a non-standard name on your system.])
|
uses a non-standard name on your system.])
|
||||||
fi
|
ax_pthread_joinable_attr_defined=yes
|
||||||
|
])
|
||||||
|
|
||||||
AC_MSG_CHECKING([if more special flags are required for pthreads])
|
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
||||||
flag=no
|
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
||||||
case ${host_os} in
|
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
||||||
aix* | freebsd* | darwin*) flag="-D_THREAD_SAFE";;
|
case $host_os in
|
||||||
osf* | hpux*) flag="-D_REENTRANT";;
|
|
||||||
solaris*)
|
solaris*)
|
||||||
if test "$GCC" = "yes"; then
|
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
||||||
flag="-D_REENTRANT"
|
|
||||||
else
|
|
||||||
# TODO: What about Clang on Solaris?
|
|
||||||
flag="-mt -D_REENTRANT"
|
|
||||||
fi
|
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
AC_MSG_RESULT([$flag])
|
])
|
||||||
if test "x$flag" != xno; then
|
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
||||||
PTHREAD_CFLAGS="$flag $PTHREAD_CFLAGS"
|
test "x$ax_pthread_special_flags_added" != "xyes"],
|
||||||
fi
|
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
||||||
|
ax_pthread_special_flags_added=yes])
|
||||||
|
|
||||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT], [
|
[ax_cv_PTHREAD_PRIO_INHERIT],
|
||||||
AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
||||||
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
||||||
])
|
])
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes"],
|
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
||||||
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])])
|
test "x$ax_pthread_prio_inherit_defined" != "xyes"],
|
||||||
|
[AC_DEFINE([HAVE_PTHREAD_PRIO_INHERIT], [1], [Have PTHREAD_PRIO_INHERIT.])
|
||||||
|
ax_pthread_prio_inherit_defined=yes
|
||||||
|
])
|
||||||
|
|
||||||
LIBS="$save_LIBS"
|
CFLAGS="$ax_pthread_save_CFLAGS"
|
||||||
CFLAGS="$save_CFLAGS"
|
LIBS="$ax_pthread_save_LIBS"
|
||||||
|
|
||||||
# More AIX lossage: compile with *_r variant
|
# More AIX lossage: compile with *_r variant
|
||||||
if test "x$GCC" != xyes; then
|
if test "x$GCC" != "xyes"; then
|
||||||
case $host_os in
|
case $host_os in
|
||||||
aix*)
|
aix*)
|
||||||
AS_CASE(["x/$CC"],
|
AS_CASE(["x/$CC"],
|
||||||
@@ -321,7 +474,7 @@ AC_SUBST([PTHREAD_CFLAGS])
|
|||||||
AC_SUBST([PTHREAD_CC])
|
AC_SUBST([PTHREAD_CC])
|
||||||
|
|
||||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
||||||
if test x"$ax_pthread_ok" = xyes; then
|
if test "x$ax_pthread_ok" = "xyes"; then
|
||||||
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
ifelse([$1],,[AC_DEFINE([HAVE_PTHREAD],[1],[Define if you have POSIX threads libraries and header files.])],[$1])
|
||||||
:
|
:
|
||||||
else
|
else
|
||||||
|
|||||||
73
m4/faad.m4
73
m4/faad.m4
@@ -1,73 +0,0 @@
|
|||||||
AC_DEFUN([AM_PATH_FAAD],
|
|
||||||
[dnl ##
|
|
||||||
dnl faad
|
|
||||||
dnl ##
|
|
||||||
|
|
||||||
AC_ARG_ENABLE(aac,
|
|
||||||
AS_HELP_STRING([--disable-aac],
|
|
||||||
[disable AAC support (default: enable)]),,
|
|
||||||
enable_aac=yes)
|
|
||||||
|
|
||||||
if test x$enable_aac = xyes; then
|
|
||||||
FAAD_LIBS="-lfaad"
|
|
||||||
FAAD_CFLAGS=""
|
|
||||||
|
|
||||||
oldcflags=$CFLAGS
|
|
||||||
oldlibs=$LIBS
|
|
||||||
oldcppflags=$CPPFLAGS
|
|
||||||
CFLAGS="$CFLAGS $FAAD_CFLAGS"
|
|
||||||
LIBS="$LIBS $FAAD_LIBS"
|
|
||||||
CPPFLAGS=$CFLAGS
|
|
||||||
AC_CHECK_HEADER(faad.h,,enable_aac=no)
|
|
||||||
if test x$enable_aac = xyes; then
|
|
||||||
AC_CHECK_DECL(FAAD2_VERSION,,enable_aac=no,[#include <faad.h>])
|
|
||||||
fi
|
|
||||||
if test x$enable_aac = xyes; then
|
|
||||||
AC_CHECK_LIB(faad,NeAACDecInit2,,enable_aac=no)
|
|
||||||
fi
|
|
||||||
if test x$enable_aac = xyes; then
|
|
||||||
AC_MSG_CHECKING(that FAAD2 can even be used)
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_SOURCE([
|
|
||||||
#include <faad.h>
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
char buffer;
|
|
||||||
NeAACDecHandle decoder;
|
|
||||||
NeAACDecFrameInfo frameInfo;
|
|
||||||
NeAACDecConfigurationPtr config;
|
|
||||||
unsigned char channels;
|
|
||||||
long sampleRate;
|
|
||||||
long bufferlen = 0;
|
|
||||||
|
|
||||||
decoder = NeAACDecOpen();
|
|
||||||
config = NeAACDecGetCurrentConfiguration(decoder);
|
|
||||||
config->outputFormat = FAAD_FMT_16BIT;
|
|
||||||
NeAACDecSetConfiguration(decoder,config);
|
|
||||||
NeAACDecInit(decoder,&buffer,bufferlen,&sampleRate,&channels);
|
|
||||||
NeAACDecInit2(decoder,&buffer,bufferlen,&sampleRate,&channels);
|
|
||||||
NeAACDecDecode(decoder,&frameInfo,&buffer,bufferlen);
|
|
||||||
NeAACDecClose(decoder);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
])],AC_MSG_RESULT(yes),[AC_MSG_RESULT(no);enable_aac=no])
|
|
||||||
fi
|
|
||||||
if test x$enable_aac = xyes; then
|
|
||||||
AC_DEFINE(HAVE_FAAD,1,[Define to use FAAD2 for AAC decoding])
|
|
||||||
else
|
|
||||||
AC_MSG_WARN([faad2 lib needed for MP4/AAC support -- disabling MP4/AAC support])
|
|
||||||
fi
|
|
||||||
CFLAGS=$oldcflags
|
|
||||||
LIBS=$oldlibs
|
|
||||||
CPPFLAGS=$oldcppflags
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$enable_aac = xno; then
|
|
||||||
FAAD_LIBS=""
|
|
||||||
FAAD_CFLAGS=""
|
|
||||||
fi
|
|
||||||
|
|
||||||
AC_SUBST(FAAD_CFLAGS)
|
|
||||||
AC_SUBST(FAAD_LIBS)
|
|
||||||
|
|
||||||
])
|
|
||||||
201
m4/mpd_auto.m4
201
m4/mpd_auto.m4
@@ -1,23 +1,18 @@
|
|||||||
|
dnl Parameters: varname1, description
|
||||||
AC_DEFUN([MPD_AUTO_ENABLED], [
|
AC_DEFUN([MPD_AUTO_ENABLED], [
|
||||||
var="enable_$1"
|
if test x$[]enable_$1 = xauto; then
|
||||||
feature="$2"
|
AC_MSG_NOTICE([auto-detected $2])
|
||||||
|
enable_$1=yes
|
||||||
if eval "test x`echo '$'$var` = xauto"; then
|
|
||||||
AC_MSG_NOTICE([auto-detected $feature])
|
|
||||||
eval "$var=yes"
|
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl Parameters: varname1, description, errmsg
|
||||||
AC_DEFUN([MPD_AUTO_DISABLED], [
|
AC_DEFUN([MPD_AUTO_DISABLED], [
|
||||||
var="enable_$1"
|
if test x$[]enable_$1 = xauto; then
|
||||||
feature="$2"
|
AC_MSG_WARN([$3 -- disabling $2])
|
||||||
msg="$3"
|
enable_$1=no
|
||||||
|
elif test x$[]enable_$1 = xyes; then
|
||||||
if eval "test x`echo '$'$var` = xauto"; then
|
AC_MSG_ERROR([$2: $3])
|
||||||
AC_MSG_WARN([$msg -- disabling $feature])
|
|
||||||
eval "$var=no"
|
|
||||||
elif eval "test x`echo '$'$var` = xyes"; then
|
|
||||||
AC_MSG_ERROR([$feature: $msg])
|
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
@@ -25,59 +20,59 @@ dnl Check whether a prerequisite for a feature was found. This is
|
|||||||
dnl very similar to MPD_AUTO_RESULT, but does not finalize the
|
dnl very similar to MPD_AUTO_RESULT, but does not finalize the
|
||||||
dnl detection; it assumes that more checks will follow.
|
dnl detection; it assumes that more checks will follow.
|
||||||
AC_DEFUN([MPD_AUTO_PRE], [
|
AC_DEFUN([MPD_AUTO_PRE], [
|
||||||
name="$1"
|
if test x$[]enable_$1 != xno && test x$[]found_$1 = xno; then
|
||||||
var="enable_$1"
|
MPD_AUTO_DISABLED([$1], [$2], [$3])
|
||||||
found="found_$name"
|
|
||||||
feature="$2"
|
|
||||||
msg="$3"
|
|
||||||
|
|
||||||
if eval "test x`echo '$'$var` != xno" && eval "test x`echo '$'$found` = xno"; then
|
|
||||||
MPD_AUTO_DISABLED([$name], [$feature], [$msg])
|
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
|
dnl Evaluate a check's result. Abort if the feature was requested
|
||||||
|
dnl explicitly but is unavailable.
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, description, errmsg
|
||||||
AC_DEFUN([MPD_AUTO_RESULT], [
|
AC_DEFUN([MPD_AUTO_RESULT], [
|
||||||
name="$1"
|
if test x$[]enable_$1 = xno; then
|
||||||
var="enable_$1"
|
found_$1=no
|
||||||
found="found_$name"
|
|
||||||
feature="$2"
|
|
||||||
msg="$3"
|
|
||||||
|
|
||||||
if eval "test x`echo '$'$var` = xno"; then
|
|
||||||
eval "$found=no"
|
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if eval "test x`echo '$'$found` = xyes"; then
|
if test x$[]found_$1 = xyes; then
|
||||||
MPD_AUTO_ENABLED([$name], [$feature])
|
MPD_AUTO_ENABLED([$1], [$2])
|
||||||
else
|
else
|
||||||
MPD_AUTO_DISABLED([$name], [$feature], [$msg])
|
MPD_AUTO_DISABLED([$1], [$2], [$3])
|
||||||
fi
|
fi
|
||||||
])
|
])
|
||||||
|
|
||||||
AC_DEFUN([MPD_AUTO_PKG], [
|
dnl Invoke a check if its configuration is "yes" or "auto" and call
|
||||||
if eval "test x`echo '$'enable_$1` != xno"; then
|
dnl MPD_AUTO_RESULT.
|
||||||
PKG_CHECK_MODULES([$2], [$3],
|
dnl
|
||||||
[eval "found_$1=yes"],
|
dnl Parameters: varname1, description, errmsg, check
|
||||||
[eval "found_$1=no"])
|
AC_DEFUN([MPD_AUTO], [
|
||||||
|
if test x$[]enable_$1 != xno; then
|
||||||
|
$4
|
||||||
fi
|
fi
|
||||||
|
MPD_AUTO_RESULT([$1], [$2], [$3])
|
||||||
|
])
|
||||||
|
|
||||||
MPD_AUTO_RESULT([$1], [$4], [$5])
|
dnl Wrapper for MPD_AUTO and PKG_CHECK_MODULES.
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, pkgname, description, errmsg
|
||||||
|
AC_DEFUN([MPD_AUTO_PKG], [
|
||||||
|
MPD_AUTO([$1], [$4], [$5],
|
||||||
|
[PKG_CHECK_MODULES([$2], [$3],
|
||||||
|
[found_$1=yes],
|
||||||
|
[found_$1=no])])
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl Check with pkg-config first, fall back to AC_CHECK_LIB.
|
dnl Check with pkg-config first, fall back to AC_CHECK_LIB.
|
||||||
dnl
|
dnl
|
||||||
dnl Parameters: varname1, varname2, pkgname, libname, symname, libs, cflags, description, errmsg
|
dnl Parameters: varname1, varname2, pkgname, libname, symname, libs, cflags, description, errmsg
|
||||||
AC_DEFUN([MPD_AUTO_PKG_LIB], [
|
AC_DEFUN([MPD_AUTO_PKG_LIB], [
|
||||||
if eval "test x`echo '$'enable_$1` != xno"; then
|
MPD_AUTO([$1], [$8], [$9],
|
||||||
PKG_CHECK_MODULES([$2], [$3],
|
[PKG_CHECK_MODULES([$2], [$3],
|
||||||
[eval "found_$1=yes"],
|
[found_$1=yes],
|
||||||
AC_CHECK_LIB($4, $5,
|
AC_CHECK_LIB($4, $5,
|
||||||
[eval "found_$1=yes $2_LIBS='$6' $2_CFLAGS='$7'"],
|
[found_$1=yes $2_LIBS='$6' $2_CFLAGS='$7'],
|
||||||
[eval "found_$1=no"],
|
[found_$1=no],
|
||||||
[$6]))
|
[$6]))])
|
||||||
fi
|
|
||||||
|
|
||||||
MPD_AUTO_RESULT([$1], [$8], [$9])
|
|
||||||
])
|
])
|
||||||
|
|
||||||
dnl Wrapper for AC_CHECK_LIB.
|
dnl Wrapper for AC_CHECK_LIB.
|
||||||
@@ -87,12 +82,104 @@ AC_DEFUN([MPD_AUTO_LIB], [
|
|||||||
AC_SUBST([$2_LIBS], [])
|
AC_SUBST([$2_LIBS], [])
|
||||||
AC_SUBST([$2_CFLAGS], [])
|
AC_SUBST([$2_CFLAGS], [])
|
||||||
|
|
||||||
if eval "test x`echo '$'enable_$1` != xno"; then
|
MPD_AUTO([$1], [$7], [$8],
|
||||||
AC_CHECK_LIB($3, $4,
|
[AC_CHECK_LIB($3, $4,
|
||||||
[eval "found_$1=yes $2_LIBS='$5' $2_CFLAGS='$6'"],
|
[found_$1=yes $2_LIBS='$5' $2_CFLAGS='$6'],
|
||||||
[eval "found_$1=no"],
|
[found_$1=no],
|
||||||
[$5])
|
[$5])])
|
||||||
fi
|
])
|
||||||
|
|
||||||
MPD_AUTO_RESULT([$1], [$7], [$8])
|
dnl Wrapper for AC_CHECK_HEADER.
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, header, libs, cflags, description, errmsg
|
||||||
|
AC_DEFUN([MPD_AUTO_HEADER], [
|
||||||
|
AC_SUBST([$2_LIBS], [])
|
||||||
|
AC_SUBST([$2_CFLAGS], [])
|
||||||
|
|
||||||
|
MPD_AUTO([$1], [$6], [$7],
|
||||||
|
[AC_CHECK_HEADER([$3],
|
||||||
|
[found_$1=yes $2_LIBS='$4' $2_CFLAGS='$5'],
|
||||||
|
[found_$1=no])])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Convert the given string into a string for the "default value" in
|
||||||
|
dnl the help text. If the string is a literal, then it is returned
|
||||||
|
dnl as-is; if it contains a variable reference, just "auto" is
|
||||||
|
dnl emitted.
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1
|
||||||
|
AC_DEFUN([MPD_FORMAT_DEFAULT],
|
||||||
|
[ifelse([$1], [], [auto],
|
||||||
|
index([$1], [$]), [-1], [$1],
|
||||||
|
[auto])])
|
||||||
|
|
||||||
|
dnl Wrapper for AC_ARG_ENABLE, AC_DEFINE and AM_CONDITIONAL
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, description, default, check
|
||||||
|
AC_DEFUN([MPD_ARG_ENABLE], [
|
||||||
|
AC_ARG_ENABLE(translit([$1], [_], [-]),
|
||||||
|
AS_HELP_STRING([--enable-]translit([$1], [_], [-]),
|
||||||
|
[enable $3 (default: ]MPD_FORMAT_DEFAULT([$4])[)]),,
|
||||||
|
[enable_$1=]ifelse([$4], [], [auto], [$4]))
|
||||||
|
|
||||||
|
$5
|
||||||
|
|
||||||
|
MPD_DEFINE_CONDITIONAL(enable_$1, ENABLE_$2, [$3])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Wrapper for MPD_ARG_ENABLE and MPD_AUTO
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, description, errmsg, default, check
|
||||||
|
AC_DEFUN([MPD_ENABLE_AUTO], [
|
||||||
|
MPD_ARG_ENABLE([$1], [$2], [$3], [$5], [
|
||||||
|
MPD_AUTO([$1], [$3], [$4], [$6])
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_PKG
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, pkg, description, errmsg, default, pre
|
||||||
|
AC_DEFUN([MPD_ENABLE_AUTO_PKG], [
|
||||||
|
MPD_ARG_ENABLE([$1], [$2], [$4], [$6], [
|
||||||
|
$7
|
||||||
|
MPD_AUTO_PKG($1, $2, $3, $4, $5)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_PKG_LIB
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, pkg, libname, symname, libs, cflags, description, errmsg, default, pre
|
||||||
|
AC_DEFUN([MPD_ENABLE_AUTO_PKG_LIB], [
|
||||||
|
MPD_ARG_ENABLE([$1], [$2], [$8], [$10], [
|
||||||
|
$11
|
||||||
|
MPD_AUTO_PKG_LIB($1, $2, $3, $4, $5, $6, $7, $8, $9)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_LIB
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, libname, symname, libs, cflags, description, errmsg, default, pre
|
||||||
|
AC_DEFUN([MPD_ENABLE_AUTO_LIB], [
|
||||||
|
MPD_ARG_ENABLE([$1], [$2], [$7], [$9], [
|
||||||
|
$10
|
||||||
|
MPD_AUTO_LIB($1, $2, $3, $4, $5, $6, $7, $8)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Wrapper for AC_ARG_ENABLE and MPD_AUTO_HEADER
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, header, libs, cflags, description, errmsg, default, pre
|
||||||
|
AC_DEFUN([MPD_ENABLE_AUTO_HEADER], [
|
||||||
|
MPD_ARG_ENABLE([$1], [$2], [$6], [$8], [
|
||||||
|
$9
|
||||||
|
MPD_AUTO_HEADER($1, $2, $3, $4, $5, $6, $7)
|
||||||
|
])
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Wrapper for MPD_ENABLE_AUTO_PKG and MPD_DEPENDS
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, pkg, description, errmsg, default, dep_variable, dep_errmsg
|
||||||
|
AC_DEFUN([MPD_ENABLE_AUTO_PKG_DEPENDS], [
|
||||||
|
MPD_ENABLE_AUTO_PKG([$1], [$2], [$3], [$4], [$5], [$6],
|
||||||
|
[MPD_DEPENDS([enable_$1], [$7], [$8])])
|
||||||
])
|
])
|
||||||
|
|||||||
8
m4/mpd_define_conditional.m4
Normal file
8
m4/mpd_define_conditional.m4
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
dnl Wrapper for AC_DEFINE and AM_CONDITIONAL
|
||||||
|
dnl
|
||||||
|
dnl Parameters: varname1, varname2, description
|
||||||
|
AC_DEFUN([MPD_DEFINE_CONDITIONAL], [dnl
|
||||||
|
AM_CONDITIONAL($2, test x$[]$1 = xyes)
|
||||||
|
if test x$[]$1 = xyes; then
|
||||||
|
AC_DEFINE($2, 1, [Define to enable $3])
|
||||||
|
fi])
|
||||||
@@ -6,7 +6,7 @@ AC_DEFUN([MPD_OPTIONAL_FUNC], [
|
|||||||
AC_ARG_ENABLE([$1],
|
AC_ARG_ENABLE([$1],
|
||||||
AS_HELP_STRING([--enable-$1],
|
AS_HELP_STRING([--enable-$1],
|
||||||
[use the function "$1" (default: auto)]),
|
[use the function "$1" (default: auto)]),
|
||||||
[test xenable_$1 = xyes && AC_DEFINE([$3], 1, [Define to use $1])],
|
[test x$[]enable_$1 = xyes && AC_DEFINE([$3], 1, [Define to use $1])],
|
||||||
[AC_CHECK_FUNC([$2],
|
[AC_CHECK_FUNC([$2],
|
||||||
[AC_DEFINE([$3], 1, [Define to use $1])],)])
|
[AC_DEFINE([$3], 1, [Define to use $1])],)])
|
||||||
])
|
])
|
||||||
|
|||||||
23
m4/mpd_with_flags.m4
Normal file
23
m4/mpd_with_flags.m4
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
dnl Run code with the specified CFLAGS/CXXFLAGS and LIBS appended.
|
||||||
|
dnl Restores the old values afterwards.
|
||||||
|
dnl
|
||||||
|
dnl Parameters: cflags, libs, code
|
||||||
|
AC_DEFUN([MPD_WITH_FLAGS], [
|
||||||
|
ac_save_CFLAGS="$[]CFLAGS"
|
||||||
|
ac_save_CXXFLAGS="$[]CXXFLAGS"
|
||||||
|
ac_save_LIBS="$[]LIBS"
|
||||||
|
CFLAGS="$[]CFLAGS $1"
|
||||||
|
CXXFLAGS="$[]CXXFLAGS $1"
|
||||||
|
LIBS="$[]LIBS $2"
|
||||||
|
$3
|
||||||
|
CFLAGS="$[]ac_save_CFLAGS"
|
||||||
|
CXXFLAGS="$[]ac_save_CXXFLAGS"
|
||||||
|
LIBS="$[]ac_save_LIBS"
|
||||||
|
])
|
||||||
|
|
||||||
|
dnl Run code with the specified library's CFLAGS/CXXFLAGS and LIBS
|
||||||
|
dnl appended. Restores the old values afterwards.
|
||||||
|
dnl
|
||||||
|
dnl Parameters: libname, code
|
||||||
|
AC_DEFUN([MPD_WITH_LIBRARY],
|
||||||
|
[MPD_WITH_FLAGS([$[]$1_CFLAGS], [$[]$1_LIBS], [$2])])
|
||||||
209
m4/pkg.m4
209
m4/pkg.m4
@@ -1,29 +1,60 @@
|
|||||||
# pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
||||||
# serial 1 (pkg-config-0.24)
|
dnl serial 11 (pkg-config-0.29)
|
||||||
#
|
dnl
|
||||||
# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
||||||
#
|
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
||||||
# This program is free software; you can redistribute it and/or modify
|
dnl
|
||||||
# it under the terms of the GNU General Public License as published by
|
dnl This program is free software; you can redistribute it and/or modify
|
||||||
# the Free Software Foundation; either version 2 of the License, or
|
dnl it under the terms of the GNU General Public License as published by
|
||||||
# (at your option) any later version.
|
dnl the Free Software Foundation; either version 2 of the License, or
|
||||||
#
|
dnl (at your option) any later version.
|
||||||
# This program is distributed in the hope that it will be useful, but
|
dnl
|
||||||
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
dnl This program is distributed in the hope that it will be useful, but
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
# General Public License for more details.
|
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
#
|
dnl General Public License for more details.
|
||||||
# You should have received a copy of the GNU General Public License
|
dnl
|
||||||
# along with this program; if not, write to the Free Software
|
dnl You should have received a copy of the GNU General Public License
|
||||||
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
dnl along with this program; if not, write to the Free Software
|
||||||
#
|
dnl Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
||||||
# As a special exception to the GNU General Public License, if you
|
dnl 02111-1307, USA.
|
||||||
# distribute this file as part of a program that contains a
|
dnl
|
||||||
# configuration script generated by Autoconf, you may include it under
|
dnl As a special exception to the GNU General Public License, if you
|
||||||
# the same distribution terms that you use for the rest of that program.
|
dnl distribute this file as part of a program that contains a
|
||||||
|
dnl configuration script generated by Autoconf, you may include it under
|
||||||
|
dnl the same distribution terms that you use for the rest of that
|
||||||
|
dnl program.
|
||||||
|
|
||||||
# PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
dnl PKG_PREREQ(MIN-VERSION)
|
||||||
# ----------------------------------
|
dnl -----------------------
|
||||||
|
dnl Since: 0.29
|
||||||
|
dnl
|
||||||
|
dnl Verify that the version of the pkg-config macros are at least
|
||||||
|
dnl MIN-VERSION. Unlike PKG_PROG_PKG_CONFIG, which checks the user's
|
||||||
|
dnl installed version of pkg-config, this checks the developer's version
|
||||||
|
dnl of pkg.m4 when generating configure.
|
||||||
|
dnl
|
||||||
|
dnl To ensure that this macro is defined, also add:
|
||||||
|
dnl m4_ifndef([PKG_PREREQ],
|
||||||
|
dnl [m4_fatal([must install pkg-config 0.29 or later before running autoconf/autogen])])
|
||||||
|
dnl
|
||||||
|
dnl See the "Since" comment for each macro you use to see what version
|
||||||
|
dnl of the macros you require.
|
||||||
|
m4_defun([PKG_PREREQ],
|
||||||
|
[m4_define([PKG_MACROS_VERSION], [0.29])
|
||||||
|
m4_if(m4_version_compare(PKG_MACROS_VERSION, [$1]), -1,
|
||||||
|
[m4_fatal([pkg.m4 version $1 or higher is required but ]PKG_MACROS_VERSION[ found])])
|
||||||
|
])dnl PKG_PREREQ
|
||||||
|
|
||||||
|
dnl PKG_PROG_PKG_CONFIG([MIN-VERSION])
|
||||||
|
dnl ----------------------------------
|
||||||
|
dnl Since: 0.16
|
||||||
|
dnl
|
||||||
|
dnl Search for the pkg-config tool and set the PKG_CONFIG variable to
|
||||||
|
dnl first found in the path. Checks that the version of pkg-config found
|
||||||
|
dnl is at least MIN-VERSION. If MIN-VERSION is not specified, 0.9.0 is
|
||||||
|
dnl used since that's the first version where most current features of
|
||||||
|
dnl pkg-config existed.
|
||||||
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
AC_DEFUN([PKG_PROG_PKG_CONFIG],
|
||||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
||||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
||||||
@@ -45,18 +76,19 @@ if test -n "$PKG_CONFIG"; then
|
|||||||
PKG_CONFIG=""
|
PKG_CONFIG=""
|
||||||
fi
|
fi
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# PKG_PROG_PKG_CONFIG
|
])dnl PKG_PROG_PKG_CONFIG
|
||||||
|
|
||||||
# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
#
|
dnl -------------------------------------------------------------------
|
||||||
# Check to see whether a particular set of modules exists. Similar
|
dnl Since: 0.18
|
||||||
# to PKG_CHECK_MODULES(), but does not set variables or print errors.
|
dnl
|
||||||
#
|
dnl Check to see whether a particular set of modules exists. Similar to
|
||||||
# Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
|
||||||
# only at the first occurence in configure.ac, so if the first place
|
dnl
|
||||||
# it's called might be skipped (such as if it is within an "if", you
|
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
# have to call PKG_CHECK_EXISTS manually
|
dnl only at the first occurence in configure.ac, so if the first place
|
||||||
# --------------------------------------------------------------
|
dnl it's called might be skipped (such as if it is within an "if", you
|
||||||
|
dnl have to call PKG_CHECK_EXISTS manually
|
||||||
AC_DEFUN([PKG_CHECK_EXISTS],
|
AC_DEFUN([PKG_CHECK_EXISTS],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
if test -n "$PKG_CONFIG" && \
|
if test -n "$PKG_CONFIG" && \
|
||||||
@@ -66,8 +98,10 @@ m4_ifvaln([$3], [else
|
|||||||
$3])dnl
|
$3])dnl
|
||||||
fi])
|
fi])
|
||||||
|
|
||||||
# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
dnl _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
|
||||||
# ---------------------------------------------
|
dnl ---------------------------------------------
|
||||||
|
dnl Internal wrapper calling pkg-config via PKG_CONFIG and setting
|
||||||
|
dnl pkg_failed based on the result.
|
||||||
m4_define([_PKG_CONFIG],
|
m4_define([_PKG_CONFIG],
|
||||||
[if test -n "$$1"; then
|
[if test -n "$$1"; then
|
||||||
pkg_cv_[]$1="$$1"
|
pkg_cv_[]$1="$$1"
|
||||||
@@ -79,10 +113,11 @@ m4_define([_PKG_CONFIG],
|
|||||||
else
|
else
|
||||||
pkg_failed=untried
|
pkg_failed=untried
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# _PKG_CONFIG
|
])dnl _PKG_CONFIG
|
||||||
|
|
||||||
# _PKG_SHORT_ERRORS_SUPPORTED
|
dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
# -----------------------------
|
dnl ---------------------------
|
||||||
|
dnl Internal check to see if pkg-config supports short errors.
|
||||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
||||||
@@ -90,19 +125,17 @@ if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
|||||||
else
|
else
|
||||||
_pkg_short_errors_supported=no
|
_pkg_short_errors_supported=no
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# _PKG_SHORT_ERRORS_SUPPORTED
|
])dnl _PKG_SHORT_ERRORS_SUPPORTED
|
||||||
|
|
||||||
|
|
||||||
# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||||
# [ACTION-IF-NOT-FOUND])
|
dnl [ACTION-IF-NOT-FOUND])
|
||||||
#
|
dnl --------------------------------------------------------------
|
||||||
#
|
dnl Since: 0.4.0
|
||||||
# Note that if there is a possibility the first call to
|
dnl
|
||||||
# PKG_CHECK_MODULES might not happen, you should be sure to include an
|
dnl Note that if there is a possibility the first call to
|
||||||
# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
dnl PKG_CHECK_MODULES might not happen, you should be sure to include an
|
||||||
#
|
dnl explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
||||||
#
|
|
||||||
# --------------------------------------------------------------
|
|
||||||
AC_DEFUN([PKG_CHECK_MODULES],
|
AC_DEFUN([PKG_CHECK_MODULES],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
|
||||||
@@ -156,16 +189,40 @@ else
|
|||||||
AC_MSG_RESULT([yes])
|
AC_MSG_RESULT([yes])
|
||||||
$3
|
$3
|
||||||
fi[]dnl
|
fi[]dnl
|
||||||
])# PKG_CHECK_MODULES
|
])dnl PKG_CHECK_MODULES
|
||||||
|
|
||||||
|
|
||||||
# PKG_INSTALLDIR(DIRECTORY)
|
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
||||||
# -------------------------
|
dnl [ACTION-IF-NOT-FOUND])
|
||||||
# Substitutes the variable pkgconfigdir as the location where a module
|
dnl ---------------------------------------------------------------------
|
||||||
# should install pkg-config .pc files. By default the directory is
|
dnl Since: 0.29
|
||||||
# $libdir/pkgconfig, but the default can be changed by passing
|
dnl
|
||||||
# DIRECTORY. The user can override through the --with-pkgconfigdir
|
dnl Checks for existence of MODULES and gathers its build flags with
|
||||||
# parameter.
|
dnl static libraries enabled. Sets VARIABLE-PREFIX_CFLAGS from --cflags
|
||||||
|
dnl and VARIABLE-PREFIX_LIBS from --libs.
|
||||||
|
dnl
|
||||||
|
dnl Note that if there is a possibility the first call to
|
||||||
|
dnl PKG_CHECK_MODULES_STATIC might not happen, you should be sure to
|
||||||
|
dnl include an explicit call to PKG_PROG_PKG_CONFIG in your
|
||||||
|
dnl configure.ac.
|
||||||
|
AC_DEFUN([PKG_CHECK_MODULES_STATIC],
|
||||||
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
|
_save_PKG_CONFIG=$PKG_CONFIG
|
||||||
|
PKG_CONFIG="$PKG_CONFIG --static"
|
||||||
|
PKG_CHECK_MODULES($@)
|
||||||
|
PKG_CONFIG=$_save_PKG_CONFIG[]dnl
|
||||||
|
])dnl PKG_CHECK_MODULES_STATIC
|
||||||
|
|
||||||
|
|
||||||
|
dnl PKG_INSTALLDIR([DIRECTORY])
|
||||||
|
dnl -------------------------
|
||||||
|
dnl Since: 0.27
|
||||||
|
dnl
|
||||||
|
dnl Substitutes the variable pkgconfigdir as the location where a module
|
||||||
|
dnl should install pkg-config .pc files. By default the directory is
|
||||||
|
dnl $libdir/pkgconfig, but the default can be changed by passing
|
||||||
|
dnl DIRECTORY. The user can override through the --with-pkgconfigdir
|
||||||
|
dnl parameter.
|
||||||
AC_DEFUN([PKG_INSTALLDIR],
|
AC_DEFUN([PKG_INSTALLDIR],
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
||||||
m4_pushdef([pkg_description],
|
m4_pushdef([pkg_description],
|
||||||
@@ -176,16 +233,18 @@ AC_ARG_WITH([pkgconfigdir],
|
|||||||
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
||||||
m4_popdef([pkg_default])
|
m4_popdef([pkg_default])
|
||||||
m4_popdef([pkg_description])
|
m4_popdef([pkg_description])
|
||||||
]) dnl PKG_INSTALLDIR
|
])dnl PKG_INSTALLDIR
|
||||||
|
|
||||||
|
|
||||||
# PKG_NOARCH_INSTALLDIR(DIRECTORY)
|
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
|
||||||
# -------------------------
|
dnl --------------------------------
|
||||||
# Substitutes the variable noarch_pkgconfigdir as the location where a
|
dnl Since: 0.27
|
||||||
# module should install arch-independent pkg-config .pc files. By
|
dnl
|
||||||
# default the directory is $datadir/pkgconfig, but the default can be
|
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
|
||||||
# changed by passing DIRECTORY. The user can override through the
|
dnl module should install arch-independent pkg-config .pc files. By
|
||||||
# --with-noarch-pkgconfigdir parameter.
|
dnl default the directory is $datadir/pkgconfig, but the default can be
|
||||||
|
dnl changed by passing DIRECTORY. The user can override through the
|
||||||
|
dnl --with-noarch-pkgconfigdir parameter.
|
||||||
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
AC_DEFUN([PKG_NOARCH_INSTALLDIR],
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
||||||
m4_pushdef([pkg_description],
|
m4_pushdef([pkg_description],
|
||||||
@@ -196,13 +255,15 @@ AC_ARG_WITH([noarch-pkgconfigdir],
|
|||||||
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
||||||
m4_popdef([pkg_default])
|
m4_popdef([pkg_default])
|
||||||
m4_popdef([pkg_description])
|
m4_popdef([pkg_description])
|
||||||
]) dnl PKG_NOARCH_INSTALLDIR
|
])dnl PKG_NOARCH_INSTALLDIR
|
||||||
|
|
||||||
|
|
||||||
# PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
||||||
# [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
||||||
# -------------------------------------------
|
dnl -------------------------------------------
|
||||||
# Retrieves the value of the pkg-config variable for the given module.
|
dnl Since: 0.28
|
||||||
|
dnl
|
||||||
|
dnl Retrieves the value of the pkg-config variable for the given module.
|
||||||
AC_DEFUN([PKG_CHECK_VAR],
|
AC_DEFUN([PKG_CHECK_VAR],
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
||||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
||||||
@@ -211,4 +272,4 @@ _PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
|||||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
||||||
|
|
||||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
||||||
])# PKG_CHECK_VAR
|
])dnl PKG_CHECK_VAR
|
||||||
|
|||||||
@@ -1,16 +1,6 @@
|
|||||||
AC_DEFUN([results], [
|
AC_DEFUN([results], [
|
||||||
dnl This is a hack to allow "with" names, otherwise "enable".
|
|
||||||
num=`expr $1 : 'with'`
|
|
||||||
if test "$num" != "0"; then
|
|
||||||
var="`echo '$'$1`"
|
|
||||||
else
|
|
||||||
var="`echo '$'enable_$1`"
|
|
||||||
fi
|
|
||||||
|
|
||||||
printf '('
|
printf '('
|
||||||
if eval "test x$var = xyes"; then
|
if test x$[]enable_$1 = xyes; then
|
||||||
printf '+'
|
|
||||||
elif test -n "$3" && eval "test x$var = x$3"; then
|
|
||||||
printf '+'
|
printf '+'
|
||||||
else
|
else
|
||||||
printf '-'
|
printf '-'
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Check if "struct ucred" is available.
|
# Check if "struct ucred" is available.
|
||||||
#
|
#
|
||||||
# Author: Max Kellermann <max@duempel.org>
|
# Author: Max Kellermann <max.kellermann@gmail.com>
|
||||||
|
|
||||||
AC_DEFUN([STRUCT_UCRED],[
|
AC_DEFUN([STRUCT_UCRED],[
|
||||||
AC_MSG_CHECKING([for struct ucred])
|
AC_MSG_CHECKING([for struct ucred])
|
||||||
|
|||||||
46
python/build/autotools.py
Normal file
46
python/build/autotools.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
import os.path, subprocess
|
||||||
|
|
||||||
|
from build.project import Project
|
||||||
|
|
||||||
|
class AutotoolsProject(Project):
|
||||||
|
def __init__(self, url, md5, installed, configure_args=[],
|
||||||
|
autogen=False,
|
||||||
|
cppflags='',
|
||||||
|
**kwargs):
|
||||||
|
Project.__init__(self, url, md5, installed, **kwargs)
|
||||||
|
self.configure_args = configure_args
|
||||||
|
self.autogen = autogen
|
||||||
|
self.cppflags = cppflags
|
||||||
|
|
||||||
|
def build(self, toolchain):
|
||||||
|
src = self.unpack(toolchain)
|
||||||
|
if self.autogen:
|
||||||
|
subprocess.check_call(['libtoolize', '--force'], cwd=src)
|
||||||
|
subprocess.check_call(['aclocal'], cwd=src)
|
||||||
|
subprocess.check_call(['automake', '--add-missing', '--force-missing', '--foreign'], cwd=src)
|
||||||
|
subprocess.check_call(['autoconf'], cwd=src)
|
||||||
|
|
||||||
|
build = self.make_build_path(toolchain)
|
||||||
|
|
||||||
|
configure = [
|
||||||
|
os.path.join(src, 'configure'),
|
||||||
|
'CC=' + toolchain.cc,
|
||||||
|
'CXX=' + toolchain.cxx,
|
||||||
|
'CFLAGS=' + toolchain.cflags,
|
||||||
|
'CXXFLAGS=' + toolchain.cxxflags,
|
||||||
|
'CPPFLAGS=' + toolchain.cppflags + ' ' + self.cppflags,
|
||||||
|
'LDFLAGS=' + toolchain.ldflags,
|
||||||
|
'LIBS=' + toolchain.libs,
|
||||||
|
'AR=' + toolchain.ar,
|
||||||
|
'RANLIB=' + toolchain.ranlib,
|
||||||
|
'STRIP=' + toolchain.strip,
|
||||||
|
'--host=' + toolchain.arch,
|
||||||
|
'--prefix=' + toolchain.install_prefix,
|
||||||
|
'--enable-silent-rules',
|
||||||
|
] + self.configure_args
|
||||||
|
|
||||||
|
subprocess.check_call(configure, cwd=build, env=toolchain.env)
|
||||||
|
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'],
|
||||||
|
cwd=build, env=toolchain.env)
|
||||||
|
subprocess.check_call(['/usr/bin/make', '--quiet', 'install'],
|
||||||
|
cwd=build, env=toolchain.env)
|
||||||
23
python/build/boost.py
Normal file
23
python/build/boost.py
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
import os, shutil
|
||||||
|
import re
|
||||||
|
|
||||||
|
from build.project import Project
|
||||||
|
|
||||||
|
class BoostProject(Project):
|
||||||
|
def __init__(self, url, md5, installed,
|
||||||
|
**kwargs):
|
||||||
|
m = re.match(r'.*/boost_(\d+)_(\d+)_(\d+)\.tar\.bz2$', url)
|
||||||
|
version = "%s.%s.%s" % (m.group(1), m.group(2), m.group(3))
|
||||||
|
Project.__init__(self, url, md5, installed,
|
||||||
|
name='boost', version=version,
|
||||||
|
**kwargs)
|
||||||
|
|
||||||
|
def build(self, toolchain):
|
||||||
|
src = self.unpack(toolchain)
|
||||||
|
|
||||||
|
# install the headers manually; don't build any library
|
||||||
|
# (because right now, we only use header-only libraries)
|
||||||
|
includedir = os.path.join(toolchain.install_prefix, 'include')
|
||||||
|
dest = os.path.join(includedir, 'boost')
|
||||||
|
shutil.rmtree(dest, ignore_errors=True)
|
||||||
|
shutil.copytree(os.path.join(src, 'boost'), dest)
|
||||||
9
python/build/dirs.py
Normal file
9
python/build/dirs.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import os.path
|
||||||
|
|
||||||
|
lib_path = os.path.abspath('lib')
|
||||||
|
|
||||||
|
shared_path = lib_path
|
||||||
|
if 'MPD_SHARED_LIB' in os.environ:
|
||||||
|
shared_path = os.environ['MPD_SHARED_LIB']
|
||||||
|
tarball_path = os.path.join(shared_path, 'download')
|
||||||
|
src_path = os.path.join(shared_path, 'src')
|
||||||
26
python/build/download.py
Normal file
26
python/build/download.py
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
from build.verify import verify_file_digest
|
||||||
|
import os
|
||||||
|
import urllib.request
|
||||||
|
|
||||||
|
def download_and_verify(url, md5, parent_path):
|
||||||
|
"""Download a file, verify its MD5 checksum and return the local path."""
|
||||||
|
|
||||||
|
os.makedirs(parent_path, exist_ok=True)
|
||||||
|
path = os.path.join(parent_path, os.path.basename(url))
|
||||||
|
|
||||||
|
try:
|
||||||
|
if verify_file_digest(path, md5): return path
|
||||||
|
os.unlink(path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
tmp_path = path + '.tmp'
|
||||||
|
|
||||||
|
print("download", url)
|
||||||
|
urllib.request.urlretrieve(url, tmp_path)
|
||||||
|
if not verify_file_digest(tmp_path, md5):
|
||||||
|
os.unlink(tmp_path)
|
||||||
|
raise RuntimeError("Digest mismatch")
|
||||||
|
|
||||||
|
os.rename(tmp_path, path)
|
||||||
|
return path
|
||||||
54
python/build/ffmpeg.py
Normal file
54
python/build/ffmpeg.py
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
import os.path, subprocess
|
||||||
|
|
||||||
|
from build.project import Project
|
||||||
|
|
||||||
|
class FfmpegProject(Project):
|
||||||
|
def __init__(self, url, md5, installed, configure_args=[],
|
||||||
|
cppflags='',
|
||||||
|
**kwargs):
|
||||||
|
Project.__init__(self, url, md5, installed, **kwargs)
|
||||||
|
self.configure_args = configure_args
|
||||||
|
self.cppflags = cppflags
|
||||||
|
|
||||||
|
def _filter_cflags(self, flags):
|
||||||
|
# FFmpeg expects the GNU as syntax
|
||||||
|
flags = flags.replace(' -integrated-as ', ' -no-integrated-as ')
|
||||||
|
return flags
|
||||||
|
|
||||||
|
def build(self, toolchain):
|
||||||
|
src = self.unpack(toolchain)
|
||||||
|
build = self.make_build_path(toolchain)
|
||||||
|
|
||||||
|
if toolchain.is_arm:
|
||||||
|
arch = 'arm'
|
||||||
|
else:
|
||||||
|
arch = 'x86'
|
||||||
|
|
||||||
|
if toolchain.is_windows:
|
||||||
|
target_os = 'mingw32'
|
||||||
|
else:
|
||||||
|
target_os = 'linux'
|
||||||
|
|
||||||
|
configure = [
|
||||||
|
os.path.join(src, 'configure'),
|
||||||
|
'--cc=' + toolchain.cc,
|
||||||
|
'--cxx=' + toolchain.cxx,
|
||||||
|
'--nm=' + toolchain.nm,
|
||||||
|
'--extra-cflags=' + self._filter_cflags(toolchain.cflags) + ' ' + toolchain.cppflags + ' ' + self.cppflags,
|
||||||
|
'--extra-cxxflags=' + self._filter_cflags(toolchain.cxxflags) + ' ' + toolchain.cppflags + ' ' + self.cppflags,
|
||||||
|
'--extra-ldflags=' + toolchain.ldflags,
|
||||||
|
'--extra-libs=' + toolchain.libs,
|
||||||
|
'--ar=' + toolchain.ar,
|
||||||
|
'--ranlib=' + toolchain.ranlib,
|
||||||
|
'--enable-cross-compile',
|
||||||
|
'--arch=' + arch,
|
||||||
|
'--target-os=' + target_os,
|
||||||
|
'--prefix=' + toolchain.install_prefix,
|
||||||
|
] + self.configure_args
|
||||||
|
|
||||||
|
if toolchain.is_armv7:
|
||||||
|
configure.append('--cpu=cortex-a8')
|
||||||
|
|
||||||
|
subprocess.check_call(configure, cwd=build, env=toolchain.env)
|
||||||
|
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], cwd=build, env=toolchain.env)
|
||||||
|
subprocess.check_call(['/usr/bin/make', '--quiet', 'install'], cwd=build, env=toolchain.env)
|
||||||
109
python/build/libs.py
Normal file
109
python/build/libs.py
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
from build.project import Project
|
||||||
|
from build.zlib import ZlibProject
|
||||||
|
from build.autotools import AutotoolsProject
|
||||||
|
from build.ffmpeg import FfmpegProject
|
||||||
|
from build.boost import BoostProject
|
||||||
|
|
||||||
|
libogg = AutotoolsProject(
|
||||||
|
'http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.xz',
|
||||||
|
'5c3a34309d8b98640827e5d0991a4015',
|
||||||
|
'lib/libogg.a',
|
||||||
|
['--disable-shared', '--enable-static'],
|
||||||
|
)
|
||||||
|
|
||||||
|
libvorbis = AutotoolsProject(
|
||||||
|
'http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.xz',
|
||||||
|
'28cb28097c07a735d6af56e598e1c90f',
|
||||||
|
'lib/libvorbis.a',
|
||||||
|
['--disable-shared', '--enable-static'],
|
||||||
|
)
|
||||||
|
|
||||||
|
opus = AutotoolsProject(
|
||||||
|
'http://downloads.xiph.org/releases/opus/opus-1.1.3.tar.gz',
|
||||||
|
'32bbb6b557fe1b6066adc0ae1f08b629',
|
||||||
|
'lib/libopus.a',
|
||||||
|
['--disable-shared', '--enable-static'],
|
||||||
|
)
|
||||||
|
|
||||||
|
flac = AutotoolsProject(
|
||||||
|
'http://downloads.xiph.org/releases/flac/flac-1.3.2.tar.xz',
|
||||||
|
'91cfc3ed61dc40f47f050a109b08610667d73477af6ef36dcad31c31a4a8d53f',
|
||||||
|
'lib/libFLAC.a',
|
||||||
|
[
|
||||||
|
'--disable-shared', '--enable-static',
|
||||||
|
'--disable-xmms-plugin', '--disable-cpplibs',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
zlib = ZlibProject(
|
||||||
|
'http://zlib.net/zlib-1.2.8.tar.xz',
|
||||||
|
'28f1205d8dd2001f26fec1e8c2cebe37',
|
||||||
|
'lib/libz.a',
|
||||||
|
)
|
||||||
|
|
||||||
|
libid3tag = AutotoolsProject(
|
||||||
|
'ftp://ftp.mars.org/pub/mpeg/libid3tag-0.15.1b.tar.gz',
|
||||||
|
'e5808ad997ba32c498803822078748c3',
|
||||||
|
'lib/libid3tag.a',
|
||||||
|
['--disable-shared', '--enable-static'],
|
||||||
|
autogen=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
libmad = AutotoolsProject(
|
||||||
|
'ftp://ftp.mars.org/pub/mpeg/libmad-0.15.1b.tar.gz',
|
||||||
|
'1be543bc30c56fb6bea1d7bf6a64e66c',
|
||||||
|
'lib/libmad.a',
|
||||||
|
['--disable-shared', '--enable-static'],
|
||||||
|
autogen=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
ffmpeg = FfmpegProject(
|
||||||
|
'http://ffmpeg.org/releases/ffmpeg-3.2.2.tar.xz',
|
||||||
|
'3f01bd1fe1a17a277f8c84869e5d9192b4b978cb660872aa2b54c3cc8a2fedfc',
|
||||||
|
'lib/libavcodec.a',
|
||||||
|
[
|
||||||
|
'--disable-shared', '--enable-static',
|
||||||
|
'--enable-gpl',
|
||||||
|
'--enable-small',
|
||||||
|
'--disable-pthreads',
|
||||||
|
'--disable-programs',
|
||||||
|
'--disable-doc',
|
||||||
|
'--disable-avdevice',
|
||||||
|
'--disable-swresample',
|
||||||
|
'--disable-swscale',
|
||||||
|
'--disable-postproc',
|
||||||
|
'--disable-avfilter',
|
||||||
|
'--disable-network',
|
||||||
|
'--disable-encoders',
|
||||||
|
'--disable-protocols',
|
||||||
|
'--disable-outdevs',
|
||||||
|
'--disable-filters',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
curl = AutotoolsProject(
|
||||||
|
'http://curl.haxx.se/download/curl-7.52.1.tar.lzma',
|
||||||
|
'44286d4b825936e2430fc44ad730ce899afb736a5d328cbb8b5d42462f3f2365',
|
||||||
|
'lib/libcurl.a',
|
||||||
|
[
|
||||||
|
'--disable-shared', '--enable-static',
|
||||||
|
'--disable-debug',
|
||||||
|
'--enable-http',
|
||||||
|
'--enable-ipv6',
|
||||||
|
'--disable-ftp', '--disable-file',
|
||||||
|
'--disable-ldap', '--disable-ldaps',
|
||||||
|
'--disable-rtsp', '--disable-proxy', '--disable-dict', '--disable-telnet',
|
||||||
|
'--disable-tftp', '--disable-pop3', '--disable-imap', '--disable-smtp',
|
||||||
|
'--disable-gopher',
|
||||||
|
'--disable-manual',
|
||||||
|
'--disable-threaded-resolver', '--disable-verbose', '--disable-sspi',
|
||||||
|
'--disable-crypto-auth', '--disable-ntlm-wb', '--disable-tls-srp', '--disable-cookies',
|
||||||
|
'--without-ssl', '--without-gnutls', '--without-nss', '--without-libssh2',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
boost = BoostProject(
|
||||||
|
'http://downloads.sourceforge.net/project/boost/boost/1.63.0/boost_1_63_0.tar.bz2',
|
||||||
|
'beae2529f759f6b3bf3f4969a19c2e9d6f0c503edcb2de4a61d1428519fcb3b0',
|
||||||
|
'include/boost/version.hpp',
|
||||||
|
)
|
||||||
59
python/build/project.py
Normal file
59
python/build/project.py
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
import os, shutil
|
||||||
|
import re
|
||||||
|
|
||||||
|
from build.download import download_and_verify
|
||||||
|
from build.tar import untar
|
||||||
|
|
||||||
|
class Project:
|
||||||
|
def __init__(self, url, md5, installed, name=None, version=None,
|
||||||
|
base=None,
|
||||||
|
use_cxx=False):
|
||||||
|
if base is None:
|
||||||
|
basename = os.path.basename(url)
|
||||||
|
m = re.match(r'^(.+)\.(tar(\.(gz|bz2|xz|lzma))?|zip)$', basename)
|
||||||
|
if not m: raise
|
||||||
|
self.base = m.group(1)
|
||||||
|
else:
|
||||||
|
self.base = base
|
||||||
|
|
||||||
|
if name is None or version is None:
|
||||||
|
m = re.match(r'^([-\w]+)-(\d[\d.]*[a-z]?)$', self.base)
|
||||||
|
if name is None: name = m.group(1)
|
||||||
|
if version is None: version = m.group(2)
|
||||||
|
|
||||||
|
self.name = name
|
||||||
|
self.version = version
|
||||||
|
|
||||||
|
self.url = url
|
||||||
|
self.md5 = md5
|
||||||
|
self.installed = installed
|
||||||
|
|
||||||
|
self.use_cxx = use_cxx
|
||||||
|
|
||||||
|
def download(self, toolchain):
|
||||||
|
return download_and_verify(self.url, self.md5, toolchain.tarball_path)
|
||||||
|
|
||||||
|
def is_installed(self, toolchain):
|
||||||
|
tarball = self.download(toolchain)
|
||||||
|
installed = os.path.join(toolchain.install_prefix, self.installed)
|
||||||
|
tarball_mtime = os.path.getmtime(tarball)
|
||||||
|
try:
|
||||||
|
return os.path.getmtime(installed) >= tarball_mtime
|
||||||
|
except FileNotFoundError:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def unpack(self, toolchain, out_of_tree=True):
|
||||||
|
if out_of_tree:
|
||||||
|
parent_path = toolchain.src_path
|
||||||
|
else:
|
||||||
|
parent_path = toolchain.build_path
|
||||||
|
return untar(self.download(toolchain), parent_path, self.base)
|
||||||
|
|
||||||
|
def make_build_path(self, toolchain):
|
||||||
|
path = os.path.join(toolchain.build_path, self.base)
|
||||||
|
try:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
os.makedirs(path, exist_ok=True)
|
||||||
|
return path
|
||||||
11
python/build/tar.py
Normal file
11
python/build/tar.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import os, shutil, subprocess
|
||||||
|
|
||||||
|
def untar(tarball_path, parent_path, base):
|
||||||
|
path = os.path.join(parent_path, base)
|
||||||
|
try:
|
||||||
|
shutil.rmtree(path)
|
||||||
|
except FileNotFoundError:
|
||||||
|
pass
|
||||||
|
os.makedirs(parent_path, exist_ok=True)
|
||||||
|
subprocess.check_call(['/bin/tar', 'xfC', tarball_path, parent_path])
|
||||||
|
return path
|
||||||
42
python/build/verify.py
Normal file
42
python/build/verify.py
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
import hashlib
|
||||||
|
|
||||||
|
def feed_file(h, f):
|
||||||
|
"""Feed data read from an open file into the hashlib instance."""
|
||||||
|
|
||||||
|
while True:
|
||||||
|
data = f.read(65536)
|
||||||
|
if len(data) == 0:
|
||||||
|
# end of file
|
||||||
|
break
|
||||||
|
h.update(data)
|
||||||
|
|
||||||
|
def feed_file_path(h, path):
|
||||||
|
"""Feed data read from a file (to be opened by this function) into the hashlib instance."""
|
||||||
|
|
||||||
|
with open(path, 'rb') as f:
|
||||||
|
feed_file(h, f)
|
||||||
|
|
||||||
|
def file_digest(algorithm, path):
|
||||||
|
"""Calculate the digest of a file and return it in hexadecimal notation."""
|
||||||
|
|
||||||
|
h = algorithm()
|
||||||
|
feed_file_path(h, path)
|
||||||
|
return h.hexdigest()
|
||||||
|
|
||||||
|
def guess_digest_algorithm(digest):
|
||||||
|
l = len(digest)
|
||||||
|
if l == 32:
|
||||||
|
return hashlib.md5
|
||||||
|
elif l == 40:
|
||||||
|
return hashlib.sha1
|
||||||
|
elif l == 64:
|
||||||
|
return hashlib.sha256
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def verify_file_digest(path, expected_digest):
|
||||||
|
"""Verify the digest of a file, and return True if the digest matches with the given expected digest."""
|
||||||
|
|
||||||
|
algorithm = guess_digest_algorithm(expected_digest)
|
||||||
|
assert(algorithm is not None)
|
||||||
|
return file_digest(algorithm, path) == expected_digest
|
||||||
22
python/build/zlib.py
Normal file
22
python/build/zlib.py
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import os.path, subprocess
|
||||||
|
|
||||||
|
from build.project import Project
|
||||||
|
|
||||||
|
class ZlibProject(Project):
|
||||||
|
def __init__(self, url, md5, installed,
|
||||||
|
**kwargs):
|
||||||
|
Project.__init__(self, url, md5, installed, **kwargs)
|
||||||
|
|
||||||
|
def build(self, toolchain):
|
||||||
|
src = self.unpack(toolchain, out_of_tree=False)
|
||||||
|
|
||||||
|
subprocess.check_call(['/usr/bin/make', '--quiet',
|
||||||
|
'-f', 'win32/Makefile.gcc',
|
||||||
|
'PREFIX=' + toolchain.arch + '-',
|
||||||
|
'-j12',
|
||||||
|
'install',
|
||||||
|
'INCLUDE_PATH='+ os.path.join(toolchain.install_prefix, 'include'),
|
||||||
|
'LIBRARY_PATH=' + os.path.join(toolchain.install_prefix, 'lib'),
|
||||||
|
'BINARY_PATH=' + os.path.join(toolchain.install_prefix, 'bin'),
|
||||||
|
'SHARED_MODE=1'],
|
||||||
|
cwd=src, env=toolchain.env)
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
|
||||||
* http://www.musicpd.org
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "AudioConfig.hxx"
|
|
||||||
#include "AudioFormat.hxx"
|
|
||||||
#include "AudioParser.hxx"
|
|
||||||
#include "config/ConfigData.hxx"
|
|
||||||
#include "config/ConfigGlobal.hxx"
|
|
||||||
#include "config/ConfigOption.hxx"
|
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "system/FatalError.hxx"
|
|
||||||
|
|
||||||
static AudioFormat configured_audio_format;
|
|
||||||
|
|
||||||
AudioFormat
|
|
||||||
getOutputAudioFormat(AudioFormat inAudioFormat)
|
|
||||||
{
|
|
||||||
AudioFormat out_audio_format = inAudioFormat;
|
|
||||||
out_audio_format.ApplyMask(configured_audio_format);
|
|
||||||
return out_audio_format;
|
|
||||||
}
|
|
||||||
|
|
||||||
void initAudioConfig(void)
|
|
||||||
{
|
|
||||||
const struct config_param *param = config_get_param(CONF_AUDIO_OUTPUT_FORMAT);
|
|
||||||
|
|
||||||
if (param == nullptr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
Error error;
|
|
||||||
if (!audio_format_parse(configured_audio_format, param->value.c_str(),
|
|
||||||
true, error))
|
|
||||||
FormatFatalError("error parsing line %i: %s",
|
|
||||||
param->line, error.GetMessage());
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -18,6 +18,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
|
#include "util/StringBuffer.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -40,46 +41,24 @@ AudioFormat::ApplyMask(AudioFormat mask)
|
|||||||
assert(IsValid());
|
assert(IsValid());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *
|
StringBuffer<24>
|
||||||
sample_format_to_string(SampleFormat format)
|
ToString(const AudioFormat af)
|
||||||
{
|
{
|
||||||
switch (format) {
|
StringBuffer<24> buffer;
|
||||||
case SampleFormat::UNDEFINED:
|
|
||||||
return "?";
|
|
||||||
|
|
||||||
case SampleFormat::S8:
|
if (af.format == SampleFormat::DSD && af.sample_rate > 0 &&
|
||||||
return "8";
|
af.sample_rate % 44100 == 0) {
|
||||||
|
/* use shortcuts such as "dsd64" which implies the
|
||||||
case SampleFormat::S16:
|
sample rate */
|
||||||
return "16";
|
snprintf(buffer.data(), buffer.capacity(), "dsd%u:%u",
|
||||||
|
af.sample_rate * 8 / 44100,
|
||||||
case SampleFormat::S24_P32:
|
af.channels);
|
||||||
return "24";
|
return buffer;
|
||||||
|
|
||||||
case SampleFormat::S32:
|
|
||||||
return "32";
|
|
||||||
|
|
||||||
case SampleFormat::FLOAT:
|
|
||||||
return "f";
|
|
||||||
|
|
||||||
case SampleFormat::DSD:
|
|
||||||
return "dsd";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* unreachable */
|
snprintf(buffer.data(), buffer.capacity(), "%u:%s:%u",
|
||||||
assert(false);
|
|
||||||
gcc_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *
|
|
||||||
audio_format_to_string(const AudioFormat af,
|
|
||||||
struct audio_format_string *s)
|
|
||||||
{
|
|
||||||
assert(s != nullptr);
|
|
||||||
|
|
||||||
snprintf(s->buffer, sizeof(s->buffer), "%u:%s:%u",
|
|
||||||
af.sample_rate, sample_format_to_string(af.format),
|
af.sample_rate, sample_format_to_string(af.format),
|
||||||
af.channels);
|
af.channels);
|
||||||
|
|
||||||
return s->buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,47 +20,14 @@
|
|||||||
#ifndef MPD_AUDIO_FORMAT_HXX
|
#ifndef MPD_AUDIO_FORMAT_HXX
|
||||||
#define MPD_AUDIO_FORMAT_HXX
|
#define MPD_AUDIO_FORMAT_HXX
|
||||||
|
|
||||||
|
#include "pcm/SampleFormat.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
|
||||||
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
|
template<size_t CAPACITY> class StringBuffer;
|
||||||
/* on WIN32, "FLOAT" is already defined, and this triggers -Wshadow */
|
|
||||||
#pragma GCC diagnostic push
|
|
||||||
#pragma GCC diagnostic ignored "-Wshadow"
|
|
||||||
#endif
|
|
||||||
|
|
||||||
enum class SampleFormat : uint8_t {
|
|
||||||
UNDEFINED = 0,
|
|
||||||
|
|
||||||
S8,
|
|
||||||
S16,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Signed 24 bit integer samples, packed in 32 bit integers
|
|
||||||
* (the most significant byte is filled with the sign bit).
|
|
||||||
*/
|
|
||||||
S24_P32,
|
|
||||||
|
|
||||||
S32,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 32 bit floating point samples in the host's format. The
|
|
||||||
* range is -1.0f to +1.0f.
|
|
||||||
*/
|
|
||||||
FLOAT,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Direct Stream Digital. 1-bit samples; each frame has one
|
|
||||||
* byte (8 samples) per channel.
|
|
||||||
*/
|
|
||||||
DSD,
|
|
||||||
};
|
|
||||||
|
|
||||||
#if defined(WIN32) && GCC_CHECK_VERSION(4,6)
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static constexpr unsigned MAX_CHANNELS = 8;
|
static constexpr unsigned MAX_CHANNELS = 8;
|
||||||
|
|
||||||
@@ -82,8 +49,19 @@ struct AudioFormat {
|
|||||||
SampleFormat format;
|
SampleFormat format;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The number of channels. Only mono (1) and stereo (2) are
|
* The number of channels.
|
||||||
* fully supported currently.
|
*
|
||||||
|
* Channel order follows the FLAC convention
|
||||||
|
* (https://xiph.org/flac/format.html):
|
||||||
|
*
|
||||||
|
* - 1 channel: mono
|
||||||
|
* - 2 channels: left, right
|
||||||
|
* - 3 channels: left, right, center
|
||||||
|
* - 4 channels: front left, front right, back left, back right
|
||||||
|
* - 5 channels: front left, front right, front center, back/surround left, back/surround right
|
||||||
|
* - 6 channels: front left, front right, front center, LFE, back/surround left, back/surround right
|
||||||
|
* - 7 channels: front left, front right, front center, LFE, back center, side left, side right
|
||||||
|
* - 8 channels: front left, front right, front center, LFE, back left, back right, side left, side right
|
||||||
*/
|
*/
|
||||||
uint8_t channels;
|
uint8_t channels;
|
||||||
|
|
||||||
@@ -99,8 +77,8 @@ struct AudioFormat {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Clears the #audio_format object, i.e. sets all attributes to an
|
* Clears the object, i.e. sets all attributes to an undefined
|
||||||
* undefined (invalid) value.
|
* (invalid) value.
|
||||||
*/
|
*/
|
||||||
void Clear() {
|
void Clear() {
|
||||||
sample_rate = 0;
|
sample_rate = 0;
|
||||||
@@ -148,6 +126,13 @@ struct AudioFormat {
|
|||||||
|
|
||||||
void ApplyMask(AudioFormat mask);
|
void ApplyMask(AudioFormat mask);
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
AudioFormat WithMask(AudioFormat mask) const {
|
||||||
|
AudioFormat result = *this;
|
||||||
|
result.ApplyMask(mask);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of each (mono) sample in bytes.
|
* Returns the size of each (mono) sample in bytes.
|
||||||
*/
|
*/
|
||||||
@@ -165,13 +150,6 @@ struct AudioFormat {
|
|||||||
double GetTimeToSize() const;
|
double GetTimeToSize() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Buffer for audio_format_string().
|
|
||||||
*/
|
|
||||||
struct audio_format_string {
|
|
||||||
char buffer[24];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the sample rate is valid.
|
* Checks whether the sample rate is valid.
|
||||||
*
|
*
|
||||||
@@ -183,30 +161,6 @@ audio_valid_sample_rate(unsigned sample_rate)
|
|||||||
return sample_rate > 0 && sample_rate < (1 << 30);
|
return sample_rate > 0 && sample_rate < (1 << 30);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Checks whether the sample format is valid.
|
|
||||||
*
|
|
||||||
* @param bits the number of significant bits per sample
|
|
||||||
*/
|
|
||||||
static inline bool
|
|
||||||
audio_valid_sample_format(SampleFormat format)
|
|
||||||
{
|
|
||||||
switch (format) {
|
|
||||||
case SampleFormat::S8:
|
|
||||||
case SampleFormat::S16:
|
|
||||||
case SampleFormat::S24_P32:
|
|
||||||
case SampleFormat::S32:
|
|
||||||
case SampleFormat::FLOAT:
|
|
||||||
case SampleFormat::DSD:
|
|
||||||
return true;
|
|
||||||
|
|
||||||
case SampleFormat::UNDEFINED:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the number of channels is valid.
|
* Checks whether the number of channels is valid.
|
||||||
*/
|
*/
|
||||||
@@ -242,34 +196,6 @@ AudioFormat::IsMaskValid() const
|
|||||||
(channels == 0 || audio_valid_channel_count(channels));
|
(channels == 0 || audio_valid_channel_count(channels));
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_const
|
|
||||||
static inline unsigned
|
|
||||||
sample_format_size(SampleFormat format)
|
|
||||||
{
|
|
||||||
switch (format) {
|
|
||||||
case SampleFormat::S8:
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case SampleFormat::S16:
|
|
||||||
return 2;
|
|
||||||
|
|
||||||
case SampleFormat::S24_P32:
|
|
||||||
case SampleFormat::S32:
|
|
||||||
case SampleFormat::FLOAT:
|
|
||||||
return 4;
|
|
||||||
|
|
||||||
case SampleFormat::DSD:
|
|
||||||
/* each frame has 8 samples per channel */
|
|
||||||
return 1;
|
|
||||||
|
|
||||||
case SampleFormat::UNDEFINED:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
assert(false);
|
|
||||||
gcc_unreachable();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline unsigned
|
inline unsigned
|
||||||
AudioFormat::GetSampleSize() const
|
AudioFormat::GetSampleSize() const
|
||||||
{
|
{
|
||||||
@@ -289,27 +215,14 @@ AudioFormat::GetTimeToSize() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders a #sample_format enum into a string, e.g. for printing it
|
* Renders the #AudioFormat object into a string, e.g. for printing
|
||||||
* in a log file.
|
|
||||||
*
|
|
||||||
* @param format a #sample_format enum value
|
|
||||||
* @return the string
|
|
||||||
*/
|
|
||||||
gcc_pure gcc_malloc
|
|
||||||
const char *
|
|
||||||
sample_format_to_string(SampleFormat format);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Renders the #audio_format object into a string, e.g. for printing
|
|
||||||
* it in a log file.
|
* it in a log file.
|
||||||
*
|
*
|
||||||
* @param af the #audio_format object
|
* @param af the #AudioFormat object
|
||||||
* @param s a buffer to print into
|
* @return the string buffer
|
||||||
* @return the string, or nullptr if the #audio_format object is invalid
|
|
||||||
*/
|
*/
|
||||||
gcc_pure gcc_malloc
|
gcc_const
|
||||||
const char *
|
StringBuffer<24>
|
||||||
audio_format_to_string(AudioFormat af,
|
ToString(AudioFormat af);
|
||||||
struct audio_format_string *s);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -25,73 +25,59 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "AudioParser.hxx"
|
#include "AudioParser.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "CheckAudioFormat.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "Compiler.h"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
static bool
|
static uint32_t
|
||||||
parse_sample_rate(const char *src, bool mask, uint32_t *sample_rate_r,
|
ParseSampleRate(const char *src, bool mask, const char **endptr_r)
|
||||||
const char **endptr_r, Error &error)
|
|
||||||
{
|
{
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
if (mask && *src == '*') {
|
if (mask && *src == '*') {
|
||||||
*sample_rate_r = 0;
|
|
||||||
*endptr_r = src + 1;
|
*endptr_r = src + 1;
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = strtoul(src, &endptr, 10);
|
value = strtoul(src, &endptr, 10);
|
||||||
if (endptr == src) {
|
if (endptr == src) {
|
||||||
error.Set(audio_format_domain,
|
throw std::runtime_error("Failed to parse the sample rate");
|
||||||
"Failed to parse the sample rate");
|
} else if (!audio_valid_sample_rate(value))
|
||||||
return false;
|
throw FormatRuntimeError("Invalid sample rate: %lu",
|
||||||
} else if (!audio_check_sample_rate(value, error))
|
value);
|
||||||
return false;
|
|
||||||
|
|
||||||
*sample_rate_r = value;
|
|
||||||
*endptr_r = endptr;
|
*endptr_r = endptr;
|
||||||
return true;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static SampleFormat
|
||||||
parse_sample_format(const char *src, bool mask,
|
ParseSampleFormat(const char *src, bool mask, const char **endptr_r)
|
||||||
SampleFormat *sample_format_r,
|
|
||||||
const char **endptr_r, Error &error)
|
|
||||||
{
|
{
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
SampleFormat sample_format;
|
SampleFormat sample_format;
|
||||||
|
|
||||||
if (mask && *src == '*') {
|
if (mask && *src == '*') {
|
||||||
*sample_format_r = SampleFormat::UNDEFINED;
|
|
||||||
*endptr_r = src + 1;
|
*endptr_r = src + 1;
|
||||||
return true;
|
return SampleFormat::UNDEFINED;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (*src == 'f') {
|
if (*src == 'f') {
|
||||||
*sample_format_r = SampleFormat::FLOAT;
|
|
||||||
*endptr_r = src + 1;
|
*endptr_r = src + 1;
|
||||||
return true;
|
return SampleFormat::FLOAT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (memcmp(src, "dsd", 3) == 0) {
|
if (memcmp(src, "dsd", 3) == 0) {
|
||||||
*sample_format_r = SampleFormat::DSD;
|
|
||||||
*endptr_r = src + 3;
|
*endptr_r = src + 3;
|
||||||
return true;
|
return SampleFormat::DSD;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = strtoul(src, &endptr, 10);
|
value = strtoul(src, &endptr, 10);
|
||||||
if (endptr == src) {
|
if (endptr == src)
|
||||||
error.Set(audio_format_domain,
|
throw std::runtime_error("Failed to parse the sample format");
|
||||||
"Failed to parse the sample format");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 8:
|
case 8:
|
||||||
@@ -115,99 +101,85 @@ parse_sample_format(const char *src, bool mask,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
error.Format(audio_format_domain,
|
throw FormatRuntimeError("Invalid sample format: %lu", value);
|
||||||
"Invalid sample format: %lu", value);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(audio_valid_sample_format(sample_format));
|
assert(audio_valid_sample_format(sample_format));
|
||||||
|
|
||||||
*sample_format_r = sample_format;
|
|
||||||
*endptr_r = endptr;
|
*endptr_r = endptr;
|
||||||
return true;
|
return sample_format;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static uint8_t
|
||||||
parse_channel_count(const char *src, bool mask, uint8_t *channels_r,
|
ParseChannelCount(const char *src, bool mask, const char **endptr_r)
|
||||||
const char **endptr_r, Error &error)
|
|
||||||
{
|
{
|
||||||
unsigned long value;
|
unsigned long value;
|
||||||
char *endptr;
|
char *endptr;
|
||||||
|
|
||||||
if (mask && *src == '*') {
|
if (mask && *src == '*') {
|
||||||
*channels_r = 0;
|
|
||||||
*endptr_r = src + 1;
|
*endptr_r = src + 1;
|
||||||
return true;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
value = strtoul(src, &endptr, 10);
|
value = strtoul(src, &endptr, 10);
|
||||||
if (endptr == src) {
|
if (endptr == src)
|
||||||
error.Set(audio_format_domain,
|
throw std::runtime_error("Failed to parse the channel count");
|
||||||
"Failed to parse the channel count");
|
else if (!audio_valid_channel_count(value))
|
||||||
return false;
|
throw FormatRuntimeError("Invalid channel count: %u", value);
|
||||||
} else if (!audio_check_channel_count(value, error))
|
|
||||||
return false;
|
|
||||||
|
|
||||||
*channels_r = value;
|
|
||||||
*endptr_r = endptr;
|
*endptr_r = endptr;
|
||||||
return true;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
AudioFormat
|
||||||
audio_format_parse(AudioFormat &dest, const char *src,
|
ParseAudioFormat(const char *src, bool mask)
|
||||||
bool mask, Error &error)
|
|
||||||
{
|
{
|
||||||
uint32_t rate;
|
AudioFormat dest;
|
||||||
SampleFormat sample_format;
|
|
||||||
uint8_t channels;
|
|
||||||
|
|
||||||
dest.Clear();
|
dest.Clear();
|
||||||
|
|
||||||
|
if (strncmp(src, "dsd", 3) == 0) {
|
||||||
|
/* allow format specifications such as "dsd64" which
|
||||||
|
implies the sample rate */
|
||||||
|
|
||||||
|
char *endptr;
|
||||||
|
auto dsd = strtoul(src + 3, &endptr, 10);
|
||||||
|
if (endptr > src + 3 && *endptr == ':' &&
|
||||||
|
dsd >= 32 && dsd <= 4096 && dsd % 2 == 0) {
|
||||||
|
dest.sample_rate = dsd * 44100 / 8;
|
||||||
|
dest.format = SampleFormat::DSD;
|
||||||
|
|
||||||
|
src = endptr + 1;
|
||||||
|
dest.channels = ParseChannelCount(src, mask, &src);
|
||||||
|
if (*src != 0)
|
||||||
|
throw FormatRuntimeError("Extra data after channel count: %s", src);
|
||||||
|
|
||||||
|
return dest;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* parse sample rate */
|
/* parse sample rate */
|
||||||
|
|
||||||
#if GCC_CHECK_VERSION(4,7)
|
dest.sample_rate = ParseSampleRate(src, mask, &src);
|
||||||
/* workaround -Wmaybe-uninitialized false positive */
|
|
||||||
rate = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!parse_sample_rate(src, mask, &rate, &src, error))
|
if (*src++ != ':')
|
||||||
return false;
|
throw std::runtime_error("Sample format missing");
|
||||||
|
|
||||||
if (*src++ != ':') {
|
|
||||||
error.Set(audio_format_domain, "Sample format missing");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse sample format */
|
/* parse sample format */
|
||||||
|
|
||||||
#if GCC_CHECK_VERSION(4,7)
|
dest.format = ParseSampleFormat(src, mask, &src);
|
||||||
/* workaround -Wmaybe-uninitialized false positive */
|
|
||||||
sample_format = SampleFormat::UNDEFINED;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!parse_sample_format(src, mask, &sample_format, &src, error))
|
if (*src++ != ':')
|
||||||
return false;
|
throw std::runtime_error("Channel count missing");
|
||||||
|
|
||||||
if (*src++ != ':') {
|
|
||||||
error.Set(audio_format_domain, "Channel count missing");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* parse channel count */
|
/* parse channel count */
|
||||||
|
|
||||||
if (!parse_channel_count(src, mask, &channels, &src, error))
|
dest.channels = ParseChannelCount(src, mask, &src);
|
||||||
return false;
|
|
||||||
|
|
||||||
if (*src != 0) {
|
if (*src != 0)
|
||||||
error.Format(audio_format_domain,
|
throw FormatRuntimeError("Extra data after channel count: %s", src);
|
||||||
"Extra data after channel count: %s", src);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
dest = AudioFormat(rate, sample_format, channels);
|
|
||||||
assert(mask
|
assert(mask
|
||||||
? dest.IsMaskValid()
|
? dest.IsMaskValid()
|
||||||
: dest.IsValid());
|
: dest.IsValid());
|
||||||
|
return dest;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -25,22 +25,21 @@
|
|||||||
#ifndef MPD_AUDIO_PARSER_HXX
|
#ifndef MPD_AUDIO_PARSER_HXX
|
||||||
#define MPD_AUDIO_PARSER_HXX
|
#define MPD_AUDIO_PARSER_HXX
|
||||||
|
|
||||||
|
#include "Compiler.h"
|
||||||
|
|
||||||
struct AudioFormat;
|
struct AudioFormat;
|
||||||
class Error;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an
|
* Parses a string in the form "SAMPLE_RATE:BITS:CHANNELS" into an
|
||||||
* #audio_format.
|
* #AudioFormat.
|
||||||
|
*
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
*
|
*
|
||||||
* @param dest the destination #audio_format struct
|
|
||||||
* @param src the input string
|
* @param src the input string
|
||||||
* @param mask if true, then "*" is allowed for any number of items
|
* @param mask if true, then "*" is allowed for any number of items
|
||||||
* @param error_r location to store the error occurring, or NULL to
|
|
||||||
* ignore errors
|
|
||||||
* @return true on success
|
|
||||||
*/
|
*/
|
||||||
bool
|
gcc_pure
|
||||||
audio_format_parse(AudioFormat &dest, const char *src,
|
AudioFormat
|
||||||
bool mask, Error &error);
|
ParseAudioFormat(const char *src, bool mask);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,61 +20,43 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "CheckAudioFormat.hxx"
|
#include "CheckAudioFormat.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
const Domain audio_format_domain("audio_format");
|
void
|
||||||
|
CheckSampleRate(unsigned long sample_rate)
|
||||||
bool
|
|
||||||
audio_check_sample_rate(unsigned long sample_rate, Error &error)
|
|
||||||
{
|
{
|
||||||
if (!audio_valid_sample_rate(sample_rate)) {
|
if (!audio_valid_sample_rate(sample_rate))
|
||||||
error.Format(audio_format_domain,
|
throw FormatRuntimeError("Invalid sample rate: %lu",
|
||||||
"Invalid sample rate: %lu", sample_rate);
|
sample_rate);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
audio_check_sample_format(SampleFormat sample_format, Error &error)
|
CheckSampleFormat(SampleFormat sample_format)
|
||||||
{
|
{
|
||||||
if (!audio_valid_sample_format(sample_format)) {
|
if (!audio_valid_sample_format(sample_format))
|
||||||
error.Format(audio_format_domain,
|
throw FormatRuntimeError("Invalid sample format: %u",
|
||||||
"Invalid sample format: %u",
|
|
||||||
unsigned(sample_format));
|
unsigned(sample_format));
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
audio_check_channel_count(unsigned channels, Error &error)
|
CheckChannelCount(unsigned channels)
|
||||||
{
|
{
|
||||||
if (!audio_valid_channel_count(channels)) {
|
if (!audio_valid_channel_count(channels))
|
||||||
error.Format(audio_format_domain,
|
throw FormatRuntimeError("Invalid channel count: %u",
|
||||||
"Invalid channel count: %u", channels);
|
channels);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
AudioFormat
|
||||||
audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
|
CheckAudioFormat(unsigned long sample_rate,
|
||||||
SampleFormat sample_format, unsigned channels,
|
SampleFormat sample_format, unsigned channels)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
if (audio_check_sample_rate(sample_rate, error) &&
|
CheckSampleRate(sample_rate);
|
||||||
audio_check_sample_format(sample_format, error) &&
|
CheckSampleFormat(sample_format);
|
||||||
audio_check_channel_count(channels, error)) {
|
CheckChannelCount(channels);
|
||||||
af = AudioFormat(sample_rate, sample_format, channels);
|
|
||||||
assert(af.IsValid());
|
return AudioFormat(sample_rate, sample_format, channels);
|
||||||
return true;
|
|
||||||
} else
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -22,25 +22,23 @@
|
|||||||
|
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
|
|
||||||
class Error;
|
void
|
||||||
|
CheckSampleRate(unsigned long sample_rate);
|
||||||
|
|
||||||
extern const class Domain audio_format_domain;
|
void
|
||||||
|
CheckSampleFormat(SampleFormat sample_format);
|
||||||
|
|
||||||
bool
|
void
|
||||||
audio_check_sample_rate(unsigned long sample_rate, Error &error);
|
CheckChannelCount(unsigned sample_format);
|
||||||
|
|
||||||
bool
|
|
||||||
audio_check_sample_format(SampleFormat sample_format, Error &error);
|
|
||||||
|
|
||||||
bool
|
|
||||||
audio_check_channel_count(unsigned sample_format, Error &error);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper for audio_format_init(), which checks all attributes.
|
* Check #AudioFormat attributes and construct an #AudioFormat
|
||||||
|
* instance.
|
||||||
|
*
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
*/
|
*/
|
||||||
bool
|
AudioFormat
|
||||||
audio_format_init_checked(AudioFormat &af, unsigned long sample_rate,
|
CheckAudioFormat(unsigned long sample_rate,
|
||||||
SampleFormat sample_format, unsigned channels,
|
SampleFormat sample_format, unsigned channels);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,19 +20,10 @@
|
|||||||
#ifndef MPD_CHRONO_HXX
|
#ifndef MPD_CHRONO_HXX
|
||||||
#define MPD_CHRONO_HXX
|
#define MPD_CHRONO_HXX
|
||||||
|
|
||||||
#include "Compiler.h"
|
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#if defined(__GNUC__) && !GCC_CHECK_VERSION(4,7) && !defined(__clang__)
|
|
||||||
/* std::chrono::duration operators are "constexpr" since gcc 4.7 */
|
|
||||||
#define chrono_constexpr gcc_pure
|
|
||||||
#else
|
|
||||||
#define chrono_constexpr constexpr
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A time stamp within a song. Granularity is 1 millisecond and the
|
* A time stamp within a song. Granularity is 1 millisecond and the
|
||||||
* maximum value is about 49 days.
|
* maximum value is about 49 days.
|
||||||
@@ -108,11 +99,11 @@ public:
|
|||||||
return count() > 0;
|
return count() > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
chrono_constexpr SongTime operator+(const SongTime &other) const {
|
constexpr SongTime operator+(const SongTime &other) const {
|
||||||
return SongTime(*(const Base *)this + (const Base &)other);
|
return SongTime(*(const Base *)this + (const Base &)other);
|
||||||
}
|
}
|
||||||
|
|
||||||
chrono_constexpr SongTime operator-(const SongTime &other) const {
|
constexpr SongTime operator-(const SongTime &other) const {
|
||||||
return SongTime(*(const Base *)this - (const Base &)other);
|
return SongTime(*(const Base *)this - (const Base &)other);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -212,15 +203,13 @@ public:
|
|||||||
return count() < 0;
|
return count() < 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
chrono_constexpr SignedSongTime operator+(const SignedSongTime &other) const {
|
constexpr SignedSongTime operator+(const SignedSongTime &other) const {
|
||||||
return SignedSongTime(*(const Base *)this + (const Base &)other);
|
return SignedSongTime(*(const Base *)this + (const Base &)other);
|
||||||
}
|
}
|
||||||
|
|
||||||
chrono_constexpr SignedSongTime operator-(const SignedSongTime &other) const {
|
constexpr SignedSongTime operator-(const SignedSongTime &other) const {
|
||||||
return SignedSongTime(*(const Base *)this - (const Base &)other);
|
return SignedSongTime(*(const Base *)this - (const Base &)other);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#undef chrono_constexpr
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -35,7 +35,9 @@
|
|||||||
#include "fs/Traits.hxx"
|
#include "fs/Traits.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "fs/StandardDirectory.hxx"
|
#include "fs/StandardDirectory.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "system/Error.hxx"
|
||||||
|
#include "util/Macros.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "util/OptionDef.hxx"
|
#include "util/OptionDef.hxx"
|
||||||
#include "util/OptionParser.hxx"
|
#include "util/OptionParser.hxx"
|
||||||
@@ -66,12 +68,12 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
#define CONFIG_FILE_LOCATION "mpd\\mpd.conf"
|
#define CONFIG_FILE_LOCATION PATH_LITERAL("mpd\\mpd.conf")
|
||||||
#define APP_CONFIG_FILE_LOCATION "conf\\mpd.conf"
|
#define APP_CONFIG_FILE_LOCATION PATH_LITERAL("conf\\mpd.conf")
|
||||||
#else
|
#else
|
||||||
#define USER_CONFIG_FILE_LOCATION1 ".mpdconf"
|
#define USER_CONFIG_FILE_LOCATION1 PATH_LITERAL(".mpdconf")
|
||||||
#define USER_CONFIG_FILE_LOCATION2 ".mpd/mpd.conf"
|
#define USER_CONFIG_FILE_LOCATION2 PATH_LITERAL(".mpd/mpd.conf")
|
||||||
#define USER_CONFIG_FILE_LOCATION_XDG "mpd/mpd.conf"
|
#define USER_CONFIG_FILE_LOCATION_XDG PATH_LITERAL("mpd/mpd.conf")
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static constexpr OptionDef opt_kill(
|
static constexpr OptionDef opt_kill(
|
||||||
@@ -98,40 +100,44 @@ static constexpr Domain cmdline_domain("cmdline");
|
|||||||
gcc_noreturn
|
gcc_noreturn
|
||||||
static void version(void)
|
static void version(void)
|
||||||
{
|
{
|
||||||
puts("Music Player Daemon " VERSION
|
printf("Music Player Daemon " VERSION
|
||||||
#ifdef GIT_COMMIT
|
#ifdef GIT_COMMIT
|
||||||
" (" GIT_COMMIT ")"
|
" (" GIT_COMMIT ")"
|
||||||
#endif
|
#endif
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\n"
|
"Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\n"
|
||||||
"Copyright (C) 2008-2014 Max Kellermann <max@duempel.org>\n"
|
"Copyright 2008-2017 Max Kellermann <max.kellermann@gmail.com>\n"
|
||||||
"This is free software; see the source for copying conditions. There is NO\n"
|
"This is free software; see the source for copying conditions. There is NO\n"
|
||||||
"warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n");
|
"warranty; not even MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
puts("\n"
|
"\n"
|
||||||
"Database plugins:");
|
"Database plugins:\n");
|
||||||
|
|
||||||
for (auto i = database_plugins; *i != nullptr; ++i)
|
for (auto i = database_plugins; *i != nullptr; ++i)
|
||||||
printf(" %s", (*i)->name);
|
printf(" %s", (*i)->name);
|
||||||
|
|
||||||
puts("\n\n"
|
printf("\n\n"
|
||||||
"Storage plugins:");
|
"Storage plugins:\n");
|
||||||
|
|
||||||
for (auto i = storage_plugins; *i != nullptr; ++i)
|
for (auto i = storage_plugins; *i != nullptr; ++i)
|
||||||
printf(" %s", (*i)->name);
|
printf(" %s", (*i)->name);
|
||||||
|
|
||||||
|
printf("\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
puts("\n\n"
|
"\n"
|
||||||
"Neighbor plugins:");
|
"Neighbor plugins:\n");
|
||||||
for (auto i = neighbor_plugins; *i != nullptr; ++i)
|
for (auto i = neighbor_plugins; *i != nullptr; ++i)
|
||||||
printf(" %s", (*i)->name);
|
printf(" %s", (*i)->name);
|
||||||
|
|
||||||
|
printf("\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
puts("\n\n"
|
"\n"
|
||||||
"Decoders plugins:");
|
"Decoders plugins:\n");
|
||||||
|
|
||||||
decoder_plugins_for_each([](const DecoderPlugin &plugin){
|
decoder_plugins_for_each([](const DecoderPlugin &plugin){
|
||||||
printf(" [%s]", plugin.name);
|
printf(" [%s]", plugin.name);
|
||||||
@@ -141,26 +147,39 @@ static void version(void)
|
|||||||
for (; *suffixes != nullptr; ++suffixes)
|
for (; *suffixes != nullptr; ++suffixes)
|
||||||
printf(" %s", *suffixes);
|
printf(" %s", *suffixes);
|
||||||
|
|
||||||
puts("");
|
printf("\n");
|
||||||
});
|
});
|
||||||
|
|
||||||
puts("\n"
|
printf("\n"
|
||||||
"Output plugins:");
|
"Filters:\n"
|
||||||
|
#ifdef ENABLE_LIBSAMPLERATE
|
||||||
|
" libsamplerate"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_SOXR
|
||||||
|
" soxr"
|
||||||
|
#endif
|
||||||
|
"\n\n"
|
||||||
|
"Tag plugins:\n"
|
||||||
|
#ifdef ENABLE_ID3TAG
|
||||||
|
" id3tag"
|
||||||
|
#endif
|
||||||
|
"\n\n"
|
||||||
|
"Output plugins:\n");
|
||||||
audio_output_plugins_for_each(plugin)
|
audio_output_plugins_for_each(plugin)
|
||||||
printf(" %s", plugin->name);
|
printf(" %s", plugin->name);
|
||||||
puts("");
|
printf("\n"
|
||||||
|
|
||||||
#ifdef ENABLE_ENCODER
|
#ifdef ENABLE_ENCODER
|
||||||
puts("\n"
|
"\n"
|
||||||
"Encoder plugins:");
|
"Encoder plugins:\n");
|
||||||
encoder_plugins_for_each(plugin)
|
encoder_plugins_for_each(plugin)
|
||||||
printf(" %s", plugin->name);
|
printf(" %s", plugin->name);
|
||||||
puts("");
|
printf("\n"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_ARCHIVE
|
#ifdef ENABLE_ARCHIVE
|
||||||
puts("\n"
|
"\n"
|
||||||
"Archive plugins:");
|
"Archive plugins:\n");
|
||||||
archive_plugins_for_each(plugin) {
|
archive_plugins_for_each(plugin) {
|
||||||
printf(" [%s]", plugin->name);
|
printf(" [%s]", plugin->name);
|
||||||
|
|
||||||
@@ -169,24 +188,57 @@ static void version(void)
|
|||||||
for (; *suffixes != nullptr; ++suffixes)
|
for (; *suffixes != nullptr; ++suffixes)
|
||||||
printf(" %s", *suffixes);
|
printf(" %s", *suffixes);
|
||||||
|
|
||||||
puts("");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
printf(""
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
puts("\n"
|
"\n"
|
||||||
"Input plugins:");
|
"Input plugins:\n");
|
||||||
input_plugins_for_each(plugin)
|
input_plugins_for_each(plugin)
|
||||||
printf(" %s", plugin->name);
|
printf(" %s", plugin->name);
|
||||||
|
|
||||||
puts("\n\n"
|
printf("\n\n"
|
||||||
"Playlist plugins:");
|
"Playlist plugins:\n");
|
||||||
playlist_plugins_for_each(plugin)
|
playlist_plugins_for_each(plugin)
|
||||||
printf(" %s", plugin->name);
|
printf(" %s", plugin->name);
|
||||||
|
|
||||||
puts("\n\n"
|
printf("\n\n"
|
||||||
"Protocols:");
|
"Protocols:\n");
|
||||||
print_supported_uri_schemes_to_fp(stdout);
|
print_supported_uri_schemes_to_fp(stdout);
|
||||||
|
|
||||||
|
printf("\n"
|
||||||
|
"Other features:\n"
|
||||||
|
#ifdef HAVE_AVAHI
|
||||||
|
" avahi"
|
||||||
|
#endif
|
||||||
|
#ifdef USE_EPOLL
|
||||||
|
" epoll"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ICONV
|
||||||
|
" iconv"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_ICU
|
||||||
|
" icu"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_INOTIFY
|
||||||
|
" inotify"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_IPV6
|
||||||
|
" ipv6"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
" systemd"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_TCP
|
||||||
|
" tcp"
|
||||||
|
#endif
|
||||||
|
#ifdef HAVE_UN
|
||||||
|
" un"
|
||||||
|
#endif
|
||||||
|
"\n");
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -206,12 +258,12 @@ static void PrintOption(const OptionDef &opt)
|
|||||||
gcc_noreturn
|
gcc_noreturn
|
||||||
static void help(void)
|
static void help(void)
|
||||||
{
|
{
|
||||||
puts("Usage:\n"
|
printf("Usage:\n"
|
||||||
" mpd [OPTION...] [path/to/mpd.conf]\n"
|
" mpd [OPTION...] [path/to/mpd.conf]\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Music Player Daemon - a daemon for playing music.\n"
|
"Music Player Daemon - a daemon for playing music.\n"
|
||||||
"\n"
|
"\n"
|
||||||
"Options:");
|
"Options:\n");
|
||||||
|
|
||||||
PrintOption(opt_help);
|
PrintOption(opt_help);
|
||||||
PrintOption(opt_kill);
|
PrintOption(opt_kill);
|
||||||
@@ -226,29 +278,23 @@ static void help(void)
|
|||||||
|
|
||||||
class ConfigLoader
|
class ConfigLoader
|
||||||
{
|
{
|
||||||
Error &error;
|
|
||||||
bool result;
|
|
||||||
public:
|
public:
|
||||||
ConfigLoader(Error &_error) : error(_error), result(false) { }
|
|
||||||
|
|
||||||
bool GetResult() const { return result; }
|
|
||||||
|
|
||||||
bool TryFile(const Path path);
|
bool TryFile(const Path path);
|
||||||
bool TryFile(const AllocatedPath &base_path,
|
bool TryFile(const AllocatedPath &base_path,
|
||||||
PathTraitsFS::const_pointer path);
|
PathTraitsFS::const_pointer_type path);
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ConfigLoader::TryFile(Path path)
|
bool ConfigLoader::TryFile(Path path)
|
||||||
{
|
{
|
||||||
if (FileExists(path)) {
|
if (FileExists(path)) {
|
||||||
result = ReadConfigFile(path, error);
|
ReadConfigFile(path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigLoader::TryFile(const AllocatedPath &base_path,
|
bool ConfigLoader::TryFile(const AllocatedPath &base_path,
|
||||||
PathTraitsFS::const_pointer path)
|
PathTraitsFS::const_pointer_type path)
|
||||||
{
|
{
|
||||||
if (base_path.IsNull())
|
if (base_path.IsNull())
|
||||||
return false;
|
return false;
|
||||||
@@ -256,9 +302,8 @@ bool ConfigLoader::TryFile(const AllocatedPath &base_path,
|
|||||||
return TryFile(full_path);
|
return TryFile(full_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
parse_cmdline(int argc, char **argv, struct options *options,
|
ParseCommandLine(int argc, char **argv, struct options *options)
|
||||||
Error &error)
|
|
||||||
{
|
{
|
||||||
bool use_config_file = true;
|
bool use_config_file = true;
|
||||||
options->kill = false;
|
options->kill = false;
|
||||||
@@ -296,9 +341,8 @@ parse_cmdline(int argc, char **argv, struct options *options,
|
|||||||
if (parser.CheckOption(opt_help, opt_help_alt))
|
if (parser.CheckOption(opt_help, opt_help_alt))
|
||||||
help();
|
help();
|
||||||
|
|
||||||
error.Format(cmdline_domain, "invalid option: %s",
|
throw FormatRuntimeError("invalid option: %s",
|
||||||
parser.GetOption());
|
parser.GetOption());
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the logging library, so the configuration file
|
/* initialize the logging library, so the configuration file
|
||||||
@@ -308,7 +352,7 @@ parse_cmdline(int argc, char **argv, struct options *options,
|
|||||||
if (!use_config_file) {
|
if (!use_config_file) {
|
||||||
LogDebug(cmdline_domain,
|
LogDebug(cmdline_domain,
|
||||||
"Ignoring config, using daemon defaults");
|
"Ignoring config, using daemon defaults");
|
||||||
return true;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second pass: find non-option parameters (i.e. config file)
|
// Second pass: find non-option parameters (i.e. config file)
|
||||||
@@ -320,18 +364,29 @@ parse_cmdline(int argc, char **argv, struct options *options,
|
|||||||
config_file = argv[i];
|
config_file = argv[i];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
error.Set(cmdline_domain, "too many arguments");
|
|
||||||
return false;
|
throw std::runtime_error("too many arguments");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config_file != nullptr) {
|
if (config_file != nullptr) {
|
||||||
/* use specified configuration file */
|
/* use specified configuration file */
|
||||||
return ReadConfigFile(Path::FromFS(config_file), error);
|
#ifdef _UNICODE
|
||||||
|
wchar_t buffer[MAX_PATH];
|
||||||
|
auto result = MultiByteToWideChar(CP_ACP, 0, config_file, -1,
|
||||||
|
buffer, ARRAY_SIZE(buffer));
|
||||||
|
if (result <= 0)
|
||||||
|
throw MakeLastError("MultiByteToWideChar() failed");
|
||||||
|
|
||||||
|
ReadConfigFile(Path::FromFS(buffer));
|
||||||
|
#else
|
||||||
|
ReadConfigFile(Path::FromFS(config_file));
|
||||||
|
#endif
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use default configuration file path */
|
/* use default configuration file path */
|
||||||
|
|
||||||
ConfigLoader loader(error);
|
ConfigLoader loader;
|
||||||
|
|
||||||
bool found =
|
bool found =
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
@@ -345,10 +400,6 @@ parse_cmdline(int argc, char **argv, struct options *options,
|
|||||||
loader.TryFile(GetHomeDir(), USER_CONFIG_FILE_LOCATION2) ||
|
loader.TryFile(GetHomeDir(), USER_CONFIG_FILE_LOCATION2) ||
|
||||||
loader.TryFile(Path::FromFS(SYSTEM_CONFIG_FILE_LOCATION));
|
loader.TryFile(Path::FromFS(SYSTEM_CONFIG_FILE_LOCATION));
|
||||||
#endif
|
#endif
|
||||||
if (!found) {
|
if (!found)
|
||||||
error.Set(cmdline_domain, "No configuration file found");
|
throw std::runtime_error("No configuration file found");
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return loader.GetResult();
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,8 +20,6 @@
|
|||||||
#ifndef MPD_COMMAND_LINE_HXX
|
#ifndef MPD_COMMAND_LINE_HXX
|
||||||
#define MPD_COMMAND_LINE_HXX
|
#define MPD_COMMAND_LINE_HXX
|
||||||
|
|
||||||
class Error;
|
|
||||||
|
|
||||||
struct options {
|
struct options {
|
||||||
bool kill;
|
bool kill;
|
||||||
bool daemon;
|
bool daemon;
|
||||||
@@ -29,8 +27,7 @@ struct options {
|
|||||||
bool verbose;
|
bool verbose;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool
|
void
|
||||||
parse_cmdline(int argc, char **argv, struct options *options,
|
ParseCommandLine(int argc, char **argv, struct options *options);
|
||||||
Error &error);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -28,25 +28,42 @@
|
|||||||
#define GCC_VERSION 0
|
#define GCC_VERSION 0
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef __clang__
|
||||||
|
# define CLANG_VERSION GCC_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
# define CLANG_VERSION 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we building with the specified version of gcc (not clang or any
|
||||||
|
* other compiler) or newer?
|
||||||
|
*/
|
||||||
#define GCC_CHECK_VERSION(major, minor) \
|
#define GCC_CHECK_VERSION(major, minor) \
|
||||||
(defined(__GNUC__) && GCC_VERSION >= GCC_MAKE_VERSION(major, minor, 0))
|
(CLANG_VERSION == 0 && \
|
||||||
|
GCC_VERSION >= GCC_MAKE_VERSION(major, minor, 0))
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Are we building with clang (any version) or at least the specified
|
||||||
|
* gcc version?
|
||||||
|
*/
|
||||||
|
#define CLANG_OR_GCC_VERSION(major, minor) \
|
||||||
|
(CLANG_VERSION > 0 || GCC_CHECK_VERSION(major, minor))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Are we building with gcc (not clang or any other compiler) and a
|
* Are we building with gcc (not clang or any other compiler) and a
|
||||||
* version older than the specified one?
|
* version older than the specified one?
|
||||||
*/
|
*/
|
||||||
#define GCC_OLDER_THAN(major, minor) \
|
#define GCC_OLDER_THAN(major, minor) \
|
||||||
(defined(__GNUC__) && !defined(__clang__) && \
|
(GCC_VERSION > 0 && CLANG_VERSION == 0 && \
|
||||||
GCC_VERSION < GCC_MAKE_VERSION(major, minor, 0))
|
GCC_VERSION < GCC_MAKE_VERSION(major, minor, 0))
|
||||||
|
|
||||||
#ifdef __clang__
|
#ifdef __clang__
|
||||||
# define CLANG_VERSION GCC_MAKE_VERSION(__clang_major__, __clang_minor__, __clang_patchlevel__)
|
|
||||||
# if __clang_major__ < 3
|
# if __clang_major__ < 3
|
||||||
# error Sorry, your clang version is too old. You need at least version 3.1.
|
# error Sorry, your clang version is too old. You need at least version 3.1.
|
||||||
# endif
|
# endif
|
||||||
#elif defined(__GNUC__)
|
#elif defined(__GNUC__)
|
||||||
# if GCC_OLDER_THAN(4,6)
|
# if GCC_OLDER_THAN(4,9)
|
||||||
# error Sorry, your gcc version is too old. You need at least version 4.6.
|
# error Sorry, your gcc version is too old. You need at least version 4.9.
|
||||||
# endif
|
# endif
|
||||||
#else
|
#else
|
||||||
# warning Untested compiler. Use at your own risk!
|
# warning Untested compiler. Use at your own risk!
|
||||||
@@ -56,10 +73,9 @@
|
|||||||
* Are we building with the specified version of clang or newer?
|
* Are we building with the specified version of clang or newer?
|
||||||
*/
|
*/
|
||||||
#define CLANG_CHECK_VERSION(major, minor) \
|
#define CLANG_CHECK_VERSION(major, minor) \
|
||||||
(defined(__clang__) && \
|
(CLANG_VERSION >= GCC_MAKE_VERSION(major, minor, 0))
|
||||||
CLANG_VERSION >= GCC_MAKE_VERSION(major, minor, 0))
|
|
||||||
|
|
||||||
#if GCC_CHECK_VERSION(4,0)
|
#if CLANG_OR_GCC_VERSION(4,0)
|
||||||
|
|
||||||
/* GCC 4.x */
|
/* GCC 4.x */
|
||||||
|
|
||||||
@@ -81,8 +97,6 @@
|
|||||||
#define gcc_likely(x) __builtin_expect (!!(x), 1)
|
#define gcc_likely(x) __builtin_expect (!!(x), 1)
|
||||||
#define gcc_unlikely(x) __builtin_expect (!!(x), 0)
|
#define gcc_unlikely(x) __builtin_expect (!!(x), 0)
|
||||||
|
|
||||||
#define gcc_aligned(n) __attribute__((aligned(n)))
|
|
||||||
|
|
||||||
#define gcc_visibility_hidden __attribute__((visibility("hidden")))
|
#define gcc_visibility_hidden __attribute__((visibility("hidden")))
|
||||||
#define gcc_visibility_default __attribute__((visibility("default")))
|
#define gcc_visibility_default __attribute__((visibility("default")))
|
||||||
|
|
||||||
@@ -110,8 +124,6 @@
|
|||||||
#define gcc_likely(x) (x)
|
#define gcc_likely(x) (x)
|
||||||
#define gcc_unlikely(x) (x)
|
#define gcc_unlikely(x) (x)
|
||||||
|
|
||||||
#define gcc_aligned(n)
|
|
||||||
|
|
||||||
#define gcc_visibility_hidden
|
#define gcc_visibility_hidden
|
||||||
#define gcc_visibility_default
|
#define gcc_visibility_default
|
||||||
|
|
||||||
@@ -119,7 +131,7 @@
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if GCC_CHECK_VERSION(4,3)
|
#if CLANG_OR_GCC_VERSION(4,3)
|
||||||
|
|
||||||
#define gcc_hot __attribute__((hot))
|
#define gcc_hot __attribute__((hot))
|
||||||
#define gcc_cold __attribute__((cold))
|
#define gcc_cold __attribute__((cold))
|
||||||
@@ -131,7 +143,7 @@
|
|||||||
|
|
||||||
#endif /* ! GCC_UNUSED >= 40300 */
|
#endif /* ! GCC_UNUSED >= 40300 */
|
||||||
|
|
||||||
#if GCC_CHECK_VERSION(4,6) && !defined(__clang__)
|
#if GCC_CHECK_VERSION(4,6)
|
||||||
#define gcc_flatten __attribute__((flatten))
|
#define gcc_flatten __attribute__((flatten))
|
||||||
#else
|
#else
|
||||||
#define gcc_flatten
|
#define gcc_flatten
|
||||||
@@ -140,7 +152,7 @@
|
|||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
/* plain C99 has "restrict" */
|
/* plain C99 has "restrict" */
|
||||||
#define gcc_restrict restrict
|
#define gcc_restrict restrict
|
||||||
#elif GCC_CHECK_VERSION(4,0)
|
#elif CLANG_OR_GCC_VERSION(4,0)
|
||||||
/* "__restrict__" is a GCC extension for C++ */
|
/* "__restrict__" is a GCC extension for C++ */
|
||||||
#define gcc_restrict __restrict__
|
#define gcc_restrict __restrict__
|
||||||
#else
|
#else
|
||||||
@@ -148,24 +160,6 @@
|
|||||||
#define gcc_restrict
|
#define gcc_restrict
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* C++11 features */
|
|
||||||
|
|
||||||
#if defined(__cplusplus)
|
|
||||||
|
|
||||||
/* support for C++11 "override" was added in gcc 4.7 */
|
|
||||||
#if GCC_OLDER_THAN(4,7)
|
|
||||||
#define override
|
|
||||||
#define final
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__clang__) || GCC_CHECK_VERSION(4,8)
|
|
||||||
#define gcc_alignas(T, fallback) alignas(T)
|
|
||||||
#else
|
|
||||||
#define gcc_alignas(T, fallback) gcc_aligned(fallback)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef __has_feature
|
#ifndef __has_feature
|
||||||
// define dummy macro for non-clang compilers
|
// define dummy macro for non-clang compilers
|
||||||
#define __has_feature(x) 0
|
#define __has_feature(x) 0
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -32,9 +32,9 @@
|
|||||||
|
|
||||||
struct LightSong;
|
struct LightSong;
|
||||||
class Storage;
|
class Storage;
|
||||||
|
class Path;
|
||||||
|
|
||||||
class DetachedSong {
|
class DetachedSong {
|
||||||
friend DetachedSong map_song_detach(const LightSong &song);
|
|
||||||
friend DetachedSong DatabaseDetachSong(const Storage &db,
|
friend DetachedSong DatabaseDetachSong(const Storage &db,
|
||||||
const LightSong &song);
|
const LightSong &song);
|
||||||
|
|
||||||
@@ -63,18 +63,18 @@ class DetachedSong {
|
|||||||
|
|
||||||
Tag tag;
|
Tag tag;
|
||||||
|
|
||||||
time_t mtime;
|
time_t mtime = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Start of this sub-song within the file.
|
* Start of this sub-song within the file.
|
||||||
*/
|
*/
|
||||||
SongTime start_time;
|
SongTime start_time = SongTime::zero();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End of this sub-song within the file.
|
* End of this sub-song within the file.
|
||||||
* Unused if zero.
|
* Unused if zero.
|
||||||
*/
|
*/
|
||||||
SongTime end_time;
|
SongTime end_time = SongTime::zero();
|
||||||
|
|
||||||
explicit DetachedSong(const LightSong &other);
|
explicit DetachedSong(const LightSong &other);
|
||||||
|
|
||||||
@@ -82,26 +82,18 @@ public:
|
|||||||
explicit DetachedSong(const DetachedSong &) = default;
|
explicit DetachedSong(const DetachedSong &) = default;
|
||||||
|
|
||||||
explicit DetachedSong(const char *_uri)
|
explicit DetachedSong(const char *_uri)
|
||||||
:uri(_uri),
|
:uri(_uri) {}
|
||||||
mtime(0),
|
|
||||||
start_time(SongTime::zero()), end_time(SongTime::zero()) {}
|
|
||||||
|
|
||||||
explicit DetachedSong(const std::string &_uri)
|
explicit DetachedSong(const std::string &_uri)
|
||||||
:uri(_uri),
|
:uri(_uri) {}
|
||||||
mtime(0),
|
|
||||||
start_time(SongTime::zero()), end_time(SongTime::zero()) {}
|
|
||||||
|
|
||||||
explicit DetachedSong(std::string &&_uri)
|
explicit DetachedSong(std::string &&_uri)
|
||||||
:uri(std::move(_uri)),
|
:uri(std::move(_uri)) {}
|
||||||
mtime(0),
|
|
||||||
start_time(SongTime::zero()), end_time(SongTime::zero()) {}
|
|
||||||
|
|
||||||
template<typename U>
|
template<typename U>
|
||||||
DetachedSong(U &&_uri, Tag &&_tag)
|
DetachedSong(U &&_uri, Tag &&_tag)
|
||||||
:uri(std::forward<U>(_uri)),
|
:uri(std::forward<U>(_uri)),
|
||||||
tag(std::move(_tag)),
|
tag(std::move(_tag)) {}
|
||||||
mtime(0),
|
|
||||||
start_time(SongTime::zero()), end_time(SongTime::zero()) {}
|
|
||||||
|
|
||||||
DetachedSong(DetachedSong &&) = default;
|
DetachedSong(DetachedSong &&) = default;
|
||||||
|
|
||||||
@@ -146,7 +138,9 @@ public:
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsSame(const DetachedSong &other) const {
|
bool IsSame(const DetachedSong &other) const {
|
||||||
return uri == other.uri;
|
return uri == other.uri &&
|
||||||
|
start_time == other.start_time &&
|
||||||
|
end_time == other.end_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_pure gcc_nonnull_all
|
gcc_pure gcc_nonnull_all
|
||||||
@@ -188,6 +182,14 @@ public:
|
|||||||
tag = std::move(other.tag);
|
tag = std::move(other.tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Similar to the MoveTagFrom(), but move only the #TagItem
|
||||||
|
* array.
|
||||||
|
*/
|
||||||
|
void MoveTagItemsFrom(DetachedSong &&other) {
|
||||||
|
tag.MoveItemsFrom(std::move(other.tag));
|
||||||
|
}
|
||||||
|
|
||||||
time_t GetLastModified() const {
|
time_t GetLastModified() const {
|
||||||
return mtime;
|
return mtime;
|
||||||
}
|
}
|
||||||
@@ -221,6 +223,11 @@ public:
|
|||||||
* @return true on success
|
* @return true on success
|
||||||
*/
|
*/
|
||||||
bool Update();
|
bool Update();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load #tag and #mtime from a local file.
|
||||||
|
*/
|
||||||
|
bool LoadFile(Path path);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,96 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
|
||||||
* http://www.musicpd.org
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "GlobalEvents.hxx"
|
|
||||||
#include "util/Manual.hxx"
|
|
||||||
#include "event/DeferredMonitor.hxx"
|
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
namespace GlobalEvents {
|
|
||||||
class Monitor final : public DeferredMonitor {
|
|
||||||
public:
|
|
||||||
Monitor(EventLoop &_loop):DeferredMonitor(_loop) {}
|
|
||||||
|
|
||||||
protected:
|
|
||||||
virtual void RunDeferred() override;
|
|
||||||
};
|
|
||||||
|
|
||||||
static Manual<Monitor> monitor;
|
|
||||||
|
|
||||||
static std::atomic_uint flags;
|
|
||||||
static Handler handlers[MAX];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Invoke the callback for a certain event.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
InvokeGlobalEvent(GlobalEvents::Event event)
|
|
||||||
{
|
|
||||||
assert((unsigned)event < GlobalEvents::MAX);
|
|
||||||
assert(GlobalEvents::handlers[event] != nullptr);
|
|
||||||
|
|
||||||
GlobalEvents::handlers[event]();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GlobalEvents::Monitor::RunDeferred()
|
|
||||||
{
|
|
||||||
const unsigned f = flags.exchange(0);
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < MAX; ++i)
|
|
||||||
if (f & (1u << i))
|
|
||||||
/* invoke the event handler */
|
|
||||||
InvokeGlobalEvent(Event(i));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GlobalEvents::Initialize(EventLoop &loop)
|
|
||||||
{
|
|
||||||
monitor.Construct(loop);
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GlobalEvents::Deinitialize()
|
|
||||||
{
|
|
||||||
monitor.Destruct();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GlobalEvents::Register(Event event, Handler callback)
|
|
||||||
{
|
|
||||||
assert((unsigned)event < MAX);
|
|
||||||
assert(handlers[event] == nullptr);
|
|
||||||
|
|
||||||
handlers[event] = callback;
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
GlobalEvents::Emit(Event event)
|
|
||||||
{
|
|
||||||
assert((unsigned)event < MAX);
|
|
||||||
|
|
||||||
const unsigned mask = 1u << unsigned(event);
|
|
||||||
if (GlobalEvents::flags.fetch_or(mask) == 0)
|
|
||||||
monitor->Schedule();
|
|
||||||
}
|
|
||||||
@@ -1,64 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
|
||||||
* http://www.musicpd.org
|
|
||||||
*
|
|
||||||
* 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
|
|
||||||
* the Free Software Foundation; either version 2 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along
|
|
||||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef MPD_GLOBAL_EVENTS_HXX
|
|
||||||
#define MPD_GLOBAL_EVENTS_HXX
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
#include <windows.h>
|
|
||||||
/* DELETE is a WIN32 macro that poisons our namespace; this is a
|
|
||||||
kludge to allow us to use it anyway */
|
|
||||||
#ifdef DELETE
|
|
||||||
#undef DELETE
|
|
||||||
#endif
|
|
||||||
#endif
|
|
||||||
|
|
||||||
class EventLoop;
|
|
||||||
|
|
||||||
namespace GlobalEvents {
|
|
||||||
enum Event {
|
|
||||||
/** an idle event was emitted */
|
|
||||||
IDLE,
|
|
||||||
|
|
||||||
/** must call playlist_sync() */
|
|
||||||
PLAYLIST,
|
|
||||||
|
|
||||||
/** the current song's tag has changed */
|
|
||||||
TAG,
|
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
/** shutdown requested */
|
|
||||||
SHUTDOWN,
|
|
||||||
#endif
|
|
||||||
|
|
||||||
MAX
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef void (*Handler)();
|
|
||||||
|
|
||||||
void Initialize(EventLoop &loop);
|
|
||||||
|
|
||||||
void Deinitialize();
|
|
||||||
|
|
||||||
void Register(Event event, Handler handler);
|
|
||||||
|
|
||||||
void Emit(Event event);
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* MAIN_NOTIFY_H */
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -24,8 +24,6 @@
|
|||||||
#include "thread/Thread.hxx"
|
#include "thread/Thread.hxx"
|
||||||
#include "thread/Name.hxx"
|
#include "thread/Name.hxx"
|
||||||
#include "event/Loop.hxx"
|
#include "event/Loop.hxx"
|
||||||
#include "system/FatalError.hxx"
|
|
||||||
#include "util/Error.hxx"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -74,11 +72,8 @@ io_thread_start()
|
|||||||
assert(io.loop != nullptr);
|
assert(io.loop != nullptr);
|
||||||
assert(!io.thread.IsDefined());
|
assert(!io.thread.IsDefined());
|
||||||
|
|
||||||
const ScopeLock protect(io.mutex);
|
const std::lock_guard<Mutex> protect(io.mutex);
|
||||||
|
io.thread.Start(io_thread_func, nullptr);
|
||||||
Error error;
|
|
||||||
if (!io.thread.Start(io_thread_func, nullptr, error))
|
|
||||||
FatalError(error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
class EventLoop;
|
class EventLoop;
|
||||||
|
|
||||||
void
|
void
|
||||||
io_thread_init(void);
|
io_thread_init();
|
||||||
|
|
||||||
void
|
void
|
||||||
io_thread_start();
|
io_thread_start();
|
||||||
@@ -36,7 +36,7 @@ io_thread_start();
|
|||||||
* only.
|
* only.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
io_thread_run(void);
|
io_thread_run();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Ask the I/O thread to quit, but does not wait for it. Usually, you
|
* Ask the I/O thread to quit, but does not wait for it. Usually, you
|
||||||
@@ -44,10 +44,10 @@ io_thread_run(void);
|
|||||||
* includes this.
|
* includes this.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
io_thread_quit(void);
|
io_thread_quit();
|
||||||
|
|
||||||
void
|
void
|
||||||
io_thread_deinit(void);
|
io_thread_deinit();
|
||||||
|
|
||||||
gcc_const
|
gcc_const
|
||||||
EventLoop &
|
EventLoop &
|
||||||
@@ -58,6 +58,6 @@ io_thread_get();
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool
|
bool
|
||||||
io_thread_inside(void);
|
io_thread_inside();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/TagBuilder.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
|
#include "util/StringView.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
@@ -76,7 +77,7 @@ icy_add_item(TagBuilder &tag, TagType type, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (length > 0)
|
if (length > 0)
|
||||||
tag.AddItem(type, value, length);
|
tag.AddItem(type, {value, length});
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
59
src/Idle.cxx
59
src/Idle.cxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -24,66 +24,15 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "GlobalEvents.hxx"
|
#include "Main.hxx"
|
||||||
#include "util/ASCII.hxx"
|
#include "Instance.hxx"
|
||||||
|
|
||||||
#include <atomic>
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
static std::atomic_uint idle_flags;
|
|
||||||
|
|
||||||
static const char *const idle_names[] = {
|
|
||||||
"database",
|
|
||||||
"stored_playlist",
|
|
||||||
"playlist",
|
|
||||||
"player",
|
|
||||||
"mixer",
|
|
||||||
"output",
|
|
||||||
"options",
|
|
||||||
"sticker",
|
|
||||||
"update",
|
|
||||||
"subscription",
|
|
||||||
"message",
|
|
||||||
"neighbor",
|
|
||||||
"mount",
|
|
||||||
nullptr
|
|
||||||
};
|
|
||||||
|
|
||||||
void
|
void
|
||||||
idle_add(unsigned flags)
|
idle_add(unsigned flags)
|
||||||
{
|
{
|
||||||
assert(flags != 0);
|
assert(flags != 0);
|
||||||
|
|
||||||
unsigned old_flags = idle_flags.fetch_or(flags);
|
instance->EmitIdle(flags);
|
||||||
|
|
||||||
if ((old_flags & flags) != flags)
|
|
||||||
GlobalEvents::Emit(GlobalEvents::IDLE);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
idle_get(void)
|
|
||||||
{
|
|
||||||
return idle_flags.exchange(0);
|
|
||||||
}
|
|
||||||
|
|
||||||
const char*const*
|
|
||||||
idle_get_names(void)
|
|
||||||
{
|
|
||||||
return idle_names;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned
|
|
||||||
idle_parse_name(const char *name)
|
|
||||||
{
|
|
||||||
#if !CLANG_CHECK_VERSION(3,6)
|
|
||||||
/* disabled on clang due to -Wtautological-pointer-compare */
|
|
||||||
assert(name != nullptr);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
for (unsigned i = 0; idle_names[i] != nullptr; ++i)
|
|
||||||
if (StringEqualsCaseASCII(name, idle_names[i]))
|
|
||||||
return 1 << i;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
64
src/Idle.hxx
64
src/Idle.hxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -25,47 +25,7 @@
|
|||||||
#ifndef MPD_IDLE_HXX
|
#ifndef MPD_IDLE_HXX
|
||||||
#define MPD_IDLE_HXX
|
#define MPD_IDLE_HXX
|
||||||
|
|
||||||
#include "Compiler.h"
|
#include "IdleFlags.hxx"
|
||||||
|
|
||||||
/** song database has been updated*/
|
|
||||||
static constexpr unsigned IDLE_DATABASE = 0x1;
|
|
||||||
|
|
||||||
/** a stored playlist has been modified, created, deleted or
|
|
||||||
renamed */
|
|
||||||
static constexpr unsigned IDLE_STORED_PLAYLIST = 0x2;
|
|
||||||
|
|
||||||
/** the current playlist has been modified */
|
|
||||||
static constexpr unsigned IDLE_PLAYLIST = 0x4;
|
|
||||||
|
|
||||||
/** the player state has changed: play, stop, pause, seek, ... */
|
|
||||||
static constexpr unsigned IDLE_PLAYER = 0x8;
|
|
||||||
|
|
||||||
/** the volume has been modified */
|
|
||||||
static constexpr unsigned IDLE_MIXER = 0x10;
|
|
||||||
|
|
||||||
/** an audio output device has been enabled or disabled */
|
|
||||||
static constexpr unsigned IDLE_OUTPUT = 0x20;
|
|
||||||
|
|
||||||
/** options have changed: crossfade; random; repeat; ... */
|
|
||||||
static constexpr unsigned IDLE_OPTIONS = 0x40;
|
|
||||||
|
|
||||||
/** a sticker has been modified. */
|
|
||||||
static constexpr unsigned IDLE_STICKER = 0x80;
|
|
||||||
|
|
||||||
/** a database update has started or finished. */
|
|
||||||
static constexpr unsigned IDLE_UPDATE = 0x100;
|
|
||||||
|
|
||||||
/** a client has subscribed or unsubscribed to/from a channel */
|
|
||||||
static constexpr unsigned IDLE_SUBSCRIPTION = 0x200;
|
|
||||||
|
|
||||||
/** a message on the subscribed channel was received */
|
|
||||||
static constexpr unsigned IDLE_MESSAGE = 0x400;
|
|
||||||
|
|
||||||
/** a neighbor was found or lost */
|
|
||||||
static constexpr unsigned IDLE_NEIGHBOR = 0x800;
|
|
||||||
|
|
||||||
/** the mount list has changed */
|
|
||||||
static constexpr unsigned IDLE_MOUNT = 0x1000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds idle flag (with bitwise "or") and queues notifications to all
|
* Adds idle flag (with bitwise "or") and queues notifications to all
|
||||||
@@ -74,24 +34,4 @@ static constexpr unsigned IDLE_MOUNT = 0x1000;
|
|||||||
void
|
void
|
||||||
idle_add(unsigned flags);
|
idle_add(unsigned flags);
|
||||||
|
|
||||||
/**
|
|
||||||
* Atomically reads and resets the global idle flags value.
|
|
||||||
*/
|
|
||||||
unsigned
|
|
||||||
idle_get(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get idle names
|
|
||||||
*/
|
|
||||||
const char*const*
|
|
||||||
idle_get_names(void);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Parse an idle name and return its mask. Returns 0 if the given
|
|
||||||
* name is unknown.
|
|
||||||
*/
|
|
||||||
gcc_nonnull_all gcc_pure
|
|
||||||
unsigned
|
|
||||||
idle_parse_name(const char *name);
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
67
src/IdleFlags.cxx
Normal file
67
src/IdleFlags.cxx
Normal file
@@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
|
* http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support library for the "idle" command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "IdleFlags.hxx"
|
||||||
|
#include "util/ASCII.hxx"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
|
static const char *const idle_names[] = {
|
||||||
|
"database",
|
||||||
|
"stored_playlist",
|
||||||
|
"playlist",
|
||||||
|
"player",
|
||||||
|
"mixer",
|
||||||
|
"output",
|
||||||
|
"options",
|
||||||
|
"sticker",
|
||||||
|
"update",
|
||||||
|
"subscription",
|
||||||
|
"message",
|
||||||
|
"neighbor",
|
||||||
|
"mount",
|
||||||
|
nullptr
|
||||||
|
};
|
||||||
|
|
||||||
|
const char*const*
|
||||||
|
idle_get_names(void)
|
||||||
|
{
|
||||||
|
return idle_names;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned
|
||||||
|
idle_parse_name(const char *name)
|
||||||
|
{
|
||||||
|
#if !CLANG_CHECK_VERSION(3,6)
|
||||||
|
/* disabled on clang due to -Wtautological-pointer-compare */
|
||||||
|
assert(name != nullptr);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (unsigned i = 0; idle_names[i] != nullptr; ++i)
|
||||||
|
if (StringEqualsCaseASCII(name, idle_names[i]))
|
||||||
|
return 1 << i;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
84
src/IdleFlags.hxx
Normal file
84
src/IdleFlags.hxx
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
|
* http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Support library for the "idle" command.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPD_IDLE_FLAGS_HXX
|
||||||
|
#define MPD_IDLE_FLAGS_HXX
|
||||||
|
|
||||||
|
#include "Compiler.h"
|
||||||
|
|
||||||
|
/** song database has been updated*/
|
||||||
|
static constexpr unsigned IDLE_DATABASE = 0x1;
|
||||||
|
|
||||||
|
/** a stored playlist has been modified, created, deleted or
|
||||||
|
renamed */
|
||||||
|
static constexpr unsigned IDLE_STORED_PLAYLIST = 0x2;
|
||||||
|
|
||||||
|
/** the current playlist has been modified */
|
||||||
|
static constexpr unsigned IDLE_PLAYLIST = 0x4;
|
||||||
|
|
||||||
|
/** the player state has changed: play, stop, pause, seek, ... */
|
||||||
|
static constexpr unsigned IDLE_PLAYER = 0x8;
|
||||||
|
|
||||||
|
/** the volume has been modified */
|
||||||
|
static constexpr unsigned IDLE_MIXER = 0x10;
|
||||||
|
|
||||||
|
/** an audio output device has been enabled or disabled */
|
||||||
|
static constexpr unsigned IDLE_OUTPUT = 0x20;
|
||||||
|
|
||||||
|
/** options have changed: crossfade; random; repeat; ... */
|
||||||
|
static constexpr unsigned IDLE_OPTIONS = 0x40;
|
||||||
|
|
||||||
|
/** a sticker has been modified. */
|
||||||
|
static constexpr unsigned IDLE_STICKER = 0x80;
|
||||||
|
|
||||||
|
/** a database update has started or finished. */
|
||||||
|
static constexpr unsigned IDLE_UPDATE = 0x100;
|
||||||
|
|
||||||
|
/** a client has subscribed or unsubscribed to/from a channel */
|
||||||
|
static constexpr unsigned IDLE_SUBSCRIPTION = 0x200;
|
||||||
|
|
||||||
|
/** a message on the subscribed channel was received */
|
||||||
|
static constexpr unsigned IDLE_MESSAGE = 0x400;
|
||||||
|
|
||||||
|
/** a neighbor was found or lost */
|
||||||
|
static constexpr unsigned IDLE_NEIGHBOR = 0x800;
|
||||||
|
|
||||||
|
/** the mount list has changed */
|
||||||
|
static constexpr unsigned IDLE_MOUNT = 0x1000;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get idle names
|
||||||
|
*/
|
||||||
|
const char*const*
|
||||||
|
idle_get_names();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parse an idle name and return its mask. Returns 0 if the given
|
||||||
|
* name is unknown.
|
||||||
|
*/
|
||||||
|
gcc_nonnull_all gcc_pure
|
||||||
|
unsigned
|
||||||
|
idle_parse_name(const char *name);
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -25,37 +25,27 @@
|
|||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
#include "db/DatabaseError.hxx"
|
#include "db/DatabaseError.hxx"
|
||||||
#include "db/LightSong.hxx"
|
|
||||||
|
|
||||||
#ifdef ENABLE_SQLITE
|
#ifdef ENABLE_SQLITE
|
||||||
#include "sticker/StickerDatabase.hxx"
|
#include "sticker/StickerDatabase.hxx"
|
||||||
#include "sticker/SongSticker.hxx"
|
#include "sticker/SongSticker.hxx"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Database *
|
|
||||||
Instance::GetDatabase(Error &error)
|
|
||||||
{
|
|
||||||
if (database == nullptr)
|
|
||||||
error.Set(db_domain, DB_DISABLED, "No database");
|
|
||||||
return database;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
#include <stdexcept>
|
||||||
Instance::TagModified()
|
|
||||||
{
|
|
||||||
partition->TagModified();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Instance::SyncWithPlayer()
|
|
||||||
{
|
|
||||||
partition->SyncWithPlayer();
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
|
const Database &
|
||||||
|
Instance::GetDatabaseOrThrow() const
|
||||||
|
{
|
||||||
|
if (database == nullptr)
|
||||||
|
throw DatabaseError(DatabaseErrorCode::DISABLED,
|
||||||
|
"No database");
|
||||||
|
|
||||||
|
return *database;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Instance::OnDatabaseModified()
|
Instance::OnDatabaseModified()
|
||||||
{
|
{
|
||||||
@@ -65,22 +55,24 @@ Instance::OnDatabaseModified()
|
|||||||
|
|
||||||
stats_invalidate();
|
stats_invalidate();
|
||||||
partition->DatabaseModified(*database);
|
partition->DatabaseModified(*database);
|
||||||
idle_add(IDLE_DATABASE);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Instance::OnDatabaseSongRemoved(const LightSong &song)
|
Instance::OnDatabaseSongRemoved(const char *uri)
|
||||||
{
|
{
|
||||||
assert(database != nullptr);
|
assert(database != nullptr);
|
||||||
|
|
||||||
#ifdef ENABLE_SQLITE
|
#ifdef ENABLE_SQLITE
|
||||||
/* if the song has a sticker, remove it */
|
/* if the song has a sticker, remove it */
|
||||||
if (sticker_enabled())
|
if (sticker_enabled()) {
|
||||||
sticker_song_delete(song);
|
try {
|
||||||
|
sticker_song_delete(uri);
|
||||||
|
} catch (const std::runtime_error &) {
|
||||||
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const auto uri = song.GetURI();
|
partition->StaleSong(uri);
|
||||||
partition->DeleteSong(uri.c_str());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -90,13 +82,13 @@ Instance::OnDatabaseSongRemoved(const LightSong &song)
|
|||||||
void
|
void
|
||||||
Instance::FoundNeighbor(gcc_unused const NeighborInfo &info)
|
Instance::FoundNeighbor(gcc_unused const NeighborInfo &info)
|
||||||
{
|
{
|
||||||
idle_add(IDLE_NEIGHBOR);
|
partition->EmitIdle(IDLE_NEIGHBOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Instance::LostNeighbor(gcc_unused const NeighborInfo &info)
|
Instance::LostNeighbor(gcc_unused const NeighborInfo &info)
|
||||||
{
|
{
|
||||||
idle_add(IDLE_NEIGHBOR);
|
partition->EmitIdle(IDLE_NEIGHBOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -21,6 +21,8 @@
|
|||||||
#define MPD_INSTANCE_HXX
|
#define MPD_INSTANCE_HXX
|
||||||
|
|
||||||
#include "check.h"
|
#include "check.h"
|
||||||
|
#include "event/Loop.hxx"
|
||||||
|
#include "event/MaskMonitor.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
@@ -35,14 +37,22 @@ class Storage;
|
|||||||
class UpdateService;
|
class UpdateService;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
class EventLoop;
|
|
||||||
class Error;
|
|
||||||
class ClientList;
|
class ClientList;
|
||||||
struct Partition;
|
struct Partition;
|
||||||
|
class StateFile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A utility class which, when used as the first base class, ensures
|
||||||
|
* that the #EventLoop gets initialized before the other base classes.
|
||||||
|
*/
|
||||||
|
struct EventLoopHolder {
|
||||||
|
EventLoop event_loop;
|
||||||
|
};
|
||||||
|
|
||||||
struct Instance final
|
struct Instance final
|
||||||
|
: EventLoopHolder
|
||||||
#if defined(ENABLE_DATABASE) || defined(ENABLE_NEIGHBOR_PLUGINS)
|
#if defined(ENABLE_DATABASE) || defined(ENABLE_NEIGHBOR_PLUGINS)
|
||||||
:
|
,
|
||||||
#endif
|
#endif
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
public DatabaseListener
|
public DatabaseListener
|
||||||
@@ -54,7 +64,7 @@ struct Instance final
|
|||||||
public NeighborListener
|
public NeighborListener
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
EventLoop *event_loop;
|
MaskMonitor idle_monitor;
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
NeighborGlue *neighbors;
|
NeighborGlue *neighbors;
|
||||||
@@ -67,20 +77,29 @@ struct Instance final
|
|||||||
* This is really a #CompositeStorage. To avoid heavy include
|
* This is really a #CompositeStorage. To avoid heavy include
|
||||||
* dependencies, we declare it as just #Storage.
|
* dependencies, we declare it as just #Storage.
|
||||||
*/
|
*/
|
||||||
Storage *storage;
|
Storage *storage = nullptr;
|
||||||
|
|
||||||
UpdateService *update;
|
UpdateService *update = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ClientList *client_list;
|
ClientList *client_list;
|
||||||
|
|
||||||
Partition *partition;
|
Partition *partition;
|
||||||
|
|
||||||
Instance() {
|
StateFile *state_file;
|
||||||
#ifdef ENABLE_DATABASE
|
|
||||||
storage = nullptr;
|
Instance()
|
||||||
update = nullptr;
|
:idle_monitor(event_loop, BIND_THIS_METHOD(OnIdle)), state_file(nullptr) {}
|
||||||
#endif
|
|
||||||
|
/**
|
||||||
|
* Initiate shutdown. Wrapper for EventLoop::Break().
|
||||||
|
*/
|
||||||
|
void Shutdown() {
|
||||||
|
event_loop.Break();
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitIdle(unsigned mask) {
|
||||||
|
idle_monitor.OrMask(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
@@ -89,31 +108,33 @@ struct Instance final
|
|||||||
* if this MPD configuration has no database (no
|
* if this MPD configuration has no database (no
|
||||||
* music_directory was configured).
|
* music_directory was configured).
|
||||||
*/
|
*/
|
||||||
Database *GetDatabase(Error &error);
|
Database *GetDatabase() {
|
||||||
|
return database;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the global #Database instance. Throws
|
||||||
|
* DatabaseError if this MPD configuration has no database (no
|
||||||
|
* music_directory was configured).
|
||||||
|
*/
|
||||||
|
gcc_pure
|
||||||
|
const Database &GetDatabaseOrThrow() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/**
|
|
||||||
* A tag in the play queue has been modified by the player
|
|
||||||
* thread. Propagate the change to all subsystems.
|
|
||||||
*/
|
|
||||||
void TagModified();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Synchronize the player with the play queue.
|
|
||||||
*/
|
|
||||||
void SyncWithPlayer();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
virtual void OnDatabaseModified() override;
|
void OnDatabaseModified() override;
|
||||||
virtual void OnDatabaseSongRemoved(const LightSong &song) override;
|
void OnDatabaseSongRemoved(const char *uri) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
/* virtual methods from class NeighborListener */
|
/* virtual methods from class NeighborListener */
|
||||||
virtual void FoundNeighbor(const NeighborInfo &info) override;
|
void FoundNeighbor(const NeighborInfo &info) override;
|
||||||
virtual void LostNeighbor(const NeighborInfo &info) override;
|
void LostNeighbor(const NeighborInfo &info) override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* callback for #idle_monitor */
|
||||||
|
void OnIdle(unsigned mask);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,11 +20,13 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Listen.hxx"
|
#include "Listen.hxx"
|
||||||
#include "client/Client.hxx"
|
#include "client/Client.hxx"
|
||||||
#include "config/ConfigData.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/ConfigOption.hxx"
|
||||||
|
#include "net/SocketAddress.hxx"
|
||||||
#include "event/ServerSocket.hxx"
|
#include "event/ServerSocket.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "system/Error.hxx"
|
||||||
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
@@ -48,73 +50,65 @@ public:
|
|||||||
:ServerSocket(_loop), partition(_partition) {}
|
:ServerSocket(_loop), partition(_partition) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void OnAccept(int fd, const sockaddr &address,
|
void OnAccept(int fd, SocketAddress address, int uid) override {
|
||||||
size_t address_length, int uid) {
|
|
||||||
client_new(GetEventLoop(), partition,
|
client_new(GetEventLoop(), partition,
|
||||||
fd, &address, address_length, uid);
|
fd, address, uid);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
static ClientListener *listen_socket;
|
static ClientListener *listen_socket;
|
||||||
int listen_port;
|
int listen_port;
|
||||||
|
|
||||||
static bool
|
/**
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
listen_add_config_param(unsigned int port,
|
listen_add_config_param(unsigned int port,
|
||||||
const struct config_param *param,
|
const ConfigParam *param)
|
||||||
Error &error_r)
|
|
||||||
{
|
{
|
||||||
assert(param != nullptr);
|
assert(param != nullptr);
|
||||||
|
|
||||||
if (0 == strcmp(param->value.c_str(), "any")) {
|
if (0 == strcmp(param->value.c_str(), "any")) {
|
||||||
return listen_socket->AddPort(port, error_r);
|
listen_socket->AddPort(port);
|
||||||
} else if (param->value[0] == '/' || param->value[0] == '~') {
|
} else if (param->value[0] == '/' || param->value[0] == '~') {
|
||||||
auto path = config_parse_path(param, error_r);
|
listen_socket->AddPath(param->GetPath());
|
||||||
return !path.IsNull() &&
|
|
||||||
listen_socket->AddPath(std::move(path), error_r);
|
|
||||||
} else {
|
} else {
|
||||||
return listen_socket->AddHost(param->value.c_str(), port,
|
listen_socket->AddHost(param->value.c_str(), port);
|
||||||
error_r);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD_DAEMON
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
listen_systemd_activation(Error &error_r)
|
listen_systemd_activation()
|
||||||
{
|
{
|
||||||
int n = sd_listen_fds(true);
|
int n = sd_listen_fds(true);
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
if (n < 0)
|
if (n < 0)
|
||||||
FormatErrno(listen_domain, -n,
|
throw MakeErrno(-n, "sd_listen_fds() failed");
|
||||||
"sd_listen_fds() failed");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = SD_LISTEN_FDS_START, end = SD_LISTEN_FDS_START + n;
|
for (int i = SD_LISTEN_FDS_START, end = SD_LISTEN_FDS_START + n;
|
||||||
i != end; ++i)
|
i != end; ++i)
|
||||||
if (!listen_socket->AddFD(i, error_r))
|
listen_socket->AddFD(i);
|
||||||
return false;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool
|
void
|
||||||
listen_global_init(EventLoop &loop, Partition &partition, Error &error)
|
listen_global_init(EventLoop &loop, Partition &partition)
|
||||||
{
|
{
|
||||||
int port = config_get_positive(CONF_PORT, DEFAULT_PORT);
|
int port = config_get_positive(ConfigOption::PORT, DEFAULT_PORT);
|
||||||
const struct config_param *param =
|
const auto *param = config_get_param(ConfigOption::BIND_TO_ADDRESS);
|
||||||
config_get_param(CONF_BIND_TO_ADDRESS);
|
|
||||||
|
|
||||||
listen_socket = new ClientListener(loop, partition);
|
listen_socket = new ClientListener(loop, partition);
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD_DAEMON
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
if (listen_systemd_activation(error))
|
if (listen_systemd_activation())
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
if (error.IsDefined())
|
|
||||||
return false;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (param != nullptr) {
|
if (param != nullptr) {
|
||||||
@@ -122,32 +116,35 @@ listen_global_init(EventLoop &loop, Partition &partition, Error &error)
|
|||||||
for all values */
|
for all values */
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if (!listen_add_config_param(port, param, error)) {
|
try {
|
||||||
|
listen_add_config_param(port, param);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
delete listen_socket;
|
delete listen_socket;
|
||||||
error.FormatPrefix("Failed to listen on %s (line %i): ",
|
std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)",
|
||||||
param->value.c_str(),
|
param->value.c_str(),
|
||||||
param->line);
|
param->line));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
} while ((param = param->next) != nullptr);
|
} while ((param = param->next) != nullptr);
|
||||||
} else {
|
} else {
|
||||||
/* no "bind_to_address" configured, bind the
|
/* no "bind_to_address" configured, bind the
|
||||||
configured port on all interfaces */
|
configured port on all interfaces */
|
||||||
|
|
||||||
if (!listen_socket->AddPort(port, error)) {
|
try {
|
||||||
|
listen_socket->AddPort(port);
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
delete listen_socket;
|
delete listen_socket;
|
||||||
error.FormatPrefix("Failed to listen on *:%d: ", port);
|
std::throw_with_nested(FormatRuntimeError("Failed to listen on *:%d: ", port));
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!listen_socket->Open(error)) {
|
try {
|
||||||
|
listen_socket->Open();
|
||||||
|
} catch (const std::runtime_error &e) {
|
||||||
delete listen_socket;
|
delete listen_socket;
|
||||||
return false;
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
listen_port = port;
|
listen_port = port;
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void listen_global_finish(void)
|
void listen_global_finish(void)
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -21,14 +21,14 @@
|
|||||||
#define MPD_LISTEN_HXX
|
#define MPD_LISTEN_HXX
|
||||||
|
|
||||||
class EventLoop;
|
class EventLoop;
|
||||||
class Error;
|
|
||||||
struct Partition;
|
struct Partition;
|
||||||
|
|
||||||
extern int listen_port;
|
extern int listen_port;
|
||||||
|
|
||||||
bool
|
void
|
||||||
listen_global_init(EventLoop &loop, Partition &partition, Error &error);
|
listen_global_init(EventLoop &loop, Partition &partition);
|
||||||
|
|
||||||
void listen_global_finish(void);
|
void
|
||||||
|
listen_global_finish();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
110
src/LocateUri.cxx
Normal file
110
src/LocateUri.cxx
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
|
* http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "LocateUri.hxx"
|
||||||
|
#include "client/Client.hxx"
|
||||||
|
#include "fs/AllocatedPath.hxx"
|
||||||
|
#include "ls.hxx"
|
||||||
|
#include "util/UriUtil.hxx"
|
||||||
|
#include "util/StringCompare.hxx"
|
||||||
|
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
#include "storage/StorageInterface.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static LocatedUri
|
||||||
|
LocateFileUri(const char *uri, const Client *client
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, const Storage *storage
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
auto path = AllocatedPath::FromUTF8Throw(uri);
|
||||||
|
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
if (storage != nullptr) {
|
||||||
|
const char *suffix = storage->MapToRelativeUTF8(uri);
|
||||||
|
if (suffix != nullptr)
|
||||||
|
/* this path was relative to the music
|
||||||
|
directory */
|
||||||
|
return LocatedUri(LocatedUri::Type::RELATIVE, suffix);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (client != nullptr)
|
||||||
|
client->AllowFile(path);
|
||||||
|
|
||||||
|
return LocatedUri(LocatedUri::Type::PATH, uri, std::move(path));
|
||||||
|
}
|
||||||
|
|
||||||
|
static LocatedUri
|
||||||
|
LocateAbsoluteUri(const char *uri
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, const Storage *storage
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (!uri_supported_scheme(uri))
|
||||||
|
throw std::runtime_error("Unsupported URI scheme");
|
||||||
|
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
if (storage != nullptr) {
|
||||||
|
const char *suffix = storage->MapToRelativeUTF8(uri);
|
||||||
|
if (suffix != nullptr)
|
||||||
|
return LocatedUri(LocatedUri::Type::RELATIVE, suffix);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return LocatedUri(LocatedUri::Type::ABSOLUTE, uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
LocatedUri
|
||||||
|
LocateUri(const char *uri, const Client *client
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, const Storage *storage
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
/* skip the obsolete "file://" prefix */
|
||||||
|
const char *path_utf8 = StringAfterPrefix(uri, "file://");
|
||||||
|
if (path_utf8 != nullptr) {
|
||||||
|
if (!PathTraitsUTF8::IsAbsolute(path_utf8))
|
||||||
|
throw std::runtime_error("Malformed file:// URI");
|
||||||
|
|
||||||
|
return LocateFileUri(path_utf8, client
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, storage
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
} else if (PathTraitsUTF8::IsAbsolute(uri))
|
||||||
|
return LocateFileUri(uri, client
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, storage
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
else if (uri_has_scheme(uri))
|
||||||
|
return LocateAbsoluteUri(uri
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, storage
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
else
|
||||||
|
return LocatedUri(LocatedUri::Type::RELATIVE, uri);
|
||||||
|
}
|
||||||
93
src/LocateUri.hxx
Normal file
93
src/LocateUri.hxx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
|
* http://www.musicpd.org
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
* the Free Software Foundation; either version 2 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along
|
||||||
|
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||||
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef MPD_LOCATE_URI_HXX
|
||||||
|
#define MPD_LOCATE_URI_HXX
|
||||||
|
|
||||||
|
#include "check.h"
|
||||||
|
#include "Compiler.h"
|
||||||
|
#include "fs/AllocatedPath.hxx"
|
||||||
|
|
||||||
|
#ifdef WIN32
|
||||||
|
#include <windows.h>
|
||||||
|
/* damn you, windows.h! */
|
||||||
|
#ifdef ABSOLUTE
|
||||||
|
#undef ABSOLUTE
|
||||||
|
#endif
|
||||||
|
#ifdef RELATIVE
|
||||||
|
#undef RELATIVE
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
class Client;
|
||||||
|
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
class Storage;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct LocatedUri {
|
||||||
|
enum class Type {
|
||||||
|
/**
|
||||||
|
* An absolute URI with a supported scheme.
|
||||||
|
*/
|
||||||
|
ABSOLUTE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A relative URI path.
|
||||||
|
*/
|
||||||
|
RELATIVE,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A local file. The #path attribute is valid.
|
||||||
|
*/
|
||||||
|
PATH,
|
||||||
|
} type;
|
||||||
|
|
||||||
|
const char *canonical_uri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contains the local file path if type==FILE.
|
||||||
|
*/
|
||||||
|
AllocatedPath path;
|
||||||
|
|
||||||
|
LocatedUri(Type _type, const char *_uri,
|
||||||
|
AllocatedPath &&_path=AllocatedPath::Null())
|
||||||
|
:type(_type), canonical_uri(_uri), path(std::move(_path)) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Classify a URI.
|
||||||
|
*
|
||||||
|
* Throws #std::runtime_error on error.
|
||||||
|
*
|
||||||
|
* @param client the #Client that is used to determine whether a local
|
||||||
|
* file is allowed; nullptr disables the check and allows all local
|
||||||
|
* files
|
||||||
|
* @param storage a #Storage instance which may be used to convert
|
||||||
|
* absolute URIs to relative ones, using Storage::MapToRelativeUTF8();
|
||||||
|
* that feature is disabled if this parameter is nullptr
|
||||||
|
*/
|
||||||
|
LocatedUri
|
||||||
|
LocateUri(const char *uri, const Client *client
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
, const Storage *storage
|
||||||
|
#endif
|
||||||
|
);
|
||||||
|
|
||||||
|
#endif
|
||||||
78
src/Log.cxx
78
src/Log.cxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -19,13 +19,16 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "LogV.hxx"
|
#include "LogV.hxx"
|
||||||
#include "util/Error.hxx"
|
#include "util/Domain.hxx"
|
||||||
|
|
||||||
|
#include <exception>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
|
static constexpr Domain exception_domain("exception");
|
||||||
|
|
||||||
void
|
void
|
||||||
LogFormatV(const Domain &domain, LogLevel level, const char *fmt, va_list ap)
|
LogFormatV(const Domain &domain, LogLevel level, const char *fmt, va_list ap)
|
||||||
{
|
{
|
||||||
@@ -89,20 +92,37 @@ FormatError(const Domain &domain, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const Error &error)
|
LogError(const std::exception &e)
|
||||||
{
|
{
|
||||||
Log(error.GetDomain(), LogLevel::ERROR, error.GetMessage());
|
Log(exception_domain, LogLevel::ERROR, e.what());
|
||||||
|
|
||||||
|
try {
|
||||||
|
std::rethrow_if_nested(e);
|
||||||
|
} catch (const std::exception &nested) {
|
||||||
|
LogError(nested, "nested");
|
||||||
|
} catch (...) {
|
||||||
|
Log(exception_domain, LogLevel::ERROR,
|
||||||
|
"Unrecognized nested exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const Error &error, const char *msg)
|
LogError(const std::exception &e, const char *msg)
|
||||||
{
|
{
|
||||||
LogFormat(error.GetDomain(), LogLevel::ERROR, "%s: %s",
|
FormatError(exception_domain, "%s: %s", msg, e.what());
|
||||||
msg, error.GetMessage());
|
|
||||||
|
try {
|
||||||
|
std::rethrow_if_nested(e);
|
||||||
|
} catch (const std::exception &nested) {
|
||||||
|
LogError(nested);
|
||||||
|
} catch (...) {
|
||||||
|
Log(exception_domain, LogLevel::ERROR,
|
||||||
|
"Unrecognized nested exception");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatError(const Error &error, const char *fmt, ...)
|
FormatError(const std::exception &e, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -110,7 +130,45 @@ FormatError(const Error &error, const char *fmt, ...)
|
|||||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
|
|
||||||
LogError(error, msg);
|
LogError(e, msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LogError(const std::exception_ptr &ep)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
std::rethrow_exception(ep);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LogError(e);
|
||||||
|
} catch (...) {
|
||||||
|
Log(exception_domain, LogLevel::ERROR,
|
||||||
|
"Unrecognized exception");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LogError(const std::exception_ptr &ep, const char *msg)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
std::rethrow_exception(ep);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LogError(e, msg);
|
||||||
|
} catch (...) {
|
||||||
|
FormatError(exception_domain,
|
||||||
|
"%s: Unrecognized exception", msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
FormatError(const std::exception_ptr &ep, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
char msg[1024];
|
||||||
|
va_list ap;
|
||||||
|
va_start(ap, fmt);
|
||||||
|
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||||
|
va_end(ap);
|
||||||
|
|
||||||
|
LogError(ep, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|||||||
35
src/Log.hxx
35
src/Log.hxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
#include "LogLevel.hxx"
|
#include "LogLevel.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
class Error;
|
#include <exception>
|
||||||
|
|
||||||
class Domain;
|
class Domain;
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -79,20 +80,30 @@ LogError(const Domain &domain, const char *msg)
|
|||||||
Log(domain, LogLevel::ERROR, msg);
|
Log(domain, LogLevel::ERROR, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
LogError(const std::exception &e);
|
||||||
|
|
||||||
|
void
|
||||||
|
LogError(const std::exception &e, const char *msg);
|
||||||
|
|
||||||
|
gcc_printf(2,3)
|
||||||
|
void
|
||||||
|
FormatError(const std::exception &e, const char *fmt, ...);
|
||||||
|
|
||||||
|
void
|
||||||
|
LogError(const std::exception_ptr &ep);
|
||||||
|
|
||||||
|
void
|
||||||
|
LogError(const std::exception_ptr &ep, const char *msg);
|
||||||
|
|
||||||
|
gcc_printf(2,3)
|
||||||
|
void
|
||||||
|
FormatError(const std::exception_ptr &ep, const char *fmt, ...);
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatError(const Domain &domain, const char *fmt, ...);
|
FormatError(const Domain &domain, const char *fmt, ...);
|
||||||
|
|
||||||
void
|
|
||||||
LogError(const Error &error);
|
|
||||||
|
|
||||||
void
|
|
||||||
LogError(const Error &error, const char *msg);
|
|
||||||
|
|
||||||
gcc_printf(2,3)
|
|
||||||
void
|
|
||||||
FormatError(const Error &error, const char *fmt, ...);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
LogErrno(const Domain &domain, int e, const char *msg);
|
LogErrno(const Domain &domain, int e, const char *msg);
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -23,10 +23,6 @@
|
|||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringUtil.hxx"
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
#include <glib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
@@ -65,10 +61,6 @@ ToAndroidLogLevel(LogLevel log_level)
|
|||||||
|
|
||||||
static LogLevel log_threshold = LogLevel::INFO;
|
static LogLevel log_threshold = LogLevel::INFO;
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
static const char *log_charset;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static bool enable_timestamp;
|
static bool enable_timestamp;
|
||||||
|
|
||||||
#ifdef HAVE_SYSLOG
|
#ifdef HAVE_SYSLOG
|
||||||
@@ -81,16 +73,6 @@ SetLogThreshold(LogLevel _threshold)
|
|||||||
log_threshold = _threshold;
|
log_threshold = _threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
|
|
||||||
void
|
|
||||||
SetLogCharset(const char *_charset)
|
|
||||||
{
|
|
||||||
log_charset = _charset;
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EnableLogTimestamp()
|
EnableLogTimestamp()
|
||||||
{
|
{
|
||||||
@@ -175,20 +157,6 @@ LogFinishSysLog()
|
|||||||
static void
|
static void
|
||||||
FileLog(const Domain &domain, const char *message)
|
FileLog(const Domain &domain, const char *message)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
char *converted;
|
|
||||||
|
|
||||||
if (log_charset != nullptr) {
|
|
||||||
converted = g_convert_with_fallback(message, -1,
|
|
||||||
log_charset, "utf-8",
|
|
||||||
nullptr, nullptr,
|
|
||||||
nullptr, nullptr);
|
|
||||||
if (converted != nullptr)
|
|
||||||
message = converted;
|
|
||||||
} else
|
|
||||||
converted = nullptr;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
fprintf(stderr, "%s%s: %.*s\n",
|
fprintf(stderr, "%s%s: %.*s\n",
|
||||||
enable_timestamp ? log_date() : "",
|
enable_timestamp ? log_date() : "",
|
||||||
domain.GetName(),
|
domain.GetName(),
|
||||||
@@ -199,10 +167,6 @@ FileLog(const Domain &domain, const char *message)
|
|||||||
to have an effect on WIN32 */
|
to have an effect on WIN32 */
|
||||||
fflush(stderr);
|
fflush(stderr);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
g_free(converted);
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* !ANDROID */
|
#endif /* !ANDROID */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -26,13 +26,6 @@
|
|||||||
void
|
void
|
||||||
SetLogThreshold(LogLevel _threshold);
|
SetLogThreshold(LogLevel _threshold);
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
|
|
||||||
void
|
|
||||||
SetLogCharset(const char *_charset);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void
|
void
|
||||||
EnableLogTimestamp();
|
EnableLogTimestamp();
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -21,25 +21,19 @@
|
|||||||
#include "LogInit.hxx"
|
#include "LogInit.hxx"
|
||||||
#include "LogBackend.hxx"
|
#include "LogBackend.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "config/ConfigData.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/ConfigOption.hxx"
|
||||||
#include "system/FatalError.hxx"
|
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "system/FatalError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
|
#include "system/Error.hxx"
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
#include <glib.h>
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <time.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define LOG_LEVEL_SECURE LogLevel::INFO
|
#define LOG_LEVEL_SECURE LogLevel::INFO
|
||||||
@@ -51,16 +45,16 @@ static constexpr Domain log_domain("log");
|
|||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
|
|
||||||
static int out_fd;
|
static int out_fd = -1;
|
||||||
static AllocatedPath out_path = AllocatedPath::Null();
|
static AllocatedPath out_path = AllocatedPath::Null();
|
||||||
|
|
||||||
static void redirect_logs(int fd)
|
static void redirect_logs(int fd)
|
||||||
{
|
{
|
||||||
assert(fd >= 0);
|
assert(fd >= 0);
|
||||||
if (dup2(fd, STDOUT_FILENO) < 0)
|
if (dup2(fd, STDOUT_FILENO) < 0)
|
||||||
FatalSystemError("Failed to dup2 stdout");
|
throw MakeErrno("Failed to dup2 stdout");
|
||||||
if (dup2(fd, STDERR_FILENO) < 0)
|
if (dup2(fd, STDERR_FILENO) < 0)
|
||||||
FatalSystemError("Failed to dup2 stderr");
|
throw MakeErrno("Failed to dup2 stderr");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@@ -71,25 +65,30 @@ open_log_file(void)
|
|||||||
return OpenFile(out_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
|
return OpenFile(out_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
log_init_file(unsigned line, Error &error)
|
log_init_file(int line)
|
||||||
{
|
{
|
||||||
assert(!out_path.IsNull());
|
assert(!out_path.IsNull());
|
||||||
|
|
||||||
out_fd = open_log_file();
|
out_fd = open_log_file();
|
||||||
if (out_fd < 0) {
|
if (out_fd < 0) {
|
||||||
|
#ifdef WIN32
|
||||||
const std::string out_path_utf8 = out_path.ToUTF8();
|
const std::string out_path_utf8 = out_path.ToUTF8();
|
||||||
error.FormatErrno("failed to open log file \"%s\" (config line %u)",
|
throw FormatRuntimeError("failed to open log file \"%s\" (config line %d)",
|
||||||
out_path_utf8.c_str(), line);
|
out_path_utf8.c_str(), line);
|
||||||
return false;
|
#else
|
||||||
|
int e = errno;
|
||||||
|
const std::string out_path_utf8 = out_path.ToUTF8();
|
||||||
|
throw FormatErrno(e, "failed to open log file \"%s\" (config line %d)",
|
||||||
|
out_path_utf8.c_str(), line);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
EnableLogTimestamp();
|
EnableLogTimestamp();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline LogLevel
|
static inline LogLevel
|
||||||
parse_log_level(const char *value, unsigned line)
|
parse_log_level(const char *value, int line)
|
||||||
{
|
{
|
||||||
if (0 == strcmp(value, "default"))
|
if (0 == strcmp(value, "default"))
|
||||||
return LogLevel::DEFAULT;
|
return LogLevel::DEFAULT;
|
||||||
@@ -97,10 +96,9 @@ parse_log_level(const char *value, unsigned line)
|
|||||||
return LOG_LEVEL_SECURE;
|
return LOG_LEVEL_SECURE;
|
||||||
else if (0 == strcmp(value, "verbose"))
|
else if (0 == strcmp(value, "verbose"))
|
||||||
return LogLevel::DEBUG;
|
return LogLevel::DEBUG;
|
||||||
else {
|
else
|
||||||
FormatFatalError("unknown log level \"%s\" at line %u",
|
throw FormatRuntimeError("unknown log level \"%s\" at line %d",
|
||||||
value, line);
|
value, line);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -119,54 +117,36 @@ log_early_init(bool verbose)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
void
|
||||||
log_init(bool verbose, bool use_stdout, Error &error)
|
log_init(bool verbose, bool use_stdout)
|
||||||
{
|
{
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
(void)verbose;
|
(void)verbose;
|
||||||
(void)use_stdout;
|
(void)use_stdout;
|
||||||
(void)error;
|
|
||||||
|
|
||||||
return true;
|
|
||||||
#else
|
#else
|
||||||
const struct config_param *param;
|
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
const char *charset;
|
|
||||||
g_get_charset(&charset);
|
|
||||||
SetLogCharset(charset);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (verbose)
|
if (verbose)
|
||||||
SetLogThreshold(LogLevel::DEBUG);
|
SetLogThreshold(LogLevel::DEBUG);
|
||||||
else if ((param = config_get_param(CONF_LOG_LEVEL)) != nullptr)
|
else if (const auto ¶m = config_get_param(ConfigOption::LOG_LEVEL))
|
||||||
SetLogThreshold(parse_log_level(param->value.c_str(),
|
SetLogThreshold(parse_log_level(param->value.c_str(),
|
||||||
param->line));
|
param->line));
|
||||||
|
|
||||||
if (use_stdout) {
|
if (use_stdout) {
|
||||||
return true;
|
out_fd = STDOUT_FILENO;
|
||||||
} else {
|
} else {
|
||||||
param = config_get_param(CONF_LOG_FILE);
|
const auto *param = config_get_param(ConfigOption::LOG_FILE);
|
||||||
if (param == nullptr) {
|
if (param == nullptr) {
|
||||||
#ifdef HAVE_SYSLOG
|
|
||||||
/* no configuration: default to syslog (if
|
/* no configuration: default to syslog (if
|
||||||
available) */
|
available) */
|
||||||
LogInitSysLog();
|
#ifndef HAVE_SYSLOG
|
||||||
return true;
|
throw std::runtime_error("config parameter 'log_file' not found");
|
||||||
#else
|
|
||||||
error.Set(log_domain,
|
|
||||||
"config parameter 'log_file' not found");
|
|
||||||
return false;
|
|
||||||
#endif
|
#endif
|
||||||
#ifdef HAVE_SYSLOG
|
#ifdef HAVE_SYSLOG
|
||||||
} else if (strcmp(param->value.c_str(), "syslog") == 0) {
|
} else if (strcmp(param->value.c_str(), "syslog") == 0) {
|
||||||
LogInitSysLog();
|
LogInitSysLog();
|
||||||
return true;
|
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
out_path = config_get_path(CONF_LOG_FILE, error);
|
out_path = param->GetPath();
|
||||||
return !out_path.IsNull() &&
|
log_init_file(param->line);
|
||||||
log_init_file(param->line, error);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -193,12 +173,10 @@ log_deinit(void)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void setup_log_output(bool use_stdout)
|
void setup_log_output()
|
||||||
{
|
{
|
||||||
#ifdef ANDROID
|
#ifndef ANDROID
|
||||||
(void)use_stdout;
|
if (out_fd == STDOUT_FILENO)
|
||||||
#else
|
|
||||||
if (use_stdout)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
fflush(nullptr);
|
fflush(nullptr);
|
||||||
@@ -216,10 +194,6 @@ void setup_log_output(bool use_stdout)
|
|||||||
redirect_logs(out_fd);
|
redirect_logs(out_fd);
|
||||||
close(out_fd);
|
close(out_fd);
|
||||||
out_fd = -1;
|
out_fd = -1;
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
SetLogCharset(nullptr);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,8 +20,6 @@
|
|||||||
#ifndef MPD_LOG_INIT_HXX
|
#ifndef MPD_LOG_INIT_HXX
|
||||||
#define MPD_LOG_INIT_HXX
|
#define MPD_LOG_INIT_HXX
|
||||||
|
|
||||||
class Error;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure a logging destination for daemon startup, before the
|
* Configure a logging destination for daemon startup, before the
|
||||||
* configuration file is read. This allows the daemon to use the
|
* configuration file is read. This allows the daemon to use the
|
||||||
@@ -33,14 +31,19 @@ class Error;
|
|||||||
void
|
void
|
||||||
log_early_init(bool verbose);
|
log_early_init(bool verbose);
|
||||||
|
|
||||||
bool
|
/**
|
||||||
log_init(bool verbose, bool use_stdout, Error &error);
|
* Throws #std::runtime_error on error.
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
log_init(bool verbose, bool use_stdout);
|
||||||
|
|
||||||
void
|
void
|
||||||
log_deinit(void);
|
log_deinit();
|
||||||
|
|
||||||
void setup_log_output(bool use_stdout);
|
void
|
||||||
|
setup_log_output();
|
||||||
|
|
||||||
int cycle_log_files(void);
|
int
|
||||||
|
cycle_log_files();
|
||||||
|
|
||||||
#endif /* LOG_H */
|
#endif /* LOG_H */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
374
src/Main.cxx
374
src/Main.cxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -22,10 +22,9 @@
|
|||||||
#include "Instance.hxx"
|
#include "Instance.hxx"
|
||||||
#include "CommandLine.hxx"
|
#include "CommandLine.hxx"
|
||||||
#include "PlaylistFile.hxx"
|
#include "PlaylistFile.hxx"
|
||||||
#include "PlaylistGlobal.hxx"
|
|
||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
#include "StateFile.hxx"
|
#include "StateFile.hxx"
|
||||||
#include "PlayerThread.hxx"
|
#include "player/Thread.hxx"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "Permission.hxx"
|
#include "Permission.hxx"
|
||||||
#include "Listen.hxx"
|
#include "Listen.hxx"
|
||||||
@@ -34,11 +33,10 @@
|
|||||||
#include "command/AllCommands.hxx"
|
#include "command/AllCommands.hxx"
|
||||||
#include "Partition.hxx"
|
#include "Partition.hxx"
|
||||||
#include "tag/TagConfig.hxx"
|
#include "tag/TagConfig.hxx"
|
||||||
#include "ReplayGainConfig.hxx"
|
#include "ReplayGainGlobal.hxx"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "LogInit.hxx"
|
#include "LogInit.hxx"
|
||||||
#include "GlobalEvents.hxx"
|
|
||||||
#include "input/Init.hxx"
|
#include "input/Init.hxx"
|
||||||
#include "event/Loop.hxx"
|
#include "event/Loop.hxx"
|
||||||
#include "IOThread.hxx"
|
#include "IOThread.hxx"
|
||||||
@@ -47,22 +45,22 @@
|
|||||||
#include "playlist/PlaylistRegistry.hxx"
|
#include "playlist/PlaylistRegistry.hxx"
|
||||||
#include "zeroconf/ZeroconfGlue.hxx"
|
#include "zeroconf/ZeroconfGlue.hxx"
|
||||||
#include "decoder/DecoderList.hxx"
|
#include "decoder/DecoderList.hxx"
|
||||||
#include "AudioConfig.hxx"
|
#include "AudioParser.hxx"
|
||||||
#include "pcm/PcmConvert.hxx"
|
#include "pcm/PcmConvert.hxx"
|
||||||
#include "unix/SignalHandlers.hxx"
|
#include "unix/SignalHandlers.hxx"
|
||||||
#include "unix/Daemon.hxx"
|
|
||||||
#include "system/FatalError.hxx"
|
#include "system/FatalError.hxx"
|
||||||
#include "util/UriUtil.hxx"
|
|
||||||
#include "util/Error.hxx"
|
|
||||||
#include "thread/Id.hxx"
|
|
||||||
#include "thread/Slack.hxx"
|
#include "thread/Slack.hxx"
|
||||||
#include "lib/icu/Init.hxx"
|
#include "lib/icu/Init.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/ConfigData.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/ConfigDefaults.hxx"
|
#include "config/ConfigDefaults.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/ConfigOption.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/ConfigError.hxx"
|
||||||
#include "Stats.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
|
|
||||||
|
#ifdef ENABLE_DAEMON
|
||||||
|
#include "unix/Daemon.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
#include "db/update/Service.hxx"
|
#include "db/update/Service.hxx"
|
||||||
@@ -98,8 +96,8 @@
|
|||||||
#include "org_musicpd_Bridge.h"
|
#include "org_musicpd_Bridge.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
#include <glib.h>
|
#include <systemd/sd-daemon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@@ -128,55 +126,50 @@ Context *context;
|
|||||||
|
|
||||||
Instance *instance;
|
Instance *instance;
|
||||||
|
|
||||||
static StateFile *state_file;
|
struct Config {
|
||||||
|
ReplayGainConfig replay_gain;
|
||||||
|
};
|
||||||
|
|
||||||
#ifndef ANDROID
|
gcc_const
|
||||||
|
static Config
|
||||||
static bool
|
LoadConfig()
|
||||||
glue_daemonize_init(const struct options *options, Error &error)
|
|
||||||
{
|
{
|
||||||
auto pid_file = config_get_path(CONF_PID_FILE, error);
|
return {LoadReplayGainConfig()};
|
||||||
if (pid_file.IsNull() && error.IsDefined())
|
}
|
||||||
return false;
|
|
||||||
|
|
||||||
daemonize_init(config_get_string(CONF_USER, nullptr),
|
#ifdef ENABLE_DAEMON
|
||||||
config_get_string(CONF_GROUP, nullptr),
|
|
||||||
std::move(pid_file));
|
static void
|
||||||
|
glue_daemonize_init(const struct options *options)
|
||||||
|
{
|
||||||
|
daemonize_init(config_get_string(ConfigOption::USER, nullptr),
|
||||||
|
config_get_string(ConfigOption::GROUP, nullptr),
|
||||||
|
config_get_path(ConfigOption::PID_FILE));
|
||||||
|
|
||||||
if (options->kill)
|
if (options->kill)
|
||||||
daemonize_kill();
|
daemonize_kill();
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
glue_mapper_init(Error &error)
|
glue_mapper_init()
|
||||||
{
|
{
|
||||||
auto playlist_dir = config_get_path(CONF_PLAYLIST_DIR, error);
|
mapper_init(config_get_path(ConfigOption::PLAYLIST_DIR));
|
||||||
if (playlist_dir.IsNull() && error.IsDefined())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
mapper_init(std::move(playlist_dir));
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
InitStorage(Error &error)
|
InitStorage()
|
||||||
{
|
{
|
||||||
Storage *storage = CreateConfiguredStorage(io_thread_get(), error);
|
Storage *storage = CreateConfiguredStorage(io_thread_get());
|
||||||
if (storage == nullptr)
|
if (storage == nullptr)
|
||||||
return !error.IsDefined();
|
return;
|
||||||
|
|
||||||
assert(!error.IsDefined());
|
|
||||||
|
|
||||||
CompositeStorage *composite = new CompositeStorage();
|
CompositeStorage *composite = new CompositeStorage();
|
||||||
instance->storage = composite;
|
instance->storage = composite;
|
||||||
composite->Mount("", storage);
|
composite->Mount("", storage);
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -187,20 +180,13 @@ InitStorage(Error &error)
|
|||||||
static bool
|
static bool
|
||||||
glue_db_init_and_load(void)
|
glue_db_init_and_load(void)
|
||||||
{
|
{
|
||||||
Error error;
|
|
||||||
instance->database =
|
instance->database =
|
||||||
CreateConfiguredDatabase(*instance->event_loop, *instance,
|
CreateConfiguredDatabase(instance->event_loop, *instance);
|
||||||
error);
|
if (instance->database == nullptr)
|
||||||
if (instance->database == nullptr) {
|
|
||||||
if (error.IsDefined())
|
|
||||||
FatalError(error);
|
|
||||||
else
|
|
||||||
return true;
|
return true;
|
||||||
}
|
|
||||||
|
|
||||||
if (instance->database->GetPlugin().flags & DatabasePlugin::FLAG_REQUIRE_STORAGE) {
|
if (instance->database->GetPlugin().flags & DatabasePlugin::FLAG_REQUIRE_STORAGE) {
|
||||||
if (!InitStorage(error))
|
InitStorage();
|
||||||
FatalError(error);
|
|
||||||
|
|
||||||
if (instance->storage == nullptr) {
|
if (instance->storage == nullptr) {
|
||||||
delete instance->database;
|
delete instance->database;
|
||||||
@@ -217,14 +203,17 @@ glue_db_init_and_load(void)
|
|||||||
"because the database does not need it");
|
"because the database does not need it");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance->database->Open(error))
|
try {
|
||||||
FatalError(error);
|
instance->database->Open();
|
||||||
|
} catch (...) {
|
||||||
|
std::throw_with_nested(std::runtime_error("Failed to open database plugin"));
|
||||||
|
}
|
||||||
|
|
||||||
if (!instance->database->IsPlugin(simple_db_plugin))
|
if (!instance->database->IsPlugin(simple_db_plugin))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
SimpleDatabase &db = *(SimpleDatabase *)instance->database;
|
SimpleDatabase &db = *(SimpleDatabase *)instance->database;
|
||||||
instance->update = new UpdateService(*instance->event_loop, db,
|
instance->update = new UpdateService(instance->event_loop, db,
|
||||||
static_cast<CompositeStorage &>(*instance->storage),
|
static_cast<CompositeStorage &>(*instance->storage),
|
||||||
*instance);
|
*instance);
|
||||||
|
|
||||||
@@ -245,49 +234,41 @@ InitDatabaseAndStorage()
|
|||||||
* Configure and initialize the sticker subsystem.
|
* Configure and initialize the sticker subsystem.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
glue_sticker_init(void)
|
glue_sticker_init()
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_SQLITE
|
#ifdef ENABLE_SQLITE
|
||||||
Error error;
|
auto sticker_file = config_get_path(ConfigOption::STICKER_FILE);
|
||||||
auto sticker_file = config_get_path(CONF_STICKER_FILE, error);
|
if (sticker_file.IsNull())
|
||||||
if (sticker_file.IsNull()) {
|
|
||||||
if (error.IsDefined())
|
|
||||||
FatalError(error);
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if (!sticker_global_init(std::move(sticker_file), error))
|
sticker_global_init(std::move(sticker_file));
|
||||||
FatalError(error);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static void
|
||||||
glue_state_file_init(Error &error)
|
glue_state_file_init()
|
||||||
{
|
{
|
||||||
auto path_fs = config_get_path(CONF_STATE_FILE, error);
|
auto path_fs = config_get_path(ConfigOption::STATE_FILE);
|
||||||
if (path_fs.IsNull()) {
|
if (path_fs.IsNull()) {
|
||||||
if (error.IsDefined())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
const auto cache_dir = GetUserCacheDir();
|
const auto cache_dir = GetUserCacheDir();
|
||||||
if (cache_dir.IsNull())
|
if (cache_dir.IsNull())
|
||||||
return true;
|
return;
|
||||||
|
|
||||||
path_fs = AllocatedPath::Build(cache_dir, "state");
|
path_fs = AllocatedPath::Build(cache_dir, "state");
|
||||||
#else
|
#else
|
||||||
return true;
|
return;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned interval = config_get_unsigned(CONF_STATE_FILE_INTERVAL,
|
const auto interval =
|
||||||
|
config_get_unsigned(ConfigOption::STATE_FILE_INTERVAL,
|
||||||
StateFile::DEFAULT_INTERVAL);
|
StateFile::DEFAULT_INTERVAL);
|
||||||
|
|
||||||
state_file = new StateFile(std::move(path_fs), interval,
|
instance->state_file = new StateFile(std::move(path_fs), interval,
|
||||||
*instance->partition,
|
*instance->partition,
|
||||||
*instance->event_loop);
|
instance->event_loop);
|
||||||
state_file->Read();
|
instance->state_file->Read();
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -313,12 +294,12 @@ static void winsock_init(void)
|
|||||||
* Initialize the decoder and player core, including the music pipe.
|
* Initialize the decoder and player core, including the music pipe.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
initialize_decoder_and_player(void)
|
initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config)
|
||||||
{
|
{
|
||||||
const struct config_param *param;
|
const ConfigParam *param;
|
||||||
|
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
param = config_get_param(CONF_AUDIO_BUFFER_SIZE);
|
param = config_get_param(ConfigOption::AUDIO_BUFFER_SIZE);
|
||||||
if (param != nullptr) {
|
if (param != nullptr) {
|
||||||
char *test;
|
char *test;
|
||||||
long tmp = strtol(param->value.c_str(), &test, 10);
|
long tmp = strtol(param->value.c_str(), &test, 10);
|
||||||
@@ -339,7 +320,7 @@ initialize_decoder_and_player(void)
|
|||||||
(unsigned long)buffer_size);
|
(unsigned long)buffer_size);
|
||||||
|
|
||||||
float perc;
|
float perc;
|
||||||
param = config_get_param(CONF_BUFFER_BEFORE_PLAY);
|
param = config_get_param(ConfigOption::BUFFER_BEFORE_PLAY);
|
||||||
if (param != nullptr) {
|
if (param != nullptr) {
|
||||||
char *test;
|
char *test;
|
||||||
perc = strtod(param->value.c_str(), &test);
|
perc = strtod(param->value.c_str(), &test);
|
||||||
@@ -357,45 +338,51 @@ initialize_decoder_and_player(void)
|
|||||||
buffered_before_play = buffered_chunks;
|
buffered_before_play = buffered_chunks;
|
||||||
|
|
||||||
const unsigned max_length =
|
const unsigned max_length =
|
||||||
config_get_positive(CONF_MAX_PLAYLIST_LENGTH,
|
config_get_positive(ConfigOption::MAX_PLAYLIST_LENGTH,
|
||||||
DEFAULT_PLAYLIST_MAX_LENGTH);
|
DEFAULT_PLAYLIST_MAX_LENGTH);
|
||||||
|
|
||||||
|
AudioFormat configured_audio_format = AudioFormat::Undefined();
|
||||||
|
param = config_get_param(ConfigOption::AUDIO_OUTPUT_FORMAT);
|
||||||
|
if (param != nullptr) {
|
||||||
|
try {
|
||||||
|
configured_audio_format = ParseAudioFormat(param->value.c_str(),
|
||||||
|
true);
|
||||||
|
} catch (const std::runtime_error &) {
|
||||||
|
std::throw_with_nested(FormatRuntimeError("error parsing line %i",
|
||||||
|
param->line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
instance->partition = new Partition(*instance,
|
instance->partition = new Partition(*instance,
|
||||||
max_length,
|
max_length,
|
||||||
buffered_chunks,
|
buffered_chunks,
|
||||||
buffered_before_play);
|
buffered_before_play,
|
||||||
|
configured_audio_format,
|
||||||
|
replay_gain_config);
|
||||||
|
|
||||||
|
try {
|
||||||
|
param = config_get_param(ConfigOption::REPLAYGAIN);
|
||||||
|
if (param != nullptr)
|
||||||
|
instance->partition->replay_gain_mode =
|
||||||
|
FromString(param->value.c_str());
|
||||||
|
} catch (...) {
|
||||||
|
std::throw_with_nested(FormatRuntimeError("Failed to parse line %i",
|
||||||
|
param->line));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
void
|
||||||
* Handler for GlobalEvents::IDLE.
|
Instance::OnIdle(unsigned flags)
|
||||||
*/
|
|
||||||
static void
|
|
||||||
idle_event_emitted(void)
|
|
||||||
{
|
{
|
||||||
/* send "idle" notifications to all subscribed
|
/* send "idle" notifications to all subscribed
|
||||||
clients */
|
clients */
|
||||||
unsigned flags = idle_get();
|
client_list->IdleAdd(flags);
|
||||||
if (flags != 0)
|
|
||||||
instance->client_list->IdleAdd(flags);
|
|
||||||
|
|
||||||
if (flags & (IDLE_PLAYLIST|IDLE_PLAYER|IDLE_MIXER|IDLE_OUTPUT) &&
|
if (flags & (IDLE_PLAYLIST|IDLE_PLAYER|IDLE_MIXER|IDLE_OUTPUT) &&
|
||||||
state_file != nullptr)
|
state_file != nullptr)
|
||||||
state_file->CheckModified();
|
state_file->CheckModified();
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WIN32
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handler for GlobalEvents::SHUTDOWN.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
shutdown_event_emitted(void)
|
|
||||||
{
|
|
||||||
instance->event_loop->Break();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
@@ -409,38 +396,29 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int mpd_main_after_fork(struct options);
|
static int
|
||||||
|
mpd_main_after_fork(const Config &config);
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
static inline
|
static inline
|
||||||
#endif
|
#endif
|
||||||
int mpd_main(int argc, char *argv[])
|
int mpd_main(int argc, char *argv[])
|
||||||
{
|
try {
|
||||||
struct options options;
|
struct options options;
|
||||||
Error error;
|
|
||||||
|
#ifdef ENABLE_DAEMON
|
||||||
|
daemonize_close_stdin();
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
daemonize_close_stdin();
|
|
||||||
|
|
||||||
#ifdef HAVE_LOCALE_H
|
#ifdef HAVE_LOCALE_H
|
||||||
/* initialize locale */
|
/* initialize locale */
|
||||||
setlocale(LC_CTYPE,"");
|
setlocale(LC_CTYPE,"");
|
||||||
#endif
|
setlocale(LC_COLLATE, "");
|
||||||
|
|
||||||
#ifdef HAVE_GLIB
|
|
||||||
g_set_application_name("Music Player Daemon");
|
|
||||||
|
|
||||||
#if !GLIB_CHECK_VERSION(2,32,0)
|
|
||||||
/* enable GLib's thread safety code */
|
|
||||||
g_thread_init(nullptr);
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!IcuInit(error)) {
|
IcuInit();
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
winsock_init();
|
winsock_init();
|
||||||
io_thread_init();
|
io_thread_init();
|
||||||
@@ -450,47 +428,32 @@ int mpd_main(int argc, char *argv[])
|
|||||||
(void)argc;
|
(void)argc;
|
||||||
(void)argv;
|
(void)argv;
|
||||||
|
|
||||||
{
|
|
||||||
const auto sdcard = Environment::getExternalStorageDirectory();
|
const auto sdcard = Environment::getExternalStorageDirectory();
|
||||||
if (!sdcard.IsNull()) {
|
if (!sdcard.IsNull()) {
|
||||||
const auto config_path =
|
const auto config_path =
|
||||||
AllocatedPath::Build(sdcard, "mpd.conf");
|
AllocatedPath::Build(sdcard, "mpd.conf");
|
||||||
if (FileExists(config_path) &&
|
if (FileExists(config_path))
|
||||||
!ReadConfigFile(config_path, error)) {
|
ReadConfigFile(config_path);
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (!parse_cmdline(argc, argv, &options, error)) {
|
ParseCommandLine(argc, argv, &options);
|
||||||
LogError(error);
|
#endif
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
const auto config = LoadConfig();
|
||||||
|
|
||||||
if (!glue_daemonize_init(&options, error)) {
|
#ifdef ENABLE_DAEMON
|
||||||
LogError(error);
|
glue_daemonize_init(&options);
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
stats_global_init();
|
|
||||||
TagLoadConfig();
|
TagLoadConfig();
|
||||||
|
|
||||||
if (!log_init(options.verbose, options.log_stderr, error)) {
|
log_init(options.verbose, options.log_stderr);
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance = new Instance();
|
instance = new Instance();
|
||||||
instance->event_loop = new EventLoop();
|
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
instance->neighbors = new NeighborGlue();
|
instance->neighbors = new NeighborGlue();
|
||||||
if (!instance->neighbors->Init(io_thread_get(), *instance, error)) {
|
instance->neighbors->Init(io_thread_get(), *instance);
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (instance->neighbors->IsEmpty()) {
|
if (instance->neighbors->IsEmpty()) {
|
||||||
delete instance->neighbors;
|
delete instance->neighbors;
|
||||||
@@ -498,18 +461,15 @@ int mpd_main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const unsigned max_clients = config_get_positive(CONF_MAX_CONN, 10);
|
const unsigned max_clients =
|
||||||
|
config_get_positive(ConfigOption::MAX_CONN, 10);
|
||||||
instance->client_list = new ClientList(max_clients);
|
instance->client_list = new ClientList(max_clients);
|
||||||
|
|
||||||
initialize_decoder_and_player();
|
initialize_decoder_and_player(config.replay_gain);
|
||||||
|
|
||||||
if (!listen_global_init(*instance->event_loop, *instance->partition,
|
listen_global_init(instance->event_loop, *instance->partition);
|
||||||
error)) {
|
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifdef ENABLE_DAEMON
|
||||||
daemonize_set_user();
|
daemonize_set_user();
|
||||||
daemonize_begin(options.daemon);
|
daemonize_begin(options.daemon);
|
||||||
#endif
|
#endif
|
||||||
@@ -522,43 +482,32 @@ int mpd_main(int argc, char *argv[])
|
|||||||
This must be run after forking; if dispatch is called before forking,
|
This must be run after forking; if dispatch is called before forking,
|
||||||
the child process will have a broken internal dispatch state. */
|
the child process will have a broken internal dispatch state. */
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
exit(mpd_main_after_fork(options));
|
exit(mpd_main_after_fork(config));
|
||||||
});
|
});
|
||||||
dispatch_main();
|
dispatch_main();
|
||||||
return EXIT_FAILURE; // unreachable, because dispatch_main never returns
|
return EXIT_FAILURE; // unreachable, because dispatch_main never returns
|
||||||
#else
|
#else
|
||||||
return mpd_main_after_fork(options);
|
return mpd_main_after_fork(config);
|
||||||
#endif
|
#endif
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LogError(e);
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mpd_main_after_fork(struct options options)
|
static int
|
||||||
{
|
mpd_main_after_fork(const Config &config)
|
||||||
Error error;
|
try {
|
||||||
|
|
||||||
GlobalEvents::Initialize(*instance->event_loop);
|
|
||||||
GlobalEvents::Register(GlobalEvents::IDLE, idle_event_emitted);
|
|
||||||
#ifdef WIN32
|
|
||||||
GlobalEvents::Register(GlobalEvents::SHUTDOWN, shutdown_event_emitted);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
ConfigureFS();
|
ConfigureFS();
|
||||||
|
|
||||||
if (!glue_mapper_init(error)) {
|
glue_mapper_init();
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
initPermissions();
|
initPermissions();
|
||||||
playlist_global_init();
|
|
||||||
spl_global_init();
|
spl_global_init();
|
||||||
#ifdef ENABLE_ARCHIVE
|
#ifdef ENABLE_ARCHIVE
|
||||||
archive_plugin_init_all();
|
archive_plugin_init_all();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!pcm_convert_global_init(error)) {
|
pcm_convert_global_init();
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
decoder_plugin_init_all();
|
decoder_plugin_init_all();
|
||||||
|
|
||||||
@@ -569,36 +518,34 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
glue_sticker_init();
|
glue_sticker_init();
|
||||||
|
|
||||||
command_init();
|
command_init();
|
||||||
initAudioConfig();
|
|
||||||
instance->partition->outputs.Configure(*instance->event_loop,
|
instance->partition->outputs.Configure(instance->event_loop,
|
||||||
|
config.replay_gain,
|
||||||
instance->partition->pc);
|
instance->partition->pc);
|
||||||
|
instance->partition->UpdateEffectiveReplayGainMode();
|
||||||
|
|
||||||
client_manager_init();
|
client_manager_init();
|
||||||
replay_gain_global_init();
|
input_stream_global_init();
|
||||||
|
|
||||||
if (!input_stream_global_init(error)) {
|
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
playlist_list_global_init();
|
playlist_list_global_init();
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifdef ENABLE_DAEMON
|
||||||
daemonize_commit();
|
daemonize_commit();
|
||||||
|
#endif
|
||||||
|
|
||||||
setup_log_output(options.log_stderr);
|
#ifndef ANDROID
|
||||||
|
setup_log_output();
|
||||||
|
|
||||||
SignalHandlersInit(*instance->event_loop);
|
SignalHandlersInit(instance->event_loop);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
io_thread_start();
|
io_thread_start();
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
if (instance->neighbors != nullptr &&
|
if (instance->neighbors != nullptr)
|
||||||
!instance->neighbors->Open(error))
|
instance->neighbors->Open();
|
||||||
FatalError(error);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ZeroconfInit(*instance->event_loop);
|
ZeroconfInit(instance->event_loop);
|
||||||
|
|
||||||
StartPlayerThread(instance->partition->pc);
|
StartPlayerThread(instance->partition->pc);
|
||||||
|
|
||||||
@@ -612,22 +559,17 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!glue_state_file_init(error)) {
|
glue_state_file_init();
|
||||||
LogError(error);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
|
||||||
|
|
||||||
instance->partition->outputs.SetReplayGainMode(replay_gain_get_real_mode(instance->partition->playlist.queue.random));
|
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
if (config_get_bool(CONF_AUTO_UPDATE, false)) {
|
if (config_get_bool(ConfigOption::AUTO_UPDATE, false)) {
|
||||||
#ifdef ENABLE_INOTIFY
|
#ifdef ENABLE_INOTIFY
|
||||||
if (instance->storage != nullptr &&
|
if (instance->storage != nullptr &&
|
||||||
instance->update != nullptr)
|
instance->update != nullptr)
|
||||||
mpd_inotify_init(*instance->event_loop,
|
mpd_inotify_init(instance->event_loop,
|
||||||
*instance->storage,
|
*instance->storage,
|
||||||
*instance->update,
|
*instance->update,
|
||||||
config_get_unsigned(CONF_AUTO_UPDATE_DEPTH,
|
config_get_unsigned(ConfigOption::AUTO_UPDATE_DEPTH,
|
||||||
INT_MAX));
|
INT_MAX));
|
||||||
#else
|
#else
|
||||||
FormatWarning(config_domain,
|
FormatWarning(config_domain,
|
||||||
@@ -640,7 +582,7 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
|
|
||||||
/* enable all audio outputs (if not already done by
|
/* enable all audio outputs (if not already done by
|
||||||
playlist_state_restore() */
|
playlist_state_restore() */
|
||||||
instance->partition->pc.UpdateAudio();
|
instance->partition->pc.LockUpdateAudio();
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
win32_app_started();
|
win32_app_started();
|
||||||
@@ -650,8 +592,12 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
a huge value to allow the kernel to reduce CPU wakeups */
|
a huge value to allow the kernel to reduce CPU wakeups */
|
||||||
SetThreadTimerSlackMS(100);
|
SetThreadTimerSlackMS(100);
|
||||||
|
|
||||||
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
sd_notify(0, "READY=1");
|
||||||
|
#endif
|
||||||
|
|
||||||
/* run the main loop */
|
/* run the main loop */
|
||||||
instance->event_loop->Run();
|
instance->event_loop.Run();
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
win32_app_stopping();
|
win32_app_stopping();
|
||||||
@@ -666,9 +612,9 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
instance->update->CancelAllAsync();
|
instance->update->CancelAllAsync();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (state_file != nullptr) {
|
if (instance->state_file != nullptr) {
|
||||||
state_file->Write();
|
instance->state_file->Write();
|
||||||
delete state_file;
|
delete instance->state_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->partition->pc.Kill();
|
instance->partition->pc.Kill();
|
||||||
@@ -698,8 +644,6 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
sticker_global_finish();
|
sticker_global_finish();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
GlobalEvents::Deinitialize();
|
|
||||||
|
|
||||||
playlist_list_global_finish();
|
playlist_list_global_finish();
|
||||||
input_stream_global_finish();
|
input_stream_global_finish();
|
||||||
|
|
||||||
@@ -707,6 +651,8 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
mapper_finish();
|
mapper_finish();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
DeinitFS();
|
||||||
|
|
||||||
delete instance->partition;
|
delete instance->partition;
|
||||||
command_finish();
|
command_finish();
|
||||||
decoder_plugin_deinit_all();
|
decoder_plugin_deinit_all();
|
||||||
@@ -718,12 +664,13 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
SignalHandlersFinish();
|
SignalHandlersFinish();
|
||||||
#endif
|
#endif
|
||||||
delete instance->event_loop;
|
|
||||||
delete instance;
|
delete instance;
|
||||||
instance = nullptr;
|
instance = nullptr;
|
||||||
#ifndef ANDROID
|
|
||||||
|
#ifdef ENABLE_DAEMON
|
||||||
daemonize_finish();
|
daemonize_finish();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WIN32
|
#ifdef WIN32
|
||||||
WSACleanup();
|
WSACleanup();
|
||||||
#endif
|
#endif
|
||||||
@@ -732,6 +679,9 @@ static int mpd_main_after_fork(struct options options)
|
|||||||
|
|
||||||
log_deinit();
|
log_deinit();
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
LogError(e);
|
||||||
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
@@ -757,7 +707,7 @@ JNIEXPORT void JNICALL
|
|||||||
Java_org_musicpd_Bridge_shutdown(JNIEnv *, jclass)
|
Java_org_musicpd_Bridge_shutdown(JNIEnv *, jclass)
|
||||||
{
|
{
|
||||||
if (instance != nullptr)
|
if (instance != nullptr)
|
||||||
instance->event_loop->Break();
|
instance->Shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -61,7 +61,7 @@ win32_main(int argc, char *argv[]);
|
|||||||
* This function should be called just before entering main loop.
|
* This function should be called just before entering main loop.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
win32_app_started(void);
|
win32_app_started();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When running as a service reports to service control manager
|
* When running as a service reports to service control manager
|
||||||
@@ -71,7 +71,7 @@ win32_app_started(void);
|
|||||||
* This function should be called just after leaving main loop.
|
* This function should be called just after leaving main loop.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
win32_app_stopping(void);
|
win32_app_stopping();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -24,9 +24,8 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/Traits.hxx"
|
|
||||||
#include "fs/Charset.hxx"
|
|
||||||
#include "fs/CheckFile.hxx"
|
#include "fs/CheckFile.hxx"
|
||||||
|
#include "util/StringCompare.hxx"
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
#include "storage/StorageInterface.hxx"
|
#include "storage/StorageInterface.hxx"
|
||||||
@@ -59,7 +58,8 @@ mapper_init(AllocatedPath &&_playlist_dir)
|
|||||||
mapper_set_playlist_dir(std::move(_playlist_dir));
|
mapper_set_playlist_dir(std::move(_playlist_dir));
|
||||||
}
|
}
|
||||||
|
|
||||||
void mapper_finish(void)
|
void
|
||||||
|
mapper_finish()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,9 +86,9 @@ map_uri_fs(const char *uri)
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
map_fs_to_utf8(const char *path_fs)
|
map_fs_to_utf8(Path path_fs)
|
||||||
{
|
{
|
||||||
if (PathTraitsFS::IsSeparator(path_fs[0])) {
|
if (path_fs.IsAbsolute()) {
|
||||||
if (instance->storage == nullptr)
|
if (instance->storage == nullptr)
|
||||||
return std::string();
|
return std::string();
|
||||||
|
|
||||||
@@ -96,18 +96,20 @@ map_fs_to_utf8(const char *path_fs)
|
|||||||
if (music_dir_fs.IsNull())
|
if (music_dir_fs.IsNull())
|
||||||
return std::string();
|
return std::string();
|
||||||
|
|
||||||
path_fs = music_dir_fs.RelativeFS(path_fs);
|
auto relative = music_dir_fs.Relative(path_fs);
|
||||||
if (path_fs == nullptr || *path_fs == 0)
|
if (relative == nullptr || StringIsEmpty(relative))
|
||||||
return std::string();
|
return std::string();
|
||||||
|
|
||||||
|
path_fs = Path::FromFS(relative);
|
||||||
}
|
}
|
||||||
|
|
||||||
return PathToUTF8(path_fs);
|
return path_fs.ToUTF8();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const AllocatedPath &
|
const AllocatedPath &
|
||||||
map_spl_path(void)
|
map_spl_path()
|
||||||
{
|
{
|
||||||
return playlist_dir_fs;
|
return playlist_dir_fs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -30,12 +30,14 @@
|
|||||||
|
|
||||||
#define PLAYLIST_FILE_SUFFIX ".m3u"
|
#define PLAYLIST_FILE_SUFFIX ".m3u"
|
||||||
|
|
||||||
|
class Path;
|
||||||
class AllocatedPath;
|
class AllocatedPath;
|
||||||
|
|
||||||
void
|
void
|
||||||
mapper_init(AllocatedPath &&playlist_dir);
|
mapper_init(AllocatedPath &&playlist_dir);
|
||||||
|
|
||||||
void mapper_finish(void);
|
void
|
||||||
|
mapper_finish();
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
@@ -58,7 +60,7 @@ map_uri_fs(const char *uri);
|
|||||||
*/
|
*/
|
||||||
gcc_pure
|
gcc_pure
|
||||||
std::string
|
std::string
|
||||||
map_fs_to_utf8(const char *path_fs);
|
map_fs_to_utf8(Path path_fs);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -67,7 +69,7 @@ map_fs_to_utf8(const char *path_fs);
|
|||||||
*/
|
*/
|
||||||
gcc_const
|
gcc_const
|
||||||
const AllocatedPath &
|
const AllocatedPath &
|
||||||
map_spl_path(void);
|
map_spl_path();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Maps a playlist name (without the ".m3u" suffix) to a file system
|
* Maps a playlist name (without the ".m3u" suffix) to a file system
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,20 +20,17 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "MusicBuffer.hxx"
|
#include "MusicBuffer.hxx"
|
||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
#include "system/FatalError.hxx"
|
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
MusicBuffer::MusicBuffer(unsigned num_chunks)
|
MusicBuffer::MusicBuffer(unsigned num_chunks)
|
||||||
:buffer(num_chunks) {
|
:buffer(num_chunks) {
|
||||||
if (buffer.IsOOM())
|
|
||||||
FatalError("Failed to allocate buffer");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicChunk *
|
MusicChunk *
|
||||||
MusicBuffer::Allocate()
|
MusicBuffer::Allocate()
|
||||||
{
|
{
|
||||||
const ScopeLock protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
return buffer.Allocate();
|
return buffer.Allocate();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +39,7 @@ MusicBuffer::Return(MusicChunk *chunk)
|
|||||||
{
|
{
|
||||||
assert(chunk != nullptr);
|
assert(chunk != nullptr);
|
||||||
|
|
||||||
const ScopeLock protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
if (chunk->other != nullptr) {
|
if (chunk->other != nullptr) {
|
||||||
assert(chunk->other->other == nullptr);
|
assert(chunk->other->other == nullptr);
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -48,7 +48,7 @@ struct MusicChunk {
|
|||||||
* An optional chunk which should be mixed into this chunk.
|
* An optional chunk which should be mixed into this chunk.
|
||||||
* This is used for cross-fading.
|
* This is used for cross-fading.
|
||||||
*/
|
*/
|
||||||
MusicChunk *other;
|
MusicChunk *other = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current mix ratio for cross-fading: 1.0 means play 100%
|
* The current mix ratio for cross-fading: 1.0 means play 100%
|
||||||
@@ -57,7 +57,7 @@ struct MusicChunk {
|
|||||||
float mix_ratio;
|
float mix_ratio;
|
||||||
|
|
||||||
/** number of bytes stored in this chunk */
|
/** number of bytes stored in this chunk */
|
||||||
uint16_t length;
|
uint16_t length = 0;
|
||||||
|
|
||||||
/** current bit rate of the source file */
|
/** current bit rate of the source file */
|
||||||
uint16_t bit_rate;
|
uint16_t bit_rate;
|
||||||
@@ -71,7 +71,7 @@ struct MusicChunk {
|
|||||||
* object is owned by this chunk, and must be freed when this
|
* object is owned by this chunk, and must be freed when this
|
||||||
* chunk is deinitialized.
|
* chunk is deinitialized.
|
||||||
*/
|
*/
|
||||||
Tag *tag;
|
Tag *tag = nullptr;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replay gain information associated with this chunk.
|
* Replay gain information associated with this chunk.
|
||||||
@@ -84,7 +84,7 @@ struct MusicChunk {
|
|||||||
* changed since the last chunk. The magic value 0 indicates
|
* changed since the last chunk. The magic value 0 indicates
|
||||||
* that there is no replay gain info available.
|
* that there is no replay gain info available.
|
||||||
*/
|
*/
|
||||||
unsigned replay_gain_serial;
|
unsigned replay_gain_serial = 0;
|
||||||
|
|
||||||
/** the data (probably PCM) */
|
/** the data (probably PCM) */
|
||||||
uint8_t data[CHUNK_SIZE];
|
uint8_t data[CHUNK_SIZE];
|
||||||
@@ -93,14 +93,14 @@ struct MusicChunk {
|
|||||||
AudioFormat audio_format;
|
AudioFormat audio_format;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
MusicChunk()
|
MusicChunk() = default;
|
||||||
:other(nullptr),
|
|
||||||
length(0),
|
MusicChunk(const MusicChunk &) = delete;
|
||||||
tag(nullptr),
|
|
||||||
replay_gain_serial(0) {}
|
|
||||||
|
|
||||||
~MusicChunk();
|
~MusicChunk();
|
||||||
|
|
||||||
|
MusicChunk &operator=(const MusicChunk &) = delete;
|
||||||
|
|
||||||
bool IsEmpty() const {
|
bool IsEmpty() const {
|
||||||
return length == 0 && tag == nullptr;
|
return length == 0 && tag == nullptr;
|
||||||
}
|
}
|
||||||
@@ -119,13 +119,10 @@ struct MusicChunk {
|
|||||||
* where you may write into. After you are finished, call
|
* where you may write into. After you are finished, call
|
||||||
* Expand().
|
* Expand().
|
||||||
*
|
*
|
||||||
* @param chunk the MusicChunk object
|
* @param af the audio format for the appended data;
|
||||||
* @param audio_format the audio format for the appended data;
|
|
||||||
* must stay the same for the life cycle of this chunk
|
* must stay the same for the life cycle of this chunk
|
||||||
* @param data_time the time within the song
|
* @param data_time the time within the song
|
||||||
* @param bit_rate the current bit rate of the source file
|
* @param bit_rate the current bit rate of the source file
|
||||||
* @param max_length_r the maximum write length is returned
|
|
||||||
* here
|
|
||||||
* @return a writable buffer, or nullptr if the chunk is full
|
* @return a writable buffer, or nullptr if the chunk is full
|
||||||
*/
|
*/
|
||||||
WritableBuffer<void> Write(AudioFormat af,
|
WritableBuffer<void> Write(AudioFormat af,
|
||||||
@@ -136,8 +133,7 @@ struct MusicChunk {
|
|||||||
* Increases the length of the chunk after the caller has written to
|
* Increases the length of the chunk after the caller has written to
|
||||||
* the buffer returned by Write().
|
* the buffer returned by Write().
|
||||||
*
|
*
|
||||||
* @param chunk the MusicChunk object
|
* @param af the audio format for the appended data; must
|
||||||
* @param audio_format the audio format for the appended data; must
|
|
||||||
* stay the same for the life cycle of this chunk
|
* stay the same for the life cycle of this chunk
|
||||||
* @param length the number of bytes which were appended
|
* @param length the number of bytes which were appended
|
||||||
* @return true if the chunk is full
|
* @return true if the chunk is full
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
bool
|
bool
|
||||||
MusicPipe::Contains(const MusicChunk *chunk) const
|
MusicPipe::Contains(const MusicChunk *chunk) const
|
||||||
{
|
{
|
||||||
const ScopeLock protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
for (const MusicChunk *i = head; i != nullptr; i = i->next)
|
for (const MusicChunk *i = head; i != nullptr; i = i->next)
|
||||||
if (i == chunk)
|
if (i == chunk)
|
||||||
@@ -41,7 +41,7 @@ MusicPipe::Contains(const MusicChunk *chunk) const
|
|||||||
MusicChunk *
|
MusicChunk *
|
||||||
MusicPipe::Shift()
|
MusicPipe::Shift()
|
||||||
{
|
{
|
||||||
const ScopeLock protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
MusicChunk *chunk = head;
|
MusicChunk *chunk = head;
|
||||||
if (chunk != nullptr) {
|
if (chunk != nullptr) {
|
||||||
@@ -87,7 +87,7 @@ MusicPipe::Push(MusicChunk *chunk)
|
|||||||
assert(!chunk->IsEmpty());
|
assert(!chunk->IsEmpty());
|
||||||
assert(chunk->length == 0 || chunk->audio_format.IsValid());
|
assert(chunk->length == 0 || chunk->audio_format.IsValid());
|
||||||
|
|
||||||
const ScopeLock protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
assert(size > 0 || !audio_format.IsDefined());
|
assert(size > 0 || !audio_format.IsDefined());
|
||||||
assert(!audio_format.IsDefined() ||
|
assert(!audio_format.IsDefined() ||
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -38,31 +38,28 @@ class MusicBuffer;
|
|||||||
*/
|
*/
|
||||||
class MusicPipe {
|
class MusicPipe {
|
||||||
/** the first chunk */
|
/** the first chunk */
|
||||||
MusicChunk *head;
|
MusicChunk *head = nullptr;
|
||||||
|
|
||||||
/** a pointer to the tail of the chunk */
|
/** a pointer to the tail of the chunk */
|
||||||
MusicChunk **tail_r;
|
MusicChunk **tail_r = &head;
|
||||||
|
|
||||||
/** the current number of chunks */
|
/** the current number of chunks */
|
||||||
unsigned size;
|
unsigned size = 0;
|
||||||
|
|
||||||
/** a mutex which protects #head and #tail_r */
|
/** a mutex which protects #head and #tail_r */
|
||||||
mutable Mutex mutex;
|
mutable Mutex mutex;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
AudioFormat audio_format;
|
AudioFormat audio_format = AudioFormat::Undefined();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* Creates a new #MusicPipe object. It is empty.
|
* Creates a new #MusicPipe object. It is empty.
|
||||||
*/
|
*/
|
||||||
MusicPipe()
|
MusicPipe() = default;
|
||||||
:head(nullptr), tail_r(&head), size(0) {
|
|
||||||
#ifndef NDEBUG
|
MusicPipe(const MusicPipe &) = delete;
|
||||||
audio_format.Clear();
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the object. It must be empty now.
|
* Frees the object. It must be empty now.
|
||||||
@@ -72,6 +69,8 @@ public:
|
|||||||
assert(tail_r == &head);
|
assert(tail_r == &head);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MusicPipe &operator=(const MusicPipe &) = delete;
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/**
|
/**
|
||||||
* Checks if the audio format if the chunk is equal to the specified
|
* Checks if the audio format if the chunk is equal to the specified
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -19,18 +19,66 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Partition.hxx"
|
#include "Partition.hxx"
|
||||||
|
#include "Instance.hxx"
|
||||||
#include "DetachedSong.hxx"
|
#include "DetachedSong.hxx"
|
||||||
#include "output/MultipleOutputs.hxx"
|
|
||||||
#include "mixer/Volume.hxx"
|
#include "mixer/Volume.hxx"
|
||||||
#include "Idle.hxx"
|
#include "IdleFlags.hxx"
|
||||||
#include "GlobalEvents.hxx"
|
|
||||||
|
Partition::Partition(Instance &_instance,
|
||||||
|
unsigned max_length,
|
||||||
|
unsigned buffer_chunks,
|
||||||
|
unsigned buffered_before_play,
|
||||||
|
AudioFormat configured_audio_format,
|
||||||
|
const ReplayGainConfig &replay_gain_config)
|
||||||
|
:instance(_instance),
|
||||||
|
global_events(instance.event_loop, BIND_THIS_METHOD(OnGlobalEvent)),
|
||||||
|
playlist(max_length, *this),
|
||||||
|
outputs(*this),
|
||||||
|
pc(*this, outputs, buffer_chunks, buffered_before_play,
|
||||||
|
configured_audio_format, replay_gain_config)
|
||||||
|
{
|
||||||
|
UpdateEffectiveReplayGainMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Partition::EmitIdle(unsigned mask)
|
||||||
|
{
|
||||||
|
instance.EmitIdle(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Partition::UpdateEffectiveReplayGainMode()
|
||||||
|
{
|
||||||
|
auto mode = replay_gain_mode;
|
||||||
|
if (mode == ReplayGainMode::AUTO)
|
||||||
|
mode = playlist.queue.random
|
||||||
|
? ReplayGainMode::TRACK
|
||||||
|
: ReplayGainMode::ALBUM;
|
||||||
|
|
||||||
|
pc.LockSetReplayGainMode(mode);
|
||||||
|
|
||||||
|
outputs.SetReplayGainMode(mode);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
|
const Database *
|
||||||
|
Partition::GetDatabase() const
|
||||||
|
{
|
||||||
|
return instance.GetDatabase();
|
||||||
|
}
|
||||||
|
|
||||||
|
const Database &
|
||||||
|
Partition::GetDatabaseOrThrow() const
|
||||||
|
{
|
||||||
|
return instance.GetDatabaseOrThrow();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Partition::DatabaseModified(const Database &db)
|
Partition::DatabaseModified(const Database &db)
|
||||||
{
|
{
|
||||||
playlist.DatabaseModified(db);
|
playlist.DatabaseModified(db);
|
||||||
|
EmitIdle(IDLE_DATABASE);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -51,16 +99,34 @@ Partition::SyncWithPlayer()
|
|||||||
playlist.SyncWithPlayer(pc);
|
playlist.SyncWithPlayer(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Partition::OnQueueModified()
|
||||||
|
{
|
||||||
|
EmitIdle(IDLE_PLAYLIST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Partition::OnQueueOptionsChanged()
|
||||||
|
{
|
||||||
|
EmitIdle(IDLE_OPTIONS);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Partition::OnQueueSongStarted()
|
||||||
|
{
|
||||||
|
EmitIdle(IDLE_PLAYER);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Partition::OnPlayerSync()
|
Partition::OnPlayerSync()
|
||||||
{
|
{
|
||||||
GlobalEvents::Emit(GlobalEvents::PLAYLIST);
|
EmitGlobalEvent(SYNC_WITH_PLAYER);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Partition::OnPlayerTagModified()
|
Partition::OnPlayerTagModified()
|
||||||
{
|
{
|
||||||
GlobalEvents::Emit(GlobalEvents::TAG);
|
EmitGlobalEvent(TAG_MODIFIED);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -69,5 +135,15 @@ Partition::OnMixerVolumeChanged(gcc_unused Mixer &mixer, gcc_unused int volume)
|
|||||||
InvalidateHardwareVolume();
|
InvalidateHardwareVolume();
|
||||||
|
|
||||||
/* notify clients */
|
/* notify clients */
|
||||||
idle_add(IDLE_MIXER);
|
EmitIdle(IDLE_MIXER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Partition::OnGlobalEvent(unsigned mask)
|
||||||
|
{
|
||||||
|
if ((mask & TAG_MODIFIED) != 0)
|
||||||
|
TagModified();
|
||||||
|
|
||||||
|
if ((mask & SYNC_WITH_PLAYER) != 0)
|
||||||
|
SyncWithPlayer();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -20,11 +20,14 @@
|
|||||||
#ifndef MPD_PARTITION_HXX
|
#ifndef MPD_PARTITION_HXX
|
||||||
#define MPD_PARTITION_HXX
|
#define MPD_PARTITION_HXX
|
||||||
|
|
||||||
|
#include "event/MaskMonitor.hxx"
|
||||||
#include "queue/Playlist.hxx"
|
#include "queue/Playlist.hxx"
|
||||||
|
#include "queue/Listener.hxx"
|
||||||
#include "output/MultipleOutputs.hxx"
|
#include "output/MultipleOutputs.hxx"
|
||||||
#include "mixer/Listener.hxx"
|
#include "mixer/Listener.hxx"
|
||||||
#include "PlayerControl.hxx"
|
#include "player/Control.hxx"
|
||||||
#include "PlayerListener.hxx"
|
#include "player/Listener.hxx"
|
||||||
|
#include "ReplayGainMode.hxx"
|
||||||
#include "Chrono.hxx"
|
#include "Chrono.hxx"
|
||||||
#include "Compiler.h"
|
#include "Compiler.h"
|
||||||
|
|
||||||
@@ -36,39 +39,50 @@ class SongLoader;
|
|||||||
* A partition of the Music Player Daemon. It is a separate unit with
|
* A partition of the Music Player Daemon. It is a separate unit with
|
||||||
* a playlist, a player, outputs etc.
|
* a playlist, a player, outputs etc.
|
||||||
*/
|
*/
|
||||||
struct Partition final : private PlayerListener, private MixerListener {
|
struct Partition final : QueueListener, PlayerListener, MixerListener {
|
||||||
|
static constexpr unsigned TAG_MODIFIED = 0x1;
|
||||||
|
static constexpr unsigned SYNC_WITH_PLAYER = 0x2;
|
||||||
|
|
||||||
Instance &instance;
|
Instance &instance;
|
||||||
|
|
||||||
|
MaskMonitor global_events;
|
||||||
|
|
||||||
struct playlist playlist;
|
struct playlist playlist;
|
||||||
|
|
||||||
MultipleOutputs outputs;
|
MultipleOutputs outputs;
|
||||||
|
|
||||||
PlayerControl pc;
|
PlayerControl pc;
|
||||||
|
|
||||||
|
ReplayGainMode replay_gain_mode = ReplayGainMode::OFF;
|
||||||
|
|
||||||
Partition(Instance &_instance,
|
Partition(Instance &_instance,
|
||||||
unsigned max_length,
|
unsigned max_length,
|
||||||
unsigned buffer_chunks,
|
unsigned buffer_chunks,
|
||||||
unsigned buffered_before_play)
|
unsigned buffered_before_play,
|
||||||
:instance(_instance), playlist(max_length),
|
AudioFormat configured_audio_format,
|
||||||
outputs(*this),
|
const ReplayGainConfig &replay_gain_config);
|
||||||
pc(*this, outputs, buffer_chunks, buffered_before_play) {}
|
|
||||||
|
void EmitGlobalEvent(unsigned mask) {
|
||||||
|
global_events.OrMask(mask);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EmitIdle(unsigned mask);
|
||||||
|
|
||||||
void ClearQueue() {
|
void ClearQueue() {
|
||||||
playlist.Clear(pc);
|
playlist.Clear(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned AppendURI(const SongLoader &loader,
|
unsigned AppendURI(const SongLoader &loader,
|
||||||
const char *uri_utf8,
|
const char *uri_utf8) {
|
||||||
Error &error) {
|
return playlist.AppendURI(pc, loader, uri_utf8);
|
||||||
return playlist.AppendURI(pc, loader, uri_utf8, error);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult DeletePosition(unsigned position) {
|
void DeletePosition(unsigned position) {
|
||||||
return playlist.DeletePosition(pc, position);
|
playlist.DeletePosition(pc, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult DeleteId(unsigned id) {
|
void DeleteId(unsigned id) {
|
||||||
return playlist.DeleteId(pc, id);
|
playlist.DeleteId(pc, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -77,60 +91,53 @@ struct Partition final : private PlayerListener, private MixerListener {
|
|||||||
* @param start the position of the first song to delete
|
* @param start the position of the first song to delete
|
||||||
* @param end the position after the last song to delete
|
* @param end the position after the last song to delete
|
||||||
*/
|
*/
|
||||||
PlaylistResult DeleteRange(unsigned start, unsigned end) {
|
void DeleteRange(unsigned start, unsigned end) {
|
||||||
return playlist.DeleteRange(pc, start, end);
|
playlist.DeleteRange(pc, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
void StaleSong(const char *uri) {
|
||||||
|
playlist.StaleSong(pc, uri);
|
||||||
void DeleteSong(const char *uri) {
|
|
||||||
playlist.DeleteSong(pc, uri);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Shuffle(unsigned start, unsigned end) {
|
void Shuffle(unsigned start, unsigned end) {
|
||||||
playlist.Shuffle(pc, start, end);
|
playlist.Shuffle(pc, start, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult MoveRange(unsigned start, unsigned end, int to) {
|
void MoveRange(unsigned start, unsigned end, int to) {
|
||||||
return playlist.MoveRange(pc, start, end, to);
|
playlist.MoveRange(pc, start, end, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult MoveId(unsigned id, int to) {
|
void MoveId(unsigned id, int to) {
|
||||||
return playlist.MoveId(pc, id, to);
|
playlist.MoveId(pc, id, to);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult SwapPositions(unsigned song1, unsigned song2) {
|
void SwapPositions(unsigned song1, unsigned song2) {
|
||||||
return playlist.SwapPositions(pc, song1, song2);
|
playlist.SwapPositions(pc, song1, song2);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult SwapIds(unsigned id1, unsigned id2) {
|
void SwapIds(unsigned id1, unsigned id2) {
|
||||||
return playlist.SwapIds(pc, id1, id2);
|
playlist.SwapIds(pc, id1, id2);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult SetPriorityRange(unsigned start_position,
|
void SetPriorityRange(unsigned start_position, unsigned end_position,
|
||||||
unsigned end_position,
|
|
||||||
uint8_t priority) {
|
uint8_t priority) {
|
||||||
return playlist.SetPriorityRange(pc,
|
playlist.SetPriorityRange(pc, start_position, end_position,
|
||||||
start_position, end_position,
|
|
||||||
priority);
|
priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult SetPriorityId(unsigned song_id,
|
void SetPriorityId(unsigned song_id, uint8_t priority) {
|
||||||
uint8_t priority) {
|
playlist.SetPriorityId(pc, song_id, priority);
|
||||||
return playlist.SetPriorityId(pc, song_id, priority);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Stop() {
|
void Stop() {
|
||||||
playlist.Stop(pc);
|
playlist.Stop(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult PlayPosition(int position) {
|
void PlayPosition(int position) {
|
||||||
return playlist.PlayPosition(pc, position);
|
return playlist.PlayPosition(pc, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult PlayId(int id) {
|
void PlayId(int id) {
|
||||||
return playlist.PlayId(pc, id);
|
return playlist.PlayId(pc, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,17 +149,16 @@ struct Partition final : private PlayerListener, private MixerListener {
|
|||||||
return playlist.PlayPrevious(pc);
|
return playlist.PlayPrevious(pc);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult SeekSongPosition(unsigned song_position,
|
void SeekSongPosition(unsigned song_position, SongTime seek_time) {
|
||||||
SongTime seek_time) {
|
playlist.SeekSongPosition(pc, song_position, seek_time);
|
||||||
return playlist.SeekSongPosition(pc, song_position, seek_time);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult SeekSongId(unsigned song_id, SongTime seek_time) {
|
void SeekSongId(unsigned song_id, SongTime seek_time) {
|
||||||
return playlist.SeekSongId(pc, song_id, seek_time);
|
playlist.SeekSongId(pc, song_id, seek_time);
|
||||||
}
|
}
|
||||||
|
|
||||||
PlaylistResult SeekCurrent(SignedSongTime seek_time, bool relative) {
|
void SeekCurrent(SignedSongTime seek_time, bool relative) {
|
||||||
return playlist.SeekCurrent(pc, seek_time, relative);
|
playlist.SeekCurrent(pc, seek_time, relative);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRepeat(bool new_value) {
|
void SetRepeat(bool new_value) {
|
||||||
@@ -175,7 +181,28 @@ struct Partition final : private PlayerListener, private MixerListener {
|
|||||||
playlist.SetConsume(new_value);
|
playlist.SetConsume(new_value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SetReplayGainMode(ReplayGainMode mode) {
|
||||||
|
replay_gain_mode = mode;
|
||||||
|
UpdateEffectiveReplayGainMode();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Publishes the effective #ReplayGainMode to all subsystems.
|
||||||
|
* #ReplayGainMode::AUTO is substituted.
|
||||||
|
*/
|
||||||
|
void UpdateEffectiveReplayGainMode();
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
/**
|
||||||
|
* Returns the global #Database instance. May return nullptr
|
||||||
|
* if this MPD configuration has no database (no
|
||||||
|
* music_directory was configured).
|
||||||
|
*/
|
||||||
|
const Database *GetDatabase() const;
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
const Database &GetDatabaseOrThrow() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The database has been modified. Propagate the change to
|
* The database has been modified. Propagate the change to
|
||||||
* all subsystems.
|
* all subsystems.
|
||||||
@@ -195,12 +222,20 @@ struct Partition final : private PlayerListener, private MixerListener {
|
|||||||
void SyncWithPlayer();
|
void SyncWithPlayer();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
/* virtual methods from class QueueListener */
|
||||||
|
void OnQueueModified() override;
|
||||||
|
void OnQueueOptionsChanged() override;
|
||||||
|
void OnQueueSongStarted() override;
|
||||||
|
|
||||||
/* virtual methods from class PlayerListener */
|
/* virtual methods from class PlayerListener */
|
||||||
virtual void OnPlayerSync() override;
|
void OnPlayerSync() override;
|
||||||
virtual void OnPlayerTagModified() override;
|
void OnPlayerTagModified() override;
|
||||||
|
|
||||||
/* virtual methods from class MixerListener */
|
/* virtual methods from class MixerListener */
|
||||||
virtual void OnMixerVolumeChanged(Mixer &mixer, int volume) override;
|
void OnMixerVolumeChanged(Mixer &mixer, int volume) override;
|
||||||
|
|
||||||
|
/* callback for #global_events */
|
||||||
|
void OnGlobalEvent(unsigned mask);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2003-2014 The Music Player Daemon Project
|
* Copyright 2003-2017 The Music Player Daemon Project
|
||||||
* http://www.musicpd.org
|
* http://www.musicpd.org
|
||||||
*
|
*
|
||||||
* This program is free software; you can redistribute it and/or modify
|
* This program is free software; you can redistribute it and/or modify
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Permission.hxx"
|
#include "Permission.hxx"
|
||||||
#include "config/ConfigData.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/ConfigGlobal.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/ConfigOption.hxx"
|
||||||
#include "system/FatalError.hxx"
|
#include "system/FatalError.hxx"
|
||||||
@@ -87,12 +87,12 @@ static unsigned parsePermissions(const char *string)
|
|||||||
void initPermissions(void)
|
void initPermissions(void)
|
||||||
{
|
{
|
||||||
unsigned permission;
|
unsigned permission;
|
||||||
const struct config_param *param;
|
const ConfigParam *param;
|
||||||
|
|
||||||
permission_default = PERMISSION_READ | PERMISSION_ADD |
|
permission_default = PERMISSION_READ | PERMISSION_ADD |
|
||||||
PERMISSION_CONTROL | PERMISSION_ADMIN;
|
PERMISSION_CONTROL | PERMISSION_ADMIN;
|
||||||
|
|
||||||
param = config_get_param(CONF_PASSWORD);
|
param = config_get_param(ConfigOption::PASSWORD);
|
||||||
|
|
||||||
if (param) {
|
if (param) {
|
||||||
permission_default = 0;
|
permission_default = 0;
|
||||||
@@ -118,7 +118,7 @@ void initPermissions(void)
|
|||||||
} while ((param = param->next) != nullptr);
|
} while ((param = param->next) != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
param = config_get_param(CONF_DEFAULT_PERMS);
|
param = config_get_param(ConfigOption::DEFAULT_PERMS);
|
||||||
|
|
||||||
if (param)
|
if (param)
|
||||||
permission_default = parsePermissions(param->value.c_str());
|
permission_default = parsePermissions(param->value.c_str());
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user