Compare commits
1671 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4634b94c83 | ||
|
|
6e04a327b4 | ||
|
|
7ec887eea2 | ||
|
|
1477b64d4f | ||
|
|
a2c108f5ef | ||
|
|
f546e76490 | ||
|
|
2568bc3957 | ||
|
|
7104ac963b | ||
|
|
2cb36590b2 | ||
|
|
af7b928d7c | ||
|
|
c0d8a9b07a | ||
|
|
5b0d23d553 | ||
|
|
ab30695bd1 | ||
|
|
53a4de35c4 | ||
|
|
22e6d95c4b | ||
|
|
1c7bd7d5c4 | ||
|
|
3c4ed9cbe3 | ||
|
|
2677b90244 | ||
|
|
1b20fa441d | ||
|
|
18c042d4cf | ||
|
|
98f92d828a | ||
|
|
76268773b5 | ||
|
|
87542e3080 | ||
|
|
66f5b0fed7 | ||
|
|
5cb603983e | ||
|
|
9c5790ab1d | ||
|
|
4b7078297d | ||
|
|
841694ccf2 | ||
|
|
12f4a8255a | ||
|
|
bda77ffc5b | ||
|
|
ed9ece5ea3 | ||
|
|
ce49d99c2f | ||
|
|
2e450bbf95 | ||
|
|
303b3071e4 | ||
|
|
eb6d5f34fc | ||
|
|
f80126959d | ||
|
|
4fb4f6d1b7 | ||
|
|
43df4a7500 | ||
|
|
4cdcaa8630 | ||
|
|
04f632296f | ||
|
|
7c8dbcfaac | ||
|
|
436ba3c96c | ||
|
|
5d12f52873 | ||
|
|
a8bf8ede01 | ||
|
|
8682183bc3 | ||
|
|
94c31d0da9 | ||
|
|
464a4cbeec | ||
|
|
9f0cbf418a | ||
|
|
b477f86c92 | ||
|
|
020371f145 | ||
|
|
ccafe3f3cf | ||
|
|
3830748de5 | ||
|
|
1a43f5145d | ||
|
|
7f143a83c1 | ||
|
|
6ccc254179 | ||
|
|
7db2450447 | ||
|
|
6c2a6a65e0 | ||
|
|
4247a757b3 | ||
|
|
57e34823d8 | ||
|
|
3c93decdf0 | ||
|
|
89e7a5018d | ||
|
|
7235b46e5e | ||
|
|
0852226a48 | ||
|
|
e20d215abf | ||
|
|
e4b9b67e24 | ||
|
|
685b78828d | ||
|
|
060908d5c4 | ||
|
|
0b0f4c61f1 | ||
|
|
228bf7eb09 | ||
|
|
5eaf2b8fc3 | ||
|
|
e097fef79e | ||
|
|
9a813cd3b1 | ||
|
|
1c60c8e014 | ||
|
|
eddda95900 | ||
|
|
72184dccfc | ||
|
|
fee75dc766 | ||
|
|
ba5c856f15 | ||
|
|
12308a0f55 | ||
|
|
a958abde2f | ||
|
|
583208db7e | ||
|
|
7b5ba15170 | ||
|
|
d5e0d49f86 | ||
|
|
73b22d82aa | ||
|
|
db51cc4e02 | ||
|
|
be8a52a914 | ||
|
|
ad597a8ff0 | ||
|
|
b1fe105904 | ||
|
|
451b142e3a | ||
|
|
2833625266 | ||
|
|
0464028872 | ||
|
|
98985c03b0 | ||
|
|
793fd8c479 | ||
|
|
6c602811df | ||
|
|
6d48a5684a | ||
|
|
bd115a4008 | ||
|
|
08272cdee2 | ||
|
|
b14a5141a6 | ||
|
|
aa0e4500c6 | ||
|
|
4e6b8edf72 | ||
|
|
ac0852b4e3 | ||
|
|
6fe43ed969 | ||
|
|
b34bc06624 | ||
|
|
08e41e60e5 | ||
|
|
10ec478a9c | ||
|
|
86f1074905 | ||
|
|
8e66b855a3 | ||
|
|
e3bc85d7bf | ||
|
|
6f242836e6 | ||
|
|
f2c926f3b6 | ||
|
|
aba18924ee | ||
|
|
aa6bef54dd | ||
|
|
528f5b9cb9 | ||
|
|
96ae0ec93a | ||
|
|
5a5229b499 | ||
|
|
bba22c9c8c | ||
|
|
694c437a2c | ||
|
|
587172efa3 | ||
|
|
2a926063b2 | ||
|
|
d6f239e54f | ||
|
|
b8989fafeb | ||
|
|
795789e79d | ||
|
|
cd8bc57c0d | ||
|
|
55b355618d | ||
|
|
ba25a5388e | ||
|
|
657ef48518 | ||
|
|
b1d68fe995 | ||
|
|
8a492c8f39 | ||
|
|
901a48c9a4 | ||
|
|
b0994bad31 | ||
|
|
f5c9071494 | ||
|
|
d1f85240a2 | ||
|
|
2148d4bb31 | ||
|
|
e79d06d595 | ||
|
|
c60cf944f5 | ||
|
|
4b8ee58638 | ||
|
|
9305730993 | ||
|
|
16bc97e9e5 | ||
|
|
482c18982e | ||
|
|
06ca08ce55 | ||
|
|
9fc00a817b | ||
|
|
f47696f5f8 | ||
|
|
190006e9dc | ||
|
|
30eaae10c1 | ||
|
|
b878111404 | ||
|
|
db21d7de0b | ||
|
|
8454083efa | ||
|
|
a0e5729117 | ||
|
|
534853cd32 | ||
|
|
fb0ead1788 | ||
|
|
32013ad4a6 | ||
|
|
7352d6a38d | ||
|
|
f649ec1fd8 | ||
|
|
56112a237c | ||
|
|
64da9399ca | ||
|
|
dd8e14e121 | ||
|
|
09e2202cd6 | ||
|
|
fe7e1ae8aa | ||
|
|
aa07e8a8fe | ||
|
|
83d598bdfd | ||
|
|
0ec31b4aa4 | ||
|
|
a943f4063c | ||
|
|
ce9f09c69a | ||
|
|
3ddc7a5353 | ||
|
|
e575392b94 | ||
|
|
c6f61a699c | ||
|
|
0307b49f43 | ||
|
|
413ab80295 | ||
|
|
daffefdb10 | ||
|
|
5fb21fbdb1 | ||
|
|
f5857c4689 | ||
|
|
2c388434dd | ||
|
|
c97469283c | ||
|
|
1f8d707082 | ||
|
|
9b1f44e758 | ||
|
|
804ccddf7e | ||
|
|
bb5918932b | ||
|
|
aa77bc323f | ||
|
|
901229699e | ||
|
|
c92f0a1336 | ||
|
|
8463441afe | ||
|
|
9b6a2589e5 | ||
|
|
92523f8cf2 | ||
|
|
e33c08357a | ||
|
|
2dc5648e57 | ||
|
|
d0349880da | ||
|
|
f178163217 | ||
|
|
889e4869f9 | ||
|
|
f77135f307 | ||
|
|
eeae9a04d3 | ||
|
|
8bb35e7bb6 | ||
|
|
3e78c9ab48 | ||
|
|
9ec86acb9c | ||
|
|
426bde3f75 | ||
|
|
30e22b753b | ||
|
|
f7141c9201 | ||
|
|
c2a2573aa5 | ||
|
|
66ab2de578 | ||
|
|
e28d1e0f65 | ||
|
|
a491d8ae24 | ||
|
|
3cd5dd15f8 | ||
|
|
562ae44d38 | ||
|
|
92541dedc0 | ||
|
|
650a67dc38 | ||
|
|
c63f24e58e | ||
|
|
3be8b02cc2 | ||
|
|
bdfaea0c25 | ||
|
|
ed5c0d6546 | ||
|
|
86dc621086 | ||
|
|
fbea965c70 | ||
|
|
a2cd66ed6f | ||
|
|
68894e822a | ||
|
|
937f49f1e9 | ||
|
|
ee59e20c28 | ||
|
|
01b6e1cbf2 | ||
|
|
eefc0f5d80 | ||
|
|
1f94cea889 | ||
|
|
69749eb591 | ||
|
|
94592c1406 | ||
|
|
13ce142df1 | ||
|
|
89bf4c5fad | ||
|
|
f80ebf68b0 | ||
|
|
1155a29096 | ||
|
|
030e603940 | ||
|
|
9c1bf9ac5f | ||
|
|
5f8dac6822 | ||
|
|
2f07b8f482 | ||
|
|
6c40a27809 | ||
|
|
8736a3533b | ||
|
|
608d232373 | ||
|
|
1702e98fdf | ||
|
|
2ec94c0497 | ||
|
|
bf372e3e1f | ||
|
|
0d971963fd | ||
|
|
287cff40b9 | ||
|
|
0e0bc7976f | ||
|
|
8c638c50a3 | ||
|
|
5b2374b949 | ||
|
|
c1600bcf3d | ||
|
|
a82d864c91 | ||
|
|
dcac32a6c4 | ||
|
|
5286477f73 | ||
|
|
2f3845ef51 | ||
|
|
1191025bbf | ||
|
|
bfd261929e | ||
|
|
84de88841b | ||
|
|
224400074c | ||
|
|
863722545f | ||
|
|
d3d1d37782 | ||
|
|
1a2012a97e | ||
|
|
90f4e97751 | ||
|
|
d1bcd98f79 | ||
|
|
39542de69d | ||
|
|
1d00d55d53 | ||
|
|
a190db0873 | ||
|
|
e3142312bb | ||
|
|
e5d1ac0bd0 | ||
|
|
c0411fa412 | ||
|
|
781e690012 | ||
|
|
9a2d71341e | ||
|
|
6db6d3c50c | ||
|
|
0e2c597884 | ||
|
|
debdf9bb96 | ||
|
|
218d9383d7 | ||
|
|
af64bd5088 | ||
|
|
050f81c4fe | ||
|
|
6ebe772e2f | ||
|
|
c9ee6dd4ca | ||
|
|
38b183fac2 | ||
|
|
ab678787f4 | ||
|
|
23556585ca | ||
|
|
728e4e9a38 | ||
|
|
2d6f9f9a9c | ||
|
|
c2e2e5543e | ||
|
|
349d8eb248 | ||
|
|
94b96bde9b | ||
|
|
45ffc864c5 | ||
|
|
19d9ce260a | ||
|
|
0701333ec1 | ||
|
|
a8e70f0901 | ||
|
|
c7c32a3ce9 | ||
|
|
53170ca2f2 | ||
|
|
94694e0f33 | ||
|
|
a73176a1e9 | ||
|
|
e6a974a93e | ||
|
|
9894967fcb | ||
|
|
92da483ecd | ||
|
|
9cc960ac5e | ||
|
|
18dd082f1e | ||
|
|
81b734be10 | ||
|
|
c59be7ced3 | ||
|
|
c5c4d4a57e | ||
|
|
2d0b429b6a | ||
|
|
60620d9af5 | ||
|
|
15b2a4862e | ||
|
|
2915d2dd0f | ||
|
|
590687fdea | ||
|
|
993f8d6a5e | ||
|
|
68f824a186 | ||
|
|
b9cca49e14 | ||
|
|
931b571e3d | ||
|
|
b7b93bb67e | ||
|
|
35eca08d48 | ||
|
|
7137ca375a | ||
|
|
fe2f7a3e5a | ||
|
|
98eed1f5ab | ||
|
|
5d0a463f09 | ||
|
|
dd461400fb | ||
|
|
b1390ec27f | ||
|
|
dda5516eec | ||
|
|
adc5c5db88 | ||
|
|
0642ce4795 | ||
|
|
d11e1d5880 | ||
|
|
b143477774 | ||
|
|
d092a88a93 | ||
|
|
ab7597b089 | ||
|
|
84df470008 | ||
|
|
5ca0b7a28f | ||
|
|
21d621e7ad | ||
|
|
d036e20826 | ||
|
|
9151b84c25 | ||
|
|
5d7dd12f7a | ||
|
|
21783ff5f7 | ||
|
|
fd923d5d96 | ||
|
|
ebf607eef8 | ||
|
|
e092eadd8d | ||
|
|
185148f57c | ||
|
|
ede7434901 | ||
|
|
ba3b422ce5 | ||
|
|
1f3ce380ed | ||
|
|
dfc1f6342a | ||
|
|
94092f1f90 | ||
|
|
a84b83f20f | ||
|
|
614e410fe7 | ||
|
|
4a1e885c0a | ||
|
|
eee91aa4ea | ||
|
|
855750c784 | ||
|
|
4f2163e76c | ||
|
|
eef66dee04 | ||
|
|
7ad440ca1c | ||
|
|
13b3e9e7b3 | ||
|
|
8106929d60 | ||
|
|
795baed3f5 | ||
|
|
5487d40be9 | ||
|
|
5e512763d3 | ||
|
|
a65d02d3ae | ||
|
|
2156fc64f4 | ||
|
|
441440101d | ||
|
|
ec54754e22 | ||
|
|
0ebba73cb8 | ||
|
|
50c7337965 | ||
|
|
b5c569cd30 | ||
|
|
11396d4fba | ||
|
|
4c6ae4e9e8 | ||
|
|
9cb9154b08 | ||
|
|
234a6193bb | ||
|
|
2bf5f32224 | ||
|
|
82d0f68acf | ||
|
|
616c8383c0 | ||
|
|
5de46268af | ||
|
|
489e11072e | ||
|
|
5e2af15e94 | ||
|
|
3fbb54e0a4 | ||
|
|
fe6de14faf | ||
|
|
e85b9960f0 | ||
|
|
75c836fbd9 | ||
|
|
94b1025780 | ||
|
|
36ca9d01fb | ||
|
|
3bceed1b53 | ||
|
|
90de2c4bd6 | ||
|
|
9d63c8220b | ||
|
|
edd9d16c84 | ||
|
|
ec373eba5d | ||
|
|
0dfb27b7e5 | ||
|
|
735f62be0c | ||
|
|
a04e01d5f5 | ||
|
|
b03f05f28a | ||
|
|
0b7d7fe069 | ||
|
|
616abdda26 | ||
|
|
cc64c715a2 | ||
|
|
9999914c74 | ||
|
|
bd32a11016 | ||
|
|
140aeea300 | ||
|
|
afd0fe666a | ||
|
|
4accc1f159 | ||
|
|
80839b5372 | ||
|
|
dafa3f985a | ||
|
|
f865e1393c | ||
|
|
c99416fbe0 | ||
|
|
3caef29b93 | ||
|
|
5f95c07305 | ||
|
|
1a9659ef45 | ||
|
|
aaa438e745 | ||
|
|
4531e4cc55 | ||
|
|
1ba35e1fd4 | ||
|
|
4ba3812baf | ||
|
|
4797357fa9 | ||
|
|
f6b3a88723 | ||
|
|
82e8913c05 | ||
|
|
c46483a4ab | ||
|
|
0f19108ce3 | ||
|
|
4208fe29b5 | ||
|
|
1b593462d3 | ||
|
|
0cf9c941af | ||
|
|
c1b33533da | ||
|
|
66fcd25b7e | ||
|
|
01d3777574 | ||
|
|
87570cdd9b | ||
|
|
0ea6a2dd99 | ||
|
|
cacc1ffdad | ||
|
|
cfe34647e1 | ||
|
|
737267cedc | ||
|
|
84054203af | ||
|
|
0c1a899fbe | ||
|
|
52521d02ea | ||
|
|
2127a482da | ||
|
|
7df0d3b7fc | ||
|
|
fdd101c4c5 | ||
|
|
4218f56f6c | ||
|
|
dd18fe34a7 | ||
|
|
5b09504a71 | ||
|
|
0c1a001622 | ||
|
|
148c38fbb9 | ||
|
|
fbfefcc0a3 | ||
|
|
b4c517c501 | ||
|
|
b39bc85e60 | ||
|
|
603ce87ac2 | ||
|
|
4b16a8bf84 | ||
|
|
ca4c81dd84 | ||
|
|
e9881bbfc8 | ||
|
|
69f4178bff | ||
|
|
027e562f65 | ||
|
|
2d2120338b | ||
|
|
e5e623ffaa | ||
|
|
e47e3205b3 | ||
|
|
592d2ebd26 | ||
|
|
299c809272 | ||
|
|
d929d0c26f | ||
|
|
90201e9970 | ||
|
|
a31da51fd9 | ||
|
|
cf471e830f | ||
|
|
22192adbc8 | ||
|
|
b8f3de693f | ||
|
|
68c023cdd8 | ||
|
|
b18b0bf328 | ||
|
|
2a2c5d50ff | ||
|
|
dfda0faac7 | ||
|
|
95acc4be07 | ||
|
|
330a4cf573 | ||
|
|
6ffbb151a0 | ||
|
|
271e49db5d | ||
|
|
8d2101ccb4 | ||
|
|
7aa8497546 | ||
|
|
7a8d5070f5 | ||
|
|
8707ae6fd4 | ||
|
|
8786b61636 | ||
|
|
1b5faf5cbf | ||
|
|
2da5b7cb65 | ||
|
|
1e88e71b9a | ||
|
|
e16fd4a09b | ||
|
|
097e2b6c62 | ||
|
|
7db7568dcf | ||
|
|
409d3c7136 | ||
|
|
7f81375861 | ||
|
|
0de39a431b | ||
|
|
54c20f6aa1 | ||
|
|
1726278ccc | ||
|
|
8661a51aba | ||
|
|
42ec67168a | ||
|
|
91af2ebc2a | ||
|
|
f7fb8a33d7 | ||
|
|
0505cb8f7e | ||
|
|
2cfccc1c34 | ||
|
|
438366effc | ||
|
|
29d5ad667c | ||
|
|
235ddc0990 | ||
|
|
517f5b1999 | ||
|
|
a8ac8b2563 | ||
|
|
78a65cf281 | ||
|
|
96017f58a5 | ||
|
|
c8e6f50d55 | ||
|
|
9263d6d07d | ||
|
|
5271e81ebe | ||
|
|
a174159496 | ||
|
|
efb2051b30 | ||
|
|
a2b24cb5a2 | ||
|
|
a54f9ede2e | ||
|
|
05fb624031 | ||
|
|
2de98b652b | ||
|
|
361ad92da9 | ||
|
|
84ff71002e | ||
|
|
7f1b134137 | ||
|
|
504776a10f | ||
|
|
184b90bb88 | ||
|
|
cf85fcec79 | ||
|
|
b34fd905c8 | ||
|
|
821f77325c | ||
|
|
bd8cf7c53d | ||
|
|
88c19c21ee | ||
|
|
40ec819330 | ||
|
|
34dbd03be1 | ||
|
|
42d41647b5 | ||
|
|
c91db14cef | ||
|
|
10b925e7ac | ||
|
|
c9942846c9 | ||
|
|
6235cf066a | ||
|
|
86979c8f04 | ||
|
|
8a689e68bc | ||
|
|
b98263e86f | ||
|
|
f30265a9ee | ||
|
|
fcbcec6856 | ||
|
|
b778fb38a9 | ||
|
|
32290d5eb8 | ||
|
|
f87265a4d5 | ||
|
|
6448b31b11 | ||
|
|
998227cffc | ||
|
|
09f743dc1a | ||
|
|
035f986a91 | ||
|
|
b168a9d469 | ||
|
|
2b1d6ad396 | ||
|
|
641447bf9b | ||
|
|
06c2aef3c7 | ||
|
|
1caa0ef58d | ||
|
|
51951c9442 | ||
|
|
104b8b4c4c | ||
|
|
3b95523e07 | ||
|
|
3ca312bd4a | ||
|
|
d06ef76e58 | ||
|
|
57729683b6 | ||
|
|
9ff2606bb8 | ||
|
|
fd80683ade | ||
|
|
49efb6071c | ||
|
|
8df98932b1 | ||
|
|
95481dda86 | ||
|
|
1b4181d983 | ||
|
|
113141bf2a | ||
|
|
bcc1e51097 | ||
|
|
e8a7c6cee3 | ||
|
|
0c8ffa1ac3 | ||
|
|
4f678aa244 | ||
|
|
3a4a430f6c | ||
|
|
36db40b224 | ||
|
|
426b9672cf | ||
|
|
4d80419982 | ||
|
|
3983caa2c8 | ||
|
|
0b4e0b7bcb | ||
|
|
a9b8d5ecb6 | ||
|
|
60b2338091 | ||
|
|
d2594c6380 | ||
|
|
667daab056 | ||
|
|
2fc0a738ce | ||
|
|
86c531b37d | ||
|
|
a5b14a2ea7 | ||
|
|
bf582bd969 | ||
|
|
ad866f7a7d | ||
|
|
338a6f2a96 | ||
|
|
c3aa53cc97 | ||
|
|
24a86dce21 | ||
|
|
0209bc4ba7 | ||
|
|
dd57b81989 | ||
|
|
ffe6819966 | ||
|
|
8af75c78f8 | ||
|
|
696add259b | ||
|
|
f18695eb45 | ||
|
|
d6b0ecac1b | ||
|
|
61a119b607 | ||
|
|
ea5096ac90 | ||
|
|
428c2ec0e3 | ||
|
|
1a82981d07 | ||
|
|
0ff0aca2e2 | ||
|
|
7b02c0224c | ||
|
|
57d77cc8a0 | ||
|
|
9fe0585056 | ||
|
|
8c366f0774 | ||
|
|
d6529d8c60 | ||
|
|
edb44a536a | ||
|
|
eeaaea802a | ||
|
|
15c36baefd | ||
|
|
33deb84aa1 | ||
|
|
b211d31a64 | ||
|
|
5b192beaa5 | ||
|
|
ef38330d74 | ||
|
|
987b60ae73 | ||
|
|
7db0f7c4da | ||
|
|
a4eeaff63f | ||
|
|
7807ddae57 | ||
|
|
566af6827e | ||
|
|
bf046d895e | ||
|
|
af33a9f4b8 | ||
|
|
e9a4570891 | ||
|
|
99d5b61698 | ||
|
|
79e89eb23b | ||
|
|
d13a64455c | ||
|
|
816603fd9a | ||
|
|
bf5f12a51f | ||
|
|
866821765a | ||
|
|
c457d8e442 | ||
|
|
c58dffa685 | ||
|
|
ba41690063 | ||
|
|
86a37d0ed6 | ||
|
|
2fb5dbe62b | ||
|
|
d2835e2989 | ||
|
|
543e8a98a7 | ||
|
|
86b7890f67 | ||
|
|
9c6b52ccee | ||
|
|
79937c9495 | ||
|
|
a47ecf9cb1 | ||
|
|
8aa2c57413 | ||
|
|
524a7f4560 | ||
|
|
56bfff5a57 | ||
|
|
1d30df9b15 | ||
|
|
ef84e5c8fa | ||
|
|
6d2a30b860 | ||
|
|
9e0fa8e9ec | ||
|
|
5e8e038811 | ||
|
|
e61a804b80 | ||
|
|
a9d6ad4759 | ||
|
|
987124610a | ||
|
|
40a1ebee29 | ||
|
|
d4ce9c0df2 | ||
|
|
680fdb0338 | ||
|
|
727078f65d | ||
|
|
d7f770ce73 | ||
|
|
e1ddb63054 | ||
|
|
24b14c5aa5 | ||
|
|
2e116c9e28 | ||
|
|
37897d1550 | ||
|
|
b153591790 | ||
|
|
ee5653338d | ||
|
|
032f47c0b0 | ||
|
|
1f4e4dd9b3 | ||
|
|
d43218ed16 | ||
|
|
3d43e4e954 | ||
|
|
b0d587ded7 | ||
|
|
1245b4a49f | ||
|
|
d4ce6049c9 | ||
|
|
c236a85c13 | ||
|
|
9cf43eef67 | ||
|
|
ed6d0aa548 | ||
|
|
3d27fffc50 | ||
|
|
de0ee26432 | ||
|
|
45cccbce59 | ||
|
|
479de9c7cb | ||
|
|
60821232b9 | ||
|
|
9b4156a282 | ||
|
|
89b1e27d2e | ||
|
|
1dcaf8f76a | ||
|
|
18508d1919 | ||
|
|
9f77d568e2 | ||
|
|
0d0569b9af | ||
|
|
0f18e7baf9 | ||
|
|
d8b03d4927 | ||
|
|
72b6c09a73 | ||
|
|
c05bca6f2c | ||
|
|
73c95d1fb2 | ||
|
|
2c30e16371 | ||
|
|
72437ca9e2 | ||
|
|
9be14bbe82 | ||
|
|
d47f37f23a | ||
|
|
a22aed7acf | ||
|
|
38b58715ae | ||
|
|
d88e00c0a4 | ||
|
|
a72d1200fb | ||
|
|
9a29d02e7e | ||
|
|
45139f94bb | ||
|
|
80cb680fca | ||
|
|
b9ff6383a4 | ||
|
|
ebc006ab52 | ||
|
|
86a02871fc | ||
|
|
e152e843d8 | ||
|
|
9ff1ff75cb | ||
|
|
abea4a24ba | ||
|
|
3d3a1232b1 | ||
|
|
09d4176210 | ||
|
|
30d41e45e2 | ||
|
|
bd9a5021da | ||
|
|
1624a5eb8d | ||
|
|
1bca29f9e2 | ||
|
|
efb8a9bd2c | ||
|
|
82954d1d6f | ||
|
|
5a02324c09 | ||
|
|
eb93bebbc1 | ||
|
|
2be905b2e2 | ||
|
|
076be809c2 | ||
|
|
88f1233d7b | ||
|
|
54d295c247 | ||
|
|
e81b089612 | ||
|
|
9f14e7a98d | ||
|
|
cb412b221c | ||
|
|
1ca1269a59 | ||
|
|
6681b14b71 | ||
|
|
12f2418445 | ||
|
|
ae8a2ab652 | ||
|
|
d0fbf6db59 | ||
|
|
01d8eb6290 | ||
|
|
197968d65e | ||
|
|
2cb83a1f84 | ||
|
|
d7c94e30c5 | ||
|
|
510d2514a0 | ||
|
|
5217a74b7f | ||
|
|
cccf35d140 | ||
|
|
249316c8fc | ||
|
|
cd24449495 | ||
|
|
687834328c | ||
|
|
4d015aff30 | ||
|
|
ba8040d068 | ||
|
|
5fa94d2a85 | ||
|
|
7eee79c145 | ||
|
|
9626523420 | ||
|
|
0150131984 | ||
|
|
2ddd45e5e1 | ||
|
|
03c89c9cec | ||
|
|
640de5518b | ||
|
|
a92c694f1b | ||
|
|
a159299a4b | ||
|
|
d048545f1a | ||
|
|
aea6d354b7 | ||
|
|
d3793dfe5b | ||
|
|
234f8d287a | ||
|
|
8d49c2d028 | ||
|
|
e560f6bc63 | ||
|
|
fbfbc5682a | ||
|
|
d4141bf7f1 | ||
|
|
6c81fa1ec5 | ||
|
|
24874b8286 | ||
|
|
b63664988f | ||
|
|
eeb00ac45b | ||
|
|
37e25f93d6 | ||
|
|
d58d65ebf0 | ||
|
|
adf2d3aff2 | ||
|
|
32064a23c1 | ||
|
|
c60b50b1ae | ||
|
|
f3ffdaf21f | ||
|
|
3aade67046 | ||
|
|
dc111bbec2 | ||
|
|
acd61a0e8e | ||
|
|
58590b71d1 | ||
|
|
66a1e8b737 | ||
|
|
a8568d7246 | ||
|
|
43a43c1e2b | ||
|
|
e08598e7e2 | ||
|
|
d301a79dcf | ||
|
|
98d76627a5 | ||
|
|
8a809013f3 | ||
|
|
485ed0b156 | ||
|
|
7d546f80f9 | ||
|
|
5dfdc15f93 | ||
|
|
a6e5873443 | ||
|
|
e2cf777538 | ||
|
|
9c61760713 | ||
|
|
5f86c6d404 | ||
|
|
6edc834143 | ||
|
|
b7dc3fae7c | ||
|
|
d84cd500bb | ||
|
|
5b456cadc4 | ||
|
|
4be80982a4 | ||
|
|
4d7f1f0c35 | ||
|
|
d3f097c7f1 | ||
|
|
a3d1b107f4 | ||
|
|
0ab6c176af | ||
|
|
5b0e8c6de0 | ||
|
|
67274c018d | ||
|
|
e89c421313 | ||
|
|
47d1d3c855 | ||
|
|
1628d801f9 | ||
|
|
1fb358249b | ||
|
|
b30a510b45 | ||
|
|
9f6af4f2cc | ||
|
|
60efdce5ff | ||
|
|
a68f2cb9fa | ||
|
|
5f5be823f3 | ||
|
|
03700ad37c | ||
|
|
6d01ee9284 | ||
|
|
cc3c1f31d0 | ||
|
|
5909502a13 | ||
|
|
88bbd847e0 | ||
|
|
34d14df297 | ||
|
|
bfc886cd54 | ||
|
|
8624d8c144 | ||
|
|
420582ec5e | ||
|
|
36207d9726 | ||
|
|
855d1bc5a1 | ||
|
|
081d15a830 | ||
|
|
d29d186d62 | ||
|
|
61f2ce67dd | ||
|
|
60dbf1bea0 | ||
|
|
58bb866e2d | ||
|
|
b2ec5d0f01 | ||
|
|
0c300bd4b4 | ||
|
|
53acb7bfcb | ||
|
|
65bbb0e0aa | ||
|
|
5147654f6c | ||
|
|
250b6a3d52 | ||
|
|
73ddbcc876 | ||
|
|
ce2b6dc84d | ||
|
|
7d16d8c887 | ||
|
|
1df5c5a76e | ||
|
|
52da387a1d | ||
|
|
c1221c5c87 | ||
|
|
befd669075 | ||
|
|
b6013a92e0 | ||
|
|
19af364400 | ||
|
|
3fd9a86f3c | ||
|
|
ce68701c0c | ||
|
|
6ea2cb3644 | ||
|
|
199c8aaa25 | ||
|
|
9ce6828d72 | ||
|
|
7ff5cf8372 | ||
|
|
eb771eaf0d | ||
|
|
6908555ed3 | ||
|
|
3890bc5a96 | ||
|
|
2c65f986d6 | ||
|
|
ea402b765c | ||
|
|
497e0669ff | ||
|
|
13ac74e0a2 | ||
|
|
c2f23d92dc | ||
|
|
7027da3cd3 | ||
|
|
005bb59797 | ||
|
|
88bc3a9271 | ||
|
|
2e32cf7b87 | ||
|
|
3ecf5fd442 | ||
|
|
3e9c3c8ae8 | ||
|
|
ec31e8df1d | ||
|
|
b56bfbae26 | ||
|
|
f55b1415d4 | ||
|
|
67693c6ad0 | ||
|
|
fce061b544 | ||
|
|
93765fcb30 | ||
|
|
b221bd7472 | ||
|
|
fd0a5a1116 | ||
|
|
47fa8c4cf6 | ||
|
|
7640609b41 | ||
|
|
e8e6357b73 | ||
|
|
4398101706 | ||
|
|
2e1481f49d | ||
|
|
c7c087a0d2 | ||
|
|
3461580b34 | ||
|
|
fcfdeac1c7 | ||
|
|
97f670658f | ||
|
|
4324fb2fbe | ||
|
|
e4cb74cf7b | ||
|
|
be137a191e | ||
|
|
fe1f3df36e | ||
|
|
4a330a4c33 | ||
|
|
75e60669a7 | ||
|
|
db379c6172 | ||
|
|
1da64fb79c | ||
|
|
8b42fd0a28 | ||
|
|
2c401f1102 | ||
|
|
d084950b1a | ||
|
|
2ce10f2fed | ||
|
|
036094799b | ||
|
|
2da6ab2a45 | ||
|
|
91a512606b | ||
|
|
b6d858f4d6 | ||
|
|
dedede3caa | ||
|
|
b14fc907f9 | ||
|
|
542bbb0889 | ||
|
|
714e69e708 | ||
|
|
cb87ed29d8 | ||
|
|
570c6765b0 | ||
|
|
12a2285ba5 | ||
|
|
1c023eac70 | ||
|
|
1e3f0650df | ||
|
|
1e9da09f62 | ||
|
|
5caf351c44 | ||
|
|
7d789a984a | ||
|
|
d921114832 | ||
|
|
39a1f03d5c | ||
|
|
c6a4a4edf1 | ||
|
|
45748a2bb0 | ||
|
|
9b13d862c1 | ||
|
|
590edc648a | ||
|
|
3326c87a88 | ||
|
|
0ec1863fcb | ||
|
|
2b67a14155 | ||
|
|
eac8caa4de | ||
|
|
61eb2aa328 | ||
|
|
a9847ebf54 | ||
|
|
4ca1089f60 | ||
|
|
926d4150c5 | ||
|
|
6f267adc14 | ||
|
|
0095e2d7d8 | ||
|
|
147f64e1fc | ||
|
|
b8e5932506 | ||
|
|
1ea04cd8cc | ||
|
|
b334643b68 | ||
|
|
6e6a0275b5 | ||
|
|
f5590806e0 | ||
|
|
f686e838fe | ||
|
|
ea8642dec9 | ||
|
|
eef5b58211 | ||
|
|
1de68b72b9 | ||
|
|
720df085e5 | ||
|
|
f90f17227b | ||
|
|
36f7eaadef | ||
|
|
1eb9300658 | ||
|
|
27e4656515 | ||
|
|
e0a09dbd69 | ||
|
|
30832ab33a | ||
|
|
d20b545a94 | ||
|
|
20d01be1ad | ||
|
|
d6b62d7512 | ||
|
|
ab9d9541a8 | ||
|
|
c3b8568560 | ||
|
|
8bd95a4eb1 | ||
|
|
2dac3ef58e | ||
|
|
86c7ab29f4 | ||
|
|
db89e5ec28 | ||
|
|
d096f75fb8 | ||
|
|
854424a758 | ||
|
|
fe5d0ce827 | ||
|
|
2fed3b5e5b | ||
|
|
1ecad094bd | ||
|
|
187cc573a7 | ||
|
|
0ead72a404 | ||
|
|
bbc5212436 | ||
|
|
c4f7740b80 | ||
|
|
6c239f7a00 | ||
|
|
7d5b859756 | ||
|
|
3e2e0d062b | ||
|
|
c45fe3517c | ||
|
|
d588da69e5 | ||
|
|
ec54a5c72c | ||
|
|
735a371249 | ||
|
|
5ab086e337 | ||
|
|
68f660dbcc | ||
|
|
0066f7a818 | ||
|
|
65059f2add | ||
|
|
23dff4f209 | ||
|
|
4a304bf34e | ||
|
|
36a6405e8b | ||
|
|
42c1fe963b | ||
|
|
465b154fc0 | ||
|
|
a0c4102b5a | ||
|
|
9420066895 | ||
|
|
74eac1d449 | ||
|
|
96676f8f3b | ||
|
|
93b51d56aa | ||
|
|
86c50574d2 | ||
|
|
efb528f979 | ||
|
|
edcd0b9913 | ||
|
|
55d1473918 | ||
|
|
0211c7f7f3 | ||
|
|
5913994169 | ||
|
|
26b1573cbe | ||
|
|
7fe07324d7 | ||
|
|
8e29430f21 | ||
|
|
326488aeeb | ||
|
|
cb86023bd7 | ||
|
|
bd2cb40424 | ||
|
|
e9a3ff0e70 | ||
|
|
5148e229e0 | ||
|
|
1ad21c27c9 | ||
|
|
f392e13077 | ||
|
|
3fe5b42b2b | ||
|
|
70c4b621cf | ||
|
|
a8df5e109b | ||
|
|
ba4f1da466 | ||
|
|
0bfbe6771e | ||
|
|
d1df0fec19 | ||
|
|
031ccce8b7 | ||
|
|
34eef0ed84 | ||
|
|
be068f360d | ||
|
|
5b18b66282 | ||
|
|
7b2283c28b | ||
|
|
c74e018359 | ||
|
|
4a120f8090 | ||
|
|
79b0f97a3f | ||
|
|
e3ef3e8d71 | ||
|
|
7574dfd339 | ||
|
|
a5b93008f5 | ||
|
|
0227af5bb7 | ||
|
|
192f4240e3 | ||
|
|
ef71df60f6 | ||
|
|
f52b3b4e04 | ||
|
|
7e4e32cfe0 | ||
|
|
9f8649884b | ||
|
|
f1ee4caddd | ||
|
|
051b8fbb31 | ||
|
|
b0ea32f660 | ||
|
|
8322ae5a4c | ||
|
|
98a7c62d7a | ||
|
|
859e59262e | ||
|
|
ec113420f1 | ||
|
|
1954e94de2 | ||
|
|
f6ec43b9ec | ||
|
|
6d0d8cf9cf | ||
|
|
14f669f4fb | ||
|
|
5ede02aed8 | ||
|
|
bbabb7a14c | ||
|
|
b13ebe3ddb | ||
|
|
b0199245d5 | ||
|
|
b93e3b2cf6 | ||
|
|
ae7fcf4c6b | ||
|
|
1607754771 | ||
|
|
028f659c40 | ||
|
|
8dfdacf128 | ||
|
|
f4a56f839f | ||
|
|
67a8eedca0 | ||
|
|
be65c7d5d0 | ||
|
|
7c5306a841 | ||
|
|
201210cfe1 | ||
|
|
cd6de3b24e | ||
|
|
dcd483bd99 | ||
|
|
3c5e4e2788 | ||
|
|
3f4f7b0a53 | ||
|
|
0a4b866d8a | ||
|
|
8c7d7dfa5b | ||
|
|
cdf615f783 | ||
|
|
7d96883d64 | ||
|
|
28c5e7e6a7 | ||
|
|
dbfc4abfd6 | ||
|
|
5544375002 | ||
|
|
1fd8d46064 | ||
|
|
46406d6cca | ||
|
|
196df1ccd5 | ||
|
|
d2358b42b6 | ||
|
|
e387d94ff1 | ||
|
|
3bb9c704de | ||
|
|
10537c5095 | ||
|
|
551ac56a33 | ||
|
|
5227582e90 | ||
|
|
42959982a9 | ||
|
|
78c73fb9e7 | ||
|
|
a06bf388d9 | ||
|
|
de0c3e717e | ||
|
|
1194998ce9 | ||
|
|
7171e23700 | ||
|
|
dee378b775 | ||
|
|
f76262ef79 | ||
|
|
6a755b0663 | ||
|
|
c40354bbcb | ||
|
|
c04aafb4e3 | ||
|
|
e31abe6d6b | ||
|
|
e1349ccadc | ||
|
|
8838bdc1e3 | ||
|
|
d6386bc80f | ||
|
|
a2c2288cd6 | ||
|
|
edef62df86 | ||
|
|
e2621d5e44 | ||
|
|
0e3ff12dd3 | ||
|
|
b335ac4156 | ||
|
|
03cf6591c0 | ||
|
|
2e0949d8e6 | ||
|
|
5a728a069e | ||
|
|
7384ec199e | ||
|
|
7bce6329e3 | ||
|
|
49619fbd77 | ||
|
|
fb9a2c5431 | ||
|
|
cd38aa3b2a | ||
|
|
daeb7ae949 | ||
|
|
82a79565de | ||
|
|
078839c711 | ||
|
|
90cc32f6f8 | ||
|
|
9aec2f019a | ||
|
|
5da455080b | ||
|
|
17558102f2 | ||
|
|
e1c39f3fdc | ||
|
|
20555c8e37 | ||
|
|
300a619991 | ||
|
|
4319dedb23 | ||
|
|
f8bb66b4e0 | ||
|
|
5d6a8b3840 | ||
|
|
6a8c2848f6 | ||
|
|
6439727afc | ||
|
|
27b0a581a6 | ||
|
|
15a54230f1 | ||
|
|
f0d184884a | ||
|
|
8fca04f140 | ||
|
|
3b2b5edd26 | ||
|
|
5bd1fbb0d6 | ||
|
|
0772e571b7 | ||
|
|
910496cea9 | ||
|
|
739e1da279 | ||
|
|
08b4a7aaf2 | ||
|
|
1f0770ca55 | ||
|
|
505d0bfa51 | ||
|
|
860d13c7d8 | ||
|
|
76d77af0f0 | ||
|
|
ea8ab4ddf2 | ||
|
|
4bcc38c749 | ||
|
|
5becffbba5 | ||
|
|
d0194a6fb3 | ||
|
|
e45d13d469 | ||
|
|
a431274b32 | ||
|
|
994c9a01e3 | ||
|
|
ad1d5e8248 | ||
|
|
b2670eaba5 | ||
|
|
54aff33118 | ||
|
|
499e053d58 | ||
|
|
9f33c6fe03 | ||
|
|
73e69edac3 | ||
|
|
4c4fa68268 | ||
|
|
43d2fd73ab | ||
|
|
71f1ec0bc8 | ||
|
|
99f4bce112 | ||
|
|
6b77ee9a5e | ||
|
|
25fa3ccade | ||
|
|
c6a95395b5 | ||
|
|
cb3042ffb2 | ||
|
|
d293aaf945 | ||
|
|
1d559bf00c | ||
|
|
4286f55c52 | ||
|
|
0a7cad9074 | ||
|
|
069a7fe71e | ||
|
|
9c8a45854a | ||
|
|
7d035edf9d | ||
|
|
36899dba0b | ||
|
|
6a31446671 | ||
|
|
451fbbcea1 | ||
|
|
a17a481e30 | ||
|
|
5f9d4a02a5 | ||
|
|
7094d88958 | ||
|
|
8ac73a9eba | ||
|
|
86a06a7acc | ||
|
|
d05c3f4e4d | ||
|
|
de178e90f4 | ||
|
|
3d960b5e55 | ||
|
|
39dc83bd82 | ||
|
|
503063cddc | ||
|
|
914df18bf9 | ||
|
|
a539094c06 | ||
|
|
cd3ed720e0 | ||
|
|
37c27fa606 | ||
|
|
093ca5d492 | ||
|
|
1d24dd3067 | ||
|
|
b9659ba0c0 | ||
|
|
b6af7abb1a | ||
|
|
edee8a3446 | ||
|
|
5582367d68 | ||
|
|
7a55ab6acc | ||
|
|
6246d36fe6 | ||
|
|
fbc4bb29dc | ||
|
|
7ba7ce3af7 | ||
|
|
087fcc4e6e | ||
|
|
520c520512 | ||
|
|
a6910313b4 | ||
|
|
2f32df1f09 | ||
|
|
23adf50194 | ||
|
|
0691ecc052 | ||
|
|
d917f44b5b | ||
|
|
602bb7170a | ||
|
|
75582d47b9 | ||
|
|
28fdf1e9ed | ||
|
|
9a8a3beae4 | ||
|
|
2a774a1fea | ||
|
|
b13b023c6b | ||
|
|
b652ad9568 | ||
|
|
624e679e35 | ||
|
|
618704f504 | ||
|
|
3b3ec402d6 | ||
|
|
2b3c1d640e | ||
|
|
f70b4e02c4 | ||
|
|
7d579e7400 | ||
|
|
e0f777d4eb | ||
|
|
febd1ad09c | ||
|
|
1040b85785 | ||
|
|
e2c81aa9ea | ||
|
|
e4a147218b | ||
|
|
4b2b89eb5e | ||
|
|
4b2bb88375 | ||
|
|
fb01e41e8a | ||
|
|
ff9759c09d | ||
|
|
a92e0e8540 | ||
|
|
9d47b220a4 | ||
|
|
c582a9faae | ||
|
|
cf483107c9 | ||
|
|
b57e2f5521 | ||
|
|
bf3ced6a34 | ||
|
|
390e830994 | ||
|
|
44c60567dd | ||
|
|
967d81b782 | ||
|
|
20199e770c | ||
|
|
4c824e5309 | ||
|
|
981bc85879 | ||
|
|
015527d870 | ||
|
|
6464b4b372 | ||
|
|
fef9747fbf | ||
|
|
13816c1c7d | ||
|
|
c54a920d13 | ||
|
|
83f8eeec44 | ||
|
|
b83fbad6a1 | ||
|
|
ec20784046 | ||
|
|
42ad753e39 | ||
|
|
1ccd2a7b11 | ||
|
|
4c1d29c86c | ||
|
|
0db7a0c9e2 | ||
|
|
13f6b1b344 | ||
|
|
593d82c6a9 | ||
|
|
43dccbd45d | ||
|
|
0ff4350352 | ||
|
|
5fd2b7cc79 | ||
|
|
7e16ac305d | ||
|
|
59a8836924 | ||
|
|
9d4020501c | ||
|
|
81350d65bc | ||
|
|
02642a64fd | ||
|
|
3c41e9f022 | ||
|
|
2670e13cbd | ||
|
|
49784513b1 | ||
|
|
523051132d | ||
|
|
55e6629fb4 | ||
|
|
b6251c6968 | ||
|
|
c51fe089ba | ||
|
|
fee9f1482c | ||
|
|
ae67f44c6e | ||
|
|
54dd1ad09b | ||
|
|
e2a74051dc | ||
|
|
b7e035b6f3 | ||
|
|
890f1f5928 | ||
|
|
b30c37eb79 | ||
|
|
b08cb148ae | ||
|
|
034bb13e1c | ||
|
|
6657801fb1 | ||
|
|
a199366157 | ||
|
|
2a6d5583d1 | ||
|
|
ddabe1a6df | ||
|
|
e7b47ce335 | ||
|
|
ab05b70423 | ||
|
|
b177bffa6a | ||
|
|
b4b468eb27 | ||
|
|
bd50a0d2ef | ||
|
|
9256e748c8 | ||
|
|
af033c0d1d | ||
|
|
e96513c8db | ||
|
|
da9657aac4 | ||
|
|
2886766fb5 | ||
|
|
6e7f866288 | ||
|
|
6fa403edd9 | ||
|
|
431eb7bc8c | ||
|
|
9df4853e23 | ||
|
|
18c4ef09d5 | ||
|
|
bc93c7a1fc | ||
|
|
c8a2a557db | ||
|
|
9f827c99cb | ||
|
|
7b2b965415 | ||
|
|
c3cfa18ebe | ||
|
|
b46835e15e | ||
|
|
3e5ce3c92c | ||
|
|
e5c9b4cd75 | ||
|
|
8753e558f2 | ||
|
|
f6691579de | ||
|
|
cfc152d979 | ||
|
|
513212c5e8 | ||
|
|
99a447dff5 | ||
|
|
56a9bf459d | ||
|
|
11dbba3503 | ||
|
|
8662427d48 | ||
|
|
821480d329 | ||
|
|
5ce93d6fa8 | ||
|
|
20a5ef2798 | ||
|
|
735eabb066 | ||
|
|
412ff762bb | ||
|
|
44bbf42a9f | ||
|
|
030f87c90c | ||
|
|
ae941a7665 | ||
|
|
4d563e08e1 | ||
|
|
8a81b986c0 | ||
|
|
a6e62479be | ||
|
|
6c825064ea | ||
|
|
13d02968bd | ||
|
|
e576556149 | ||
|
|
66e74900df | ||
|
|
aadc735d71 | ||
|
|
a13897cf6f | ||
|
|
b188ae0e5c | ||
|
|
c196710fae | ||
|
|
e4f62483ff | ||
|
|
8d9347edc5 | ||
|
|
eff821c1ca | ||
|
|
3bcd6ecbad | ||
|
|
e76f4c2ae9 | ||
|
|
f46ac45d69 | ||
|
|
1d1259a86d | ||
|
|
101f08ca75 | ||
|
|
3b7f9827ab | ||
|
|
f98bf39005 | ||
|
|
9e7df54ccd | ||
|
|
db23c2f27b | ||
|
|
9744f437d8 | ||
|
|
01f84b0e53 | ||
|
|
5dbdd36263 | ||
|
|
96b557c1f0 | ||
|
|
ebdb7c8de2 | ||
|
|
1fda842ee6 | ||
|
|
f71e20d0ce | ||
|
|
988680de33 | ||
|
|
cdf92c6300 | ||
|
|
be5b726c0a | ||
|
|
3491218915 | ||
|
|
d0f6131ba4 | ||
|
|
9cc37bdea2 | ||
|
|
3f754fd350 | ||
|
|
91438b6540 | ||
|
|
987c505906 | ||
|
|
598bb93cc2 | ||
|
|
dc531b64ae | ||
|
|
91d4b5cfed | ||
|
|
c24b8460e0 | ||
|
|
2e471daef1 | ||
|
|
7ae57a3531 | ||
|
|
11f36c0bd6 | ||
|
|
fd520eeed2 | ||
|
|
30a5dd267b | ||
|
|
2f0d683378 | ||
|
|
a1309a90ac | ||
|
|
010855a294 | ||
|
|
71ed3ff992 | ||
|
|
d4266d0063 | ||
|
|
8225064aab | ||
|
|
e5ee357903 | ||
|
|
8aef518c05 | ||
|
|
309ed77ef4 | ||
|
|
9a6d2b791f | ||
|
|
2a5010a426 | ||
|
|
be29da46f8 | ||
|
|
d0734e27ba | ||
|
|
732f6aaa30 | ||
|
|
dd422c7b8b | ||
|
|
c8f7a859ea | ||
|
|
28a2d41b85 | ||
|
|
7e76656a18 | ||
|
|
0b93f52ba4 | ||
|
|
aa9c6062b0 | ||
|
|
95637fd153 | ||
|
|
5ac72211cd | ||
|
|
94525d3952 | ||
|
|
7f9a2f8adb | ||
|
|
cd0e92878f | ||
|
|
9033f07724 | ||
|
|
b7d0890bc0 | ||
|
|
b2b079a26b | ||
|
|
b886dfae4d | ||
|
|
902fbb3347 | ||
|
|
9f16c798d0 | ||
|
|
318f80d113 | ||
|
|
9df8b32f10 | ||
|
|
6f37f5752b | ||
|
|
9d0a71f245 | ||
|
|
ff1b435232 | ||
|
|
b57a272f67 | ||
|
|
ef79647e85 | ||
|
|
d3fd89552f | ||
|
|
6d43e70a93 | ||
|
|
e8333316ee | ||
|
|
85edcb858d | ||
|
|
bab5f1a93f | ||
|
|
6de8303df8 | ||
|
|
33b4114534 | ||
|
|
7a4457402f | ||
|
|
9056dcaf7d | ||
|
|
2119e4fd3e | ||
|
|
bcd5190f1d | ||
|
|
d705a92e43 | ||
|
|
614b3634d4 | ||
|
|
b234f4307f | ||
|
|
e38c213ee0 | ||
|
|
699f41e114 | ||
|
|
424e1363ed | ||
|
|
7484bc31b4 | ||
|
|
5a495cc165 | ||
|
|
9ff4717738 | ||
|
|
0c1740982d | ||
|
|
3c7c0515d8 | ||
|
|
56cb92fdaf | ||
|
|
c00b6ff999 | ||
|
|
df5cc3f0f6 | ||
|
|
eb0ff32efb | ||
|
|
cf0120e8e0 | ||
|
|
1f47dc990d | ||
|
|
9a5bcc6db0 | ||
|
|
492b20a89d | ||
|
|
fcfc8bacc0 | ||
|
|
0800d9427c | ||
|
|
4e113a7086 | ||
|
|
39f422ded8 | ||
|
|
d2cdaa041c | ||
|
|
d84dae488e | ||
|
|
79e75bfbb9 | ||
|
|
73b15c1bee | ||
|
|
b180604422 | ||
|
|
fab12ef241 | ||
|
|
917881aa48 | ||
|
|
9259e989a4 | ||
|
|
da90f484aa | ||
|
|
817e912025 | ||
|
|
7f83d38bca | ||
|
|
54de8b8e77 | ||
|
|
796956970e | ||
|
|
c0020142da | ||
|
|
ee6eea95af | ||
|
|
a257504ba4 | ||
|
|
fb0dbce15b | ||
|
|
8333551331 | ||
|
|
292d794806 | ||
|
|
91ce76af9d | ||
|
|
33bd9e80bb | ||
|
|
d310f3e9b7 | ||
|
|
8c832f4c50 | ||
|
|
31bad5f7af | ||
|
|
1cf7f3d87c | ||
|
|
9c9a9ccd5c | ||
|
|
7381236de6 | ||
|
|
fe9ffcb9d2 | ||
|
|
bea5681fd8 | ||
|
|
e11229494e | ||
|
|
ccc0fcb5b7 | ||
|
|
6e24381962 | ||
|
|
3ab905644d | ||
|
|
f46d545307 | ||
|
|
8134b0073b | ||
|
|
6ab19c7ef2 | ||
|
|
d22361f7c7 | ||
|
|
06c7e55188 | ||
|
|
b3eb8489f3 | ||
|
|
5431fca99b | ||
|
|
47c9d6ac64 | ||
|
|
d0157af13e | ||
|
|
fc04620519 | ||
|
|
d4ee165253 | ||
|
|
4f7f577a57 | ||
|
|
612def5c11 | ||
|
|
704825be96 | ||
|
|
b8be7ec90e | ||
|
|
a3d71f4b91 | ||
|
|
9250819b75 | ||
|
|
04738636ca | ||
|
|
33f67d418f | ||
|
|
07d1b3780d | ||
|
|
27d68d8fdd | ||
|
|
546b773b21 | ||
|
|
15dcaeda0f | ||
|
|
8f42ba13ef | ||
|
|
5990017d51 | ||
|
|
3197c0fd7d | ||
|
|
4580c685f1 | ||
|
|
67232453d4 | ||
|
|
b4cce80727 | ||
|
|
89a2e5ded3 | ||
|
|
9d6b4f46d4 | ||
|
|
a4019cb6aa | ||
|
|
d29bdf3e81 | ||
|
|
501a4af914 | ||
|
|
dad7d7e798 | ||
|
|
4b94ae8040 | ||
|
|
b04679b429 | ||
|
|
19358d1c42 | ||
|
|
8679074be7 | ||
|
|
ba09e22c30 | ||
|
|
6515b9727d | ||
|
|
4af8e5bdb5 | ||
|
|
2db8cf477b | ||
|
|
3cfefa53f7 | ||
|
|
bce89feb13 | ||
|
|
88f5220acf | ||
|
|
3e87ac75a1 | ||
|
|
9237f2a80c | ||
|
|
61aca389c4 | ||
|
|
80438c4876 | ||
|
|
70ac4fa96b | ||
|
|
6e2b348758 | ||
|
|
5ed5d7fe60 | ||
|
|
613dd67784 | ||
|
|
58683f02ec | ||
|
|
7cb82fe8f3 | ||
|
|
0494779ecb | ||
|
|
0500990d23 | ||
|
|
22a82f1eaa | ||
|
|
13b04dc908 | ||
|
|
011106b517 | ||
|
|
7467b85019 | ||
|
|
7dea615f74 | ||
|
|
3010d182fc | ||
|
|
a72a02f0f2 | ||
|
|
614df96382 | ||
|
|
669d7a6feb | ||
|
|
d600b937f1 | ||
|
|
ae713cb099 | ||
|
|
979f1b6c39 | ||
|
|
1fa1790da5 | ||
|
|
dd29e6e475 | ||
|
|
ae4b30a697 | ||
|
|
353299168a | ||
|
|
a50b2c3b85 | ||
|
|
ebecee3d85 | ||
|
|
194f733ca7 | ||
|
|
3907ddbcc4 | ||
|
|
e616be0a42 | ||
|
|
5eef146871 | ||
|
|
2e65686fc0 | ||
|
|
e5847f1ddf | ||
|
|
86d05e98e5 | ||
|
|
cdd2d4cc1d | ||
|
|
3bcabad28c | ||
|
|
c629ac7168 | ||
|
|
0195d5590f | ||
|
|
e7bebb0089 | ||
|
|
7b05df8d33 | ||
|
|
a8db9ae304 | ||
|
|
e6e9b2041e | ||
|
|
77c747a8fd | ||
|
|
907fb257cd | ||
|
|
60bd60db03 | ||
|
|
0fcc28a108 | ||
|
|
ab8005f03e | ||
|
|
5e8f578e78 | ||
|
|
a4b1633e11 | ||
|
|
fea211a109 | ||
|
|
59e4f1ee0f | ||
|
|
86a0a42a8d | ||
|
|
662842126d | ||
|
|
66e3801b1e | ||
|
|
a30cf60422 | ||
|
|
c2b8b818c7 | ||
|
|
4284b0e2b8 | ||
|
|
9def9b35b9 | ||
|
|
377a2860cc | ||
|
|
0a3a5a7c65 | ||
|
|
c5996c0593 | ||
|
|
cde5a07981 | ||
|
|
4faef28cc5 | ||
|
|
89b900432e | ||
|
|
8bb9d0960b | ||
|
|
59181ac5fb | ||
|
|
2a831fa547 | ||
|
|
4abadc890e | ||
|
|
b0ce551523 | ||
|
|
8b0269c264 | ||
|
|
d68772d45a | ||
|
|
52cb425e33 | ||
|
|
ed3220f37f | ||
|
|
043cbec68f | ||
|
|
7d7217ef89 | ||
|
|
67c709170d | ||
|
|
f6e428ac22 | ||
|
|
45fbafae94 | ||
|
|
803b73a34b | ||
|
|
b1512201ab | ||
|
|
424e9cbc43 | ||
|
|
95b62a843a | ||
|
|
ccb4f44caf | ||
|
|
c788c76dc9 | ||
|
|
2e4e1c7f48 | ||
|
|
f85d4d28d1 | ||
|
|
b4e4bdcda9 | ||
|
|
dae8b78569 | ||
|
|
e26d49efb7 | ||
|
|
e9e853b19a | ||
|
|
e48ea5f23a | ||
|
|
a99bab935a | ||
|
|
3eee35e1f7 | ||
|
|
c7396b0675 | ||
|
|
e3ee60e7af | ||
|
|
05b8ddac4c | ||
|
|
668724de4e | ||
|
|
71ce1a25dd | ||
|
|
cd522f524d | ||
|
|
ca559b1db6 | ||
|
|
a8e76fb345 | ||
|
|
1d445d1039 | ||
|
|
29d03ab937 | ||
|
|
46aa4d2f91 | ||
|
|
d0b4bd08e1 | ||
|
|
512e81c629 | ||
|
|
452666f742 | ||
|
|
72008d951b | ||
|
|
72146e7800 | ||
|
|
f7af1bb8e2 | ||
|
|
f88f1fca3f | ||
|
|
26e4a40cc7 | ||
|
|
8b1931072a | ||
|
|
45e15b6cc6 | ||
|
|
be7e52c882 | ||
|
|
4162ce0bc5 | ||
|
|
7e46277016 | ||
|
|
3b84b99804 | ||
|
|
1786f9b1bb | ||
|
|
1e972174a6 | ||
|
|
77178e0590 | ||
|
|
9a909d9f27 | ||
|
|
90d25a40a0 | ||
|
|
c335f18be7 | ||
|
|
7dc3e73782 | ||
|
|
47dffe66aa | ||
|
|
6636c69a11 | ||
|
|
0ccaf4a1ff | ||
|
|
5cdbad7937 | ||
|
|
fc0508c047 | ||
|
|
78ca5491e6 | ||
|
|
4146475c73 | ||
|
|
329c3ab21b | ||
|
|
3b7f6641d2 | ||
|
|
781487c4dd | ||
|
|
5ba5bc8ba1 | ||
|
|
82c66ce078 | ||
|
|
9324fbf921 | ||
|
|
5e081de14a | ||
|
|
d1456ae039 | ||
|
|
115af4f565 | ||
|
|
822724d1aa | ||
|
|
87c9856b20 | ||
|
|
835136dcd3 | ||
|
|
4a80e9cb25 | ||
|
|
de80c270bd | ||
|
|
b92bff2658 | ||
|
|
42f1e26540 | ||
|
|
cfd056231b | ||
|
|
b1c7649edb | ||
|
|
853740f1e2 | ||
|
|
14986b153a | ||
|
|
9e503b21c1 | ||
|
|
67a958a326 | ||
|
|
3850716522 | ||
|
|
1e0a60e73d | ||
|
|
e9c99e0518 | ||
|
|
332baa4f67 | ||
|
|
08879d2a20 | ||
|
|
1292af4768 | ||
|
|
4d88a099f9 | ||
|
|
777e15bd78 | ||
|
|
f689e28958 | ||
|
|
d184231169 | ||
|
|
7225e919fc | ||
|
|
7a185f1ead | ||
|
|
c1fa5279f4 | ||
|
|
4f0fe66f69 | ||
|
|
76380b2b45 | ||
|
|
67b7d46432 | ||
|
|
29453ba196 | ||
|
|
599d77643b | ||
|
|
09d87d5ef1 | ||
|
|
2f3f075e4f | ||
|
|
17097d96b7 | ||
|
|
a3e28c2d1a | ||
|
|
03a97d87ea | ||
|
|
8cbf099054 | ||
|
|
c287452255 | ||
|
|
07ce915c66 | ||
|
|
73f58c57e8 | ||
|
|
43348a3e13 | ||
|
|
e716b1f4d7 | ||
|
|
82e74a4ebd | ||
|
|
16b260e371 | ||
|
|
3102e05da4 | ||
|
|
df4af2b550 | ||
|
|
97132e3d38 | ||
|
|
5ad1fe77b1 | ||
|
|
8d4ed1e988 | ||
|
|
add953fb6e | ||
|
|
3854211694 | ||
|
|
58ac72f79d | ||
|
|
6d5904801e | ||
|
|
d4993c405e | ||
|
|
7af8e3937f | ||
|
|
f8eeded528 | ||
|
|
c3fa7e13cf | ||
|
|
5c18b0a94d | ||
|
|
ecbad638f1 | ||
|
|
611ce6e756 | ||
|
|
4140e9b857 | ||
|
|
8fd9d91974 | ||
|
|
d3f35dab1e | ||
|
|
487e2618cd | ||
|
|
30d5186db4 | ||
|
|
cbe59714d4 | ||
|
|
704a28ca17 | ||
|
|
8d70d10aba | ||
|
|
ddd8b16f2b | ||
|
|
b79ce77ec5 | ||
|
|
fead4bbfd9 | ||
|
|
872ecc1aed |
82
.gitignore
vendored
82
.gitignore
vendored
@@ -1,88 +1,8 @@
|
|||||||
*.Plo
|
|
||||||
*.Po
|
|
||||||
*.a
|
|
||||||
*.d
|
|
||||||
*.la
|
|
||||||
*.lo
|
|
||||||
*.o
|
|
||||||
*.exe
|
|
||||||
|
|
||||||
*~
|
*~
|
||||||
|
|
||||||
.#*
|
.#*
|
||||||
.stgit*
|
.stgit*
|
||||||
.deps
|
|
||||||
.dirstamp
|
|
||||||
|
|
||||||
tags
|
/output/
|
||||||
|
|
||||||
/Makefile
|
|
||||||
/Makefile.in
|
|
||||||
/aclocal.m4
|
|
||||||
/autom4te.cache
|
|
||||||
/config.h
|
|
||||||
/config.h.in
|
|
||||||
/config.log
|
|
||||||
/config.mk
|
|
||||||
/config.status
|
|
||||||
/config_detected.h
|
|
||||||
/config_detected.mk
|
|
||||||
/configure
|
|
||||||
/configure.lineno
|
|
||||||
/depmode
|
|
||||||
/libtool
|
|
||||||
/ltmain.sh
|
|
||||||
/mkinstalldirs
|
|
||||||
/build
|
|
||||||
/src/mpd
|
|
||||||
/systemd/system/mpd.service
|
|
||||||
/systemd/user/mpd.service
|
|
||||||
/stamp-h1
|
|
||||||
|
|
||||||
/src/dsd2pcm/dsd2pcm
|
|
||||||
/src/win32/mpd_win32_rc.rc
|
|
||||||
|
|
||||||
/doc/doxygen.conf
|
|
||||||
/doc/protocol.html
|
|
||||||
/doc/protocol
|
|
||||||
/doc/user
|
|
||||||
/doc/developer
|
|
||||||
/doc/sticker
|
|
||||||
/doc/api
|
|
||||||
|
|
||||||
/test/software_volume
|
|
||||||
/test/run_convert
|
|
||||||
/test/run_decoder
|
|
||||||
/test/read_tags
|
|
||||||
/test/run_filter
|
|
||||||
/test/run_encoder
|
|
||||||
/test/run_output
|
|
||||||
/test/read_conf
|
|
||||||
/test/run_input
|
|
||||||
/test/read_mixer
|
|
||||||
/test/dump_playlist
|
|
||||||
/test/run_normalize
|
|
||||||
/test/tmp
|
|
||||||
/test/run_inotify
|
|
||||||
/test/test_queue_priority
|
|
||||||
/test/test_protocol
|
|
||||||
/test/run_ntp_server
|
|
||||||
/test/run_resolver
|
|
||||||
/test/run_tcp_connect
|
|
||||||
/test/test_pcm
|
|
||||||
/test/dump_rva2
|
|
||||||
/test/dump_text_file
|
|
||||||
/test/test_util
|
|
||||||
/test/test_byte_reverse
|
|
||||||
/test/test_mixramp
|
|
||||||
/test/test_vorbis_encoder
|
|
||||||
/test/DumpDatabase
|
|
||||||
|
|
||||||
/lib/
|
|
||||||
|
|
||||||
/*.tar.gz
|
|
||||||
/*.tar.bz2
|
|
||||||
/*.tar.xz
|
|
||||||
/mpd-*/
|
|
||||||
|
|
||||||
__pycache__/
|
__pycache__/
|
||||||
|
|||||||
92
.travis.yml
92
.travis.yml
@@ -1,36 +1,82 @@
|
|||||||
dist: trusty
|
|
||||||
language: cpp
|
language: cpp
|
||||||
|
|
||||||
addons:
|
matrix:
|
||||||
apt:
|
include:
|
||||||
packages:
|
- os: linux
|
||||||
- libcppunit-dev
|
dist: trusty
|
||||||
- libboost-dev
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- sourceline: 'ppa:saiarcot895/chromium-dev' # for ninja-build
|
||||||
|
- sourceline: 'ppa:deadsnakes/ppa' # for Python 3.7 (required by Meson)
|
||||||
|
packages:
|
||||||
|
- g++-6
|
||||||
|
- libgtest-dev
|
||||||
|
- boost1.67
|
||||||
|
- python3.6
|
||||||
|
- python3-urllib3
|
||||||
|
- ninja-build
|
||||||
|
before_install:
|
||||||
|
- wget https://bootstrap.pypa.io/get-pip.py
|
||||||
|
- /usr/bin/python3.6 get-pip.py --user
|
||||||
|
install:
|
||||||
|
- /usr/bin/python3.6 $HOME/.local/bin/pip install --user meson
|
||||||
|
env:
|
||||||
|
# use gold as workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=17068
|
||||||
|
- MATRIX_EVAL="export CC=gcc-6 CXX=g++-6 LDFLAGS=-fuse-ld=gold PATH=$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
os:
|
- os: linux
|
||||||
- linux
|
dist: trusty
|
||||||
- osx
|
addons:
|
||||||
|
apt:
|
||||||
|
sources:
|
||||||
|
- ubuntu-toolchain-r-test
|
||||||
|
- sourceline: 'ppa:mhier/libboost-latest'
|
||||||
|
- sourceline: 'ppa:saiarcot895/chromium-dev' # for ninja-build
|
||||||
|
- sourceline: 'ppa:deadsnakes/ppa' # for Python 3.7 (required by Meson)
|
||||||
|
packages:
|
||||||
|
- g++-8
|
||||||
|
- libgtest-dev
|
||||||
|
- boost1.67
|
||||||
|
- python3.6
|
||||||
|
- python3-urllib3
|
||||||
|
- ninja-build
|
||||||
|
before_install:
|
||||||
|
- wget https://bootstrap.pypa.io/get-pip.py
|
||||||
|
- /usr/bin/python3.6 get-pip.py --user
|
||||||
|
install:
|
||||||
|
- /usr/bin/python3.6 $HOME/.local/bin/pip install --user meson
|
||||||
|
env:
|
||||||
|
# use gold as workaround for https://sourceware.org/bugzilla/show_bug.cgi?id=17068
|
||||||
|
- MATRIX_EVAL="export CC=gcc-8 CXX=g++-8 LDFLAGS=-fuse-ld=gold PATH=$HOME/.local/bin:$PATH"
|
||||||
|
|
||||||
env:
|
- os: osx
|
||||||
global:
|
osx_image: xcode9.3beta
|
||||||
- MAKEFLAGS="-j2"
|
env:
|
||||||
|
- MATRIX_EVAL=""
|
||||||
|
|
||||||
|
cache:
|
||||||
|
- apt
|
||||||
|
- ccache
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
|
- eval "${MATRIX_EVAL}"
|
||||||
# C++14
|
# C++14
|
||||||
- test "$TRAVIS_OS_NAME" != "linux" || sudo add-apt-repository -y ppa:ubuntu-toolchain-r/test
|
|
||||||
- test "$TRAVIS_OS_NAME" != "linux" || sudo apt-get update -qq
|
|
||||||
- test "$TRAVIS_OS_NAME" != "osx" || brew update
|
- test "$TRAVIS_OS_NAME" != "osx" || brew update
|
||||||
|
|
||||||
install:
|
install:
|
||||||
# C++14
|
# C++14
|
||||||
- test "$TRAVIS_OS_NAME" != "linux" || sudo apt-get install -qq g++-5
|
- test "$TRAVIS_OS_NAME" != "osx" || brew install ccache meson
|
||||||
- test "$TRAVIS_OS_NAME" != "osx" || brew install cppunit
|
- test "$TRAVIS_OS_NAME" != "osx" || brew install --HEAD https://gist.githubusercontent.com/Kronuz/96ac10fbd8472eb1e7566d740c4034f8/raw/gtest.rb
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- ccache -s
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- OPTIONS="--enable-test"
|
- eval "${MATRIX_EVAL}"
|
||||||
- test "$TRAVIS_OS_NAME" != "linux" || export CC=gcc-5 CXX=g++-5
|
- OPTIONS="-Dtest=true"
|
||||||
- test "$TRAVIS_OS_NAME" != "osx" || OPTIONS="$OPTIONS --enable-osx"
|
- meson . output --werror $OPTIONS
|
||||||
- ./autogen.sh
|
- ninja -C output -v test
|
||||||
- ./configure --disable-silent-rules --disable-dependency-tracking $OPTIONS
|
- ccache -s
|
||||||
- make
|
|
||||||
- make check
|
|
||||||
|
|||||||
13
AUTHORS
13
AUTHORS
@@ -1,5 +1,5 @@
|
|||||||
Music Player Daemon - http://www.musicpd.org
|
Music Player Daemon - http://www.musicpd.org
|
||||||
Copyright 2003-2017 The Music Player Daemon Project
|
Copyright 2003-2018 The Music Player Daemon Project
|
||||||
|
|
||||||
The following people have contributed code to MPD:
|
The following people have contributed code to MPD:
|
||||||
|
|
||||||
@@ -36,3 +36,14 @@ The following people have contributed code to MPD:
|
|||||||
François Revol <revol@free.fr>
|
François Revol <revol@free.fr>
|
||||||
Jacob Vosmaer <contact@jacobvosmaer.nl>
|
Jacob Vosmaer <contact@jacobvosmaer.nl>
|
||||||
Thomas Guillem <thomas@gllm.fr>
|
Thomas Guillem <thomas@gllm.fr>
|
||||||
|
Andrew Basterfield <abasterfield@gmail.com>
|
||||||
|
Bart Nagel <bart@tremby.net>
|
||||||
|
Christian Kröner <ckroener@gmx.net>
|
||||||
|
Christopher Zimmermann <madroach@gmerlin.de>
|
||||||
|
John Regan <john@jrjrtech.com>
|
||||||
|
Joshua Wise <joshua@joshuawise.com>
|
||||||
|
Ryan Walklin
|
||||||
|
Stefan Roellin <stefan@roellin-baumann.ch>
|
||||||
|
Stefano Miccoli <stefano.miccoli@polimi.it>
|
||||||
|
Steven O'Brien <steven_obrien1@yahoo.co.uk>
|
||||||
|
Thomas Zander <thomas.e.zander@googlemail.com>
|
||||||
|
|||||||
2499
Makefile.am
2499
Makefile.am
File diff suppressed because it is too large
Load Diff
102
NEWS
102
NEWS
@@ -1,3 +1,105 @@
|
|||||||
|
ver 0.21.4 (2019/01/04)
|
||||||
|
* database
|
||||||
|
- inotify: fix crash bug "terminate called after throwing ..."
|
||||||
|
- upnp: implement "list ... group"
|
||||||
|
* output
|
||||||
|
- httpd: declare protocol "HTTP/1.1" instead of "ICY"
|
||||||
|
* remove libwrap support
|
||||||
|
* Windows
|
||||||
|
- fix "Failed to accept connection: unknown error"
|
||||||
|
* fix Haiku build
|
||||||
|
|
||||||
|
ver 0.21.3 (2018/11/16)
|
||||||
|
* output
|
||||||
|
- alsa: fix crash bug
|
||||||
|
- alsa: fix stuttering at start of playback
|
||||||
|
- alsa: fix discarded samples at end of song
|
||||||
|
- alsa: clear error after reopening device
|
||||||
|
* log: default to journal if MPD was started as systemd service
|
||||||
|
|
||||||
|
ver 0.21.2 (2018/11/12)
|
||||||
|
* protocol
|
||||||
|
- operator "=~" matches a regular expression
|
||||||
|
- operator "contains" matches substrings
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: require FFmpeg 3.1 or later
|
||||||
|
- ffmpeg: fix broken sound with certain codecs
|
||||||
|
* output
|
||||||
|
- alsa: fix high CPU usage with dmix
|
||||||
|
- httpd: fix three crash bugs
|
||||||
|
* mixer
|
||||||
|
- alsa: fix more rounding errors
|
||||||
|
* fix zlib support
|
||||||
|
|
||||||
|
ver 0.21.1 (2018/11/04)
|
||||||
|
* protocol
|
||||||
|
- allow escaping quotes in filter expressions
|
||||||
|
- operator "==" never searches substrings in filter expressions
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: fix build failure with non-standard FFmpeg installation path
|
||||||
|
- flac: fix linker failure when building without FLAC support
|
||||||
|
* encoder
|
||||||
|
- vorbis: fix linker failure when building without Vorbis decoder
|
||||||
|
* fix build failure on Linux-PowerPC
|
||||||
|
* fix build failure on FreeBSD
|
||||||
|
* eliminate DLL dependencies on Windows
|
||||||
|
* add warning about buggy Boost version 1.67
|
||||||
|
* require Meson 0.47.2 because a Meson 0.47.1 bug breaks our build
|
||||||
|
|
||||||
|
ver 0.21 (2018/10/31)
|
||||||
|
* configuration
|
||||||
|
- add "include" directive, allows including config files
|
||||||
|
- incremental "metadata_to_use" setting
|
||||||
|
* protocol
|
||||||
|
- "tagtypes" can be used to hide tags
|
||||||
|
- "find" and "search" can sort
|
||||||
|
- "outputs" prints the plugin name
|
||||||
|
- "outputset" sets runtime attributes
|
||||||
|
- close connection when client sends HTTP request
|
||||||
|
- new filter syntax for "find"/"search" etc. with negation
|
||||||
|
* database
|
||||||
|
- simple: scan audio formats
|
||||||
|
- proxy: require libmpdclient 2.9
|
||||||
|
- proxy: forward `sort` and `window` to server
|
||||||
|
* player
|
||||||
|
- hard-code "buffer_before_play" to 1 second, independent of audio format
|
||||||
|
- "one-shot" single mode
|
||||||
|
* input
|
||||||
|
- curl: download to buffer instead of throttling transfer
|
||||||
|
- qobuz: new plugin to play Qobuz streams
|
||||||
|
- tidal: new plugin to play Tidal streams
|
||||||
|
* tags
|
||||||
|
- new tags "OriginalDate", "MUSICBRAINZ_WORKID"
|
||||||
|
* decoder
|
||||||
|
- ffmpeg: require at least version 11.12
|
||||||
|
- gme: try loading m3u sidecar files
|
||||||
|
- hybrid_dsd: new decoder plugin
|
||||||
|
- mad: move "gapless_mp3_playback" setting to "decoder" block
|
||||||
|
- mikmod: require at least version 3.2
|
||||||
|
- pcm: support audio/L24 (RFC 3190)
|
||||||
|
- sidplay: support basic and kernal rom (libsidplayfp)
|
||||||
|
* resampler
|
||||||
|
- soxr: flush resampler at end of song
|
||||||
|
* output
|
||||||
|
- alsa: non-blocking mode
|
||||||
|
- alsa: change "dop" and "allowed_formats" settings at runtime
|
||||||
|
- ao: fix crash bug due to partial frames
|
||||||
|
- shout: support the Shine encoder plugin
|
||||||
|
- sndio: remove support for the broken RoarAudio sndio emulation
|
||||||
|
- osx: initial support for DSD over PCM
|
||||||
|
- roar: removed
|
||||||
|
- httpd_output: support for unix sockets
|
||||||
|
* mixer
|
||||||
|
- sndio: new mixer plugin
|
||||||
|
* encoder
|
||||||
|
- opus: support for sending metadata using ogg stream chaining
|
||||||
|
* listen on $XDG_RUNTIME_DIR/mpd/socket by default
|
||||||
|
* append hostname to Zeroconf service name
|
||||||
|
* systemd watchdog support
|
||||||
|
* require GCC 6
|
||||||
|
* build with Meson instead of autotools
|
||||||
|
* use GTest instead of cppunit
|
||||||
|
|
||||||
ver 0.20.23 (2018/10/29)
|
ver 0.20.23 (2018/10/29)
|
||||||
* protocol
|
* protocol
|
||||||
- emit "player" idle event when restarting the current song
|
- emit "player" idle event when restarting the current song
|
||||||
|
|||||||
1
android/.gitignore
vendored
1
android/.gitignore
vendored
@@ -1 +0,0 @@
|
|||||||
/build
|
|
||||||
@@ -2,8 +2,8 @@
|
|||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="org.musicpd"
|
package="org.musicpd"
|
||||||
android:installLocation="auto"
|
android:installLocation="auto"
|
||||||
android:versionCode="22"
|
android:versionCode="26"
|
||||||
android:versionName="0.20.23">
|
android:versionName="0.21.4">
|
||||||
|
|
||||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="26"/>
|
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="26"/>
|
||||||
|
|
||||||
|
|||||||
21
android/apk/make-unsigned-apk.sh
Executable file
21
android/apk/make-unsigned-apk.sh
Executable file
@@ -0,0 +1,21 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
S=`dirname "$0"`
|
||||||
|
ANDROID_ABI=$1
|
||||||
|
STRIP=$2
|
||||||
|
ZIP=$3
|
||||||
|
UNSIGNED_APK=$4
|
||||||
|
LIBMPD_SO=$5
|
||||||
|
CLASSES_DEX=$6
|
||||||
|
RESOURCES_APK=$7
|
||||||
|
D=`dirname "$UNSIGNED_APK"`
|
||||||
|
|
||||||
|
rm -rf "$D/apk"
|
||||||
|
mkdir -p "$D/apk/lib/$ANDROID_ABI"
|
||||||
|
|
||||||
|
"$STRIP" "$LIBMPD_SO" -o "$D/apk/lib/$ANDROID_ABI/`basename $LIBMPD_SO`"
|
||||||
|
cp "$CLASSES_DEX" "$D/apk/"
|
||||||
|
cp "$RESOURCES_APK" "$UNSIGNED_APK"
|
||||||
|
|
||||||
|
cd "$D/apk"
|
||||||
|
exec zip -q -r -X "../`basename $UNSIGNED_APK`" .
|
||||||
59
android/apk/meson.build
Normal file
59
android/apk/meson.build
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
unsigned_apk = custom_target(
|
||||||
|
'mpd-unsigned.apk',
|
||||||
|
output: 'mpd-unsigned.apk',
|
||||||
|
input: [mpd, classes_dex, resources_apk[0]],
|
||||||
|
command: [
|
||||||
|
join_paths(meson.current_source_dir(), 'make-unsigned-apk.sh'),
|
||||||
|
android_abi,
|
||||||
|
get_option('android_strip'),
|
||||||
|
zip,
|
||||||
|
'@OUTPUT0@',
|
||||||
|
'@INPUT@',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
if get_option('android_debug_keystore') != ''
|
||||||
|
debug_apk = custom_target(
|
||||||
|
'mpd-debug.apk',
|
||||||
|
output: 'mpd-debug.apk',
|
||||||
|
input: unsigned_apk,
|
||||||
|
command: [
|
||||||
|
jarsigner,
|
||||||
|
'-keystore', get_option('android_debug_keystore'),
|
||||||
|
'-storepass', 'android',
|
||||||
|
'-signedjar', '@OUTPUT@',
|
||||||
|
'@INPUT@',
|
||||||
|
'androiddebugkey',
|
||||||
|
],
|
||||||
|
build_by_default: true
|
||||||
|
)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('android_keystore') != '' and get_option('android_keyalias') != '' and get_option('android_keypass') != ''
|
||||||
|
unaligned_apk = custom_target(
|
||||||
|
'mpd-unaligned.apk',
|
||||||
|
output: 'mpd-unaligned.apk',
|
||||||
|
input: unsigned_apk,
|
||||||
|
command: [
|
||||||
|
jarsigner,
|
||||||
|
'-digestalg', 'SHA1', '-sigalg', 'MD5withRSA',
|
||||||
|
'-keystore', get_option('android_keystore'),
|
||||||
|
'-storepass', get_option('android_keypass'),
|
||||||
|
'-signedjar', '@OUTPUT@',
|
||||||
|
'@INPUT@',
|
||||||
|
get_option('android_keyalias'),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
apk = custom_target(
|
||||||
|
'mpd.apk',
|
||||||
|
output: 'mpd.apk',
|
||||||
|
input: unaligned_apk,
|
||||||
|
command: [
|
||||||
|
android_zipalign,
|
||||||
|
'-f', '4',
|
||||||
|
'@INPUT@', '@OUTPUT@',
|
||||||
|
],
|
||||||
|
build_by_default: true
|
||||||
|
)
|
||||||
|
endif
|
||||||
@@ -57,6 +57,7 @@ sys.path[0] = os.path.join(mpd_path, 'python')
|
|||||||
|
|
||||||
# output directories
|
# output directories
|
||||||
from build.dirs import lib_path, tarball_path, src_path
|
from build.dirs import lib_path, tarball_path, src_path
|
||||||
|
from build.meson import configure as run_meson
|
||||||
|
|
||||||
arch_path = os.path.join(lib_path, arch)
|
arch_path = os.path.join(lib_path, arch)
|
||||||
build_path = os.path.join(arch_path, 'build')
|
build_path = os.path.join(arch_path, 'build')
|
||||||
@@ -146,7 +147,15 @@ class AndroidNdkToolchain:
|
|||||||
|
|
||||||
# redirect pkg-config to use our root directory instead of the
|
# redirect pkg-config to use our root directory instead of the
|
||||||
# default one on the build host
|
# default one on the build host
|
||||||
self.env['PKG_CONFIG_LIBDIR'] = os.path.join(install_prefix, 'lib/pkgconfig')
|
import shutil
|
||||||
|
bin_dir = os.path.join(install_prefix, 'bin')
|
||||||
|
try:
|
||||||
|
os.makedirs(bin_dir)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
self.pkg_config = shutil.copy(os.path.join(mpd_path, 'build', 'pkg-config.sh'),
|
||||||
|
os.path.join(bin_dir, 'pkg-config'))
|
||||||
|
self.env['PKG_CONFIG'] = self.pkg_config
|
||||||
|
|
||||||
# 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 *
|
from build.libs import *
|
||||||
@@ -175,32 +184,13 @@ for x in thirdparty_libs:
|
|||||||
toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
|
toolchain = AndroidNdkToolchain(tarball_path, src_path, build_path,
|
||||||
use_cxx=True)
|
use_cxx=True)
|
||||||
|
|
||||||
configure = [
|
configure_args += [
|
||||||
os.path.join(mpd_path, 'configure'),
|
'-Dandroid_sdk=' + sdk_path,
|
||||||
'CC=' + toolchain.cc,
|
'-Dandroid_ndk=' + ndk_path,
|
||||||
'CXX=' + toolchain.cxx,
|
'-Dandroid_abi=' + android_abi,
|
||||||
'CFLAGS=' + toolchain.cflags,
|
'-Dandroid_strip=' + toolchain.strip,
|
||||||
'CXXFLAGS=' + toolchain.cxxflags,
|
]
|
||||||
'CPPFLAGS=' + toolchain.cppflags,
|
|
||||||
'LDFLAGS=' + toolchain.ldflags,
|
|
||||||
'LIBS=' + toolchain.libs,
|
|
||||||
'AR=' + toolchain.ar,
|
|
||||||
'RANLIB=' + toolchain.ranlib,
|
|
||||||
'STRIP=' + toolchain.strip,
|
|
||||||
'--host=' + toolchain.arch,
|
|
||||||
'--prefix=' + toolchain.install_prefix,
|
|
||||||
'--with-sysroot=' + toolchain.sysroot,
|
|
||||||
'--with-android-sdk=' + sdk_path,
|
|
||||||
|
|
||||||
'--enable-silent-rules',
|
from build.meson import configure as run_meson
|
||||||
|
run_meson(toolchain, mpd_path, '.', configure_args)
|
||||||
'--disable-icu',
|
subprocess.check_call(['/usr/bin/ninja'], env=toolchain.env)
|
||||||
|
|
||||||
] + configure_args
|
|
||||||
|
|
||||||
from build.cmdline import concatenate_cmdline_variables
|
|
||||||
configure = concatenate_cmdline_variables(configure,
|
|
||||||
set(('CFLAGS', 'CXXFLAGS', 'CPPFLAGS', 'LDFLAGS', 'LIBS')))
|
|
||||||
|
|
||||||
subprocess.check_call(configure, env=toolchain.env)
|
|
||||||
subprocess.check_call(['/usr/bin/make', '--quiet', '-j12'], env=toolchain.env)
|
|
||||||
|
|||||||
24
android/make-resources-apk.sh
Executable file
24
android/make-resources-apk.sh
Executable file
@@ -0,0 +1,24 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
S=`dirname "$0"`
|
||||||
|
AAPT=$1
|
||||||
|
BASE_JAR=$2
|
||||||
|
JAVA_PKG=$3
|
||||||
|
JAVA_PKG_PATH=$4
|
||||||
|
APK_FILE="$5"
|
||||||
|
D=`dirname "$APK_FILE"`
|
||||||
|
|
||||||
|
rm -rf "$D/res"
|
||||||
|
mkdir -p "$D/res/drawable" "$D/src"
|
||||||
|
cp "$D/icon.png" "$D/notification_icon.png" "$D/res/drawable/"
|
||||||
|
|
||||||
|
"$AAPT" package -f -m --auto-add-overlay \
|
||||||
|
--custom-package "$JAVA_PKG" \
|
||||||
|
-M "$S/AndroidManifest.xml" \
|
||||||
|
-S "$D/res" \
|
||||||
|
-S "$S/res" \
|
||||||
|
-J "$D/src" \
|
||||||
|
-I "$BASE_JAR" \
|
||||||
|
-F "$D/resources.apk"
|
||||||
|
|
||||||
|
cp "$D/src/$JAVA_PKG_PATH/R.java" "$D/"
|
||||||
140
android/meson.build
Normal file
140
android/meson.build
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
android_package = 'org.musicpd'
|
||||||
|
android_package_path = join_paths(android_package.split('.'))
|
||||||
|
|
||||||
|
android_ndk = get_option('android_ndk')
|
||||||
|
android_sdk = get_option('android_sdk')
|
||||||
|
android_abi = get_option('android_abi')
|
||||||
|
|
||||||
|
android_sdk_build_tools_version = '27.0.0'
|
||||||
|
android_sdk_platform = 'android-21'
|
||||||
|
|
||||||
|
android_build_tools_dir = join_paths(android_sdk, 'build-tools', android_sdk_build_tools_version)
|
||||||
|
android_sdk_platform_dir = join_paths(android_sdk, 'platforms', android_sdk_platform)
|
||||||
|
|
||||||
|
android_aidl = join_paths(android_build_tools_dir, 'aidl')
|
||||||
|
android_aapt = join_paths(android_build_tools_dir, 'aapt')
|
||||||
|
android_dx = join_paths(android_build_tools_dir, 'dx')
|
||||||
|
android_zipalign = join_paths(android_build_tools_dir, 'zipalign')
|
||||||
|
|
||||||
|
javac = find_program('javac')
|
||||||
|
jarsigner = find_program('jarsigner')
|
||||||
|
rsvg_convert = find_program('rsvg-convert')
|
||||||
|
convert = find_program('convert')
|
||||||
|
zip = find_program('zip')
|
||||||
|
|
||||||
|
common_cppflags += '-I' + join_paths(meson.current_build_dir(), 'include')
|
||||||
|
|
||||||
|
#
|
||||||
|
# AIDL
|
||||||
|
#
|
||||||
|
|
||||||
|
IMainCallback_java = custom_target(
|
||||||
|
'IMainCallback.java',
|
||||||
|
output: 'IMainCallback.java',
|
||||||
|
input: join_paths(meson.current_source_dir(), 'src', 'IMainCallback.aidl'),
|
||||||
|
command: [
|
||||||
|
join_paths(meson.current_source_dir(), 'run-aidl.sh'),
|
||||||
|
android_aidl,
|
||||||
|
'@INPUT@',
|
||||||
|
'@OUTPUT@',
|
||||||
|
join_paths(meson.current_build_dir(), 'src'),
|
||||||
|
android_package_path,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
IMain_java = custom_target(
|
||||||
|
'IMain.java',
|
||||||
|
output: 'IMain.java',
|
||||||
|
input: join_paths(meson.current_source_dir(), 'src', 'IMain.aidl'),
|
||||||
|
depends: IMainCallback_java,
|
||||||
|
command: [
|
||||||
|
join_paths(meson.current_source_dir(), 'run-aidl.sh'),
|
||||||
|
android_aidl,
|
||||||
|
'@INPUT@',
|
||||||
|
'@OUTPUT@',
|
||||||
|
join_paths(meson.current_build_dir(), 'src'),
|
||||||
|
android_package_path,
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Resources
|
||||||
|
#
|
||||||
|
|
||||||
|
android_icon = custom_target(
|
||||||
|
'Android icon',
|
||||||
|
output: 'icon.png',
|
||||||
|
input: '../mpd.svg',
|
||||||
|
command: [
|
||||||
|
rsvg_convert, '--width=48', '--height=48', '@INPUT@', '-o', '@OUTPUT@',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
android_notification_icon = custom_target(
|
||||||
|
'Android notification icon',
|
||||||
|
output: 'notification_icon.png',
|
||||||
|
input: android_icon,
|
||||||
|
command: [
|
||||||
|
convert, '@INPUT@', '-colorspace', 'Gray', '-gamma', '2.2', '@OUTPUT@',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
resources_apk = custom_target(
|
||||||
|
'resources.apk',
|
||||||
|
output: ['resources.apk', 'R.java'],
|
||||||
|
input: [
|
||||||
|
'res/layout/custom_notification_gb.xml',
|
||||||
|
'res/layout/log_item.xml',
|
||||||
|
'res/layout/settings.xml',
|
||||||
|
'res/values/strings.xml',
|
||||||
|
android_icon,
|
||||||
|
android_notification_icon,
|
||||||
|
],
|
||||||
|
command: [
|
||||||
|
join_paths(meson.current_source_dir(), 'make-resources-apk.sh'),
|
||||||
|
android_aapt,
|
||||||
|
join_paths(android_sdk_platform_dir, 'android.jar'),
|
||||||
|
android_package,
|
||||||
|
android_package_path,
|
||||||
|
'@OUTPUT0@',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Compile Java
|
||||||
|
#
|
||||||
|
|
||||||
|
classes_jar = custom_target(
|
||||||
|
'classes.jar',
|
||||||
|
output: 'classes.jar',
|
||||||
|
input: [
|
||||||
|
'src/Bridge.java',
|
||||||
|
'src/Loader.java',
|
||||||
|
'src/Main.java',
|
||||||
|
'src/Receiver.java',
|
||||||
|
'src/Settings.java',
|
||||||
|
IMain_java,
|
||||||
|
IMainCallback_java,
|
||||||
|
resources_apk[1],
|
||||||
|
],
|
||||||
|
command: [
|
||||||
|
join_paths(meson.current_source_dir(), 'run-javac.sh'),
|
||||||
|
javac,
|
||||||
|
join_paths(android_sdk_platform_dir, 'android.jar'),
|
||||||
|
android_package_path,
|
||||||
|
zip,
|
||||||
|
'@OUTPUT@',
|
||||||
|
'@INPUT@',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
classes_dex = custom_target(
|
||||||
|
'classes.dex',
|
||||||
|
output: 'classes.dex',
|
||||||
|
input: classes_jar,
|
||||||
|
command: [
|
||||||
|
android_dx,
|
||||||
|
'--dex', '--output', '@OUTPUT@',
|
||||||
|
'@INPUT@',
|
||||||
|
],
|
||||||
|
)
|
||||||
12
android/run-aidl.sh
Executable file
12
android/run-aidl.sh
Executable file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
AIDL=$1
|
||||||
|
SRC=$2
|
||||||
|
DST=$3
|
||||||
|
GENSRC=$4
|
||||||
|
JAVA_PKG_PATH=$5
|
||||||
|
|
||||||
|
mkdir -p "$GENSRC/$JAVA_PKG_PATH"
|
||||||
|
cp "$SRC" "$GENSRC/$JAVA_PKG_PATH/"
|
||||||
|
"$AIDL" -I"$GENSRC" -o"$GENSRC" "$GENSRC/$JAVA_PKG_PATH/`basename $SRC`"
|
||||||
|
exec cp "$GENSRC/$JAVA_PKG_PATH/`basename $DST`" "$DST"
|
||||||
22
android/run-javac.sh
Executable file
22
android/run-javac.sh
Executable file
@@ -0,0 +1,22 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
JAVAC=$1
|
||||||
|
CLASSPATH=$2
|
||||||
|
JAVA_PKG_PATH=$3
|
||||||
|
ZIP=$4
|
||||||
|
JARFILE=`realpath "$5"`
|
||||||
|
shift 5
|
||||||
|
|
||||||
|
D=`dirname "$JARFILE"`
|
||||||
|
GENSRC="$D/src"
|
||||||
|
GENCLASS="$D/classes"
|
||||||
|
GENINCLUDE="$D/include"
|
||||||
|
|
||||||
|
mkdir -p "$GENSRC/$JAVA_PKG_PATH"
|
||||||
|
"$JAVAC" -source 1.6 -target 1.6 -Xlint:-options \
|
||||||
|
-cp "$CLASSPATH" \
|
||||||
|
-h "$GENINCLUDE" \
|
||||||
|
-d "$GENCLASS" \
|
||||||
|
"$@"
|
||||||
|
cd "$GENCLASS"
|
||||||
|
zip -q -r "$JARFILE" .
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
|
|||||||
11
autogen.sh
11
autogen.sh
@@ -1,11 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
set -e
|
|
||||||
|
|
||||||
rm -rf config.cache build
|
|
||||||
mkdir build
|
|
||||||
|
|
||||||
aclocal -I m4 $ACLOCAL_FLAGS
|
|
||||||
autoheader
|
|
||||||
automake --add-missing $AUTOMAKE_FLAGS
|
|
||||||
autoconf
|
|
||||||
9
build/pkg-config.sh
Executable file
9
build/pkg-config.sh
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
BIN=`dirname $0`
|
||||||
|
ROOT=`dirname "$BIN"`
|
||||||
|
|
||||||
|
export PKG_CONFIG_DIR=
|
||||||
|
export PKG_CONFIG_LIBDIR="${ROOT}/lib/pkgconfig:${ROOT}/share/pkgconfig"
|
||||||
|
|
||||||
|
exec /usr/bin/pkg-config "$@"
|
||||||
1528
configure.ac
1528
configure.ac
File diff suppressed because it is too large
Load Diff
214
doc/conf.py
Normal file
214
doc/conf.py
Normal file
@@ -0,0 +1,214 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
# -- General configuration ------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#
|
||||||
|
# needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be
|
||||||
|
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom
|
||||||
|
# ones.
|
||||||
|
extensions = ['sphinx.ext.intersphinx']
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix(es) of source filenames.
|
||||||
|
# You can specify multiple suffix as a list of string:
|
||||||
|
#
|
||||||
|
# source_suffix = ['.rst', '.md']
|
||||||
|
source_suffix = '.rst'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#
|
||||||
|
# source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'index'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = 'Music Player Daemon'
|
||||||
|
copyright = '2003-2018 The Music Player Daemon Project'
|
||||||
|
author = 'Max Kellermann'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The short X.Y version.
|
||||||
|
version = '0.21.4'
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
release = version
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
#
|
||||||
|
# This is also used if you do content translation via gettext catalogs.
|
||||||
|
# Usually you set "language" from the command line for these cases.
|
||||||
|
language = None
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#
|
||||||
|
# today = ''
|
||||||
|
#
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#
|
||||||
|
# today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
# This patterns also effect to html_static_path and html_extra_path
|
||||||
|
exclude_patterns = ['_build', 'Thumbs.db', '.DS_Store']
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all
|
||||||
|
# documents.
|
||||||
|
#
|
||||||
|
# default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#
|
||||||
|
# add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#
|
||||||
|
# add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#
|
||||||
|
# show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
# modindex_common_prefix = []
|
||||||
|
|
||||||
|
# If true, keep warnings as "system message" paragraphs in the built documents.
|
||||||
|
# keep_warnings = False
|
||||||
|
|
||||||
|
# If true, `todo` and `todoList` produce output, else they produce nothing.
|
||||||
|
todo_include_todos = False
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ----------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
#
|
||||||
|
html_theme = 'classic'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
#
|
||||||
|
# html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
# html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents.
|
||||||
|
# "<project> v<release> documentation" by default.
|
||||||
|
#
|
||||||
|
# html_title = ''
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
#
|
||||||
|
# html_short_title = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#
|
||||||
|
# html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to use as a favicon of
|
||||||
|
# the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#
|
||||||
|
# html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# Add any extra paths that contain custom files (such as robots.txt or
|
||||||
|
# .htaccess) here, relative to this directory. These files are copied
|
||||||
|
# directly to the root of the documentation.
|
||||||
|
#
|
||||||
|
# html_extra_path = []
|
||||||
|
|
||||||
|
# If not None, a 'Last updated on:' timestamp is inserted at every page
|
||||||
|
# bottom, using the given strftime format.
|
||||||
|
# The empty string is equivalent to '%b %d, %Y'.
|
||||||
|
#
|
||||||
|
# html_last_updated_fmt = None
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#
|
||||||
|
# html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#
|
||||||
|
# html_sidebars = {}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#
|
||||||
|
# html_additional_pages = {}
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
#
|
||||||
|
# html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
#
|
||||||
|
# html_use_index = True
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#
|
||||||
|
# html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
#
|
||||||
|
# html_show_sourcelink = True
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#
|
||||||
|
# html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#
|
||||||
|
# html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#
|
||||||
|
# html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
# html_file_suffix = None
|
||||||
|
|
||||||
|
# Language to be used for generating the HTML full-text search index.
|
||||||
|
# Sphinx supports the following languages:
|
||||||
|
# 'da', 'de', 'en', 'es', 'fi', 'fr', 'h', 'it', 'ja'
|
||||||
|
# 'nl', 'no', 'pt', 'ro', 'r', 'sv', 'tr', 'zh'
|
||||||
|
#
|
||||||
|
# html_search_language = 'en'
|
||||||
|
|
||||||
|
# A dictionary with options for the search language support, empty by default.
|
||||||
|
# 'ja' uses this config value.
|
||||||
|
# 'zh' user can custom change `jieba` dictionary path.
|
||||||
|
#
|
||||||
|
# html_search_options = {'type': 'default'}
|
||||||
|
|
||||||
|
# The name of a javascript file (relative to the configuration directory) that
|
||||||
|
# implements a search results scorer. If empty, the default will be used.
|
||||||
|
#
|
||||||
|
# html_search_scorer = 'scorer.js'
|
||||||
128
doc/developer.rst
Normal file
128
doc/developer.rst
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
Developer's Manual
|
||||||
|
##################
|
||||||
|
|
||||||
|
Introduction
|
||||||
|
============
|
||||||
|
|
||||||
|
This is a guide for those who wish to hack on the MPD source code. MPD is an open project, and we are always happy about contributions. So far, more than 150 people have contributed patches. This document is work in progress. Most of it may be incomplete yet. Please help!
|
||||||
|
|
||||||
|
Code Style
|
||||||
|
==========
|
||||||
|
|
||||||
|
* indent with tabs (width 8)
|
||||||
|
* don't write CPP when you can write C++: use inline functions and constexpr instead of macros
|
||||||
|
* comment your code, document your APIs
|
||||||
|
* the code should be C++14 compliant, and must compile with :program:`GCC` 6.0 and :program:`clang` 3.4
|
||||||
|
* report error conditions with C++ exceptions, preferable derived from :envvar:`std::runtime_error`
|
||||||
|
* all code must be exception-safe
|
||||||
|
* classes and functions names use CamelCase; variables are lower-case with words separated by underscore
|
||||||
|
|
||||||
|
Some example code:
|
||||||
|
~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
Foo(const char *abc, int xyz)
|
||||||
|
{
|
||||||
|
if (abc == nullptr) {
|
||||||
|
LogWarning("Foo happened!");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return xyz;
|
||||||
|
}
|
||||||
|
|
||||||
|
Hacking The Source
|
||||||
|
==================
|
||||||
|
|
||||||
|
MPD sources are managed in a git repository on
|
||||||
|
`Github <https://github.com/MusicPlayerDaemon/>`_.
|
||||||
|
|
||||||
|
Always write your code against the latest git:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
git clone git://github.com/MusicPlayerDaemon/MPD
|
||||||
|
|
||||||
|
If you already have a clone, update it:
|
||||||
|
|
||||||
|
.. code-block:: none
|
||||||
|
|
||||||
|
git pull --rebase git://github.com/MusicPlayerDaemon/MPD master
|
||||||
|
|
||||||
|
You can do without :code:`--rebase`, but we recommend that you rebase
|
||||||
|
your repository on the "master" repository all the time.
|
||||||
|
|
||||||
|
Configure with the option :code:`--werror`. Enable as many plugins as
|
||||||
|
possible, to be sure that you don't break any disabled code.
|
||||||
|
|
||||||
|
Don't mix several changes in one single patch. Create a separate patch for every change. Tools like :program:`stgit` help you with that. This way, we can review your patches more easily, and we can pick the patches we like most first.
|
||||||
|
|
||||||
|
Basic stgit usage
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
stgit allows you to create a set of patches and refine all of them: you can go back to any patch at any time, and re-edit it (both the code and the commit message). You can reorder patches and insert new patches at any position. It encourages creating separate patches for tiny changes.
|
||||||
|
|
||||||
|
stgit needs to be initialized on a git repository:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
stg init
|
||||||
|
|
||||||
|
Before you edit the code, create a patch:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
stg new my-patch-name
|
||||||
|
|
||||||
|
stgit now asks you for the commit message.
|
||||||
|
|
||||||
|
Now edit the code. Once you're finished, you have to "refresh" the patch, i.e. your edits are incorporated into the patch you have created:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
stg refresh
|
||||||
|
|
||||||
|
You may now continue editing the same patch, and refresh it as often as you like. Create more patches, edit and refresh them.
|
||||||
|
|
||||||
|
To view the list of patches, type stg series. To go back to a specific patch, type stg goto my-patch-name; now you can re-edit it (don't forget stg refresh when you're finished with that patch).
|
||||||
|
|
||||||
|
When the whole patch series is finished, convert stgit patches to git commits:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
stg commit
|
||||||
|
|
||||||
|
Submitting Patches
|
||||||
|
==================
|
||||||
|
|
||||||
|
Send your patches to the mailing list:
|
||||||
|
Email: `mpd-devel <mpd-devel@musicpd.org>`_
|
||||||
|
|
||||||
|
:program:`git pull` requests are preferred.
|
||||||
|
|
||||||
|
Development Tools
|
||||||
|
=================
|
||||||
|
|
||||||
|
Clang Static Analyzer
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The `static analyzer <http://clang-analyzer.llvm.org/>`_ is a tool that helps find bugs. To run it on the MPD code base, install LLVM and clang. configure MPD to use clang:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
./configure --enable-debug CXX=clang++ CC=clang ...
|
||||||
|
|
||||||
|
It is recommended to use :code:`--enable-debug`, because the analyzer
|
||||||
|
takes advantage of :dfn:`assert()` calls, which are only enabled in
|
||||||
|
the debug build.
|
||||||
|
|
||||||
|
Now run the analyzer:
|
||||||
|
|
||||||
|
.. code-block:: sh
|
||||||
|
|
||||||
|
scan-build --use-c++=clang++ --use-cc=clang make
|
||||||
|
|
||||||
|
The options :code:`--use-c++` and :code:`--use-cc` are necessary
|
||||||
|
because it invokes :command:`cc` for actually compiling the sources by
|
||||||
|
default. That breaks, because MPD requires a C99 compiler.
|
||||||
@@ -1,231 +0,0 @@
|
|||||||
<?xml version='1.0' encoding="utf-8"?>
|
|
||||||
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.5//EN"
|
|
||||||
"http://www.oasis-open.org/docbook/xml/4.5/docbookx.dtd">
|
|
||||||
|
|
||||||
<book>
|
|
||||||
<title>The Music Player Daemon - Developer's Manual</title>
|
|
||||||
|
|
||||||
<chapter id="introduction">
|
|
||||||
<title>Introduction</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This is a guide for those who wish to hack on the MPD source
|
|
||||||
code. MPD is an open project, and we are always happy about
|
|
||||||
contributions. So far, more than 150 people have contributed
|
|
||||||
patches.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
This document is work in progress. Most of it may be incomplete
|
|
||||||
yet. Please help!
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
||||||
|
|
||||||
<chapter id="code_style">
|
|
||||||
<title>Code Style</title>
|
|
||||||
|
|
||||||
<itemizedlist>
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
indent with tabs (width 8)
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
don't write CPP when you can write C++: use inline
|
|
||||||
functions and constexpr instead of macros
|
|
||||||
</para>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
comment your code, document your APIs
|
|
||||||
</para>
|
|
||||||
</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>
|
|
||||||
</listitem>
|
|
||||||
|
|
||||||
<listitem>
|
|
||||||
<para>
|
|
||||||
Some example code:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting lang="C">static inline int
|
|
||||||
Foo(const char *abc, int xyz)
|
|
||||||
{
|
|
||||||
if (abc == nullptr) {
|
|
||||||
LogWarning("Foo happened!");
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return xyz;
|
|
||||||
}
|
|
||||||
</programlisting>
|
|
||||||
</listitem>
|
|
||||||
</itemizedlist>
|
|
||||||
</chapter>
|
|
||||||
|
|
||||||
<chapter id="hacking">
|
|
||||||
<title>Hacking The Source</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
MPD sources are managed in a git repository on <ulink
|
|
||||||
url="https://github.com/MusicPlayerDaemon/">GitHub</ulink>.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Always write your code against the latest git:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>git clone git://github.com/MusicPlayerDaemon/MPD</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
If you already have a clone, update it:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>git pull --rebase git://github.com/MusicPlayerDaemon/MPD master</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You can do without "--rebase", but we recommend that you rebase
|
|
||||||
your repository on the "master" repository all the time.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Configure with the options <option>--enable-debug
|
|
||||||
--enable-werror</option>. Enable as many plugins as possible,
|
|
||||||
to be sure that you don't break any disabled code.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Don't mix several changes in one single patch. Create a
|
|
||||||
separate patch for every change. Tools like
|
|
||||||
<application>stgit</application> help you with that. This way,
|
|
||||||
we can review your patches more easily, and we can pick the
|
|
||||||
patches we like most first.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title> Basic stgit usage</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
stgit allows you to create a set of patches and refine all of
|
|
||||||
them: you can go back to any patch at any time, and re-edit it
|
|
||||||
(both the code and the commit message). You can reorder
|
|
||||||
patches and insert new patches at any position. It encourages
|
|
||||||
creating separate patches for tiny changes.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
stgit needs to be initialized on a git repository: stg init
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Before you edit the code, create a patch: stg new
|
|
||||||
my-patch-name (stgit now asks you for the commit message).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Now edit the code. Once you're finished, you have to "refresh"
|
|
||||||
the patch, i.e. your edits are incorporated into the patch you
|
|
||||||
have created: stg refresh
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
You may now continue editing the same patch, and refresh it as
|
|
||||||
often as you like. Create more patches, edit and refresh them.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
To view the list of patches, type stg series. To go back to a
|
|
||||||
specific patch, type stg goto my-patch-name; now you can
|
|
||||||
re-edit it (don't forget stg refresh when you're finished with
|
|
||||||
that patch).
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
When the whole patch series is finished, convert stgit patches
|
|
||||||
to git commits: stg commit
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
|
|
||||||
<chapter id="submitting_patches">
|
|
||||||
<title>Submitting Patches</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Send your patches to the mailing list:
|
|
||||||
<email>mpd-devel@musicpd.org</email> (<ulink
|
|
||||||
url="http://mailman.blarg.de/listinfo/mpd-devel">subscribe
|
|
||||||
here</ulink>)
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
<command>git pull</command> requests are preferred.
|
|
||||||
</para>
|
|
||||||
</chapter>
|
|
||||||
|
|
||||||
<chapter id="tools">
|
|
||||||
<title>Development Tools</title>
|
|
||||||
|
|
||||||
<section>
|
|
||||||
<title>Clang Static Analyzer</title>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The <ulink url="http://clang-analyzer.llvm.org/">clang static
|
|
||||||
analyzer</ulink> is a tool that helps find bugs. To run it on
|
|
||||||
the MPD code base, install LLVM and clang. Configure MPD to
|
|
||||||
use clang:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>./configure --enable-debug CXX=clang++ CC=clang ...</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
It is recommended to use <option>--enable-debug</option>,
|
|
||||||
because the analyzer takes advantage of
|
|
||||||
<function>assert()</function> calls, which are only enabled in
|
|
||||||
the debug build.
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
Now run the analyzer:
|
|
||||||
</para>
|
|
||||||
|
|
||||||
<programlisting>scan-build --use-c++=clang++ --use-cc=clang make</programlisting>
|
|
||||||
|
|
||||||
<para>
|
|
||||||
The options <option>--use-c++</option> and
|
|
||||||
<option>--use-cc</option> are necessary because it invokes
|
|
||||||
<command>cc</command> for actually compiling the sources by
|
|
||||||
default. That breaks, because MPD requires a C99 compiler.
|
|
||||||
</para>
|
|
||||||
</section>
|
|
||||||
</chapter>
|
|
||||||
</book>
|
|
||||||
@@ -153,4 +153,13 @@
|
|||||||
database.
|
database.
|
||||||
</para>
|
</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para>
|
||||||
|
<varname>musicbrainz_workid</varname>: the work id in the
|
||||||
|
<ulink
|
||||||
|
url="https://picard.musicbrainz.org/docs/mappings/">MusicBrainz</ulink>
|
||||||
|
database.
|
||||||
|
</para>
|
||||||
|
</listitem>
|
||||||
</itemizedlist>
|
</itemizedlist>
|
||||||
|
|||||||
18
doc/index.rst
Normal file
18
doc/index.rst
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
Music Player Daemon
|
||||||
|
===================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
:caption: Contents:
|
||||||
|
|
||||||
|
user
|
||||||
|
plugins
|
||||||
|
developer
|
||||||
|
protocol
|
||||||
|
|
||||||
|
|
||||||
|
Indices and tables
|
||||||
|
==================
|
||||||
|
|
||||||
|
* :ref:`genindex`
|
||||||
|
* :ref:`search`
|
||||||
33
doc/meson.build
Normal file
33
doc/meson.build
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
install_man(['mpd.1', 'mpd.conf.5'])
|
||||||
|
|
||||||
|
sphinx = find_program('sphinx-build')
|
||||||
|
sphinx_output = custom_target(
|
||||||
|
'HTML documentation',
|
||||||
|
output: 'html',
|
||||||
|
input: [
|
||||||
|
'index.rst', 'user.rst', 'developer.rst',
|
||||||
|
'plugins.rst',
|
||||||
|
'protocol.rst',
|
||||||
|
'conf.py',
|
||||||
|
],
|
||||||
|
command: [sphinx, '-q', '-b', 'html', '-d', '@OUTDIR@/doctrees', meson.current_source_dir(), '@OUTPUT@'],
|
||||||
|
build_by_default: true,
|
||||||
|
install: true,
|
||||||
|
install_dir: join_paths(get_option('datadir'), 'doc', meson.project_name()),
|
||||||
|
)
|
||||||
|
|
||||||
|
custom_target(
|
||||||
|
'upload',
|
||||||
|
input: sphinx_output,
|
||||||
|
output: 'upload',
|
||||||
|
build_always_stale: true,
|
||||||
|
command: [
|
||||||
|
'rsync', '-vpruz', '--delete', meson.current_build_dir() + '/',
|
||||||
|
'www.musicpd.org:/var/www/mpd/doc/',
|
||||||
|
'--chmod=Dug+rwx,Do+rx,Fug+rw,Fo+r',
|
||||||
|
'--include=html', '--include=html/**',
|
||||||
|
'--exclude=*',
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -72,19 +72,6 @@ never run as root, and you may use this option to make MPD change its
|
|||||||
user id after initialization. Do not use this option if you start MPD
|
user id after initialization. Do not use this option if you start MPD
|
||||||
as an unprivileged user.
|
as an unprivileged user.
|
||||||
.TP
|
.TP
|
||||||
.B bind_to_address <ip address or hostname or any>
|
|
||||||
This specifies which address mpd binds to and listens on. Multiple
|
|
||||||
bind_to_address parameters may be specified. The default is "any", which binds
|
|
||||||
to all available addresses.
|
|
||||||
|
|
||||||
You can set a port that is different from the global port setting,
|
|
||||||
e.g. "localhost:6602". IPv6 addresses must be enclosed in square
|
|
||||||
brackets if you want to configure a port, e.g. "[::1]:6602".
|
|
||||||
|
|
||||||
To bind to a Unix domain socket, specify an absolute path or a path starting
|
|
||||||
with a tilde (~). For a system-wide MPD, we suggest the path
|
|
||||||
"\fB/var/run/mpd/socket\fP".
|
|
||||||
.TP
|
|
||||||
.B port <port>
|
.B port <port>
|
||||||
This specifies the port that mpd listens on. The default is 6600.
|
This specifies the port that mpd listens on. The default is 6600.
|
||||||
.TP
|
.TP
|
||||||
@@ -112,23 +99,8 @@ information will be published with Zeroconf. The default is yes.
|
|||||||
.B zeroconf_name <name>
|
.B zeroconf_name <name>
|
||||||
If Zeroconf is enabled, this is the service name to publish. This name should
|
If Zeroconf is enabled, this is the service name to publish. This name should
|
||||||
be unique to your local network, but name collisions will be properly dealt
|
be unique to your local network, but name collisions will be properly dealt
|
||||||
with. The default is "Music Player".
|
with. The default is "Music Player @ %h", where %h will be replaced with the
|
||||||
.TP
|
hostname of the machine running MPD.
|
||||||
.B password <password@permissions>
|
|
||||||
This specifies a password for access to mpd. The format is
|
|
||||||
"password@permissions" where permissions is a comma delimited list composed
|
|
||||||
of "read", "add", "control", and/or "admin". "read" allows for reading of the
|
|
||||||
database, displaying the current playlist, and current status of mpd. "add"
|
|
||||||
allows for adding songs and loading playlists. "control" allows for all other
|
|
||||||
player and playlist manipulations. "admin" allows the db to be updated and for
|
|
||||||
the client to kill mpd. An example value is "somePassword@read,add". Multiple
|
|
||||||
password parameters may be specified.
|
|
||||||
.TP
|
|
||||||
.B default_permissions <permissions>
|
|
||||||
This specifies the permissions of a client that has not been authenticated
|
|
||||||
using a password. The format of permissions is specified in the description of
|
|
||||||
the "password" config parameter. If no passwords are specified, the default is
|
|
||||||
"read,add,control,admin", otherwise it is "" (no permissions).
|
|
||||||
.TP
|
.TP
|
||||||
.B audio_output
|
.B audio_output
|
||||||
See \fBDESCRIPTION\fP and the various \fBAUDIO OUTPUT PARAMETERS\fP sections
|
See \fBDESCRIPTION\fP and the various \fBAUDIO OUTPUT PARAMETERS\fP sections
|
||||||
@@ -156,14 +128,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 gapless_mp3_playback <yes or no>
|
|
||||||
This specifies whether to support gapless playback of MP3s which have the
|
|
||||||
necessary headers. Useful if your MP3s have headers with incorrect
|
|
||||||
information. If you have such MP3s, it is highly recommended that you fix them
|
|
||||||
using vbrfix (available from <http://www.willwap.co.uk/Programs/vbrfix.php>)
|
|
||||||
instead of disabling gapless MP3 playback. The default is to support gapless
|
|
||||||
MP3 playback.
|
|
||||||
.TP
|
|
||||||
.B save_absolute_paths_in_playlists <yes or no>
|
.B save_absolute_paths_in_playlists <yes or no>
|
||||||
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".
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
# settings.
|
# settings.
|
||||||
#
|
#
|
||||||
# The special value "syslog" makes MPD use the local syslog daemon. This
|
# The special value "syslog" makes MPD use the local syslog daemon. This
|
||||||
# setting defaults to logging to syslog, otherwise logging is disabled.
|
# setting defaults to logging to syslog.
|
||||||
#
|
#
|
||||||
#log_file "~/.mpd/log"
|
#log_file "~/.mpd/log"
|
||||||
#
|
#
|
||||||
@@ -96,14 +96,6 @@
|
|||||||
#
|
#
|
||||||
#log_level "default"
|
#log_level "default"
|
||||||
#
|
#
|
||||||
# If you have a problem with your MP3s ending abruptly it is recommended that
|
|
||||||
# you set this argument to "no" to attempt to fix the problem. If this solves
|
|
||||||
# the problem, it is highly recommended to fix the MP3 files with vbrfix
|
|
||||||
# (available from <http://www.willwap.co.uk/Programs/vbrfix.php>), at which
|
|
||||||
# point gapless MP3 playback can be enabled.
|
|
||||||
#
|
|
||||||
#gapless_mp3_playback "yes"
|
|
||||||
#
|
|
||||||
# Setting "restore_paused" to "yes" puts MPD into pause mode instead
|
# Setting "restore_paused" to "yes" puts MPD into pause mode instead
|
||||||
# of starting playback after startup.
|
# of starting playback after startup.
|
||||||
#
|
#
|
||||||
@@ -119,6 +111,10 @@
|
|||||||
# found in the user manual.
|
# 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 example just enables the "comment" tag without disabling all
|
||||||
|
# the other supported tags:
|
||||||
|
#metadata_to_use "+comment"
|
||||||
|
#
|
||||||
# This setting enables automatic update of MPD's database when files in
|
# This setting enables automatic update of MPD's database when files in
|
||||||
# music_directory are changed.
|
# music_directory are changed.
|
||||||
#
|
#
|
||||||
@@ -155,9 +151,9 @@
|
|||||||
#zeroconf_enabled "yes"
|
#zeroconf_enabled "yes"
|
||||||
#
|
#
|
||||||
# The argument to this setting will be the Zeroconf / Avahi unique name for
|
# The argument to this setting will be the Zeroconf / Avahi unique name for
|
||||||
# this MPD server on the network.
|
# this MPD server on the network. %h will be replaced with the hostname.
|
||||||
#
|
#
|
||||||
#zeroconf_name "Music Player"
|
#zeroconf_name "Music Player @ %h"
|
||||||
#
|
#
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
@@ -310,7 +306,7 @@ input {
|
|||||||
#audio_output {
|
#audio_output {
|
||||||
# type "sndio"
|
# type "sndio"
|
||||||
# name "sndio output"
|
# name "sndio output"
|
||||||
# mixer_type "software"
|
# mixer_type "hardware"
|
||||||
#}
|
#}
|
||||||
#
|
#
|
||||||
# An example of an OS X output:
|
# An example of an OS X output:
|
||||||
|
|||||||
1073
doc/plugins.rst
Normal file
1073
doc/plugins.rst
Normal file
File diff suppressed because it is too large
Load Diff
1291
doc/protocol.rst
Normal file
1291
doc/protocol.rst
Normal file
File diff suppressed because it is too large
Load Diff
2575
doc/protocol.xml
2575
doc/protocol.xml
File diff suppressed because it is too large
Load Diff
1019
doc/user.rst
Normal file
1019
doc/user.rst
Normal file
File diff suppressed because it is too large
Load Diff
4670
doc/user.xml
4670
doc/user.xml
File diff suppressed because it is too large
Load Diff
@@ -1,67 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_append_compile_flags.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_APPEND_COMPILE_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# For every FLAG1, FLAG2 it is checked whether the compiler works with the
|
|
||||||
# flag. If it does, the flag is added FLAGS-VARIABLE
|
|
||||||
#
|
|
||||||
# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
|
|
||||||
# CFLAGS) is used. During the check the flag is always added to the
|
|
||||||
# current language's flags.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
|
||||||
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
|
||||||
#
|
|
||||||
# NOTE: This macro depends on the AX_APPEND_FLAG and
|
|
||||||
# AX_CHECK_COMPILE_FLAG. Please keep this macro in sync with
|
|
||||||
# AX_APPEND_LINK_FLAGS.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 5
|
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_COMPILE_FLAGS],
|
|
||||||
[AX_REQUIRE_DEFINED([AX_CHECK_COMPILE_FLAG])
|
|
||||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
|
||||||
for flag in $1; do
|
|
||||||
AX_CHECK_COMPILE_FLAG([$flag], [AX_APPEND_FLAG([$flag], [$2])], [], [$3], [$4])
|
|
||||||
done
|
|
||||||
])dnl AX_APPEND_COMPILE_FLAGS
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_append_flag.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_APPEND_FLAG(FLAG, [FLAGS-VARIABLE])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# FLAG is appended to the FLAGS-VARIABLE shell variable, with a space
|
|
||||||
# added in between.
|
|
||||||
#
|
|
||||||
# If FLAGS-VARIABLE is not specified, the current language's flags (e.g.
|
|
||||||
# CFLAGS) is used. FLAGS-VARIABLE is not changed if it already contains
|
|
||||||
# FLAG. If FLAGS-VARIABLE is unset in the shell, it is set to exactly
|
|
||||||
# FLAG.
|
|
||||||
#
|
|
||||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 6
|
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_FLAG],
|
|
||||||
[dnl
|
|
||||||
AC_PREREQ(2.64)dnl for _AC_LANG_PREFIX and AS_VAR_SET_IF
|
|
||||||
AS_VAR_PUSHDEF([FLAGS], [m4_default($2,_AC_LANG_PREFIX[FLAGS])])
|
|
||||||
AS_VAR_SET_IF(FLAGS,[
|
|
||||||
AS_CASE([" AS_VAR_GET(FLAGS) "],
|
|
||||||
[*" $1 "*], [AC_RUN_LOG([: FLAGS already contains $1])],
|
|
||||||
[
|
|
||||||
AS_VAR_APPEND(FLAGS,[" $1"])
|
|
||||||
AC_RUN_LOG([: FLAGS="$FLAGS"])
|
|
||||||
])
|
|
||||||
],
|
|
||||||
[
|
|
||||||
AS_VAR_SET(FLAGS,[$1])
|
|
||||||
AC_RUN_LOG([: FLAGS="$FLAGS"])
|
|
||||||
])
|
|
||||||
AS_VAR_POPDEF([FLAGS])dnl
|
|
||||||
])dnl AX_APPEND_FLAG
|
|
||||||
@@ -1,65 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_append_link_flags.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_APPEND_LINK_FLAGS([FLAG1 FLAG2 ...], [FLAGS-VARIABLE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# For every FLAG1, FLAG2 it is checked whether the linker works with the
|
|
||||||
# flag. If it does, the flag is added FLAGS-VARIABLE
|
|
||||||
#
|
|
||||||
# If FLAGS-VARIABLE is not specified, the linker's flags (LDFLAGS) is
|
|
||||||
# used. During the check the flag is always added to the linker's flags.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
|
|
||||||
# when the check is done. The check is thus made with the flags: "LDFLAGS
|
|
||||||
# EXTRA-FLAGS FLAG". This can for example be used to force the linker 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 AX_CHECK_LINK_FLAG.
|
|
||||||
# Please keep this macro in sync with AX_APPEND_COMPILE_FLAGS.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 5
|
|
||||||
|
|
||||||
AC_DEFUN([AX_APPEND_LINK_FLAGS],
|
|
||||||
[AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
|
||||||
AX_REQUIRE_DEFINED([AX_APPEND_FLAG])
|
|
||||||
for flag in $1; do
|
|
||||||
AX_CHECK_LINK_FLAG([$flag], [AX_APPEND_FLAG([$flag], [m4_default([$2], [LDFLAGS])])], [], [$3], [$4])
|
|
||||||
done
|
|
||||||
])dnl AX_APPEND_LINK_FLAGS
|
|
||||||
@@ -1,285 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_boost_base.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_BOOST_BASE([MINIMUM-VERSION], [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Test for the Boost C++ libraries of a particular version (or newer)
|
|
||||||
#
|
|
||||||
# If no path to the installed boost library is given the macro searchs
|
|
||||||
# under /usr, /usr/local, /opt and /opt/local and evaluates the
|
|
||||||
# $BOOST_ROOT environment variable. Further documentation is available at
|
|
||||||
# <http://randspringer.de/boost/index.html>.
|
|
||||||
#
|
|
||||||
# This macro calls:
|
|
||||||
#
|
|
||||||
# AC_SUBST(BOOST_CPPFLAGS) / AC_SUBST(BOOST_LDFLAGS)
|
|
||||||
#
|
|
||||||
# And sets:
|
|
||||||
#
|
|
||||||
# HAVE_BOOST
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
|
|
||||||
# Copyright (c) 2009 Peter Adolphs
|
|
||||||
#
|
|
||||||
# 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 27
|
|
||||||
|
|
||||||
AC_DEFUN([AX_BOOST_BASE],
|
|
||||||
[
|
|
||||||
AC_ARG_WITH([boost],
|
|
||||||
[AS_HELP_STRING([--with-boost@<:@=ARG@:>@],
|
|
||||||
[use Boost library from a standard location (ARG=yes),
|
|
||||||
from the specified location (ARG=<path>),
|
|
||||||
or disable it (ARG=no)
|
|
||||||
@<:@ARG=yes@:>@ ])],
|
|
||||||
[
|
|
||||||
if test "$withval" = "no"; then
|
|
||||||
want_boost="no"
|
|
||||||
elif test "$withval" = "yes"; then
|
|
||||||
want_boost="yes"
|
|
||||||
ac_boost_path=""
|
|
||||||
else
|
|
||||||
want_boost="yes"
|
|
||||||
ac_boost_path="$withval"
|
|
||||||
fi
|
|
||||||
],
|
|
||||||
[want_boost="yes"])
|
|
||||||
|
|
||||||
|
|
||||||
AC_ARG_WITH([boost-libdir],
|
|
||||||
AS_HELP_STRING([--with-boost-libdir=LIB_DIR],
|
|
||||||
[Force given directory for boost libraries. Note that this will override library path detection, so use this parameter only if default library detection fails and you know exactly where your boost libraries are located.]),
|
|
||||||
[
|
|
||||||
if test -d "$withval"
|
|
||||||
then
|
|
||||||
ac_boost_lib_path="$withval"
|
|
||||||
else
|
|
||||||
AC_MSG_ERROR(--with-boost-libdir expected directory name)
|
|
||||||
fi
|
|
||||||
],
|
|
||||||
[ac_boost_lib_path=""]
|
|
||||||
)
|
|
||||||
|
|
||||||
if test "x$want_boost" = "xyes"; then
|
|
||||||
boost_lib_version_req=ifelse([$1], ,1.20.0,$1)
|
|
||||||
boost_lib_version_req_shorten=`expr $boost_lib_version_req : '\([[0-9]]*\.[[0-9]]*\)'`
|
|
||||||
boost_lib_version_req_major=`expr $boost_lib_version_req : '\([[0-9]]*\)'`
|
|
||||||
boost_lib_version_req_minor=`expr $boost_lib_version_req : '[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
boost_lib_version_req_sub_minor=`expr $boost_lib_version_req : '[[0-9]]*\.[[0-9]]*\.\([[0-9]]*\)'`
|
|
||||||
if test "x$boost_lib_version_req_sub_minor" = "x" ; then
|
|
||||||
boost_lib_version_req_sub_minor="0"
|
|
||||||
fi
|
|
||||||
WANT_BOOST_VERSION=`expr $boost_lib_version_req_major \* 100000 \+ $boost_lib_version_req_minor \* 100 \+ $boost_lib_version_req_sub_minor`
|
|
||||||
AC_MSG_CHECKING(for boostlib >= $boost_lib_version_req)
|
|
||||||
succeeded=no
|
|
||||||
|
|
||||||
dnl On 64-bit systems check for system libraries in both lib64 and lib.
|
|
||||||
dnl The former is specified by FHS, but e.g. Debian does not adhere to
|
|
||||||
dnl this (as it rises problems for generic multi-arch support).
|
|
||||||
dnl The last entry in the list is chosen by default when no libraries
|
|
||||||
dnl are found, e.g. when only header-only libraries are installed!
|
|
||||||
libsubdirs="lib"
|
|
||||||
ax_arch=`uname -m`
|
|
||||||
case $ax_arch in
|
|
||||||
x86_64)
|
|
||||||
libsubdirs="lib64 libx32 lib lib64"
|
|
||||||
;;
|
|
||||||
ppc64|s390x|sparc64|aarch64|ppc64le)
|
|
||||||
libsubdirs="lib64 lib lib64"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
dnl allow for real multi-arch paths e.g. /usr/lib/x86_64-linux-gnu. Give
|
|
||||||
dnl them priority over the other paths since, if libs are found there, they
|
|
||||||
dnl are almost assuredly the ones desired.
|
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
|
||||||
libsubdirs="lib/${host_cpu}-${host_os} $libsubdirs"
|
|
||||||
|
|
||||||
case ${host_cpu} in
|
|
||||||
i?86)
|
|
||||||
libsubdirs="lib/i386-${host_os} $libsubdirs"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
dnl first we check the system location for boost libraries
|
|
||||||
dnl this location ist chosen if boost libraries are installed with the --layout=system option
|
|
||||||
dnl or if you install boost with RPM
|
|
||||||
if test "$ac_boost_path" != ""; then
|
|
||||||
BOOST_CPPFLAGS="-I$ac_boost_path/include"
|
|
||||||
for ac_boost_path_tmp in $libsubdirs; do
|
|
||||||
if test -d "$ac_boost_path"/"$ac_boost_path_tmp" ; then
|
|
||||||
BOOST_LDFLAGS="-L$ac_boost_path/$ac_boost_path_tmp"
|
|
||||||
break
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
elif test "$cross_compiling" != yes; then
|
|
||||||
for ac_boost_path_tmp in /usr /usr/local /opt /opt/local ; do
|
|
||||||
if test -d "$ac_boost_path_tmp/include/boost" && test -r "$ac_boost_path_tmp/include/boost"; then
|
|
||||||
for libsubdir in $libsubdirs ; do
|
|
||||||
if ls "$ac_boost_path_tmp/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
|
|
||||||
done
|
|
||||||
BOOST_LDFLAGS="-L$ac_boost_path_tmp/$libsubdir"
|
|
||||||
BOOST_CPPFLAGS="-I$ac_boost_path_tmp/include"
|
|
||||||
break;
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
dnl overwrite ld flags if we have required special directory with
|
|
||||||
dnl --with-boost-libdir parameter
|
|
||||||
if test "$ac_boost_lib_path" != ""; then
|
|
||||||
BOOST_LDFLAGS="-L$ac_boost_lib_path"
|
|
||||||
fi
|
|
||||||
|
|
||||||
CPPFLAGS_SAVED="$CPPFLAGS"
|
|
||||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
|
||||||
export CPPFLAGS
|
|
||||||
|
|
||||||
LDFLAGS_SAVED="$LDFLAGS"
|
|
||||||
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
|
|
||||||
export LDFLAGS
|
|
||||||
|
|
||||||
AC_REQUIRE([AC_PROG_CXX])
|
|
||||||
AC_LANG_PUSH(C++)
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
|
||||||
@%:@include <boost/version.hpp>
|
|
||||||
]], [[
|
|
||||||
#if BOOST_VERSION >= $WANT_BOOST_VERSION
|
|
||||||
// Everything is okay
|
|
||||||
#else
|
|
||||||
# error Boost version is too old
|
|
||||||
#endif
|
|
||||||
]])],[
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
succeeded=yes
|
|
||||||
found_system=yes
|
|
||||||
],[
|
|
||||||
])
|
|
||||||
AC_LANG_POP([C++])
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
if test "x$succeeded" != "xyes"; then
|
|
||||||
CPPFLAGS="$CPPFLAGS_SAVED"
|
|
||||||
LDFLAGS="$LDFLAGS_SAVED"
|
|
||||||
BOOST_CPPFLAGS=
|
|
||||||
BOOST_LDFLAGS=
|
|
||||||
_version=0
|
|
||||||
if test "$ac_boost_path" != ""; then
|
|
||||||
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
|
||||||
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
|
|
||||||
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
|
|
||||||
V_CHECK=`expr $_version_tmp \> $_version`
|
|
||||||
if test "$V_CHECK" = "1" ; then
|
|
||||||
_version=$_version_tmp
|
|
||||||
fi
|
|
||||||
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
|
||||||
BOOST_CPPFLAGS="-I$ac_boost_path/include/boost-$VERSION_UNDERSCORE"
|
|
||||||
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
|
|
||||||
else
|
|
||||||
if test "$cross_compiling" != yes; then
|
|
||||||
for ac_boost_path in /usr /usr/local /opt /opt/local ; do
|
|
||||||
if test -d "$ac_boost_path" && test -r "$ac_boost_path"; then
|
|
||||||
for i in `ls -d $ac_boost_path/include/boost-* 2>/dev/null`; do
|
|
||||||
_version_tmp=`echo $i | sed "s#$ac_boost_path##" | sed 's/\/include\/boost-//' | sed 's/_/./'`
|
|
||||||
V_CHECK=`expr $_version_tmp \> $_version`
|
|
||||||
if test "$V_CHECK" = "1" ; then
|
|
||||||
_version=$_version_tmp
|
|
||||||
best_path=$ac_boost_path
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
|
|
||||||
VERSION_UNDERSCORE=`echo $_version | sed 's/\./_/'`
|
|
||||||
BOOST_CPPFLAGS="-I$best_path/include/boost-$VERSION_UNDERSCORE"
|
|
||||||
if test "$ac_boost_lib_path" = ""; then
|
|
||||||
for libsubdir in $libsubdirs ; do
|
|
||||||
if ls "$best_path/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
|
|
||||||
done
|
|
||||||
BOOST_LDFLAGS="-L$best_path/$libsubdir"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "x$BOOST_ROOT" != "x"; then
|
|
||||||
for libsubdir in $libsubdirs ; do
|
|
||||||
if ls "$BOOST_ROOT/stage/$libsubdir/libboost_"* >/dev/null 2>&1 ; then break; fi
|
|
||||||
done
|
|
||||||
if test -d "$BOOST_ROOT" && test -r "$BOOST_ROOT" && test -d "$BOOST_ROOT/stage/$libsubdir" && test -r "$BOOST_ROOT/stage/$libsubdir"; then
|
|
||||||
version_dir=`expr //$BOOST_ROOT : '.*/\(.*\)'`
|
|
||||||
stage_version=`echo $version_dir | sed 's/boost_//' | sed 's/_/./g'`
|
|
||||||
stage_version_shorten=`expr $stage_version : '\([[0-9]]*\.[[0-9]]*\)'`
|
|
||||||
V_CHECK=`expr $stage_version_shorten \>\= $_version`
|
|
||||||
if test "$V_CHECK" = "1" -a "$ac_boost_lib_path" = "" ; then
|
|
||||||
AC_MSG_NOTICE(We will use a staged boost library from $BOOST_ROOT)
|
|
||||||
BOOST_CPPFLAGS="-I$BOOST_ROOT"
|
|
||||||
BOOST_LDFLAGS="-L$BOOST_ROOT/stage/$libsubdir"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS $BOOST_CPPFLAGS"
|
|
||||||
export CPPFLAGS
|
|
||||||
LDFLAGS="$LDFLAGS $BOOST_LDFLAGS"
|
|
||||||
export LDFLAGS
|
|
||||||
|
|
||||||
AC_LANG_PUSH(C++)
|
|
||||||
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
|
|
||||||
@%:@include <boost/version.hpp>
|
|
||||||
]], [[
|
|
||||||
#if BOOST_VERSION >= $WANT_BOOST_VERSION
|
|
||||||
// Everything is okay
|
|
||||||
#else
|
|
||||||
# error Boost version is too old
|
|
||||||
#endif
|
|
||||||
]])],[
|
|
||||||
AC_MSG_RESULT(yes)
|
|
||||||
succeeded=yes
|
|
||||||
found_system=yes
|
|
||||||
],[
|
|
||||||
])
|
|
||||||
AC_LANG_POP([C++])
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test "$succeeded" != "yes" ; then
|
|
||||||
if test "$_version" = "0" ; then
|
|
||||||
AC_MSG_NOTICE([[We could not detect the boost libraries (version $boost_lib_version_req_shorten or higher). If you have a staged boost library (still not installed) please specify \$BOOST_ROOT in your environment and do not give a PATH to --with-boost option. If you are sure you have boost installed, then check your version number looking in <boost/version.hpp>. See http://randspringer.de/boost for more documentation.]])
|
|
||||||
else
|
|
||||||
AC_MSG_NOTICE([Your boost libraries seems to old (version $_version).])
|
|
||||||
fi
|
|
||||||
# execute ACTION-IF-NOT-FOUND (if present):
|
|
||||||
ifelse([$3], , :, [$3])
|
|
||||||
else
|
|
||||||
AC_SUBST(BOOST_CPPFLAGS)
|
|
||||||
AC_SUBST(BOOST_LDFLAGS)
|
|
||||||
AC_DEFINE(HAVE_BOOST,,[define if the Boost library is available])
|
|
||||||
# execute ACTION-IF-FOUND (if present):
|
|
||||||
ifelse([$2], , :, [$2])
|
|
||||||
fi
|
|
||||||
|
|
||||||
CPPFLAGS="$CPPFLAGS_SAVED"
|
|
||||||
LDFLAGS="$LDFLAGS_SAVED"
|
|
||||||
fi
|
|
||||||
|
|
||||||
])
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_check_compile_flag.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_CHECK_COMPILE_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Check whether the given FLAG works with the current language's compiler
|
|
||||||
# or gives an error. (Warnings, however, are ignored)
|
|
||||||
#
|
|
||||||
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
|
||||||
# success/failure.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the current language's default
|
|
||||||
# flags (e.g. CFLAGS) when the check is done. The check is thus made with
|
|
||||||
# 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.
|
|
||||||
#
|
|
||||||
# INPUT gives an alternative input source to AC_COMPILE_IFELSE.
|
|
||||||
#
|
|
||||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
|
||||||
# macro in sync with AX_CHECK_{PREPROC,LINK}_FLAG.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 4
|
|
||||||
|
|
||||||
AC_DEFUN([AX_CHECK_COMPILE_FLAG],
|
|
||||||
[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
|
|
||||||
AC_CACHE_CHECK([whether _AC_LANG compiler accepts $1], CACHEVAR, [
|
|
||||||
ax_check_save_flags=$[]_AC_LANG_PREFIX[]FLAGS
|
|
||||||
_AC_LANG_PREFIX[]FLAGS="$[]_AC_LANG_PREFIX[]FLAGS $4 $1"
|
|
||||||
AC_COMPILE_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[no])])
|
|
||||||
_AC_LANG_PREFIX[]FLAGS=$ax_check_save_flags])
|
|
||||||
AS_VAR_IF(CACHEVAR,yes,
|
|
||||||
[m4_default([$2], :)],
|
|
||||||
[m4_default([$3], :)])
|
|
||||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
|
||||||
])dnl AX_CHECK_COMPILE_FLAGS
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_check_link_flag.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_CHECK_LINK_FLAG(FLAG, [ACTION-SUCCESS], [ACTION-FAILURE], [EXTRA-FLAGS], [INPUT])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# Check whether the given FLAG works with the linker or gives an error.
|
|
||||||
# (Warnings, however, are ignored)
|
|
||||||
#
|
|
||||||
# ACTION-SUCCESS/ACTION-FAILURE are shell commands to execute on
|
|
||||||
# success/failure.
|
|
||||||
#
|
|
||||||
# If EXTRA-FLAGS is defined, it is added to the linker's default flags
|
|
||||||
# when the check is done. The check is thus made with the flags: "LDFLAGS
|
|
||||||
# EXTRA-FLAGS FLAG". This can for example be used to force the linker to
|
|
||||||
# issue an error when a bad flag is given.
|
|
||||||
#
|
|
||||||
# INPUT gives an alternative input source to AC_LINK_IFELSE.
|
|
||||||
#
|
|
||||||
# NOTE: Implementation based on AX_CFLAGS_GCC_OPTION. Please keep this
|
|
||||||
# macro in sync with AX_CHECK_{PREPROC,COMPILE}_FLAG.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Guido U. Draheim <guidod@gmx.de>
|
|
||||||
# Copyright (c) 2011 Maarten Bosmans <mkbosmans@gmail.com>
|
|
||||||
#
|
|
||||||
# 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 3 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 4
|
|
||||||
|
|
||||||
AC_DEFUN([AX_CHECK_LINK_FLAG],
|
|
||||||
[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, [
|
|
||||||
ax_check_save_flags=$LDFLAGS
|
|
||||||
LDFLAGS="$LDFLAGS $4 $1"
|
|
||||||
AC_LINK_IFELSE([m4_default([$5],[AC_LANG_PROGRAM()])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[yes])],
|
|
||||||
[AS_VAR_SET(CACHEVAR,[no])])
|
|
||||||
LDFLAGS=$ax_check_save_flags])
|
|
||||||
AS_VAR_IF(CACHEVAR,yes,
|
|
||||||
[m4_default([$2], :)],
|
|
||||||
[m4_default([$3], :)])
|
|
||||||
AS_VAR_POPDEF([CACHEVAR])dnl
|
|
||||||
])dnl AX_CHECK_LINK_FLAGS
|
|
||||||
@@ -1,564 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# 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,34 +0,0 @@
|
|||||||
# ============================================================================
|
|
||||||
# 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])])
|
|
||||||
485
m4/ax_pthread.m4
485
m4/ax_pthread.m4
@@ -1,485 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_pthread.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# This macro figures out how to build C programs using POSIX threads. It
|
|
||||||
# sets the PTHREAD_LIBS output variable to the threads library and linker
|
|
||||||
# flags, and the PTHREAD_CFLAGS output variable to any special C compiler
|
|
||||||
# flags that are needed. (The user can also force certain compiler
|
|
||||||
# flags/libs to be tested by setting these environment variables.)
|
|
||||||
#
|
|
||||||
# Also sets PTHREAD_CC to any special C compiler that is needed for
|
|
||||||
# multi-threaded programs (defaults to the value of CC otherwise). (This
|
|
||||||
# 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,
|
|
||||||
# but also to link with them as well. For example, you might link with
|
|
||||||
# $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
|
|
||||||
#
|
|
||||||
# If you are only building threaded programs, you may wish to use these
|
|
||||||
# variables in your default LIBS, CFLAGS, and CC:
|
|
||||||
#
|
|
||||||
# LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
# CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
# CC="$PTHREAD_CC"
|
|
||||||
#
|
|
||||||
# In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
|
|
||||||
# has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
|
|
||||||
# that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
|
|
||||||
#
|
|
||||||
# Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
|
|
||||||
# PTHREAD_PRIO_INHERIT symbol is defined when compiling with
|
|
||||||
# PTHREAD_CFLAGS.
|
|
||||||
#
|
|
||||||
# ACTION-IF-FOUND is a list of shell commands to run if a threads library
|
|
||||||
# is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
|
|
||||||
# is not found. If ACTION-IF-FOUND is not specified, the default action
|
|
||||||
# will define HAVE_PTHREAD.
|
|
||||||
#
|
|
||||||
# Please let the authors know if this macro fails on any platform, or if
|
|
||||||
# you have any other suggestions or comments. This macro was based on work
|
|
||||||
# by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
|
|
||||||
# from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
|
|
||||||
# Alejandro Forero Cuervo to the autoconf macro repository. We are also
|
|
||||||
# grateful for the helpful feedback of numerous users.
|
|
||||||
#
|
|
||||||
# Updated for Autoconf 2.68 by Daniel Richard G.
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2008 Steven G. Johnson <stevenj@alum.mit.edu>
|
|
||||||
# Copyright (c) 2011 Daniel Richard G. <skunk@iSKUNK.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 3 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, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
# As a special exception, the respective Autoconf Macro's copyright owner
|
|
||||||
# gives unlimited permission to copy, distribute and modify the configure
|
|
||||||
# scripts that are the output of Autoconf when processing the Macro. You
|
|
||||||
# need not follow the terms of the GNU General Public License when using
|
|
||||||
# or distributing such scripts, even though portions of the text of the
|
|
||||||
# Macro appear in them. The GNU General Public License (GPL) does govern
|
|
||||||
# all other use of the material that constitutes the Autoconf Macro.
|
|
||||||
#
|
|
||||||
# This special exception to the GPL applies to versions of the Autoconf
|
|
||||||
# Macro released by the Autoconf Archive. When you make and distribute a
|
|
||||||
# modified version of the Autoconf Macro, you may extend this special
|
|
||||||
# exception to the GPL to apply to your modified version as well.
|
|
||||||
|
|
||||||
#serial 23
|
|
||||||
|
|
||||||
AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
|
|
||||||
AC_DEFUN([AX_PTHREAD], [
|
|
||||||
AC_REQUIRE([AC_CANONICAL_HOST])
|
|
||||||
AC_REQUIRE([AC_PROG_CC])
|
|
||||||
AC_REQUIRE([AC_PROG_SED])
|
|
||||||
AC_LANG_PUSH([C])
|
|
||||||
ax_pthread_ok=no
|
|
||||||
|
|
||||||
# We used to check for pthread.h first, but this fails if pthread.h
|
|
||||||
# requires special compiler flags (e.g. on Tru64 or Sequent).
|
|
||||||
# It gets checked for in the link test anyway.
|
|
||||||
|
|
||||||
# First of all, check if the user has set any of the PTHREAD_LIBS,
|
|
||||||
# etcetera environment variables, and if threads linking works using
|
|
||||||
# them:
|
|
||||||
if test "x$PTHREAD_CFLAGS$PTHREAD_LIBS" != "x"; then
|
|
||||||
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"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
AC_MSG_CHECKING([for pthread_join using $CC $PTHREAD_CFLAGS $PTHREAD_LIBS])
|
|
||||||
AC_LINK_IFELSE([AC_LANG_CALL([], [pthread_join])], [ax_pthread_ok=yes])
|
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
|
||||||
if test "x$ax_pthread_ok" = "xno"; then
|
|
||||||
PTHREAD_LIBS=""
|
|
||||||
PTHREAD_CFLAGS=""
|
|
||||||
fi
|
|
||||||
CC="$ax_pthread_save_CC"
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
|
||||||
fi
|
|
||||||
|
|
||||||
# We must check for the threads library under a number of different
|
|
||||||
# names; the ordering is very important because some systems
|
|
||||||
# (e.g. DEC) have both -lpthread and -lpthreads, where one of the
|
|
||||||
# libraries is broken (non-POSIX).
|
|
||||||
|
|
||||||
# Create a list of thread flags to try. Items starting with a "-" are
|
|
||||||
# C compiler flags, and other items are library names, except for "none"
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
ax_pthread_flags="pthreads none -Kthread -pthread -pthreads -mthreads pthread --thread-safe -mt pthread-config"
|
|
||||||
|
|
||||||
# The ordering *is* (sometimes) important. Some notes on the
|
|
||||||
# individual items follow:
|
|
||||||
|
|
||||||
# pthreads: AIX (must check this before -lpthread)
|
|
||||||
# none: in case threads are in libc; should be tried before -Kthread and
|
|
||||||
# other compiler flags to prevent continual compiler warnings
|
|
||||||
# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
|
|
||||||
# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
|
|
||||||
# (Note: HP C rejects this with "bad form for `-t' option")
|
|
||||||
# -pthreads: Solaris/gcc (Note: HP C also rejects)
|
|
||||||
# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
|
|
||||||
# doesn't hurt to check since this sometimes defines pthreads and
|
|
||||||
# -D_REENTRANT too), HP C (must be checked before -lpthread, which
|
|
||||||
# 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
|
|
||||||
# --thread-safe: KAI C++
|
|
||||||
# pthread-config: use pthread-config program (for GNU Pth library)
|
|
||||||
|
|
||||||
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*)
|
|
||||||
|
|
||||||
# On Solaris (at least, for some versions), libc contains stubbed
|
|
||||||
# (non-functional) versions of the pthreads routines, so link-based
|
|
||||||
# tests will erroneously succeed. (N.B.: The stubs are missing
|
|
||||||
# pthread_cleanup_push, or rather a function called by this macro,
|
|
||||||
# so we could check for that, but who knows whether they'll stub
|
|
||||||
# that too in a future libc.) So we'll check first for the
|
|
||||||
# standard Solaris way of linking pthreads (-mt -lpthread).
|
|
||||||
|
|
||||||
ax_pthread_flags="-mt,pthread pthread $ax_pthread_flags"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
# GCC generally uses -pthread, or -pthreads on some platforms (e.g. SPARC)
|
|
||||||
|
|
||||||
AS_IF([test "x$GCC" = "xyes"],
|
|
||||||
[ax_pthread_flags="-pthread -pthreads $ax_pthread_flags"])
|
|
||||||
|
|
||||||
# The presence of a feature test macro requesting re-entrant function
|
|
||||||
# definitions is, on some systems, a strong hint that pthreads support is
|
|
||||||
# correctly enabled
|
|
||||||
|
|
||||||
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)
|
|
||||||
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 $ax_pthread_try_flag])
|
|
||||||
PTHREAD_CFLAGS="$ax_pthread_try_flag"
|
|
||||||
;;
|
|
||||||
|
|
||||||
pthread-config)
|
|
||||||
AC_CHECK_PROG([ax_pthread_config], [pthread-config], [yes], [no])
|
|
||||||
AS_IF([test "x$ax_pthread_config" = "xno"], [continue])
|
|
||||||
PTHREAD_CFLAGS="`pthread-config --cflags`"
|
|
||||||
PTHREAD_LIBS="`pthread-config --ldflags` `pthread-config --libs`"
|
|
||||||
;;
|
|
||||||
|
|
||||||
*)
|
|
||||||
AC_MSG_CHECKING([for the pthreads library -l$ax_pthread_try_flag])
|
|
||||||
PTHREAD_LIBS="-l$ax_pthread_try_flag"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
|
|
||||||
# Check for various functions. We must include pthread.h,
|
|
||||||
# since some functions may be macros. (On the Sequent, we
|
|
||||||
# need a special flag -Kthread to make this header compile.)
|
|
||||||
# We check for pthread_join because it is in -lpthread on IRIX
|
|
||||||
# while pthread_create is in libc. We check for pthread_attr_init
|
|
||||||
# due to DEC craziness with -lpthreads. We check for
|
|
||||||
# pthread_cleanup_push because it is one of the few pthread
|
|
||||||
# functions on Solaris that doesn't have a non-functional libc stub.
|
|
||||||
# We try pthread_create on general principles.
|
|
||||||
|
|
||||||
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 *start_routine(void *a) { return a; }],
|
|
||||||
[pthread_t th; pthread_attr_t attr;
|
|
||||||
pthread_create(&th, 0, start_routine, 0);
|
|
||||||
pthread_join(th, 0);
|
|
||||||
pthread_attr_init(&attr);
|
|
||||||
pthread_cleanup_push(routine, 0);
|
|
||||||
pthread_cleanup_pop(0) /* ; */])],
|
|
||||||
[ax_pthread_ok=yes],
|
|
||||||
[])
|
|
||||||
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
|
||||||
|
|
||||||
AC_MSG_RESULT([$ax_pthread_ok])
|
|
||||||
AS_IF([test "x$ax_pthread_ok" = "xyes"], [break])
|
|
||||||
|
|
||||||
PTHREAD_LIBS=""
|
|
||||||
PTHREAD_CFLAGS=""
|
|
||||||
done
|
|
||||||
fi
|
|
||||||
|
|
||||||
# Various other checks:
|
|
||||||
if test "x$ax_pthread_ok" = "xyes"; then
|
|
||||||
ax_pthread_save_CFLAGS="$CFLAGS"
|
|
||||||
ax_pthread_save_LIBS="$LIBS"
|
|
||||||
CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
|
|
||||||
LIBS="$PTHREAD_LIBS $LIBS"
|
|
||||||
|
|
||||||
# Detect AIX lossage: JOINABLE attribute is called UNDETACHED.
|
|
||||||
AC_CACHE_CHECK([for joinable pthread attribute],
|
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR],
|
|
||||||
[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>],
|
|
||||||
[int attr = $ax_pthread_attr; return attr /* ; */])],
|
|
||||||
[ax_cv_PTHREAD_JOINABLE_ATTR=$ax_pthread_attr; break],
|
|
||||||
[])
|
|
||||||
done
|
|
||||||
])
|
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_JOINABLE_ATTR" != "xunknown" && \
|
|
||||||
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
|
|
||||||
uses a non-standard name on your system.])
|
|
||||||
ax_pthread_joinable_attr_defined=yes
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([whether more special flags are required for pthreads],
|
|
||||||
[ax_cv_PTHREAD_SPECIAL_FLAGS],
|
|
||||||
[ax_cv_PTHREAD_SPECIAL_FLAGS=no
|
|
||||||
case $host_os in
|
|
||||||
solaris*)
|
|
||||||
ax_cv_PTHREAD_SPECIAL_FLAGS="-D_POSIX_PTHREAD_SEMANTICS"
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
])
|
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_SPECIAL_FLAGS" != "xno" && \
|
|
||||||
test "x$ax_pthread_special_flags_added" != "xyes"],
|
|
||||||
[PTHREAD_CFLAGS="$ax_cv_PTHREAD_SPECIAL_FLAGS $PTHREAD_CFLAGS"
|
|
||||||
ax_pthread_special_flags_added=yes])
|
|
||||||
|
|
||||||
AC_CACHE_CHECK([for PTHREAD_PRIO_INHERIT],
|
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT],
|
|
||||||
[AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <pthread.h>]],
|
|
||||||
[[int i = PTHREAD_PRIO_INHERIT;]])],
|
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=yes],
|
|
||||||
[ax_cv_PTHREAD_PRIO_INHERIT=no])
|
|
||||||
])
|
|
||||||
AS_IF([test "x$ax_cv_PTHREAD_PRIO_INHERIT" = "xyes" && \
|
|
||||||
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
|
|
||||||
])
|
|
||||||
|
|
||||||
CFLAGS="$ax_pthread_save_CFLAGS"
|
|
||||||
LIBS="$ax_pthread_save_LIBS"
|
|
||||||
|
|
||||||
# More AIX lossage: compile with *_r variant
|
|
||||||
if test "x$GCC" != "xyes"; then
|
|
||||||
case $host_os in
|
|
||||||
aix*)
|
|
||||||
AS_CASE(["x/$CC"],
|
|
||||||
[x*/c89|x*/c89_128|x*/c99|x*/c99_128|x*/cc|x*/cc128|x*/xlc|x*/xlc_v6|x*/xlc128|x*/xlc128_v6],
|
|
||||||
[#handle absolute path differently from PATH based program lookup
|
|
||||||
AS_CASE(["x$CC"],
|
|
||||||
[x/*],
|
|
||||||
[AS_IF([AS_EXECUTABLE_P([${CC}_r])],[PTHREAD_CC="${CC}_r"])],
|
|
||||||
[AC_CHECK_PROGS([PTHREAD_CC],[${CC}_r],[$CC])])])
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
test -n "$PTHREAD_CC" || PTHREAD_CC="$CC"
|
|
||||||
|
|
||||||
AC_SUBST([PTHREAD_LIBS])
|
|
||||||
AC_SUBST([PTHREAD_CFLAGS])
|
|
||||||
AC_SUBST([PTHREAD_CC])
|
|
||||||
|
|
||||||
# Finally, execute ACTION-IF-FOUND/ACTION-IF-NOT-FOUND:
|
|
||||||
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])
|
|
||||||
:
|
|
||||||
else
|
|
||||||
ax_pthread_ok=no
|
|
||||||
$2
|
|
||||||
fi
|
|
||||||
AC_LANG_POP
|
|
||||||
])dnl AX_PTHREAD
|
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
# ===========================================================================
|
|
||||||
# http://www.gnu.org/software/autoconf-archive/ax_require_defined.html
|
|
||||||
# ===========================================================================
|
|
||||||
#
|
|
||||||
# SYNOPSIS
|
|
||||||
#
|
|
||||||
# AX_REQUIRE_DEFINED(MACRO)
|
|
||||||
#
|
|
||||||
# DESCRIPTION
|
|
||||||
#
|
|
||||||
# AX_REQUIRE_DEFINED is a simple helper for making sure other macros have
|
|
||||||
# been defined and thus are available for use. This avoids random issues
|
|
||||||
# where a macro isn't expanded. Instead the configure script emits a
|
|
||||||
# non-fatal:
|
|
||||||
#
|
|
||||||
# ./configure: line 1673: AX_CFLAGS_WARN_ALL: command not found
|
|
||||||
#
|
|
||||||
# It's like AC_REQUIRE except it doesn't expand the required macro.
|
|
||||||
#
|
|
||||||
# Here's an example:
|
|
||||||
#
|
|
||||||
# AX_REQUIRE_DEFINED([AX_CHECK_LINK_FLAG])
|
|
||||||
#
|
|
||||||
# LICENSE
|
|
||||||
#
|
|
||||||
# Copyright (c) 2014 Mike Frysinger <vapier@gentoo.org>
|
|
||||||
#
|
|
||||||
# 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 1
|
|
||||||
|
|
||||||
AC_DEFUN([AX_REQUIRE_DEFINED], [dnl
|
|
||||||
m4_ifndef([$1], [m4_fatal([macro ]$1[ is not defined; is a m4 file missing?])])
|
|
||||||
])dnl AX_REQUIRE_DEFINED
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
dnl
|
|
||||||
dnl Usage:
|
|
||||||
dnl AC_CHECK_LIBWRAP([ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
|
||||||
dnl
|
|
||||||
|
|
||||||
AC_DEFUN([AC_CHECK_LIBWRAP],[
|
|
||||||
AC_CHECK_HEADERS([tcpd.h],
|
|
||||||
AC_CHECK_LIB([wrap], [request_init],
|
|
||||||
[LIBWRAP_CFLAGS=""
|
|
||||||
LIBWRAP_LDFLAGS="-lwrap"
|
|
||||||
$1],
|
|
||||||
$2),
|
|
||||||
$2)
|
|
||||||
])
|
|
||||||
185
m4/mpd_auto.m4
185
m4/mpd_auto.m4
@@ -1,185 +0,0 @@
|
|||||||
dnl Parameters: varname1, description
|
|
||||||
AC_DEFUN([MPD_AUTO_ENABLED], [
|
|
||||||
if test x$[]enable_$1 = xauto; then
|
|
||||||
AC_MSG_NOTICE([auto-detected $2])
|
|
||||||
enable_$1=yes
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl Parameters: varname1, description, errmsg
|
|
||||||
AC_DEFUN([MPD_AUTO_DISABLED], [
|
|
||||||
if test x$[]enable_$1 = xauto; then
|
|
||||||
AC_MSG_WARN([$3 -- disabling $2])
|
|
||||||
enable_$1=no
|
|
||||||
elif test x$[]enable_$1 = xyes; then
|
|
||||||
AC_MSG_ERROR([$2: $3])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
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 detection; it assumes that more checks will follow.
|
|
||||||
AC_DEFUN([MPD_AUTO_PRE], [
|
|
||||||
if test x$[]enable_$1 != xno && test x$[]found_$1 = xno; then
|
|
||||||
MPD_AUTO_DISABLED([$1], [$2], [$3])
|
|
||||||
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], [
|
|
||||||
if test x$[]enable_$1 = xno; then
|
|
||||||
found_$1=no
|
|
||||||
fi
|
|
||||||
|
|
||||||
if test x$[]found_$1 = xyes; then
|
|
||||||
MPD_AUTO_ENABLED([$1], [$2])
|
|
||||||
else
|
|
||||||
MPD_AUTO_DISABLED([$1], [$2], [$3])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl Invoke a check if its configuration is "yes" or "auto" and call
|
|
||||||
dnl MPD_AUTO_RESULT.
|
|
||||||
dnl
|
|
||||||
dnl Parameters: varname1, description, errmsg, check
|
|
||||||
AC_DEFUN([MPD_AUTO], [
|
|
||||||
if test x$[]enable_$1 != xno; then
|
|
||||||
$4
|
|
||||||
fi
|
|
||||||
MPD_AUTO_RESULT([$1], [$2], [$3])
|
|
||||||
])
|
|
||||||
|
|
||||||
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
|
|
||||||
dnl Parameters: varname1, varname2, pkgname, libname, symname, libs, cflags, description, errmsg
|
|
||||||
AC_DEFUN([MPD_AUTO_PKG_LIB], [
|
|
||||||
MPD_AUTO([$1], [$8], [$9],
|
|
||||||
[PKG_CHECK_MODULES([$2], [$3],
|
|
||||||
[found_$1=yes],
|
|
||||||
AC_CHECK_LIB($4, $5,
|
|
||||||
[found_$1=yes $2_LIBS='$6' $2_CFLAGS='$7'],
|
|
||||||
[found_$1=no],
|
|
||||||
[$6]))])
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl Wrapper for AC_CHECK_LIB.
|
|
||||||
dnl
|
|
||||||
dnl Parameters: varname1, varname2, libname, symname, libs, cflags, description, errmsg
|
|
||||||
AC_DEFUN([MPD_AUTO_LIB], [
|
|
||||||
AC_SUBST([$2_LIBS], [])
|
|
||||||
AC_SUBST([$2_CFLAGS], [])
|
|
||||||
|
|
||||||
MPD_AUTO([$1], [$7], [$8],
|
|
||||||
[AC_CHECK_LIB($3, $4,
|
|
||||||
[found_$1=yes $2_LIBS='$5' $2_CFLAGS='$6'],
|
|
||||||
[found_$1=no],
|
|
||||||
[$5])])
|
|
||||||
])
|
|
||||||
|
|
||||||
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])])
|
|
||||||
])
|
|
||||||
@@ -1,8 +0,0 @@
|
|||||||
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])
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
AC_DEFUN([MPD_DEPENDS], [
|
|
||||||
if test x$$2 = xno; then
|
|
||||||
if test x$$1 = xauto; then
|
|
||||||
$1=no
|
|
||||||
elif test x$$1 = xyes; then
|
|
||||||
AC_MSG_ERROR([$3])
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
@@ -1,25 +0,0 @@
|
|||||||
dnl MPD_OPTIONAL_FUNC(name, func, macro)
|
|
||||||
dnl
|
|
||||||
dnl Allow the user to enable or disable the use of a function. If the
|
|
||||||
dnl option is not specified, the function is auto-detected.
|
|
||||||
AC_DEFUN([MPD_OPTIONAL_FUNC], [
|
|
||||||
AC_ARG_ENABLE([$1],
|
|
||||||
AS_HELP_STRING([--enable-$1],
|
|
||||||
[use the function "$1" (default: auto)]),
|
|
||||||
[test x$[]enable_$1 = xyes && AC_DEFINE([$3], 1, [Define to use $1])],
|
|
||||||
[AC_CHECK_FUNC([$2],
|
|
||||||
[AC_DEFINE([$3], 1, [Define to use $1])],)])
|
|
||||||
])
|
|
||||||
|
|
||||||
dnl MPD_OPTIONAL_FUNC_NODEF(name, func)
|
|
||||||
dnl
|
|
||||||
dnl Allow the user to enable or disable the use of a function.
|
|
||||||
dnl Works similar to MPD_OPTIONAL_FUNC, however MPD_OPTIONAL_FUNC_NODEF
|
|
||||||
dnl does not invoke AC_DEFINE when function is enabled. Shell variable
|
|
||||||
dnl enable_$name is set to "yes" instead.
|
|
||||||
AC_DEFUN([MPD_OPTIONAL_FUNC_NODEF], [
|
|
||||||
AC_ARG_ENABLE([$1],
|
|
||||||
AS_HELP_STRING([--enable-$1],
|
|
||||||
[use the function "$1" (default: auto)]),,
|
|
||||||
[AC_CHECK_FUNC([$2], [enable_$1=yes],)])
|
|
||||||
])
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
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])])
|
|
||||||
275
m4/pkg.m4
275
m4/pkg.m4
@@ -1,275 +0,0 @@
|
|||||||
dnl pkg.m4 - Macros to locate and utilise pkg-config. -*- Autoconf -*-
|
|
||||||
dnl serial 11 (pkg-config-0.29)
|
|
||||||
dnl
|
|
||||||
dnl Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
|
|
||||||
dnl Copyright © 2012-2015 Dan Nicholson <dbn.lists@gmail.com>
|
|
||||||
dnl
|
|
||||||
dnl 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 the Free Software Foundation; either version 2 of the License, or
|
|
||||||
dnl (at your option) any later version.
|
|
||||||
dnl
|
|
||||||
dnl This program is distributed in the hope that it will be useful, but
|
|
||||||
dnl WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
||||||
dnl General Public License for more details.
|
|
||||||
dnl
|
|
||||||
dnl 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 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
|
|
||||||
dnl 02111-1307, USA.
|
|
||||||
dnl
|
|
||||||
dnl As a special exception to the GNU General Public License, if you
|
|
||||||
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.
|
|
||||||
|
|
||||||
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],
|
|
||||||
[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
|
|
||||||
m4_pattern_allow([^PKG_CONFIG(_(PATH|LIBDIR|SYSROOT_DIR|ALLOW_SYSTEM_(CFLAGS|LIBS)))?$])
|
|
||||||
m4_pattern_allow([^PKG_CONFIG_(DISABLE_UNINSTALLED|TOP_BUILD_DIR|DEBUG_SPEW)$])
|
|
||||||
AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])
|
|
||||||
AC_ARG_VAR([PKG_CONFIG_PATH], [directories to add to pkg-config's search path])
|
|
||||||
AC_ARG_VAR([PKG_CONFIG_LIBDIR], [path overriding pkg-config's built-in search path])
|
|
||||||
|
|
||||||
if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
|
|
||||||
AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
|
|
||||||
fi
|
|
||||||
if test -n "$PKG_CONFIG"; then
|
|
||||||
_pkg_min_version=m4_default([$1], [0.9.0])
|
|
||||||
AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
|
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
else
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
PKG_CONFIG=""
|
|
||||||
fi
|
|
||||||
fi[]dnl
|
|
||||||
])dnl PKG_PROG_PKG_CONFIG
|
|
||||||
|
|
||||||
dnl PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
|
||||||
dnl -------------------------------------------------------------------
|
|
||||||
dnl Since: 0.18
|
|
||||||
dnl
|
|
||||||
dnl Check to see whether a particular set of modules exists. Similar to
|
|
||||||
dnl PKG_CHECK_MODULES(), but does not set variables or print errors.
|
|
||||||
dnl
|
|
||||||
dnl Please remember that m4 expands AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
|
||||||
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_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
|
||||||
if test -n "$PKG_CONFIG" && \
|
|
||||||
AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
|
|
||||||
m4_default([$2], [:])
|
|
||||||
m4_ifvaln([$3], [else
|
|
||||||
$3])dnl
|
|
||||||
fi])
|
|
||||||
|
|
||||||
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],
|
|
||||||
[if test -n "$$1"; then
|
|
||||||
pkg_cv_[]$1="$$1"
|
|
||||||
elif test -n "$PKG_CONFIG"; then
|
|
||||||
PKG_CHECK_EXISTS([$3],
|
|
||||||
[pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`
|
|
||||||
test "x$?" != "x0" && pkg_failed=yes ],
|
|
||||||
[pkg_failed=yes])
|
|
||||||
else
|
|
||||||
pkg_failed=untried
|
|
||||||
fi[]dnl
|
|
||||||
])dnl _PKG_CONFIG
|
|
||||||
|
|
||||||
dnl _PKG_SHORT_ERRORS_SUPPORTED
|
|
||||||
dnl ---------------------------
|
|
||||||
dnl Internal check to see if pkg-config supports short errors.
|
|
||||||
AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
|
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
|
|
||||||
if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
|
|
||||||
_pkg_short_errors_supported=yes
|
|
||||||
else
|
|
||||||
_pkg_short_errors_supported=no
|
|
||||||
fi[]dnl
|
|
||||||
])dnl _PKG_SHORT_ERRORS_SUPPORTED
|
|
||||||
|
|
||||||
|
|
||||||
dnl PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
|
||||||
dnl [ACTION-IF-NOT-FOUND])
|
|
||||||
dnl --------------------------------------------------------------
|
|
||||||
dnl Since: 0.4.0
|
|
||||||
dnl
|
|
||||||
dnl 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 explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
|
|
||||||
AC_DEFUN([PKG_CHECK_MODULES],
|
|
||||||
[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][_LIBS], [linker flags for $1, overriding pkg-config])dnl
|
|
||||||
|
|
||||||
pkg_failed=no
|
|
||||||
AC_MSG_CHECKING([for $1])
|
|
||||||
|
|
||||||
_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
|
|
||||||
_PKG_CONFIG([$1][_LIBS], [libs], [$2])
|
|
||||||
|
|
||||||
m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
|
|
||||||
and $1[]_LIBS to avoid the need to call pkg-config.
|
|
||||||
See the pkg-config man page for more details.])
|
|
||||||
|
|
||||||
if test $pkg_failed = yes; then
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
_PKG_SHORT_ERRORS_SUPPORTED
|
|
||||||
if test $_pkg_short_errors_supported = yes; then
|
|
||||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "$2" 2>&1`
|
|
||||||
else
|
|
||||||
$1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "$2" 2>&1`
|
|
||||||
fi
|
|
||||||
# Put the nasty error message in config.log where it belongs
|
|
||||||
echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
|
|
||||||
|
|
||||||
m4_default([$4], [AC_MSG_ERROR(
|
|
||||||
[Package requirements ($2) were not met:
|
|
||||||
|
|
||||||
$$1_PKG_ERRORS
|
|
||||||
|
|
||||||
Consider adjusting the PKG_CONFIG_PATH environment variable if you
|
|
||||||
installed software in a non-standard prefix.
|
|
||||||
|
|
||||||
_PKG_TEXT])[]dnl
|
|
||||||
])
|
|
||||||
elif test $pkg_failed = untried; then
|
|
||||||
AC_MSG_RESULT([no])
|
|
||||||
m4_default([$4], [AC_MSG_FAILURE(
|
|
||||||
[The pkg-config script could not be found or is too old. Make sure it
|
|
||||||
is in your PATH or set the PKG_CONFIG environment variable to the full
|
|
||||||
path to pkg-config.
|
|
||||||
|
|
||||||
_PKG_TEXT
|
|
||||||
|
|
||||||
To get pkg-config, see <http://pkg-config.freedesktop.org/>.])[]dnl
|
|
||||||
])
|
|
||||||
else
|
|
||||||
$1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
|
|
||||||
$1[]_LIBS=$pkg_cv_[]$1[]_LIBS
|
|
||||||
AC_MSG_RESULT([yes])
|
|
||||||
$3
|
|
||||||
fi[]dnl
|
|
||||||
])dnl PKG_CHECK_MODULES
|
|
||||||
|
|
||||||
|
|
||||||
dnl PKG_CHECK_MODULES_STATIC(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
|
|
||||||
dnl [ACTION-IF-NOT-FOUND])
|
|
||||||
dnl ---------------------------------------------------------------------
|
|
||||||
dnl Since: 0.29
|
|
||||||
dnl
|
|
||||||
dnl Checks for existence of MODULES and gathers its build flags with
|
|
||||||
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],
|
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${libdir}/pkgconfig'])])
|
|
||||||
m4_pushdef([pkg_description],
|
|
||||||
[pkg-config installation directory @<:@]pkg_default[@:>@])
|
|
||||||
AC_ARG_WITH([pkgconfigdir],
|
|
||||||
[AS_HELP_STRING([--with-pkgconfigdir], pkg_description)],,
|
|
||||||
[with_pkgconfigdir=]pkg_default)
|
|
||||||
AC_SUBST([pkgconfigdir], [$with_pkgconfigdir])
|
|
||||||
m4_popdef([pkg_default])
|
|
||||||
m4_popdef([pkg_description])
|
|
||||||
])dnl PKG_INSTALLDIR
|
|
||||||
|
|
||||||
|
|
||||||
dnl PKG_NOARCH_INSTALLDIR([DIRECTORY])
|
|
||||||
dnl --------------------------------
|
|
||||||
dnl Since: 0.27
|
|
||||||
dnl
|
|
||||||
dnl Substitutes the variable noarch_pkgconfigdir as the location where a
|
|
||||||
dnl module should install arch-independent pkg-config .pc files. By
|
|
||||||
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],
|
|
||||||
[m4_pushdef([pkg_default], [m4_default([$1], ['${datadir}/pkgconfig'])])
|
|
||||||
m4_pushdef([pkg_description],
|
|
||||||
[pkg-config arch-independent installation directory @<:@]pkg_default[@:>@])
|
|
||||||
AC_ARG_WITH([noarch-pkgconfigdir],
|
|
||||||
[AS_HELP_STRING([--with-noarch-pkgconfigdir], pkg_description)],,
|
|
||||||
[with_noarch_pkgconfigdir=]pkg_default)
|
|
||||||
AC_SUBST([noarch_pkgconfigdir], [$with_noarch_pkgconfigdir])
|
|
||||||
m4_popdef([pkg_default])
|
|
||||||
m4_popdef([pkg_description])
|
|
||||||
])dnl PKG_NOARCH_INSTALLDIR
|
|
||||||
|
|
||||||
|
|
||||||
dnl PKG_CHECK_VAR(VARIABLE, MODULE, CONFIG-VARIABLE,
|
|
||||||
dnl [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
|
|
||||||
dnl -------------------------------------------
|
|
||||||
dnl Since: 0.28
|
|
||||||
dnl
|
|
||||||
dnl Retrieves the value of the pkg-config variable for the given module.
|
|
||||||
AC_DEFUN([PKG_CHECK_VAR],
|
|
||||||
[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
|
|
||||||
AC_ARG_VAR([$1], [value of $3 for $2, overriding pkg-config])dnl
|
|
||||||
|
|
||||||
_PKG_CONFIG([$1], [variable="][$3]["], [$2])
|
|
||||||
AS_VAR_COPY([$1], [pkg_cv_][$1])
|
|
||||||
|
|
||||||
AS_VAR_IF([$1], [""], [$5], [$4])dnl
|
|
||||||
])dnl PKG_CHECK_VAR
|
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
AC_DEFUN([results], [
|
|
||||||
printf '('
|
|
||||||
if test x$[]enable_$1 = xyes; then
|
|
||||||
printf '+'
|
|
||||||
else
|
|
||||||
printf '-'
|
|
||||||
fi
|
|
||||||
printf '%s) ' "$2"
|
|
||||||
])
|
|
||||||
18
m4/ucred.m4
18
m4/ucred.m4
@@ -1,18 +0,0 @@
|
|||||||
# Check if "struct ucred" is available.
|
|
||||||
#
|
|
||||||
# Author: Max Kellermann <max.kellermann@gmail.com>
|
|
||||||
|
|
||||||
AC_DEFUN([STRUCT_UCRED],[
|
|
||||||
AC_MSG_CHECKING([for struct ucred])
|
|
||||||
AC_CACHE_VAL(mpd_cv_have_struct_ucred, [
|
|
||||||
AC_TRY_COMPILE([#include <sys/socket.h>],
|
|
||||||
[struct ucred cred;],
|
|
||||||
mpd_cv_have_struct_ucred=yes,
|
|
||||||
mpd_cv_have_struct_ucred=no)
|
|
||||||
])
|
|
||||||
|
|
||||||
AC_MSG_RESULT($mpd_cv_have_struct_ucred)
|
|
||||||
if test x$mpd_cv_have_struct_ucred = xyes; then
|
|
||||||
AC_DEFINE(HAVE_STRUCT_UCRED, 1, [Define if struct ucred is present from sys/socket.h])
|
|
||||||
fi
|
|
||||||
])
|
|
||||||
470
meson.build
Normal file
470
meson.build
Normal file
@@ -0,0 +1,470 @@
|
|||||||
|
project(
|
||||||
|
'mpd',
|
||||||
|
['c', 'cpp'],
|
||||||
|
version: '0.21.4',
|
||||||
|
meson_version: '>= 0.47.2',
|
||||||
|
default_options: [
|
||||||
|
'c_std=c99',
|
||||||
|
'cpp_std=c++14'
|
||||||
|
],
|
||||||
|
license: 'GPLv2+',
|
||||||
|
)
|
||||||
|
|
||||||
|
version_cxx = vcs_tag(input: 'src/GitVersion.cxx', output: 'GitVersion.cxx')
|
||||||
|
|
||||||
|
compiler = meson.get_compiler('cpp')
|
||||||
|
c_compiler = meson.get_compiler('c')
|
||||||
|
|
||||||
|
conf = configuration_data()
|
||||||
|
conf.set_quoted('PACKAGE', meson.project_name())
|
||||||
|
conf.set_quoted('PACKAGE_NAME', meson.project_name())
|
||||||
|
conf.set_quoted('PACKAGE_VERSION', meson.project_version())
|
||||||
|
conf.set_quoted('VERSION', meson.project_version())
|
||||||
|
conf.set_quoted('PROTOCOL_VERSION', '0.21.4')
|
||||||
|
conf.set_quoted('SYSTEM_CONFIG_FILE_LOCATION', join_paths(get_option('prefix'), get_option('sysconfdir'), 'mpd.conf'))
|
||||||
|
|
||||||
|
common_cppflags = [
|
||||||
|
'-D_GNU_SOURCE',
|
||||||
|
]
|
||||||
|
|
||||||
|
common_cflags = [
|
||||||
|
]
|
||||||
|
|
||||||
|
common_cxxflags = [
|
||||||
|
]
|
||||||
|
|
||||||
|
test_common_flags = [
|
||||||
|
'-Wall',
|
||||||
|
'-Wextra',
|
||||||
|
|
||||||
|
'-fvisibility=hidden',
|
||||||
|
|
||||||
|
'-ffast-math',
|
||||||
|
'-ftree-vectorize',
|
||||||
|
]
|
||||||
|
|
||||||
|
test_cxxflags = test_common_flags + [
|
||||||
|
'-fno-threadsafe-statics',
|
||||||
|
'-fmerge-all-constants',
|
||||||
|
|
||||||
|
'-Wmissing-declarations',
|
||||||
|
'-Wshadow',
|
||||||
|
'-Wpointer-arith',
|
||||||
|
'-Wcast-qual',
|
||||||
|
'-Wwrite-strings',
|
||||||
|
'-Wsign-compare',
|
||||||
|
|
||||||
|
'-Wno-non-virtual-dtor',
|
||||||
|
|
||||||
|
# work around bogus GCC7 warning "mangled name for ... will change
|
||||||
|
# in C++17 because the exception specification is part of a function
|
||||||
|
# type"
|
||||||
|
'-Wno-noexcept-type',
|
||||||
|
]
|
||||||
|
|
||||||
|
if compiler.get_id() == 'clang'
|
||||||
|
# Workaround for clang bug
|
||||||
|
# https://bugs.llvm.org/show_bug.cgi?id=32611
|
||||||
|
test_cxxflags += '-funwind-tables'
|
||||||
|
endif
|
||||||
|
|
||||||
|
test_cflags = test_common_flags + [
|
||||||
|
'-Wmissing-prototypes',
|
||||||
|
'-Wshadow',
|
||||||
|
'-Wpointer-arith',
|
||||||
|
'-Wstrict-prototypes',
|
||||||
|
'-Wcast-qual',
|
||||||
|
'-Wwrite-strings',
|
||||||
|
'-pedantic',
|
||||||
|
]
|
||||||
|
|
||||||
|
test_ldflags = [
|
||||||
|
]
|
||||||
|
|
||||||
|
if get_option('buildtype') != 'debug'
|
||||||
|
test_cflags += [
|
||||||
|
'-ffunction-sections',
|
||||||
|
'-fdata-sections',
|
||||||
|
]
|
||||||
|
test_ldflags += [
|
||||||
|
'-Wl,--gc-sections',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
add_global_arguments(common_cxxflags + compiler.get_supported_arguments(test_cxxflags), language: 'cpp')
|
||||||
|
add_global_arguments(common_cflags + c_compiler.get_supported_arguments(test_cflags), language: 'c')
|
||||||
|
add_global_link_arguments(compiler.get_supported_link_arguments(test_ldflags), language: 'cpp')
|
||||||
|
|
||||||
|
is_linux = host_machine.system() == 'linux'
|
||||||
|
is_android = get_option('android_ndk') != ''
|
||||||
|
is_darwin = host_machine.system() == 'darwin'
|
||||||
|
is_windows = host_machine.system() == 'windows'
|
||||||
|
is_haiku = host_machine.system() == 'haiku'
|
||||||
|
|
||||||
|
if is_android
|
||||||
|
common_cppflags += '-DANDROID'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if is_windows
|
||||||
|
common_cppflags += [
|
||||||
|
'-DWIN32_LEAN_AND_MEAN',
|
||||||
|
'-DWINVER=0x0600', '-D_WIN32_WINNT=0x0600',
|
||||||
|
'-DSTRICT',
|
||||||
|
'-DUNICODE', '-D_UNICODE',
|
||||||
|
]
|
||||||
|
|
||||||
|
subdir('win32')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if is_android
|
||||||
|
subdir('android')
|
||||||
|
endif
|
||||||
|
|
||||||
|
add_global_arguments(common_cppflags, language: 'c')
|
||||||
|
add_global_arguments(common_cppflags, language: 'cpp')
|
||||||
|
|
||||||
|
enable_daemon = not is_windows and not is_android and get_option('daemon')
|
||||||
|
conf.set('ENABLE_DAEMON', enable_daemon)
|
||||||
|
|
||||||
|
conf.set('HAVE_LOCALE_H', compiler.has_header('locale.h'))
|
||||||
|
|
||||||
|
conf.set('HAVE_GETPWNAM_R', compiler.has_function('getpwnam_r'))
|
||||||
|
conf.set('HAVE_GETPWUID_R', compiler.has_function('getpwuid_r'))
|
||||||
|
conf.set('HAVE_INITGROUPS', compiler.has_function('initgroups'))
|
||||||
|
conf.set('HAVE_FNMATCH', compiler.has_function('fnmatch'))
|
||||||
|
conf.set('HAVE_STRNDUP', compiler.has_function('strndup', prefix: '#define _GNU_SOURCE\n#include <string.h>'))
|
||||||
|
conf.set('HAVE_STRCASESTR', compiler.has_function('strcasestr'))
|
||||||
|
|
||||||
|
conf.set('HAVE_PRCTL', is_linux)
|
||||||
|
|
||||||
|
conf.set('USE_EVENTFD', is_linux and get_option('eventfd'))
|
||||||
|
conf.set('USE_SIGNALFD', is_linux and get_option('signalfd'))
|
||||||
|
|
||||||
|
if is_windows
|
||||||
|
conf.set('USE_WINSELECT', true)
|
||||||
|
elif is_linux and get_option('epoll')
|
||||||
|
conf.set('USE_EPOLL', true)
|
||||||
|
else
|
||||||
|
conf.set('USE_POLL', true)
|
||||||
|
endif
|
||||||
|
|
||||||
|
if not get_option('syslog').disabled()
|
||||||
|
if compiler.has_function('syslog')
|
||||||
|
conf.set('HAVE_SYSLOG', true)
|
||||||
|
elif get_option('syslog').enabled()
|
||||||
|
error('syslog() not found')
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
|
||||||
|
enable_database = get_option('database')
|
||||||
|
conf.set('ENABLE_DATABASE', enable_database)
|
||||||
|
|
||||||
|
enable_inotify = get_option('inotify') and is_linux and enable_database
|
||||||
|
conf.set('ENABLE_INOTIFY', enable_inotify)
|
||||||
|
|
||||||
|
conf.set('ENABLE_DSD', get_option('dsd'))
|
||||||
|
|
||||||
|
inc = include_directories(
|
||||||
|
'src',
|
||||||
|
|
||||||
|
# for the generated config.h
|
||||||
|
'.',
|
||||||
|
)
|
||||||
|
|
||||||
|
boost_dep = dependency('boost', version: '>= 1.58')
|
||||||
|
if boost_dep.version() == '1.67'
|
||||||
|
# https://github.com/MusicPlayerDaemon/MPD/pull/384
|
||||||
|
# https://github.com/boostorg/lockfree/commit/12726cda009a855073b9bedbdce57b6ce7763da2
|
||||||
|
warning('Your Boost version 1.67 is known to be buggy, and the MPD build will fail. Please upgrade to Boost 1.68 or later.')
|
||||||
|
endif
|
||||||
|
|
||||||
|
sources = [
|
||||||
|
version_cxx,
|
||||||
|
'src/Main.cxx',
|
||||||
|
'src/protocol/Ack.cxx',
|
||||||
|
'src/protocol/ArgParser.cxx',
|
||||||
|
'src/protocol/Result.cxx',
|
||||||
|
'src/command/CommandError.cxx',
|
||||||
|
'src/command/AllCommands.cxx',
|
||||||
|
'src/command/QueueCommands.cxx',
|
||||||
|
'src/command/TagCommands.cxx',
|
||||||
|
'src/command/PlayerCommands.cxx',
|
||||||
|
'src/command/PlaylistCommands.cxx',
|
||||||
|
'src/command/FileCommands.cxx',
|
||||||
|
'src/command/OutputCommands.cxx',
|
||||||
|
'src/command/MessageCommands.cxx',
|
||||||
|
'src/command/ClientCommands.cxx',
|
||||||
|
'src/command/PartitionCommands.cxx',
|
||||||
|
'src/command/OtherCommands.cxx',
|
||||||
|
'src/command/CommandListBuilder.cxx',
|
||||||
|
'src/Idle.cxx',
|
||||||
|
'src/IdleFlags.cxx',
|
||||||
|
'src/decoder/Domain.cxx',
|
||||||
|
'src/decoder/Thread.cxx',
|
||||||
|
'src/decoder/Control.cxx',
|
||||||
|
'src/decoder/Bridge.cxx',
|
||||||
|
'src/decoder/DecoderPrint.cxx',
|
||||||
|
'src/client/Listener.cxx',
|
||||||
|
'src/client/Client.cxx',
|
||||||
|
'src/client/ClientEvent.cxx',
|
||||||
|
'src/client/ClientExpire.cxx',
|
||||||
|
'src/client/ClientGlobal.cxx',
|
||||||
|
'src/client/ClientIdle.cxx',
|
||||||
|
'src/client/ClientList.cxx',
|
||||||
|
'src/client/ClientNew.cxx',
|
||||||
|
'src/client/ClientProcess.cxx',
|
||||||
|
'src/client/ClientRead.cxx',
|
||||||
|
'src/client/ClientWrite.cxx',
|
||||||
|
'src/client/ClientMessage.cxx',
|
||||||
|
'src/client/ClientSubscribe.cxx',
|
||||||
|
'src/client/ClientFile.cxx',
|
||||||
|
'src/client/Response.cxx',
|
||||||
|
'src/Listen.cxx',
|
||||||
|
'src/LogInit.cxx',
|
||||||
|
'src/LogBackend.cxx',
|
||||||
|
'src/Log.cxx',
|
||||||
|
'src/ls.cxx',
|
||||||
|
'src/Instance.cxx',
|
||||||
|
'src/win32/Win32Main.cxx',
|
||||||
|
'src/MusicBuffer.cxx',
|
||||||
|
'src/MusicPipe.cxx',
|
||||||
|
'src/MusicChunk.cxx',
|
||||||
|
'src/MusicChunkPtr.cxx',
|
||||||
|
'src/Mapper.cxx',
|
||||||
|
'src/Partition.cxx',
|
||||||
|
'src/Permission.cxx',
|
||||||
|
'src/player/CrossFade.cxx',
|
||||||
|
'src/player/Thread.cxx',
|
||||||
|
'src/player/Control.cxx',
|
||||||
|
'src/PlaylistError.cxx',
|
||||||
|
'src/PlaylistPrint.cxx',
|
||||||
|
'src/PlaylistSave.cxx',
|
||||||
|
'src/playlist/PlaylistStream.cxx',
|
||||||
|
'src/playlist/PlaylistMapper.cxx',
|
||||||
|
'src/playlist/PlaylistAny.cxx',
|
||||||
|
'src/playlist/PlaylistSong.cxx',
|
||||||
|
'src/playlist/PlaylistQueue.cxx',
|
||||||
|
'src/playlist/Print.cxx',
|
||||||
|
'src/db/PlaylistVector.cxx',
|
||||||
|
'src/queue/Queue.cxx',
|
||||||
|
'src/queue/QueuePrint.cxx',
|
||||||
|
'src/queue/QueueSave.cxx',
|
||||||
|
'src/queue/Playlist.cxx',
|
||||||
|
'src/queue/PlaylistControl.cxx',
|
||||||
|
'src/queue/PlaylistEdit.cxx',
|
||||||
|
'src/queue/PlaylistTag.cxx',
|
||||||
|
'src/queue/PlaylistState.cxx',
|
||||||
|
'src/ReplayGainGlobal.cxx',
|
||||||
|
'src/LocateUri.cxx',
|
||||||
|
'src/SongUpdate.cxx',
|
||||||
|
'src/SongLoader.cxx',
|
||||||
|
'src/SongPrint.cxx',
|
||||||
|
'src/SongSave.cxx',
|
||||||
|
'src/StateFile.cxx',
|
||||||
|
'src/StateFileConfig.cxx',
|
||||||
|
'src/Stats.cxx',
|
||||||
|
'src/TagPrint.cxx',
|
||||||
|
'src/TagSave.cxx',
|
||||||
|
'src/TagFile.cxx',
|
||||||
|
'src/TagStream.cxx',
|
||||||
|
'src/TimePrint.cxx',
|
||||||
|
'src/mixer/Volume.cxx',
|
||||||
|
'src/PlaylistFile.cxx',
|
||||||
|
]
|
||||||
|
|
||||||
|
if not is_android
|
||||||
|
sources += [
|
||||||
|
'src/CommandLine.cxx',
|
||||||
|
'src/unix/SignalHandlers.cxx',
|
||||||
|
]
|
||||||
|
else
|
||||||
|
sources += [
|
||||||
|
'src/android/Context.cxx',
|
||||||
|
'src/android/Environment.cxx',
|
||||||
|
'src/android/LogListener.cxx',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
if enable_daemon
|
||||||
|
sources += 'src/unix/Daemon.cxx'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if enable_database
|
||||||
|
sources += [
|
||||||
|
'src/queue/PlaylistUpdate.cxx',
|
||||||
|
'src/command/StorageCommands.cxx',
|
||||||
|
'src/command/DatabaseCommands.cxx',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
subdir('src/util')
|
||||||
|
subdir('src/system')
|
||||||
|
subdir('src/thread')
|
||||||
|
subdir('src/event')
|
||||||
|
|
||||||
|
subdir('src/lib/dbus')
|
||||||
|
subdir('src/lib/icu')
|
||||||
|
subdir('src/lib/smbclient')
|
||||||
|
subdir('src/lib/zlib')
|
||||||
|
|
||||||
|
subdir('src/lib/alsa')
|
||||||
|
subdir('src/lib/curl')
|
||||||
|
subdir('src/lib/expat')
|
||||||
|
subdir('src/lib/ffmpeg')
|
||||||
|
subdir('src/lib/gcrypt')
|
||||||
|
subdir('src/lib/nfs')
|
||||||
|
subdir('src/lib/oss')
|
||||||
|
subdir('src/lib/pcre')
|
||||||
|
subdir('src/lib/pulse')
|
||||||
|
subdir('src/lib/sndio')
|
||||||
|
subdir('src/lib/sqlite')
|
||||||
|
subdir('src/lib/systemd')
|
||||||
|
subdir('src/lib/upnp')
|
||||||
|
subdir('src/lib/yajl')
|
||||||
|
|
||||||
|
subdir('src/fs')
|
||||||
|
subdir('src/config')
|
||||||
|
subdir('src/net')
|
||||||
|
subdir('src/tag')
|
||||||
|
subdir('src/pcm')
|
||||||
|
subdir('src/neighbor')
|
||||||
|
subdir('src/input')
|
||||||
|
subdir('src/archive')
|
||||||
|
subdir('src/filter')
|
||||||
|
subdir('src/mixer')
|
||||||
|
subdir('src/output')
|
||||||
|
subdir('src/lib/xiph')
|
||||||
|
subdir('src/decoder')
|
||||||
|
subdir('src/encoder')
|
||||||
|
subdir('src/song')
|
||||||
|
subdir('src/playlist')
|
||||||
|
subdir('src/zeroconf')
|
||||||
|
|
||||||
|
if curl_dep.found()
|
||||||
|
sources += 'src/RemoteTagCache.cxx'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if sqlite_dep.found()
|
||||||
|
sources += [
|
||||||
|
'src/command/StickerCommands.cxx',
|
||||||
|
'src/sticker/StickerDatabase.cxx',
|
||||||
|
'src/sticker/StickerPrint.cxx',
|
||||||
|
'src/sticker/SongSticker.cxx',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
basic = static_library(
|
||||||
|
'basic',
|
||||||
|
'src/ReplayGainInfo.cxx',
|
||||||
|
'src/ReplayGainMode.cxx',
|
||||||
|
'src/SingleMode.cxx',
|
||||||
|
include_directories: inc,
|
||||||
|
)
|
||||||
|
|
||||||
|
basic_dep = declare_dependency(
|
||||||
|
link_with: basic,
|
||||||
|
)
|
||||||
|
|
||||||
|
if enable_database
|
||||||
|
subdir('src/storage')
|
||||||
|
subdir('src/db')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if neighbor_glue_dep.found()
|
||||||
|
sources += 'src/command/NeighborCommands.cxx'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if archive_glue_dep.found()
|
||||||
|
sources += [
|
||||||
|
'src/TagArchive.cxx',
|
||||||
|
'src/db/update/Archive.cxx',
|
||||||
|
]
|
||||||
|
endif
|
||||||
|
|
||||||
|
if is_windows
|
||||||
|
sources += windows_resources
|
||||||
|
endif
|
||||||
|
|
||||||
|
link_args = []
|
||||||
|
more_deps = []
|
||||||
|
if is_android
|
||||||
|
subdir('src/java')
|
||||||
|
target_type = 'shared_library'
|
||||||
|
link_args += [
|
||||||
|
'-Wl,--no-undefined,-shared,-Bsymbolic',
|
||||||
|
'-llog',
|
||||||
|
'-lz',
|
||||||
|
]
|
||||||
|
more_deps += [
|
||||||
|
declare_dependency(sources: [classes_jar]),
|
||||||
|
java_dep,
|
||||||
|
]
|
||||||
|
else
|
||||||
|
target_type = 'executable'
|
||||||
|
endif
|
||||||
|
|
||||||
|
mpd = build_target(
|
||||||
|
'mpd',
|
||||||
|
sources,
|
||||||
|
target_type: target_type,
|
||||||
|
include_directories: inc,
|
||||||
|
dependencies: [
|
||||||
|
basic_dep,
|
||||||
|
config_dep,
|
||||||
|
dbus_dep,
|
||||||
|
fs_dep,
|
||||||
|
net_dep,
|
||||||
|
util_dep,
|
||||||
|
event_dep,
|
||||||
|
thread_dep,
|
||||||
|
neighbor_glue_dep,
|
||||||
|
input_glue_dep,
|
||||||
|
archive_glue_dep,
|
||||||
|
output_glue_dep,
|
||||||
|
mixer_glue_dep,
|
||||||
|
decoder_glue_dep,
|
||||||
|
encoder_glue_dep,
|
||||||
|
playlist_glue_dep,
|
||||||
|
db_glue_dep,
|
||||||
|
storage_glue_dep,
|
||||||
|
song_dep,
|
||||||
|
systemd_dep,
|
||||||
|
sqlite_dep,
|
||||||
|
zeroconf_dep,
|
||||||
|
more_deps,
|
||||||
|
],
|
||||||
|
link_args: link_args,
|
||||||
|
install: not is_android and not is_haiku,
|
||||||
|
)
|
||||||
|
|
||||||
|
if is_android
|
||||||
|
subdir('android/apk')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if is_haiku
|
||||||
|
subdir('src/haiku')
|
||||||
|
endif
|
||||||
|
|
||||||
|
configure_file(output: 'config.h', configuration: conf)
|
||||||
|
|
||||||
|
if systemd_dep.found()
|
||||||
|
subdir('systemd')
|
||||||
|
endif
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
'mpd.svg',
|
||||||
|
install_dir: join_paths(get_option('datadir'), 'icons', 'hicolor', 'scalable', 'apps'),
|
||||||
|
)
|
||||||
|
|
||||||
|
install_data(
|
||||||
|
'AUTHORS', 'COPYING', 'NEWS', 'README.md',
|
||||||
|
install_dir: join_paths(get_option('datadir'), 'doc', meson.project_name()),
|
||||||
|
)
|
||||||
|
|
||||||
|
if get_option('documentation')
|
||||||
|
subdir('doc')
|
||||||
|
endif
|
||||||
|
|
||||||
|
if get_option('test')
|
||||||
|
subdir('test')
|
||||||
|
endif
|
||||||
186
meson_options.txt
Normal file
186
meson_options.txt
Normal file
@@ -0,0 +1,186 @@
|
|||||||
|
option('documentation', type: 'boolean', value: false, description: 'Build documentation')
|
||||||
|
|
||||||
|
option('test', type: 'boolean', value: false, description: 'Build the unit tests and debug programs')
|
||||||
|
|
||||||
|
option('syslog', type: 'feature', description: 'syslog support')
|
||||||
|
option('inotify', type: 'boolean', value: true, description: 'inotify support (for automatic database update)')
|
||||||
|
|
||||||
|
option('daemon', type: 'boolean', value: true, description: 'enable daemonization')
|
||||||
|
option('systemd', type: 'feature', description: 'systemd support')
|
||||||
|
|
||||||
|
option('systemd_system_unit_dir', type: 'string', description: 'systemd system service directory')
|
||||||
|
option('systemd_user_unit_dir', type: 'string', description: 'systemd user service directory')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Android
|
||||||
|
#
|
||||||
|
|
||||||
|
option('android_sdk', type: 'string', description: 'The path where Android SDK is installed')
|
||||||
|
option('android_ndk', type: 'string', description: 'The path where Android NDK is installed')
|
||||||
|
option('android_abi', type: 'string', value: 'armeabi-v7a', description: 'The Android ABI to be built')
|
||||||
|
|
||||||
|
option('android_strip', type: 'string', value: 'strip', description: 'The "strip" tool from the NDK')
|
||||||
|
|
||||||
|
option('android_debug_keystore', type: 'string', description: 'The keystore file used to sign debug APK files')
|
||||||
|
|
||||||
|
option('android_keystore', type: 'string', description: 'The keystore file used to sign APK files')
|
||||||
|
option('android_keyalias', type: 'string', description: 'The key alias used to sign APK files')
|
||||||
|
option('android_keypass', type: 'string', description: 'The password of the keystore used to sign APK files')
|
||||||
|
|
||||||
|
#
|
||||||
|
# System call support
|
||||||
|
#
|
||||||
|
|
||||||
|
option('epoll', type: 'boolean', value: true, description: 'Use epoll on Linux')
|
||||||
|
option('eventfd', type: 'boolean', value: true, description: 'Use eventfd() on Linux')
|
||||||
|
option('signalfd', type: 'boolean', value: true, description: 'Use signalfd() on Linux')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Network support
|
||||||
|
#
|
||||||
|
|
||||||
|
option('tcp', type: 'boolean', value: true, description: 'Support for clients connecting via TCP')
|
||||||
|
option('ipv6', type: 'feature', description: 'Support for IPv6')
|
||||||
|
option('local_socket', type: 'boolean', value: true, description: 'Support for clients connecting via local sockets')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Audio formats
|
||||||
|
#
|
||||||
|
|
||||||
|
option('dsd', type: 'boolean', value: true, description: 'Support the DSD audio format')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Database plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('database', type: 'boolean', value: true, description: 'enable support for the music database')
|
||||||
|
option('upnp', type: 'feature', description: 'UPnP client support')
|
||||||
|
option('libmpdclient', type: 'feature', description: 'libmpdclient support (for the proxy database plugin)')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Neighbor plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('neighbor', type: 'boolean', value: true, description: 'enable support for neighbor discovery')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Storage plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('udisks', type: 'feature', description: 'Support for removable media using udisks2')
|
||||||
|
option('webdav', type: 'feature', description: 'WebDAV support using CURL and Expat')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Playlist plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('cue', type: 'boolean', value: true, description: 'CUE sheet support')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Input plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('cdio_paranoia', type: 'feature', description: 'libcdio_paranoia input plugin')
|
||||||
|
option('curl', type: 'feature', description: 'HTTP client using CURL')
|
||||||
|
option('mms', type: 'feature', description: 'MMS protocol support using libmms')
|
||||||
|
option('nfs', type: 'feature', description: 'NFS protocol support using libnfs')
|
||||||
|
option('smbclient', type: 'feature', description: 'SMB support using libsmbclient')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Commercial services
|
||||||
|
#
|
||||||
|
|
||||||
|
option('qobuz', type: 'feature', description: 'Qobuz client')
|
||||||
|
option('soundcloud', type: 'feature', description: 'SoundCloud client')
|
||||||
|
option('tidal', type: 'feature', description: 'Tidal client')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Archive plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('bzip2', type: 'feature', description: 'bzip2 support using libbz2')
|
||||||
|
option('iso9660', type: 'feature', description: 'ISO9660 support using libiso9660')
|
||||||
|
option('zzip', type: 'feature', description: 'ZIP support using zziplib')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Tag plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('id3tag', type: 'feature', description: 'ID3 support using libid3tag')
|
||||||
|
option('chromaprint', type: 'feature', description: 'ChromaPrint / AcoustID support')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Decoder plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('adplug', type: 'feature', description: 'AdPlug decoder plugin')
|
||||||
|
option('audiofile', type: 'feature', description: 'libaudiofile decoder plugin')
|
||||||
|
option('faad', type: 'feature', description: 'AAC decoder using libfaad')
|
||||||
|
option('ffmpeg', type: 'feature', description: 'FFmpeg codec support')
|
||||||
|
option('flac', type: 'feature', description: 'FLAC decoder plugin')
|
||||||
|
option('fluidsynth', type: 'feature', description: 'fluidsynth MIDI decoder plugin')
|
||||||
|
option('gme', type: 'feature', description: 'Game Music Emulator decoder plugin')
|
||||||
|
option('mad', type: 'feature', description: 'MP3 decoder using libmad')
|
||||||
|
option('mikmod', type: 'feature', description: 'MikMod decoder plugin')
|
||||||
|
option('modplug', type: 'feature', description: 'Modplug decoder plugin')
|
||||||
|
option('mpcdec', type: 'feature', description: 'Musepack decoder plugin')
|
||||||
|
option('mpg123', type: 'feature', description: 'MP3 decoder using libmpg123')
|
||||||
|
option('opus', type: 'feature', description: 'Opus decoder plugin')
|
||||||
|
option('sidplay', type: 'feature', description: 'C64 SID support via libsidplayfp or libsidplay2')
|
||||||
|
option('sndfile', type: 'feature', description: 'libsndfile decoder plugin')
|
||||||
|
option('vorbis', type: 'feature', description: 'Vorbis decoder plugin')
|
||||||
|
option('wavpack', type: 'feature', description: 'WavPack decoder plugin')
|
||||||
|
option('wildmidi', type: 'feature', description: 'WildMidi decoder plugin')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Encoder plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('vorbisenc', type: 'feature', description: 'Vorbis encoder plugin')
|
||||||
|
option('lame', type: 'feature', description: 'LAME MP3 encoder plugin')
|
||||||
|
option('twolame', type: 'feature', description: 'TwoLAME MP2 encoder plugin')
|
||||||
|
option('shine', type: 'feature', description: 'shine MP3 encoder plugin')
|
||||||
|
option('wave_encoder', type: 'boolean', value: true, description: 'PCM wave encoder encoder plugin')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Filter plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('libsamplerate', type: 'feature', description: 'libsamplerate resampler')
|
||||||
|
option('soxr', type: 'feature', description: 'libsoxr resampler')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Output plugins
|
||||||
|
#
|
||||||
|
|
||||||
|
option('alsa', type: 'feature', description: 'ALSA support')
|
||||||
|
option('ao', type: 'feature', description: 'libao output plugin')
|
||||||
|
option('fifo', type: 'boolean', value: true, description: 'FIFO output plugin')
|
||||||
|
option('httpd', type: 'boolean', value: true, description: 'HTTP streaming output plugin')
|
||||||
|
option('jack', type: 'feature', description: 'JACK output plugin')
|
||||||
|
option('openal', type: 'feature', description: 'OpenAL output plugin')
|
||||||
|
option('oss', type: 'feature', description: 'Open Sound System support')
|
||||||
|
option('pipe', type: 'boolean', value: true, description: 'Pipe output plugin')
|
||||||
|
option('pulse', type: 'feature', description: 'PulseAudio support')
|
||||||
|
option('recorder', type: 'boolean', value: true, description: 'Recorder output plugin')
|
||||||
|
option('shout', type: 'feature', description: 'Shoutcast streaming support using libshout')
|
||||||
|
option('sndio', type: 'feature', description: 'sndio output plugin')
|
||||||
|
option('solaris_output', type: 'feature', description: 'Solaris /dev/audio support')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Misc libraries
|
||||||
|
#
|
||||||
|
|
||||||
|
option('dbus', type: 'feature', description: 'D-Bus support')
|
||||||
|
option('expat', type: 'feature', description: 'Expat XML support')
|
||||||
|
option('icu', type: 'feature', description: 'Use libicu for Unicode')
|
||||||
|
option('iconv', type: 'feature', description: 'Use iconv() for character set conversion')
|
||||||
|
option('pcre', type: 'feature', description: 'Enable regular expression support (using libpcre)')
|
||||||
|
option('sqlite', type: 'feature', description: 'SQLite database support (for stickers)')
|
||||||
|
option('yajl', type: 'feature', description: 'libyajl for YAML support')
|
||||||
|
option('zlib', type: 'feature', description: 'zlib support (for database compression)')
|
||||||
|
|
||||||
|
option('zeroconf', type: 'combo',
|
||||||
|
choices: ['auto', 'avahi', 'bonjour', 'disabled'],
|
||||||
|
value: 'auto',
|
||||||
|
description: 'Zeroconf support')
|
||||||
@@ -1,29 +0,0 @@
|
|||||||
def concatenate_cmdline_variables(src, names):
|
|
||||||
"""Find duplicate variable declarations on the given source list, and
|
|
||||||
concatenate the values of those in the 'names' list."""
|
|
||||||
|
|
||||||
# the result list being constructed
|
|
||||||
dest = []
|
|
||||||
|
|
||||||
# a map of variable name to destination list index
|
|
||||||
positions = {}
|
|
||||||
|
|
||||||
for item in src:
|
|
||||||
i = item.find('=')
|
|
||||||
if i > 0:
|
|
||||||
# it's a variable
|
|
||||||
name = item[:i]
|
|
||||||
if name in names:
|
|
||||||
# it's a known variable
|
|
||||||
if name in positions:
|
|
||||||
# already specified: concatenate instead of
|
|
||||||
# appending it
|
|
||||||
dest[positions[name]] += ' ' + item[i + 1:]
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
# not yet seen: append it and remember the list
|
|
||||||
# index
|
|
||||||
positions[name] = len(dest)
|
|
||||||
dest.append(item)
|
|
||||||
|
|
||||||
return dest
|
|
||||||
@@ -112,8 +112,8 @@ liblame = AutotoolsProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
ffmpeg = FfmpegProject(
|
ffmpeg = FfmpegProject(
|
||||||
'http://ffmpeg.org/releases/ffmpeg-4.0.2.tar.xz',
|
'http://ffmpeg.org/releases/ffmpeg-4.1.tar.xz',
|
||||||
'a95c0cc9eb990e94031d2183f2e6e444cc61c99f6f182d1575c433d62afb2f97',
|
'a38ec4d026efb58506a99ad5cd23d5a9793b4bf415f2c4c2e9c1bb444acd1994',
|
||||||
'lib/libavcodec.a',
|
'lib/libavcodec.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
@@ -341,8 +341,8 @@ ffmpeg = FfmpegProject(
|
|||||||
)
|
)
|
||||||
|
|
||||||
curl = AutotoolsProject(
|
curl = AutotoolsProject(
|
||||||
'http://curl.haxx.se/download/curl-7.61.1.tar.xz',
|
'http://curl.haxx.se/download/curl-7.62.0.tar.xz',
|
||||||
'3d5913d6a39bd22e68e34dff697fd6e4c3c81563f580c76fca2009315cd81891',
|
'dab5643a5fe775ae92570b9f3df6b0ef4bc2a827a959361fb130c73b721275c1',
|
||||||
'lib/libcurl.a',
|
'lib/libcurl.a',
|
||||||
[
|
[
|
||||||
'--disable-shared', '--enable-static',
|
'--disable-shared', '--enable-static',
|
||||||
|
|||||||
@@ -2,48 +2,46 @@ import os.path, subprocess, sys
|
|||||||
|
|
||||||
from build.project import Project
|
from build.project import Project
|
||||||
|
|
||||||
class MesonProject(Project):
|
def make_cross_file(toolchain):
|
||||||
def __init__(self, url, md5, installed, configure_args=[],
|
if toolchain.is_windows:
|
||||||
**kwargs):
|
system = 'windows'
|
||||||
Project.__init__(self, url, md5, installed, **kwargs)
|
windres = "windres = '%s'" % toolchain.windres
|
||||||
self.configure_args = configure_args
|
else:
|
||||||
|
system = 'linux'
|
||||||
|
windres = ''
|
||||||
|
|
||||||
def _make_cross_file(self, toolchain):
|
if toolchain.is_arm:
|
||||||
if toolchain.is_windows:
|
cpu_family = 'arm'
|
||||||
system = 'windows'
|
if toolchain.is_armv7:
|
||||||
|
cpu = 'armv7'
|
||||||
else:
|
else:
|
||||||
system = 'linux'
|
cpu = 'armv6'
|
||||||
|
elif toolchain.is_aarch64:
|
||||||
if toolchain.is_arm:
|
cpu_family = 'aarch64'
|
||||||
cpu_family = 'arm'
|
cpu = 'arm64-v8a'
|
||||||
if toolchain.is_armv7:
|
else:
|
||||||
cpu = 'armv7'
|
cpu_family = 'x86'
|
||||||
else:
|
if 'x86_64' in toolchain.arch:
|
||||||
cpu = 'armv6'
|
cpu = 'x86_64'
|
||||||
elif toolchain.is_aarch64:
|
|
||||||
cpu_family = 'aarch64'
|
|
||||||
cpu = 'arm64-v8a'
|
|
||||||
else:
|
else:
|
||||||
cpu_family = 'x86'
|
cpu = 'i686'
|
||||||
if 'x86_64' in toolchain.arch:
|
|
||||||
cpu = 'x86_64'
|
|
||||||
else:
|
|
||||||
cpu = 'i686'
|
|
||||||
|
|
||||||
# TODO: support more CPUs
|
# TODO: support more CPUs
|
||||||
endian = 'little'
|
endian = 'little'
|
||||||
|
|
||||||
# TODO: write pkg-config wrapper
|
# TODO: write pkg-config wrapper
|
||||||
|
|
||||||
path = os.path.join(toolchain.build_path, 'meson.cross')
|
path = os.path.join(toolchain.build_path, 'meson.cross')
|
||||||
os.makedirs(toolchain.build_path, exist_ok=True)
|
os.makedirs(toolchain.build_path, exist_ok=True)
|
||||||
with open(path, 'w') as f:
|
with open(path, 'w') as f:
|
||||||
f.write("""
|
f.write("""
|
||||||
[binaries]
|
[binaries]
|
||||||
c = '%s'
|
c = '%s'
|
||||||
cpp = '%s'
|
cpp = '%s'
|
||||||
ar = '%s'
|
ar = '%s'
|
||||||
strip = '%s'
|
strip = '%s'
|
||||||
|
pkgconfig = '%s'
|
||||||
|
%s
|
||||||
|
|
||||||
[properties]
|
[properties]
|
||||||
root = '%s'
|
root = '%s'
|
||||||
@@ -63,37 +61,48 @@ cpu_family = '%s'
|
|||||||
cpu = '%s'
|
cpu = '%s'
|
||||||
endian = '%s'
|
endian = '%s'
|
||||||
""" % (toolchain.cc, toolchain.cxx, toolchain.ar, toolchain.strip,
|
""" % (toolchain.cc, toolchain.cxx, toolchain.ar, toolchain.strip,
|
||||||
|
toolchain.pkg_config,
|
||||||
|
windres,
|
||||||
toolchain.install_prefix,
|
toolchain.install_prefix,
|
||||||
repr((toolchain.cppflags + ' ' + toolchain.cflags).split()),
|
repr((toolchain.cppflags + ' ' + toolchain.cflags).split()),
|
||||||
repr(toolchain.ldflags.split()),
|
repr(toolchain.ldflags.split() + toolchain.libs.split()),
|
||||||
repr((toolchain.cppflags + ' ' + toolchain.cxxflags).split()),
|
repr((toolchain.cppflags + ' ' + toolchain.cxxflags).split()),
|
||||||
repr(toolchain.ldflags.split()),
|
repr(toolchain.ldflags.split() + toolchain.libs.split()),
|
||||||
system, cpu_family, cpu, endian))
|
system, cpu_family, cpu, endian))
|
||||||
return path
|
return path
|
||||||
|
|
||||||
|
def configure(toolchain, src, build, args=()):
|
||||||
|
cross_file = make_cross_file(toolchain)
|
||||||
|
configure = [
|
||||||
|
'meson',
|
||||||
|
src, build,
|
||||||
|
|
||||||
|
'--prefix', toolchain.install_prefix,
|
||||||
|
|
||||||
|
# this is necessary because Meson uses Debian's build machine
|
||||||
|
# MultiArch path (e.g. "lib/x86_64-linux-gnu") for cross
|
||||||
|
# builds, which is obviously wrong
|
||||||
|
'--libdir', 'lib',
|
||||||
|
|
||||||
|
'--buildtype', 'plain',
|
||||||
|
|
||||||
|
'--default-library=static',
|
||||||
|
|
||||||
|
'--cross-file', cross_file,
|
||||||
|
] + args
|
||||||
|
|
||||||
|
subprocess.check_call(configure, env=toolchain.env)
|
||||||
|
|
||||||
|
class MesonProject(Project):
|
||||||
|
def __init__(self, url, md5, installed, configure_args=[],
|
||||||
|
**kwargs):
|
||||||
|
Project.__init__(self, url, md5, installed, **kwargs)
|
||||||
|
self.configure_args = configure_args
|
||||||
|
|
||||||
def configure(self, toolchain):
|
def configure(self, toolchain):
|
||||||
src = self.unpack(toolchain)
|
src = self.unpack(toolchain)
|
||||||
cross_file = self._make_cross_file(toolchain)
|
|
||||||
build = self.make_build_path(toolchain)
|
build = self.make_build_path(toolchain)
|
||||||
configure = [
|
configure(toolchain, src, build, self.configure_args)
|
||||||
'meson',
|
|
||||||
src, build,
|
|
||||||
|
|
||||||
'--prefix', toolchain.install_prefix,
|
|
||||||
|
|
||||||
# this is necessary because Meson uses Debian's build machine
|
|
||||||
# MultiArch path (e.g. "lib/x86_64-linux-gnu") for cross
|
|
||||||
# builds, which is obviously wrong
|
|
||||||
'--libdir', 'lib',
|
|
||||||
|
|
||||||
'--buildtype', 'plain',
|
|
||||||
|
|
||||||
'--default-library=static',
|
|
||||||
|
|
||||||
'--cross-file', cross_file,
|
|
||||||
] + self.configure_args
|
|
||||||
|
|
||||||
subprocess.check_call(configure, env=toolchain.env)
|
|
||||||
return build
|
return build
|
||||||
|
|
||||||
def build(self, toolchain):
|
def build(self, toolchain):
|
||||||
|
|||||||
@@ -18,5 +18,5 @@ class ZlibProject(Project):
|
|||||||
'INCLUDE_PATH='+ os.path.join(toolchain.install_prefix, 'include'),
|
'INCLUDE_PATH='+ os.path.join(toolchain.install_prefix, 'include'),
|
||||||
'LIBRARY_PATH=' + os.path.join(toolchain.install_prefix, 'lib'),
|
'LIBRARY_PATH=' + os.path.join(toolchain.install_prefix, 'lib'),
|
||||||
'BINARY_PATH=' + os.path.join(toolchain.install_prefix, 'bin'),
|
'BINARY_PATH=' + os.path.join(toolchain.install_prefix, 'bin'),
|
||||||
'SHARED_MODE=1'],
|
],
|
||||||
cwd=src, env=toolchain.env)
|
cwd=src, env=toolchain.env)
|
||||||
|
|||||||
@@ -1,47 +0,0 @@
|
|||||||
#!/usr/bin/env ruby
|
|
||||||
#
|
|
||||||
# This script verifies that every source includes config.h first.
|
|
||||||
# This is very important for consistent Large File Support.
|
|
||||||
#
|
|
||||||
|
|
||||||
def check_file(file)
|
|
||||||
first = true
|
|
||||||
file.each_line do |line|
|
|
||||||
if line =~ /^\#include\s+(\S+)/ then
|
|
||||||
if $1 == '"config.h"'
|
|
||||||
unless first
|
|
||||||
puts "#{file.path}: config.h included too late"
|
|
||||||
end
|
|
||||||
else
|
|
||||||
if first
|
|
||||||
puts "#{file.path}: config.h missing"
|
|
||||||
end
|
|
||||||
end
|
|
||||||
first = false
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_path(path)
|
|
||||||
File.open(path) do |file|
|
|
||||||
check_file(file)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
if ARGV.empty?
|
|
||||||
Dir["src/*.c"].each do |path|
|
|
||||||
check_path(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
Dir["src/*/*.c"].each do |path|
|
|
||||||
check_path(path)
|
|
||||||
end
|
|
||||||
|
|
||||||
Dir["test/*.c"].each do |path|
|
|
||||||
check_path(path)
|
|
||||||
end
|
|
||||||
else
|
|
||||||
ARGV.each do |path|
|
|
||||||
check_path(path)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -44,16 +44,32 @@ AudioFormat::ApplyMask(AudioFormat mask) noexcept
|
|||||||
StringBuffer<24>
|
StringBuffer<24>
|
||||||
ToString(const AudioFormat af) noexcept
|
ToString(const AudioFormat af) noexcept
|
||||||
{
|
{
|
||||||
|
StringBuffer<24> buffer;
|
||||||
|
char *p = buffer.data();
|
||||||
|
|
||||||
if (af.format == SampleFormat::DSD && af.sample_rate > 0 &&
|
if (af.format == SampleFormat::DSD && af.sample_rate > 0 &&
|
||||||
af.sample_rate % 44100 == 0) {
|
af.sample_rate % 44100 == 0) {
|
||||||
/* use shortcuts such as "dsd64" which implies the
|
/* use shortcuts such as "dsd64" which implies the
|
||||||
sample rate */
|
sample rate */
|
||||||
return StringFormat<24>("dsd%u:%u",
|
p += sprintf(p, "dsd%u:", af.sample_rate * 8 / 44100);
|
||||||
af.sample_rate * 8 / 44100,
|
} else {
|
||||||
af.channels);
|
const char *sample_format = af.format != SampleFormat::UNDEFINED
|
||||||
|
? sample_format_to_string(af.format)
|
||||||
|
: "*";
|
||||||
|
|
||||||
|
if (af.sample_rate > 0)
|
||||||
|
p += sprintf(p, "%u:%s:", af.sample_rate,
|
||||||
|
sample_format);
|
||||||
|
else
|
||||||
|
p += sprintf(p, "*:%s:", sample_format);
|
||||||
}
|
}
|
||||||
|
|
||||||
return StringFormat<24>("%u:%s:%u",
|
if (af.channels > 0)
|
||||||
af.sample_rate, sample_format_to_string(af.format),
|
p += sprintf(p, "%u", af.channels);
|
||||||
af.channels);
|
else {
|
||||||
|
*p++ = '*';
|
||||||
|
*p = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,7 +21,9 @@
|
|||||||
#define MPD_AUDIO_FORMAT_HXX
|
#define MPD_AUDIO_FORMAT_HXX
|
||||||
|
|
||||||
#include "pcm/SampleFormat.hxx"
|
#include "pcm/SampleFormat.hxx"
|
||||||
#include "Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
@@ -132,6 +134,11 @@ struct AudioFormat {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
gcc_pure
|
||||||
|
bool MatchMask(AudioFormat mask) const noexcept {
|
||||||
|
return WithMask(mask) == *this;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the size of each (mono) sample in bytes.
|
* Returns the size of each (mono) sample in bytes.
|
||||||
*/
|
*/
|
||||||
@@ -142,11 +149,28 @@ struct AudioFormat {
|
|||||||
*/
|
*/
|
||||||
unsigned GetFrameSize() const;
|
unsigned GetFrameSize() const;
|
||||||
|
|
||||||
/**
|
template<typename D>
|
||||||
* Returns the floating point factor which converts a time
|
constexpr auto TimeToFrames(D t) const noexcept {
|
||||||
* span to a storage size in bytes.
|
using Period = typename D::period;
|
||||||
*/
|
return ((t.count() * sample_rate) / Period::den) * Period::num;
|
||||||
double GetTimeToSize() const;
|
}
|
||||||
|
|
||||||
|
template<typename D>
|
||||||
|
constexpr size_t TimeToSize(D t) const noexcept {
|
||||||
|
return size_t(size_t(TimeToFrames(t)) * GetFrameSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D>
|
||||||
|
constexpr D FramesToTime(std::uintmax_t size) const noexcept {
|
||||||
|
using Rep = typename D::rep;
|
||||||
|
using Period = typename D::period;
|
||||||
|
return D(((Rep(1) * size / Period::num) * Period::den) / sample_rate);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename D>
|
||||||
|
constexpr D SizeToTime(std::uintmax_t size) const noexcept {
|
||||||
|
return FramesToTime<D>(size / GetFrameSize());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -207,12 +231,6 @@ AudioFormat::GetFrameSize() const
|
|||||||
return GetSampleSize() * channels;
|
return GetSampleSize() * channels;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double
|
|
||||||
AudioFormat::GetTimeToSize() const
|
|
||||||
{
|
|
||||||
return sample_rate * GetFrameSize();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Renders the #AudioFormat object into a string, e.g. for printing
|
* Renders the #AudioFormat object into a string, e.g. for printing
|
||||||
* it in a log file.
|
* it in a log file.
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,7 +22,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "AudioParser.hxx"
|
#include "AudioParser.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
@@ -44,10 +43,9 @@ ParseSampleRate(const char *src, bool mask, const char **endptr_r)
|
|||||||
|
|
||||||
value = strtoul(src, &endptr, 10);
|
value = strtoul(src, &endptr, 10);
|
||||||
if (endptr == src) {
|
if (endptr == src) {
|
||||||
throw std::runtime_error("Failed to parse the sample rate");
|
throw std::invalid_argument("Failed to parse the sample rate");
|
||||||
} else if (!audio_valid_sample_rate(value))
|
} else if (!audio_valid_sample_rate(value))
|
||||||
throw FormatRuntimeError("Invalid sample rate: %lu",
|
throw FormatInvalidArgument("Invalid sample rate: %lu", value);
|
||||||
value);
|
|
||||||
|
|
||||||
*endptr_r = endptr;
|
*endptr_r = endptr;
|
||||||
return value;
|
return value;
|
||||||
@@ -77,7 +75,7 @@ ParseSampleFormat(const char *src, bool mask, const char **endptr_r)
|
|||||||
|
|
||||||
value = strtoul(src, &endptr, 10);
|
value = strtoul(src, &endptr, 10);
|
||||||
if (endptr == src)
|
if (endptr == src)
|
||||||
throw std::runtime_error("Failed to parse the sample format");
|
throw std::invalid_argument("Failed to parse the sample format");
|
||||||
|
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 8:
|
case 8:
|
||||||
@@ -101,7 +99,8 @@ ParseSampleFormat(const char *src, bool mask, const char **endptr_r)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw FormatRuntimeError("Invalid sample format: %lu", value);
|
throw FormatInvalidArgument("Invalid sample format: %lu",
|
||||||
|
value);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(audio_valid_sample_format(sample_format));
|
assert(audio_valid_sample_format(sample_format));
|
||||||
@@ -123,9 +122,10 @@ ParseChannelCount(const char *src, bool mask, const char **endptr_r)
|
|||||||
|
|
||||||
value = strtoul(src, &endptr, 10);
|
value = strtoul(src, &endptr, 10);
|
||||||
if (endptr == src)
|
if (endptr == src)
|
||||||
throw std::runtime_error("Failed to parse the channel count");
|
throw std::invalid_argument("Failed to parse the channel count");
|
||||||
else if (!audio_valid_channel_count(value))
|
else if (!audio_valid_channel_count(value))
|
||||||
throw FormatRuntimeError("Invalid channel count: %u", value);
|
throw FormatInvalidArgument("Invalid channel count: %u",
|
||||||
|
value);
|
||||||
|
|
||||||
*endptr_r = endptr;
|
*endptr_r = endptr;
|
||||||
return value;
|
return value;
|
||||||
@@ -151,7 +151,8 @@ ParseAudioFormat(const char *src, bool mask)
|
|||||||
src = endptr + 1;
|
src = endptr + 1;
|
||||||
dest.channels = ParseChannelCount(src, mask, &src);
|
dest.channels = ParseChannelCount(src, mask, &src);
|
||||||
if (*src != 0)
|
if (*src != 0)
|
||||||
throw FormatRuntimeError("Extra data after channel count: %s", src);
|
throw FormatInvalidArgument("Extra data after channel count: %s",
|
||||||
|
src);
|
||||||
|
|
||||||
return dest;
|
return dest;
|
||||||
}
|
}
|
||||||
@@ -162,21 +163,22 @@ ParseAudioFormat(const char *src, bool mask)
|
|||||||
dest.sample_rate = ParseSampleRate(src, mask, &src);
|
dest.sample_rate = ParseSampleRate(src, mask, &src);
|
||||||
|
|
||||||
if (*src++ != ':')
|
if (*src++ != ':')
|
||||||
throw std::runtime_error("Sample format missing");
|
throw std::invalid_argument("Sample format missing");
|
||||||
|
|
||||||
/* parse sample format */
|
/* parse sample format */
|
||||||
|
|
||||||
dest.format = ParseSampleFormat(src, mask, &src);
|
dest.format = ParseSampleFormat(src, mask, &src);
|
||||||
|
|
||||||
if (*src++ != ':')
|
if (*src++ != ':')
|
||||||
throw std::runtime_error("Channel count missing");
|
throw std::invalid_argument("Channel count missing");
|
||||||
|
|
||||||
/* parse channel count */
|
/* parse channel count */
|
||||||
|
|
||||||
dest.channels = ParseChannelCount(src, mask, &src);
|
dest.channels = ParseChannelCount(src, mask, &src);
|
||||||
|
|
||||||
if (*src != 0)
|
if (*src != 0)
|
||||||
throw FormatRuntimeError("Extra data after channel count: %s", src);
|
throw FormatInvalidArgument("Extra data after channel count: %s",
|
||||||
|
src);
|
||||||
|
|
||||||
assert(mask
|
assert(mask
|
||||||
? dest.IsMaskValid()
|
? dest.IsMaskValid()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "CheckAudioFormat.hxx"
|
#include "CheckAudioFormat.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,13 +24,14 @@
|
|||||||
#include <utility>
|
#include <utility>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
|
using FloatDuration = std::chrono::duration<double>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
class SongTime : public std::chrono::duration<std::uint32_t, std::milli> {
|
class SongTime : public std::chrono::duration<std::uint32_t, std::milli> {
|
||||||
typedef std::chrono::duration<std::uint32_t, std::milli> Base;
|
typedef std::chrono::duration<std::uint32_t, std::milli> Base;
|
||||||
typedef Base::rep rep;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SongTime() = default;
|
SongTime() = default;
|
||||||
@@ -42,6 +43,11 @@ public:
|
|||||||
return SongTime(Base::zero());
|
return SongTime(Base::zero());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename D>
|
||||||
|
static constexpr SongTime Cast(D src) {
|
||||||
|
return SongTime(std::chrono::duration_cast<Base>(src));
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr SongTime FromS(unsigned s) {
|
static constexpr SongTime FromS(unsigned s) {
|
||||||
return SongTime(rep(s) * 1000);
|
return SongTime(rep(s) * 1000);
|
||||||
}
|
}
|
||||||
@@ -114,7 +120,6 @@ public:
|
|||||||
*/
|
*/
|
||||||
class SignedSongTime : public std::chrono::duration<std::int32_t, std::milli> {
|
class SignedSongTime : public std::chrono::duration<std::int32_t, std::milli> {
|
||||||
typedef std::chrono::duration<std::int32_t, std::milli> Base;
|
typedef std::chrono::duration<std::int32_t, std::milli> Base;
|
||||||
typedef Base::rep rep;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SignedSongTime() = default;
|
SignedSongTime() = default;
|
||||||
@@ -138,6 +143,11 @@ public:
|
|||||||
return SignedSongTime(-1);
|
return SignedSongTime(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename D>
|
||||||
|
static constexpr SongTime Cast(D src) {
|
||||||
|
return SongTime(std::chrono::duration_cast<Base>(src));
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr SignedSongTime FromS(int s) {
|
static constexpr SignedSongTime FromS(int s) {
|
||||||
return SignedSongTime(rep(s) * 1000);
|
return SignedSongTime(rep(s) * 1000);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,10 +19,11 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "CommandLine.hxx"
|
#include "CommandLine.hxx"
|
||||||
|
#include "GitVersion.hxx"
|
||||||
#include "ls.hxx"
|
#include "ls.hxx"
|
||||||
#include "LogInit.hxx"
|
#include "LogInit.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/File.hxx"
|
||||||
#include "decoder/DecoderList.hxx"
|
#include "decoder/DecoderList.hxx"
|
||||||
#include "decoder/DecoderPlugin.hxx"
|
#include "decoder/DecoderPlugin.hxx"
|
||||||
#include "output/Registry.hxx"
|
#include "output/Registry.hxx"
|
||||||
@@ -67,53 +68,57 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
namespace {
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
#define CONFIG_FILE_LOCATION PATH_LITERAL("mpd\\mpd.conf")
|
constexpr auto CONFIG_FILE_LOCATION = Path::FromFS(PATH_LITERAL("mpd\\mpd.conf"));
|
||||||
#define APP_CONFIG_FILE_LOCATION PATH_LITERAL("conf\\mpd.conf")
|
constexpr auto APP_CONFIG_FILE_LOCATION = Path::FromFS(PATH_LITERAL("conf\\mpd.conf"));
|
||||||
#else
|
#else
|
||||||
#define USER_CONFIG_FILE_LOCATION1 PATH_LITERAL(".mpdconf")
|
constexpr auto USER_CONFIG_FILE_LOCATION1 = Path::FromFS(PATH_LITERAL(".mpdconf"));
|
||||||
#define USER_CONFIG_FILE_LOCATION2 PATH_LITERAL(".mpd/mpd.conf")
|
constexpr auto USER_CONFIG_FILE_LOCATION2 = Path::FromFS(PATH_LITERAL(".mpd/mpd.conf"));
|
||||||
#define USER_CONFIG_FILE_LOCATION_XDG PATH_LITERAL("mpd/mpd.conf")
|
constexpr auto USER_CONFIG_FILE_LOCATION_XDG = Path::FromFS(PATH_LITERAL("mpd/mpd.conf"));
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
static constexpr OptionDef opt_kill(
|
enum Option {
|
||||||
"kill", "kill the currently running mpd session");
|
OPTION_KILL,
|
||||||
static constexpr OptionDef opt_no_config(
|
OPTION_NO_CONFIG,
|
||||||
"no-config", "don't read from config");
|
OPTION_NO_DAEMON,
|
||||||
static constexpr OptionDef opt_no_daemon(
|
OPTION_STDOUT,
|
||||||
"no-daemon", "don't detach from console");
|
OPTION_STDERR,
|
||||||
static constexpr OptionDef opt_stdout(
|
OPTION_VERBOSE,
|
||||||
"stdout", nullptr); // hidden, compatibility with old versions
|
OPTION_VERSION,
|
||||||
static constexpr OptionDef opt_stderr(
|
OPTION_HELP,
|
||||||
"stderr", "print messages to stderr");
|
OPTION_HELP2,
|
||||||
static constexpr OptionDef opt_verbose(
|
};
|
||||||
"verbose", 'v', "verbose logging");
|
|
||||||
static constexpr OptionDef opt_version(
|
static constexpr OptionDef option_defs[] = {
|
||||||
"version", 'V', "print version number");
|
{"kill", "kill the currently running mpd session"},
|
||||||
static constexpr OptionDef opt_help(
|
{"no-config", "don't read from config"},
|
||||||
"help", 'h', "show help options");
|
{"no-daemon", "don't detach from console"},
|
||||||
static constexpr OptionDef opt_help_alt(
|
{"stdout", nullptr}, // hidden, compatibility with old versions
|
||||||
nullptr, '?', nullptr); // hidden, standard alias for --help
|
{"stderr", "print messages to stderr"},
|
||||||
|
{"verbose", 'v', "verbose logging"},
|
||||||
|
{"version", 'V', "print version number"},
|
||||||
|
{"help", 'h', "show help options"},
|
||||||
|
{nullptr, '?', nullptr}, // hidden, standard alias for --help
|
||||||
|
};
|
||||||
|
|
||||||
static constexpr Domain cmdline_domain("cmdline");
|
static constexpr Domain cmdline_domain("cmdline");
|
||||||
|
|
||||||
gcc_noreturn
|
gcc_noreturn
|
||||||
static void version(void)
|
static void version(void)
|
||||||
{
|
{
|
||||||
printf("Music Player Daemon " VERSION
|
printf("Music Player Daemon " VERSION " (%s)\n"
|
||||||
#ifdef GIT_COMMIT
|
|
||||||
" (" GIT_COMMIT ")"
|
|
||||||
#endif
|
|
||||||
"\n"
|
"\n"
|
||||||
"\n"
|
"Copyright 2003-2007 Warren Dukes <warren.dukes@gmail.com>\n"
|
||||||
"Copyright (C) 2003-2007 Warren Dukes <warren.dukes@gmail.com>\n"
|
"Copyright 2008-2018 Max Kellermann <max.kellermann@gmail.com>\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
|
||||||
"\n"
|
"\n"
|
||||||
"Database plugins:\n");
|
"Database plugins:\n",
|
||||||
|
GIT_VERSION);
|
||||||
|
|
||||||
for (auto i = database_plugins; *i != nullptr; ++i)
|
for (auto i = database_plugins; *i != nullptr; ++i)
|
||||||
printf(" %s", (*i)->name);
|
printf(" %s", (*i)->name);
|
||||||
@@ -195,7 +200,12 @@ static void version(void)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
"\n"
|
"\n"
|
||||||
"Input plugins:\n");
|
"Input plugins:\n"
|
||||||
|
" file"
|
||||||
|
#ifdef ENABLE_ARCHIVE
|
||||||
|
" archive"
|
||||||
|
#endif
|
||||||
|
);
|
||||||
input_plugins_for_each(plugin)
|
input_plugins_for_each(plugin)
|
||||||
printf(" %s", plugin->name);
|
printf(" %s", plugin->name);
|
||||||
|
|
||||||
@@ -213,6 +223,12 @@ static void version(void)
|
|||||||
#ifdef HAVE_AVAHI
|
#ifdef HAVE_AVAHI
|
||||||
" avahi"
|
" avahi"
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_DBUS
|
||||||
|
" dbus"
|
||||||
|
#endif
|
||||||
|
#ifdef ENABLE_UDISKS
|
||||||
|
" udisks"
|
||||||
|
#endif
|
||||||
#ifdef USE_EPOLL
|
#ifdef USE_EPOLL
|
||||||
" epoll"
|
" epoll"
|
||||||
#endif
|
#endif
|
||||||
@@ -265,89 +281,85 @@ static void help(void)
|
|||||||
"\n"
|
"\n"
|
||||||
"Options:\n");
|
"Options:\n");
|
||||||
|
|
||||||
PrintOption(opt_help);
|
for (const auto &i : option_defs)
|
||||||
PrintOption(opt_kill);
|
if(i.HasDescription() == true) // hide hidden options from help print
|
||||||
PrintOption(opt_no_config);
|
PrintOption(i);
|
||||||
PrintOption(opt_no_daemon);
|
|
||||||
PrintOption(opt_stderr);
|
|
||||||
PrintOption(opt_verbose);
|
|
||||||
PrintOption(opt_version);
|
|
||||||
|
|
||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ConfigLoader
|
class ConfigLoader
|
||||||
{
|
{
|
||||||
|
ConfigData &config;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
explicit ConfigLoader(ConfigData &_config) noexcept
|
||||||
|
:config(_config) {}
|
||||||
|
|
||||||
bool TryFile(const Path path);
|
bool TryFile(const Path path);
|
||||||
bool TryFile(const AllocatedPath &base_path,
|
bool TryFile(const AllocatedPath &base_path, Path path);
|
||||||
PathTraitsFS::const_pointer_type path);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ConfigLoader::TryFile(Path path)
|
bool ConfigLoader::TryFile(Path path)
|
||||||
{
|
{
|
||||||
if (FileExists(path)) {
|
if (FileExists(path)) {
|
||||||
ReadConfigFile(path);
|
ReadConfigFile(config, path);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ConfigLoader::TryFile(const AllocatedPath &base_path,
|
bool ConfigLoader::TryFile(const AllocatedPath &base_path, Path path)
|
||||||
PathTraitsFS::const_pointer_type path)
|
|
||||||
{
|
{
|
||||||
if (base_path.IsNull())
|
if (base_path.IsNull())
|
||||||
return false;
|
return false;
|
||||||
auto full_path = AllocatedPath::Build(base_path, path);
|
auto full_path = base_path / path;
|
||||||
return TryFile(full_path);
|
return TryFile(full_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
ParseCommandLine(int argc, char **argv, struct options *options)
|
ParseCommandLine(int argc, char **argv, struct options &options,
|
||||||
|
ConfigData &config)
|
||||||
{
|
{
|
||||||
bool use_config_file = true;
|
bool use_config_file = true;
|
||||||
options->kill = false;
|
|
||||||
options->daemon = true;
|
|
||||||
options->log_stderr = false;
|
|
||||||
options->verbose = false;
|
|
||||||
|
|
||||||
// First pass: handle command line options
|
// First pass: handle command line options
|
||||||
OptionParser parser(argc, argv);
|
OptionParser parser(option_defs, argc, argv);
|
||||||
while (parser.HasEntries()) {
|
while (auto o = parser.Next()) {
|
||||||
if (!parser.ParseNext())
|
switch (Option(o.index)) {
|
||||||
continue;
|
case OPTION_KILL:
|
||||||
if (parser.CheckOption(opt_kill)) {
|
options.kill = true;
|
||||||
options->kill = true;
|
break;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_no_config)) {
|
|
||||||
use_config_file = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_no_daemon)) {
|
|
||||||
options->daemon = false;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_stderr, opt_stdout)) {
|
|
||||||
options->log_stderr = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_verbose)) {
|
|
||||||
options->verbose = true;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if (parser.CheckOption(opt_version))
|
|
||||||
version();
|
|
||||||
if (parser.CheckOption(opt_help, opt_help_alt))
|
|
||||||
help();
|
|
||||||
|
|
||||||
throw FormatRuntimeError("invalid option: %s",
|
case OPTION_NO_CONFIG:
|
||||||
parser.GetOption());
|
use_config_file = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_NO_DAEMON:
|
||||||
|
options.daemon = false;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_STDOUT:
|
||||||
|
case OPTION_STDERR:
|
||||||
|
options.log_stderr = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_VERBOSE:
|
||||||
|
options.verbose = true;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPTION_VERSION:
|
||||||
|
version();
|
||||||
|
|
||||||
|
case OPTION_HELP:
|
||||||
|
case OPTION_HELP2:
|
||||||
|
help();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* initialize the logging library, so the configuration file
|
/* initialize the logging library, so the configuration file
|
||||||
parser can use it already */
|
parser can use it already */
|
||||||
log_early_init(options->verbose);
|
log_early_init(options.verbose);
|
||||||
|
|
||||||
if (!use_config_file) {
|
if (!use_config_file) {
|
||||||
LogDebug(cmdline_domain,
|
LogDebug(cmdline_domain,
|
||||||
@@ -357,11 +369,9 @@ ParseCommandLine(int argc, char **argv, struct options *options)
|
|||||||
|
|
||||||
// Second pass: find non-option parameters (i.e. config file)
|
// Second pass: find non-option parameters (i.e. config file)
|
||||||
const char *config_file = nullptr;
|
const char *config_file = nullptr;
|
||||||
for (int i = 1; i < argc; ++i) {
|
for (const char *i : parser.GetRemaining()) {
|
||||||
if (OptionParser::IsOption(argv[i]))
|
|
||||||
continue;
|
|
||||||
if (config_file == nullptr) {
|
if (config_file == nullptr) {
|
||||||
config_file = argv[i];
|
config_file = i;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -377,16 +387,16 @@ ParseCommandLine(int argc, char **argv, struct options *options)
|
|||||||
if (result <= 0)
|
if (result <= 0)
|
||||||
throw MakeLastError("MultiByteToWideChar() failed");
|
throw MakeLastError("MultiByteToWideChar() failed");
|
||||||
|
|
||||||
ReadConfigFile(Path::FromFS(buffer));
|
ReadConfigFile(config, Path::FromFS(buffer));
|
||||||
#else
|
#else
|
||||||
ReadConfigFile(Path::FromFS(config_file));
|
ReadConfigFile(config, Path::FromFS(config_file));
|
||||||
#endif
|
#endif
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* use default configuration file path */
|
/* use default configuration file path */
|
||||||
|
|
||||||
ConfigLoader loader;
|
ConfigLoader loader(config);
|
||||||
|
|
||||||
bool found =
|
bool found =
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,14 +20,17 @@
|
|||||||
#ifndef MPD_COMMAND_LINE_HXX
|
#ifndef MPD_COMMAND_LINE_HXX
|
||||||
#define MPD_COMMAND_LINE_HXX
|
#define MPD_COMMAND_LINE_HXX
|
||||||
|
|
||||||
|
struct ConfigData;
|
||||||
|
|
||||||
struct options {
|
struct options {
|
||||||
bool kill;
|
bool kill = false;
|
||||||
bool daemon;
|
bool daemon = true;
|
||||||
bool log_stderr;
|
bool log_stderr = false;
|
||||||
bool verbose;
|
bool verbose = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
void
|
void
|
||||||
ParseCommandLine(int argc, char **argv, struct options *options);
|
ParseCommandLine(int argc, char **argv, struct options &options,
|
||||||
|
ConfigData &config);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
22
src/GitVersion.cxx
Normal file
22
src/GitVersion.cxx
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2003-2018 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 "GitVersion.hxx"
|
||||||
|
|
||||||
|
char GIT_VERSION[] = "@VCS_TAG@";
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -17,9 +17,9 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef MPD_OUTPUT_CONTROL_HXX
|
#ifndef MPD_GIT_VERSION_HXX
|
||||||
#define MPD_OUTPUT_CONTROL_HXX
|
#define MPD_GIT_VERSION_HXX
|
||||||
|
|
||||||
struct AudioOutput;
|
extern char GIT_VERSION[];
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
119
src/IOThread.cxx
119
src/IOThread.cxx
@@ -1,119 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "IOThread.hxx"
|
|
||||||
#include "thread/Mutex.hxx"
|
|
||||||
#include "thread/Cond.hxx"
|
|
||||||
#include "thread/Thread.hxx"
|
|
||||||
#include "thread/Name.hxx"
|
|
||||||
#include "event/Loop.hxx"
|
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
|
|
||||||
static struct IOThread {
|
|
||||||
Mutex mutex;
|
|
||||||
Cond cond;
|
|
||||||
|
|
||||||
EventLoop *loop;
|
|
||||||
Thread thread;
|
|
||||||
|
|
||||||
IOThread():thread(BIND_THIS_METHOD(Run)) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void Run() noexcept;
|
|
||||||
} io;
|
|
||||||
|
|
||||||
void
|
|
||||||
io_thread_run(void)
|
|
||||||
{
|
|
||||||
assert(io_thread_inside());
|
|
||||||
assert(io.loop != nullptr);
|
|
||||||
|
|
||||||
io.loop->Run();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline void
|
|
||||||
IOThread::Run() noexcept
|
|
||||||
{
|
|
||||||
SetThreadName("io");
|
|
||||||
|
|
||||||
/* lock+unlock to synchronize with io_thread_start(), to be
|
|
||||||
sure that io.thread is set */
|
|
||||||
mutex.lock();
|
|
||||||
mutex.unlock();
|
|
||||||
|
|
||||||
io_thread_run();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
io_thread_init(void)
|
|
||||||
{
|
|
||||||
assert(io.loop == nullptr);
|
|
||||||
assert(!io.thread.IsDefined());
|
|
||||||
|
|
||||||
io.loop = new EventLoop();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
io_thread_start()
|
|
||||||
{
|
|
||||||
assert(io.loop != nullptr);
|
|
||||||
assert(!io.thread.IsDefined());
|
|
||||||
|
|
||||||
const std::lock_guard<Mutex> protect(io.mutex);
|
|
||||||
io.thread.Start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
io_thread_quit(void)
|
|
||||||
{
|
|
||||||
assert(io.loop != nullptr);
|
|
||||||
|
|
||||||
io.loop->Break();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
io_thread_deinit(void)
|
|
||||||
{
|
|
||||||
if (io.thread.IsDefined()) {
|
|
||||||
io_thread_quit();
|
|
||||||
io.thread.Join();
|
|
||||||
}
|
|
||||||
|
|
||||||
delete io.loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
EventLoop &
|
|
||||||
io_thread_get() noexcept
|
|
||||||
{
|
|
||||||
assert(io.loop != nullptr);
|
|
||||||
|
|
||||||
return *io.loop;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
|
|
||||||
bool
|
|
||||||
io_thread_inside() noexcept
|
|
||||||
{
|
|
||||||
return io.thread.IsInside();
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -17,10 +17,9 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "IcyMetaDataParser.hxx"
|
#include "IcyMetaDataParser.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
#include "tag/TagBuilder.hxx"
|
#include "tag/Builder.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "util/StringView.hxx"
|
#include "util/StringView.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
@@ -31,7 +30,7 @@
|
|||||||
static constexpr Domain icy_metadata_domain("icy_metadata");
|
static constexpr Domain icy_metadata_domain("icy_metadata");
|
||||||
|
|
||||||
void
|
void
|
||||||
IcyMetaDataParser::Reset()
|
IcyMetaDataParser::Reset() noexcept
|
||||||
{
|
{
|
||||||
if (!IsDefined())
|
if (!IsDefined())
|
||||||
return;
|
return;
|
||||||
@@ -39,14 +38,14 @@ IcyMetaDataParser::Reset()
|
|||||||
if (data_rest == 0 && meta_size > 0)
|
if (data_rest == 0 && meta_size > 0)
|
||||||
delete[] meta_data;
|
delete[] meta_data;
|
||||||
|
|
||||||
delete tag;
|
tag.reset();
|
||||||
|
|
||||||
data_rest = data_size;
|
data_rest = data_size;
|
||||||
meta_size = 0;
|
meta_size = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
IcyMetaDataParser::Data(size_t length)
|
IcyMetaDataParser::Data(size_t length) noexcept
|
||||||
{
|
{
|
||||||
assert(length > 0);
|
assert(length > 0);
|
||||||
|
|
||||||
@@ -66,7 +65,7 @@ IcyMetaDataParser::Data(size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
icy_add_item(TagBuilder &tag, TagType type, const char *value)
|
icy_add_item(TagBuilder &tag, TagType type, const char *value) noexcept
|
||||||
{
|
{
|
||||||
size_t length = strlen(value);
|
size_t length = strlen(value);
|
||||||
|
|
||||||
@@ -81,7 +80,8 @@ icy_add_item(TagBuilder &tag, TagType type, const char *value)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
icy_parse_tag_item(TagBuilder &tag, const char *name, const char *value)
|
icy_parse_tag_item(TagBuilder &tag,
|
||||||
|
const char *name, const char *value) noexcept
|
||||||
{
|
{
|
||||||
if (strcmp(name, "StreamTitle") == 0)
|
if (strcmp(name, "StreamTitle") == 0)
|
||||||
icy_add_item(tag, TAG_TITLE, value);
|
icy_add_item(tag, TAG_TITLE, value);
|
||||||
@@ -96,7 +96,7 @@ icy_parse_tag_item(TagBuilder &tag, const char *name, const char *value)
|
|||||||
* that also fails, return #end.
|
* that also fails, return #end.
|
||||||
*/
|
*/
|
||||||
static char *
|
static char *
|
||||||
find_end_quote(char *p, char *const end)
|
find_end_quote(char *p, char *const end) noexcept
|
||||||
{
|
{
|
||||||
char *fallback = std::find(p, end, '\'');
|
char *fallback = std::find(p, end, '\'');
|
||||||
if (fallback >= end - 1 || fallback[1] == ';')
|
if (fallback >= end - 1 || fallback[1] == ';')
|
||||||
@@ -115,8 +115,8 @@ find_end_quote(char *p, char *const end)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static Tag *
|
static std::unique_ptr<Tag>
|
||||||
icy_parse_tag(char *p, char *const end)
|
icy_parse_tag(char *p, char *const end) noexcept
|
||||||
{
|
{
|
||||||
assert(p != nullptr);
|
assert(p != nullptr);
|
||||||
assert(end != nullptr);
|
assert(end != nullptr);
|
||||||
@@ -165,7 +165,7 @@ icy_parse_tag(char *p, char *const end)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
IcyMetaDataParser::Meta(const void *data, size_t length)
|
IcyMetaDataParser::Meta(const void *data, size_t length) noexcept
|
||||||
{
|
{
|
||||||
const unsigned char *p = (const unsigned char *)data;
|
const unsigned char *p = (const unsigned char *)data;
|
||||||
|
|
||||||
@@ -208,8 +208,6 @@ IcyMetaDataParser::Meta(const void *data, size_t length)
|
|||||||
if (meta_position == meta_size) {
|
if (meta_position == meta_size) {
|
||||||
/* parse */
|
/* parse */
|
||||||
|
|
||||||
delete tag;
|
|
||||||
|
|
||||||
tag = icy_parse_tag(meta_data, meta_data + meta_size);
|
tag = icy_parse_tag(meta_data, meta_data + meta_size);
|
||||||
delete[] meta_data;
|
delete[] meta_data;
|
||||||
|
|
||||||
@@ -223,7 +221,7 @@ IcyMetaDataParser::Meta(const void *data, size_t length)
|
|||||||
}
|
}
|
||||||
|
|
||||||
size_t
|
size_t
|
||||||
IcyMetaDataParser::ParseInPlace(void *data, size_t length)
|
IcyMetaDataParser::ParseInPlace(void *data, size_t length) noexcept
|
||||||
{
|
{
|
||||||
uint8_t *const dest0 = (uint8_t *)data;
|
uint8_t *const dest0 = (uint8_t *)data;
|
||||||
uint8_t *dest = dest0;
|
uint8_t *dest = dest0;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,21 +20,22 @@
|
|||||||
#ifndef MPD_ICY_META_DATA_PARSER_HXX
|
#ifndef MPD_ICY_META_DATA_PARSER_HXX
|
||||||
#define MPD_ICY_META_DATA_PARSER_HXX
|
#define MPD_ICY_META_DATA_PARSER_HXX
|
||||||
|
|
||||||
|
#include "tag/Tag.hxx"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
|
||||||
struct Tag;
|
|
||||||
|
|
||||||
class IcyMetaDataParser {
|
class IcyMetaDataParser {
|
||||||
size_t data_size, data_rest;
|
size_t data_size = 0, data_rest;
|
||||||
|
|
||||||
size_t meta_size, meta_position;
|
size_t meta_size, meta_position;
|
||||||
char *meta_data;
|
char *meta_data;
|
||||||
|
|
||||||
Tag *tag;
|
std::unique_ptr<Tag> tag;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
IcyMetaDataParser():data_size(0) {}
|
~IcyMetaDataParser() noexcept {
|
||||||
~IcyMetaDataParser() {
|
|
||||||
Reset();
|
Reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ public:
|
|||||||
* Initialize an enabled icy_metadata object with the specified
|
* Initialize an enabled icy_metadata object with the specified
|
||||||
* data_size (from the icy-metaint HTTP response header).
|
* data_size (from the icy-metaint HTTP response header).
|
||||||
*/
|
*/
|
||||||
void Start(size_t _data_size) {
|
void Start(size_t _data_size) noexcept {
|
||||||
data_size = data_rest = _data_size;
|
data_size = data_rest = _data_size;
|
||||||
meta_size = 0;
|
meta_size = 0;
|
||||||
tag = nullptr;
|
tag = nullptr;
|
||||||
@@ -51,12 +52,12 @@ public:
|
|||||||
/**
|
/**
|
||||||
* Resets the icy_metadata. Call this after rewinding the stream.
|
* Resets the icy_metadata. Call this after rewinding the stream.
|
||||||
*/
|
*/
|
||||||
void Reset();
|
void Reset() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks whether the icy_metadata object is enabled.
|
* Checks whether the icy_metadata object is enabled.
|
||||||
*/
|
*/
|
||||||
bool IsDefined() const {
|
bool IsDefined() const noexcept {
|
||||||
return data_size > 0;
|
return data_size > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,26 +67,24 @@ public:
|
|||||||
* return value is smaller than "length", the caller should invoke
|
* return value is smaller than "length", the caller should invoke
|
||||||
* icy_meta().
|
* icy_meta().
|
||||||
*/
|
*/
|
||||||
size_t Data(size_t length);
|
size_t Data(size_t length) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads metadata from the stream. Returns the number of bytes
|
* Reads metadata from the stream. Returns the number of bytes
|
||||||
* consumed. If the return value is smaller than "length", the caller
|
* consumed. If the return value is smaller than "length", the caller
|
||||||
* should invoke icy_data().
|
* should invoke icy_data().
|
||||||
*/
|
*/
|
||||||
size_t Meta(const void *data, size_t length);
|
size_t Meta(const void *data, size_t length) noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Parse data and eliminate metadata.
|
* Parse data and eliminate metadata.
|
||||||
*
|
*
|
||||||
* @return the number of data bytes remaining in the buffer
|
* @return the number of data bytes remaining in the buffer
|
||||||
*/
|
*/
|
||||||
size_t ParseInPlace(void *data, size_t length);
|
size_t ParseInPlace(void *data, size_t length) noexcept;
|
||||||
|
|
||||||
Tag *ReadTag() {
|
std::unique_ptr<Tag> ReadTag() noexcept {
|
||||||
Tag *result = tag;
|
return std::exchange(tag, nullptr);
|
||||||
tag = nullptr;
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,7 +22,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "Main.hxx"
|
#include "Main.hxx"
|
||||||
#include "Instance.hxx"
|
#include "Instance.hxx"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,7 +22,6 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "IdleFlags.hxx"
|
#include "IdleFlags.hxx"
|
||||||
#include "util/ASCII.hxx"
|
#include "util/ASCII.hxx"
|
||||||
|
|
||||||
@@ -42,6 +41,7 @@ static const char *const idle_names[] = {
|
|||||||
"message",
|
"message",
|
||||||
"neighbor",
|
"neighbor",
|
||||||
"mount",
|
"mount",
|
||||||
|
"partition",
|
||||||
nullptr
|
nullptr
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 @@
|
|||||||
#ifndef MPD_IDLE_FLAGS_HXX
|
#ifndef MPD_IDLE_FLAGS_HXX
|
||||||
#define MPD_IDLE_FLAGS_HXX
|
#define MPD_IDLE_FLAGS_HXX
|
||||||
|
|
||||||
#include "Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
/** song database has been updated*/
|
/** song database has been updated*/
|
||||||
static constexpr unsigned IDLE_DATABASE = 0x1;
|
static constexpr unsigned IDLE_DATABASE = 0x1;
|
||||||
@@ -67,6 +67,9 @@ static constexpr unsigned IDLE_NEIGHBOR = 0x800;
|
|||||||
/** the mount list has changed */
|
/** the mount list has changed */
|
||||||
static constexpr unsigned IDLE_MOUNT = 0x1000;
|
static constexpr unsigned IDLE_MOUNT = 0x1000;
|
||||||
|
|
||||||
|
/** the partition list has changed */
|
||||||
|
static constexpr unsigned IDLE_PARTITION = 0x2000;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get idle names
|
* Get idle names
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,6 +23,11 @@
|
|||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "Stats.hxx"
|
#include "Stats.hxx"
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
#include "RemoteTagCache.hxx"
|
||||||
|
#include "util/UriUtil.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
#include "db/DatabaseError.hxx"
|
#include "db/DatabaseError.hxx"
|
||||||
|
|
||||||
@@ -32,7 +37,28 @@
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <stdexcept>
|
#include <exception>
|
||||||
|
|
||||||
|
Instance::Instance()
|
||||||
|
:rtio_thread(true),
|
||||||
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
systemd_watchdog(event_loop),
|
||||||
|
#endif
|
||||||
|
idle_monitor(event_loop, BIND_THIS_METHOD(OnIdle))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Instance::~Instance() noexcept = default;
|
||||||
|
|
||||||
|
Partition *
|
||||||
|
Instance::FindPartition(const char *name) noexcept
|
||||||
|
{
|
||||||
|
for (auto &partition : partitions)
|
||||||
|
if (partition.name == name)
|
||||||
|
return &partition;
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
@@ -54,7 +80,9 @@ Instance::OnDatabaseModified()
|
|||||||
/* propagate the change to all subsystems */
|
/* propagate the change to all subsystems */
|
||||||
|
|
||||||
stats_invalidate();
|
stats_invalidate();
|
||||||
partition->DatabaseModified(*database);
|
|
||||||
|
for (auto &partition : partitions)
|
||||||
|
partition.DatabaseModified(*database);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -67,12 +95,13 @@ Instance::OnDatabaseSongRemoved(const char *uri)
|
|||||||
if (sticker_enabled()) {
|
if (sticker_enabled()) {
|
||||||
try {
|
try {
|
||||||
sticker_song_delete(uri);
|
sticker_song_delete(uri);
|
||||||
} catch (const std::runtime_error &) {
|
} catch (...) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
partition->StaleSong(uri);
|
for (auto &partition : partitions)
|
||||||
|
partition.StaleSong(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -80,15 +109,45 @@ Instance::OnDatabaseSongRemoved(const char *uri)
|
|||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
|
|
||||||
void
|
void
|
||||||
Instance::FoundNeighbor(gcc_unused const NeighborInfo &info)
|
Instance::FoundNeighbor(gcc_unused const NeighborInfo &info) noexcept
|
||||||
{
|
{
|
||||||
partition->EmitIdle(IDLE_NEIGHBOR);
|
for (auto &partition : partitions)
|
||||||
|
partition.EmitIdle(IDLE_NEIGHBOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Instance::LostNeighbor(gcc_unused const NeighborInfo &info)
|
Instance::LostNeighbor(gcc_unused const NeighborInfo &info) noexcept
|
||||||
{
|
{
|
||||||
partition->EmitIdle(IDLE_NEIGHBOR);
|
for (auto &partition : partitions)
|
||||||
|
partition.EmitIdle(IDLE_NEIGHBOR);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
|
||||||
|
void
|
||||||
|
Instance::LookupRemoteTag(const char *uri) noexcept
|
||||||
|
{
|
||||||
|
if (!uri_has_scheme(uri))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!remote_tag_cache)
|
||||||
|
remote_tag_cache = std::make_unique<RemoteTagCache>(event_loop,
|
||||||
|
*this);
|
||||||
|
|
||||||
|
remote_tag_cache->Lookup(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
Instance::OnRemoteTag(const char *uri, const Tag &tag) noexcept
|
||||||
|
{
|
||||||
|
if (!tag.IsDefined())
|
||||||
|
/* boring */
|
||||||
|
return;
|
||||||
|
|
||||||
|
for (auto &partition : partitions)
|
||||||
|
partition.TagModified(uri, tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,10 +20,19 @@
|
|||||||
#ifndef MPD_INSTANCE_HXX
|
#ifndef MPD_INSTANCE_HXX
|
||||||
#define MPD_INSTANCE_HXX
|
#define MPD_INSTANCE_HXX
|
||||||
|
|
||||||
#include "check.h"
|
#include "config.h"
|
||||||
#include "event/Loop.hxx"
|
#include "event/Loop.hxx"
|
||||||
|
#include "event/Thread.hxx"
|
||||||
#include "event/MaskMonitor.hxx"
|
#include "event/MaskMonitor.hxx"
|
||||||
#include "Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
#include "lib/systemd/Watchdog.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
#include "RemoteTagCacheHandler.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
#include "neighbor/Listener.hxx"
|
#include "neighbor/Listener.hxx"
|
||||||
@@ -37,9 +46,13 @@ class Storage;
|
|||||||
class UpdateService;
|
class UpdateService;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
#include <list>
|
||||||
|
|
||||||
class ClientList;
|
class ClientList;
|
||||||
struct Partition;
|
struct Partition;
|
||||||
class StateFile;
|
class StateFile;
|
||||||
|
class RemoteTagCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A utility class which, when used as the first base class, ensures
|
* A utility class which, when used as the first base class, ensures
|
||||||
@@ -63,7 +76,27 @@ struct Instance final
|
|||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
public NeighborListener
|
public NeighborListener
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
, public RemoteTagCacheHandler
|
||||||
|
#endif
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* A thread running an #EventLoop for non-blocking (bulk) I/O.
|
||||||
|
*/
|
||||||
|
EventThread io_thread;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Another thread running an #EventLoop for non-blocking
|
||||||
|
* (real-time) I/O. This is used instead of #io_thread for
|
||||||
|
* events which require low latency, e.g. for filling hardware
|
||||||
|
* ring buffers.
|
||||||
|
*/
|
||||||
|
EventThread rtio_thread;
|
||||||
|
|
||||||
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
Systemd::Watchdog systemd_watchdog;
|
||||||
|
#endif
|
||||||
|
|
||||||
MaskMonitor idle_monitor;
|
MaskMonitor idle_monitor;
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
@@ -82,19 +115,23 @@ struct Instance final
|
|||||||
UpdateService *update = nullptr;
|
UpdateService *update = nullptr;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
std::unique_ptr<RemoteTagCache> remote_tag_cache;
|
||||||
|
#endif
|
||||||
|
|
||||||
ClientList *client_list;
|
ClientList *client_list;
|
||||||
|
|
||||||
Partition *partition;
|
std::list<Partition> partitions;
|
||||||
|
|
||||||
StateFile *state_file;
|
StateFile *state_file = nullptr;
|
||||||
|
|
||||||
Instance()
|
Instance();
|
||||||
:idle_monitor(event_loop, BIND_THIS_METHOD(OnIdle)), state_file(nullptr) {}
|
~Instance() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initiate shutdown. Wrapper for EventLoop::Break().
|
* Wrapper for EventLoop::Break(). Call to initiate shutdown.
|
||||||
*/
|
*/
|
||||||
void Shutdown() {
|
void Break() {
|
||||||
event_loop.Break();
|
event_loop.Break();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,6 +139,16 @@ struct Instance final
|
|||||||
idle_monitor.OrMask(mask);
|
idle_monitor.OrMask(mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Find a #Partition with the given name. Returns nullptr if
|
||||||
|
* no such partition was found.
|
||||||
|
*/
|
||||||
|
gcc_pure
|
||||||
|
Partition *FindPartition(const char *name) noexcept;
|
||||||
|
|
||||||
|
void BeginShutdownPartitions() noexcept;
|
||||||
|
void FinishShutdownPartitions() noexcept;
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
/**
|
/**
|
||||||
* Returns the global #Database instance. May return nullptr
|
* Returns the global #Database instance. May return nullptr
|
||||||
@@ -120,6 +167,18 @@ struct Instance final
|
|||||||
const Database &GetDatabaseOrThrow() const;
|
const Database &GetDatabaseOrThrow() const;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void BeginShutdownUpdate() noexcept;
|
||||||
|
void FinishShutdownUpdate() noexcept;
|
||||||
|
void ShutdownDatabase() noexcept;
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
void LookupRemoteTag(const char *uri) noexcept;
|
||||||
|
#else
|
||||||
|
void LookupRemoteTag(const char *) noexcept {
|
||||||
|
/* no-op */
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
void OnDatabaseModified() override;
|
void OnDatabaseModified() override;
|
||||||
@@ -128,8 +187,13 @@ private:
|
|||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
/* virtual methods from class NeighborListener */
|
/* virtual methods from class NeighborListener */
|
||||||
void FoundNeighbor(const NeighborInfo &info) override;
|
void FoundNeighbor(const NeighborInfo &info) noexcept override;
|
||||||
void LostNeighbor(const NeighborInfo &info) override;
|
void LostNeighbor(const NeighborInfo &info) noexcept override;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_CURL
|
||||||
|
/* virtual methods from class RemoteTagCacheHandler */
|
||||||
|
void OnRemoteTag(const char *uri, const Tag &tag) noexcept override;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* callback for #idle_monitor */
|
/* callback for #idle_monitor */
|
||||||
|
|||||||
166
src/Listen.cxx
166
src/Listen.cxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,21 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Listen.hxx"
|
#include "Listen.hxx"
|
||||||
#include "client/Client.hxx"
|
#include "Log.hxx"
|
||||||
|
#include "client/Listener.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/Data.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/Option.hxx"
|
||||||
#include "net/SocketAddress.hxx"
|
#include "config/Net.hxx"
|
||||||
#include "event/ServerSocket.hxx"
|
#include "net/AllocatedSocketAddress.hxx"
|
||||||
|
#include "net/UniqueSocketDescriptor.hxx"
|
||||||
|
#include "net/SocketUtil.hxx"
|
||||||
#include "system/Error.hxx"
|
#include "system/Error.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "util/Domain.hxx"
|
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "Log.hxx"
|
#include "fs/XDG.hxx"
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
@@ -38,49 +41,14 @@
|
|||||||
#include <systemd/sd-daemon.h>
|
#include <systemd/sd-daemon.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static constexpr Domain listen_domain("listen");
|
|
||||||
|
|
||||||
#define DEFAULT_PORT 6600
|
#define DEFAULT_PORT 6600
|
||||||
|
|
||||||
class ClientListener final : public ServerSocket {
|
|
||||||
Partition &partition;
|
|
||||||
|
|
||||||
public:
|
|
||||||
ClientListener(EventLoop &_loop, Partition &_partition)
|
|
||||||
:ServerSocket(_loop), partition(_partition) {}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void OnAccept(int fd, SocketAddress address, int uid) override {
|
|
||||||
client_new(GetEventLoop(), partition,
|
|
||||||
fd, address, uid);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static ClientListener *listen_socket;
|
|
||||||
int listen_port;
|
int listen_port;
|
||||||
|
|
||||||
/**
|
|
||||||
* Throws #std::runtime_error on error.
|
|
||||||
*/
|
|
||||||
static void
|
|
||||||
listen_add_config_param(unsigned int port,
|
|
||||||
const ConfigParam *param)
|
|
||||||
{
|
|
||||||
assert(param != nullptr);
|
|
||||||
|
|
||||||
if (0 == strcmp(param->value.c_str(), "any")) {
|
|
||||||
listen_socket->AddPort(port);
|
|
||||||
} else if (param->value[0] == '/' || param->value[0] == '~') {
|
|
||||||
listen_socket->AddPath(param->GetPath());
|
|
||||||
} else {
|
|
||||||
listen_socket->AddHost(param->value.c_str(), port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD_DAEMON
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
listen_systemd_activation()
|
listen_systemd_activation(ClientListener &listener)
|
||||||
{
|
{
|
||||||
int n = sd_listen_fds(true);
|
int n = sd_listen_fds(true);
|
||||||
if (n <= 0) {
|
if (n <= 0) {
|
||||||
@@ -91,67 +59,103 @@ listen_systemd_activation()
|
|||||||
|
|
||||||
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)
|
||||||
listen_socket->AddFD(i);
|
listener.AddFD(UniqueSocketDescriptor(i));
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
/**
|
||||||
listen_global_init(EventLoop &loop, Partition &partition)
|
* Listen on "$XDG_RUNTIME_DIR/mpd/socket" (if applicable).
|
||||||
|
*
|
||||||
|
* @return true if a listener socket was added
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ListenXdgRuntimeDir(ClientListener &listener) noexcept
|
||||||
{
|
{
|
||||||
int port = config_get_positive(ConfigOption::PORT, DEFAULT_PORT);
|
#if defined(USE_XDG) && defined(HAVE_UN)
|
||||||
const auto *param = config_get_param(ConfigOption::BIND_TO_ADDRESS);
|
if (geteuid() == 0)
|
||||||
|
/* this MPD instance is a system-wide daemon; don't
|
||||||
|
use $XDG_RUNTIME_DIR */
|
||||||
|
return false;
|
||||||
|
|
||||||
listen_socket = new ClientListener(loop, partition);
|
Path xdg_runtime_dir = Path::FromFS(getenv("XDG_RUNTIME_DIR"));
|
||||||
|
if (xdg_runtime_dir.IsNull())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const auto mpd_runtime_dir = xdg_runtime_dir / Path::FromFS("mpd");
|
||||||
|
mkdir(mpd_runtime_dir.c_str(), 0700);
|
||||||
|
|
||||||
|
const auto socket_path = mpd_runtime_dir / Path::FromFS("socket");
|
||||||
|
unlink(socket_path.c_str());
|
||||||
|
|
||||||
|
AllocatedSocketAddress address;
|
||||||
|
address.SetLocal(socket_path.c_str());
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto fd = socket_bind_listen(AF_LOCAL, SOCK_STREAM, 0,
|
||||||
|
address, 5);
|
||||||
|
chmod(socket_path.c_str(), 0600);
|
||||||
|
listener.AddFD(std::move(fd), std::move(address));
|
||||||
|
return true;
|
||||||
|
} catch (...) {
|
||||||
|
FormatError(std::current_exception(),
|
||||||
|
"Failed to listen on '%s' (not fatal)",
|
||||||
|
socket_path.c_str());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
(void)listener;
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
listen_global_init(const ConfigData &config, ClientListener &listener)
|
||||||
|
{
|
||||||
|
int port = config.GetPositive(ConfigOption::PORT, DEFAULT_PORT);
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD_DAEMON
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
if (listen_systemd_activation())
|
if (listen_systemd_activation(listener))
|
||||||
return;
|
return;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (param != nullptr) {
|
for (const auto ¶m : config.GetParamList(ConfigOption::BIND_TO_ADDRESS)) {
|
||||||
/* "bind_to_address" is configured, create listeners
|
try {
|
||||||
for all values */
|
ServerSocketAddGeneric(listener, param.value.c_str(),
|
||||||
|
port);
|
||||||
|
} catch (...) {
|
||||||
|
std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)",
|
||||||
|
param.value.c_str(),
|
||||||
|
param.line));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
bool have_xdg_runtime_listener = false;
|
||||||
try {
|
|
||||||
listen_add_config_param(port, param);
|
if (listener.IsEmpty()) {
|
||||||
} catch (const std::runtime_error &e) {
|
|
||||||
delete listen_socket;
|
|
||||||
std::throw_with_nested(FormatRuntimeError("Failed to listen on %s (line %i)",
|
|
||||||
param->value.c_str(),
|
|
||||||
param->line));
|
|
||||||
}
|
|
||||||
} while ((param = param->next) != nullptr);
|
|
||||||
} 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 */
|
||||||
|
|
||||||
|
have_xdg_runtime_listener = ListenXdgRuntimeDir(listener);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
listen_socket->AddPort(port);
|
listener.AddPort(port);
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (...) {
|
||||||
delete listen_socket;
|
|
||||||
std::throw_with_nested(FormatRuntimeError("Failed to listen on *:%d: ", port));
|
std::throw_with_nested(FormatRuntimeError("Failed to listen on *:%d: ", port));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
listen_socket->Open();
|
listener.Open();
|
||||||
} catch (const std::runtime_error &e) {
|
} catch (...) {
|
||||||
delete listen_socket;
|
if (have_xdg_runtime_listener)
|
||||||
throw;
|
LogError(std::current_exception(),
|
||||||
|
"Default TCP listener setup failed, but this is okay because we have a $XDG_RUNTIME_DIR listener");
|
||||||
|
else
|
||||||
|
throw;
|
||||||
}
|
}
|
||||||
|
|
||||||
listen_port = port;
|
listen_port = port;
|
||||||
}
|
}
|
||||||
|
|
||||||
void listen_global_finish(void)
|
|
||||||
{
|
|
||||||
LogDebug(listen_domain, "listen_global_finish called");
|
|
||||||
|
|
||||||
assert(listen_socket != nullptr);
|
|
||||||
|
|
||||||
delete listen_socket;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,15 +20,12 @@
|
|||||||
#ifndef MPD_LISTEN_HXX
|
#ifndef MPD_LISTEN_HXX
|
||||||
#define MPD_LISTEN_HXX
|
#define MPD_LISTEN_HXX
|
||||||
|
|
||||||
class EventLoop;
|
struct ConfigData;
|
||||||
struct Partition;
|
class ClientListener;
|
||||||
|
|
||||||
extern int listen_port;
|
extern int listen_port;
|
||||||
|
|
||||||
void
|
void
|
||||||
listen_global_init(EventLoop &loop, Partition &partition);
|
listen_global_init(const ConfigData &config, ClientListener &listener);
|
||||||
|
|
||||||
void
|
|
||||||
listen_global_finish();
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,8 @@
|
|||||||
#ifndef MPD_LOCATE_URI_HXX
|
#ifndef MPD_LOCATE_URI_HXX
|
||||||
#define MPD_LOCATE_URI_HXX
|
#define MPD_LOCATE_URI_HXX
|
||||||
|
|
||||||
#include "check.h"
|
#include "config.h"
|
||||||
#include "Compiler.h"
|
#include "util/Compiler.h"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
@@ -67,7 +67,7 @@ struct LocatedUri {
|
|||||||
AllocatedPath path;
|
AllocatedPath path;
|
||||||
|
|
||||||
LocatedUri(Type _type, const char *_uri,
|
LocatedUri(Type _type, const char *_uri,
|
||||||
AllocatedPath &&_path=AllocatedPath::Null())
|
AllocatedPath &&_path=nullptr)
|
||||||
:type(_type), canonical_uri(_uri), path(std::move(_path)) {}
|
:type(_type), canonical_uri(_uri), path(std::move(_path)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
40
src/Log.cxx
40
src/Log.cxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -17,7 +17,6 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "LogV.hxx"
|
#include "LogV.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
|
|
||||||
@@ -30,7 +29,8 @@
|
|||||||
static constexpr Domain exception_domain("exception");
|
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) noexcept
|
||||||
{
|
{
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||||
@@ -38,7 +38,7 @@ LogFormatV(const Domain &domain, LogLevel level, const char *fmt, va_list ap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogFormat(const Domain &domain, LogLevel level, const char *fmt, ...)
|
LogFormat(const Domain &domain, LogLevel level, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -47,7 +47,7 @@ LogFormat(const Domain &domain, LogLevel level, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatDebug(const Domain &domain, const char *fmt, ...)
|
FormatDebug(const Domain &domain, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -56,7 +56,7 @@ FormatDebug(const Domain &domain, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatInfo(const Domain &domain, const char *fmt, ...)
|
FormatInfo(const Domain &domain, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -65,7 +65,7 @@ FormatInfo(const Domain &domain, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatDefault(const Domain &domain, const char *fmt, ...)
|
FormatDefault(const Domain &domain, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -74,7 +74,7 @@ FormatDefault(const Domain &domain, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatWarning(const Domain &domain, const char *fmt, ...)
|
FormatWarning(const Domain &domain, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -83,7 +83,7 @@ FormatWarning(const Domain &domain, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatError(const Domain &domain, const char *fmt, ...)
|
FormatError(const Domain &domain, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -92,7 +92,7 @@ FormatError(const Domain &domain, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception &e)
|
LogError(const std::exception &e) noexcept
|
||||||
{
|
{
|
||||||
Log(exception_domain, LogLevel::ERROR, e.what());
|
Log(exception_domain, LogLevel::ERROR, e.what());
|
||||||
|
|
||||||
@@ -107,7 +107,7 @@ LogError(const std::exception &e)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception &e, const char *msg)
|
LogError(const std::exception &e, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
FormatError(exception_domain, "%s: %s", msg, e.what());
|
FormatError(exception_domain, "%s: %s", msg, e.what());
|
||||||
|
|
||||||
@@ -122,7 +122,7 @@ LogError(const std::exception &e, const char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatError(const std::exception &e, const char *fmt, ...)
|
FormatError(const std::exception &e, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -134,7 +134,7 @@ FormatError(const std::exception &e, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception_ptr &ep)
|
LogError(const std::exception_ptr &ep) noexcept
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
std::rethrow_exception(ep);
|
std::rethrow_exception(ep);
|
||||||
@@ -147,7 +147,7 @@ LogError(const std::exception_ptr &ep)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception_ptr &ep, const char *msg)
|
LogError(const std::exception_ptr &ep, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
std::rethrow_exception(ep);
|
std::rethrow_exception(ep);
|
||||||
@@ -160,7 +160,7 @@ LogError(const std::exception_ptr &ep, const char *msg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatError(const std::exception_ptr &ep, const char *fmt, ...)
|
FormatError(const std::exception_ptr &ep, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
va_list ap;
|
va_list ap;
|
||||||
@@ -172,19 +172,19 @@ FormatError(const std::exception_ptr &ep, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogErrno(const Domain &domain, int e, const char *msg)
|
LogErrno(const Domain &domain, int e, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
LogFormat(domain, LogLevel::ERROR, "%s: %s", msg, strerror(e));
|
LogFormat(domain, LogLevel::ERROR, "%s: %s", msg, strerror(e));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogErrno(const Domain &domain, const char *msg)
|
LogErrno(const Domain &domain, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
LogErrno(domain, errno, msg);
|
LogErrno(domain, errno, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
FormatErrnoV(const Domain &domain, int e, const char *fmt, va_list ap)
|
FormatErrnoV(const Domain &domain, int e, const char *fmt, va_list ap) noexcept
|
||||||
{
|
{
|
||||||
char msg[1024];
|
char msg[1024];
|
||||||
vsnprintf(msg, sizeof(msg), fmt, ap);
|
vsnprintf(msg, sizeof(msg), fmt, ap);
|
||||||
@@ -193,7 +193,7 @@ FormatErrnoV(const Domain &domain, int e, const char *fmt, va_list ap)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatErrno(const Domain &domain, int e, const char *fmt, ...)
|
FormatErrno(const Domain &domain, int e, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, fmt);
|
va_start(ap, fmt);
|
||||||
@@ -202,7 +202,7 @@ FormatErrno(const Domain &domain, int e, const char *fmt, ...)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
FormatErrno(const Domain &domain, const char *fmt, ...)
|
FormatErrno(const Domain &domain, const char *fmt, ...) noexcept
|
||||||
{
|
{
|
||||||
const int e = errno;
|
const int e = errno;
|
||||||
|
|
||||||
|
|||||||
48
src/Log.hxx
48
src/Log.hxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,101 +21,101 @@
|
|||||||
#define MPD_LOG_HXX
|
#define MPD_LOG_HXX
|
||||||
|
|
||||||
#include "LogLevel.hxx"
|
#include "LogLevel.hxx"
|
||||||
#include "Compiler.h"
|
#include "util/Compiler.h"
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
|
|
||||||
class Domain;
|
class Domain;
|
||||||
|
|
||||||
void
|
void
|
||||||
Log(const Domain &domain, LogLevel level, const char *msg);
|
Log(const Domain &domain, LogLevel level, const char *msg) noexcept;
|
||||||
|
|
||||||
gcc_printf(3,4)
|
gcc_printf(3,4)
|
||||||
void
|
void
|
||||||
LogFormat(const Domain &domain, LogLevel level, const char *fmt, ...);
|
LogFormat(const Domain &domain, LogLevel level, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
LogDebug(const Domain &domain, const char *msg)
|
LogDebug(const Domain &domain, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
Log(domain, LogLevel::DEBUG, msg);
|
Log(domain, LogLevel::DEBUG, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatDebug(const Domain &domain, const char *fmt, ...);
|
FormatDebug(const Domain &domain, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
LogInfo(const Domain &domain, const char *msg)
|
LogInfo(const Domain &domain, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
Log(domain, LogLevel::INFO, msg);
|
Log(domain, LogLevel::INFO, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatInfo(const Domain &domain, const char *fmt, ...);
|
FormatInfo(const Domain &domain, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
LogDefault(const Domain &domain, const char *msg)
|
LogDefault(const Domain &domain, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
Log(domain, LogLevel::DEFAULT, msg);
|
Log(domain, LogLevel::DEFAULT, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatDefault(const Domain &domain, const char *fmt, ...);
|
FormatDefault(const Domain &domain, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
LogWarning(const Domain &domain, const char *msg)
|
LogWarning(const Domain &domain, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
Log(domain, LogLevel::WARNING, msg);
|
Log(domain, LogLevel::WARNING, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatWarning(const Domain &domain, const char *fmt, ...);
|
FormatWarning(const Domain &domain, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
static inline void
|
static inline void
|
||||||
LogError(const Domain &domain, const char *msg)
|
LogError(const Domain &domain, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
Log(domain, LogLevel::ERROR, msg);
|
Log(domain, LogLevel::ERROR, msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception &e);
|
LogError(const std::exception &e) noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception &e, const char *msg);
|
LogError(const std::exception &e, const char *msg) noexcept;
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatError(const std::exception &e, const char *fmt, ...);
|
FormatError(const std::exception &e, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception_ptr &ep);
|
LogError(const std::exception_ptr &ep) noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
LogError(const std::exception_ptr &ep, const char *msg);
|
LogError(const std::exception_ptr &ep, const char *msg) noexcept;
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatError(const std::exception_ptr &ep, const char *fmt, ...);
|
FormatError(const std::exception_ptr &ep, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatError(const Domain &domain, const char *fmt, ...);
|
FormatError(const Domain &domain, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
LogErrno(const Domain &domain, int e, const char *msg);
|
LogErrno(const Domain &domain, int e, const char *msg) noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
LogErrno(const Domain &domain, const char *msg);
|
LogErrno(const Domain &domain, const char *msg) noexcept;
|
||||||
|
|
||||||
gcc_printf(3,4)
|
gcc_printf(3,4)
|
||||||
void
|
void
|
||||||
FormatErrno(const Domain &domain, int e, const char *fmt, ...);
|
FormatErrno(const Domain &domain, int e, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
gcc_printf(2,3)
|
gcc_printf(2,3)
|
||||||
void
|
void
|
||||||
FormatErrno(const Domain &domain, const char *fmt, ...);
|
FormatErrno(const Domain &domain, const char *fmt, ...) noexcept;
|
||||||
|
|
||||||
#endif /* LOG_H */
|
#endif /* LOG_H */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -17,11 +17,11 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "LogBackend.hxx"
|
#include "LogBackend.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "util/StringUtil.hxx"
|
#include "util/StringStrip.hxx"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
#include "Main.hxx"
|
#include "Main.hxx"
|
||||||
|
|
||||||
static int
|
static int
|
||||||
ToAndroidLogLevel(LogLevel log_level)
|
ToAndroidLogLevel(LogLevel log_level) noexcept
|
||||||
{
|
{
|
||||||
switch (log_level) {
|
switch (log_level) {
|
||||||
case LogLevel::DEBUG:
|
case LogLevel::DEBUG:
|
||||||
@@ -70,13 +70,13 @@ static bool enable_syslog;
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
void
|
void
|
||||||
SetLogThreshold(LogLevel _threshold)
|
SetLogThreshold(LogLevel _threshold) noexcept
|
||||||
{
|
{
|
||||||
log_threshold = _threshold;
|
log_threshold = _threshold;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
EnableLogTimestamp()
|
EnableLogTimestamp() noexcept
|
||||||
{
|
{
|
||||||
#ifdef HAVE_SYSLOG
|
#ifdef HAVE_SYSLOG
|
||||||
assert(!enable_syslog);
|
assert(!enable_syslog);
|
||||||
@@ -86,7 +86,8 @@ EnableLogTimestamp()
|
|||||||
enable_timestamp = true;
|
enable_timestamp = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char *log_date(void)
|
static const char *
|
||||||
|
log_date() noexcept
|
||||||
{
|
{
|
||||||
static constexpr size_t LOG_DATE_BUF_SIZE = 16;
|
static constexpr size_t LOG_DATE_BUF_SIZE = 16;
|
||||||
static char buf[LOG_DATE_BUF_SIZE];
|
static char buf[LOG_DATE_BUF_SIZE];
|
||||||
@@ -100,7 +101,7 @@ static const char *log_date(void)
|
|||||||
* characters.
|
* characters.
|
||||||
*/
|
*/
|
||||||
static int
|
static int
|
||||||
chomp_length(const char *p)
|
chomp_length(const char *p) noexcept
|
||||||
{
|
{
|
||||||
size_t length = strlen(p);
|
size_t length = strlen(p);
|
||||||
return StripRight(p, length);
|
return StripRight(p, length);
|
||||||
@@ -108,8 +109,9 @@ chomp_length(const char *p)
|
|||||||
|
|
||||||
#ifdef HAVE_SYSLOG
|
#ifdef HAVE_SYSLOG
|
||||||
|
|
||||||
|
gcc_const
|
||||||
static int
|
static int
|
||||||
ToSysLogLevel(LogLevel log_level)
|
ToSysLogLevel(LogLevel log_level) noexcept
|
||||||
{
|
{
|
||||||
switch (log_level) {
|
switch (log_level) {
|
||||||
case LogLevel::DEBUG:
|
case LogLevel::DEBUG:
|
||||||
@@ -133,7 +135,7 @@ ToSysLogLevel(LogLevel log_level)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
SysLog(const Domain &domain, LogLevel log_level, const char *message)
|
SysLog(const Domain &domain, LogLevel log_level, const char *message) noexcept
|
||||||
{
|
{
|
||||||
syslog(ToSysLogLevel(log_level), "%s: %.*s",
|
syslog(ToSysLogLevel(log_level), "%s: %.*s",
|
||||||
domain.GetName(),
|
domain.GetName(),
|
||||||
@@ -141,14 +143,14 @@ SysLog(const Domain &domain, LogLevel log_level, const char *message)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogInitSysLog()
|
LogInitSysLog() noexcept
|
||||||
{
|
{
|
||||||
openlog(PACKAGE, 0, LOG_DAEMON);
|
openlog(PACKAGE, 0, LOG_DAEMON);
|
||||||
enable_syslog = true;
|
enable_syslog = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
LogFinishSysLog()
|
LogFinishSysLog() noexcept
|
||||||
{
|
{
|
||||||
if (enable_syslog)
|
if (enable_syslog)
|
||||||
closelog();
|
closelog();
|
||||||
@@ -157,7 +159,7 @@ LogFinishSysLog()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
FileLog(const Domain &domain, const char *message)
|
FileLog(const Domain &domain, const char *message) noexcept
|
||||||
{
|
{
|
||||||
fprintf(stderr, "%s%s: %.*s\n",
|
fprintf(stderr, "%s%s: %.*s\n",
|
||||||
enable_timestamp ? log_date() : "",
|
enable_timestamp ? log_date() : "",
|
||||||
@@ -174,7 +176,7 @@ FileLog(const Domain &domain, const char *message)
|
|||||||
#endif /* !ANDROID */
|
#endif /* !ANDROID */
|
||||||
|
|
||||||
void
|
void
|
||||||
Log(const Domain &domain, LogLevel level, const char *msg)
|
Log(const Domain &domain, LogLevel level, const char *msg) noexcept
|
||||||
{
|
{
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
__android_log_print(ToAndroidLogLevel(level), "MPD",
|
__android_log_print(ToAndroidLogLevel(level), "MPD",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,18 @@
|
|||||||
#ifndef MPD_LOG_BACKEND_HXX
|
#ifndef MPD_LOG_BACKEND_HXX
|
||||||
#define MPD_LOG_BACKEND_HXX
|
#define MPD_LOG_BACKEND_HXX
|
||||||
|
|
||||||
#include "check.h"
|
|
||||||
#include "LogLevel.hxx"
|
#include "LogLevel.hxx"
|
||||||
|
|
||||||
void
|
void
|
||||||
SetLogThreshold(LogLevel _threshold);
|
SetLogThreshold(LogLevel _threshold) noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
EnableLogTimestamp();
|
EnableLogTimestamp() noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
LogInitSysLog();
|
LogInitSysLog() noexcept;
|
||||||
|
|
||||||
void
|
void
|
||||||
LogFinishSysLog();
|
LogFinishSysLog() noexcept;
|
||||||
|
|
||||||
#endif /* LOG_H */
|
#endif /* LOG_H */
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,14 +22,18 @@
|
|||||||
#include "LogBackend.hxx"
|
#include "LogBackend.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/Data.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/Option.hxx"
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "util/Domain.hxx"
|
#include "util/Domain.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
#include "system/Error.hxx"
|
#include "system/Error.hxx"
|
||||||
|
|
||||||
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
#include <systemd/sd-daemon.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
@@ -41,12 +45,13 @@
|
|||||||
#define LOG_DATE_BUF_SIZE 16
|
#define LOG_DATE_BUF_SIZE 16
|
||||||
#define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1)
|
#define LOG_DATE_LEN (LOG_DATE_BUF_SIZE - 1)
|
||||||
|
|
||||||
|
gcc_unused
|
||||||
static constexpr Domain log_domain("log");
|
static constexpr Domain log_domain("log");
|
||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
|
|
||||||
static int out_fd = -1;
|
static int out_fd = -1;
|
||||||
static AllocatedPath out_path = AllocatedPath::Null();
|
static AllocatedPath out_path = nullptr;
|
||||||
|
|
||||||
static void redirect_logs(int fd)
|
static void redirect_logs(int fd)
|
||||||
{
|
{
|
||||||
@@ -62,7 +67,7 @@ open_log_file(void)
|
|||||||
{
|
{
|
||||||
assert(!out_path.IsNull());
|
assert(!out_path.IsNull());
|
||||||
|
|
||||||
return OpenFile(out_path, O_CREAT | O_WRONLY | O_APPEND, 0666);
|
return OpenFile(out_path, O_CREAT | O_WRONLY | O_APPEND, 0666).Steal();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -118,25 +123,36 @@ log_early_init(bool verbose)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
log_init(bool verbose, bool use_stdout)
|
log_init(const ConfigData &config, bool verbose, bool use_stdout)
|
||||||
{
|
{
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
|
(void)config;
|
||||||
(void)verbose;
|
(void)verbose;
|
||||||
(void)use_stdout;
|
(void)use_stdout;
|
||||||
#else
|
#else
|
||||||
if (verbose)
|
if (verbose)
|
||||||
SetLogThreshold(LogLevel::DEBUG);
|
SetLogThreshold(LogLevel::DEBUG);
|
||||||
else if (const auto ¶m = config_get_param(ConfigOption::LOG_LEVEL))
|
else if (const auto ¶m = config.GetParam(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) {
|
||||||
out_fd = STDOUT_FILENO;
|
out_fd = STDOUT_FILENO;
|
||||||
} else {
|
} else {
|
||||||
const auto *param = config_get_param(ConfigOption::LOG_FILE);
|
const auto *param = config.GetParam(ConfigOption::LOG_FILE);
|
||||||
if (param == nullptr) {
|
if (param == nullptr) {
|
||||||
/* no configuration: default to syslog (if
|
/* no configuration: default to syslog (if
|
||||||
available) */
|
available) */
|
||||||
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
|
if (sd_booted() &&
|
||||||
|
getenv("NOTIFY_SOCKET") != nullptr) {
|
||||||
|
/* if MPD was started as a systemd
|
||||||
|
service, default to journal (which
|
||||||
|
is connected to fd=2) */
|
||||||
|
out_fd = STDOUT_FILENO;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
#ifndef HAVE_SYSLOG
|
#ifndef HAVE_SYSLOG
|
||||||
throw std::runtime_error("config parameter 'log_file' not found");
|
throw std::runtime_error("config parameter 'log_file' not found");
|
||||||
#endif
|
#endif
|
||||||
@@ -169,7 +185,7 @@ log_deinit(void)
|
|||||||
{
|
{
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
close_log_files();
|
close_log_files();
|
||||||
out_path = AllocatedPath::Null();
|
out_path = nullptr;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,6 +20,8 @@
|
|||||||
#ifndef MPD_LOG_INIT_HXX
|
#ifndef MPD_LOG_INIT_HXX
|
||||||
#define MPD_LOG_INIT_HXX
|
#define MPD_LOG_INIT_HXX
|
||||||
|
|
||||||
|
struct ConfigData;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@@ -35,7 +37,7 @@ log_early_init(bool verbose);
|
|||||||
* Throws #std::runtime_error on error.
|
* Throws #std::runtime_error on error.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
log_init(bool verbose, bool use_stdout);
|
log_init(const ConfigData &config, bool verbose, bool use_stdout);
|
||||||
|
|
||||||
void
|
void
|
||||||
log_deinit();
|
log_deinit();
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,6 +25,7 @@
|
|||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
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) noexcept;
|
||||||
|
|
||||||
#endif /* LOG_H */
|
#endif /* LOG_H */
|
||||||
|
|||||||
411
src/Main.cxx
411
src/Main.cxx
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,22 +24,21 @@
|
|||||||
#include "PlaylistFile.hxx"
|
#include "PlaylistFile.hxx"
|
||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
#include "StateFile.hxx"
|
#include "StateFile.hxx"
|
||||||
#include "player/Thread.hxx"
|
|
||||||
#include "Mapper.hxx"
|
#include "Mapper.hxx"
|
||||||
#include "Permission.hxx"
|
#include "Permission.hxx"
|
||||||
#include "Listen.hxx"
|
#include "Listen.hxx"
|
||||||
|
#include "client/Listener.hxx"
|
||||||
#include "client/Client.hxx"
|
#include "client/Client.hxx"
|
||||||
#include "client/ClientList.hxx"
|
#include "client/ClientList.hxx"
|
||||||
#include "command/AllCommands.hxx"
|
#include "command/AllCommands.hxx"
|
||||||
#include "Partition.hxx"
|
#include "Partition.hxx"
|
||||||
#include "tag/TagConfig.hxx"
|
#include "tag/Config.hxx"
|
||||||
#include "ReplayGainGlobal.hxx"
|
#include "ReplayGainGlobal.hxx"
|
||||||
#include "Idle.hxx"
|
#include "Idle.hxx"
|
||||||
#include "Log.hxx"
|
#include "Log.hxx"
|
||||||
#include "LogInit.hxx"
|
#include "LogInit.hxx"
|
||||||
#include "input/Init.hxx"
|
#include "input/Init.hxx"
|
||||||
#include "event/Loop.hxx"
|
#include "event/Loop.hxx"
|
||||||
#include "IOThread.hxx"
|
|
||||||
#include "fs/AllocatedPath.hxx"
|
#include "fs/AllocatedPath.hxx"
|
||||||
#include "fs/Config.hxx"
|
#include "fs/Config.hxx"
|
||||||
#include "playlist/PlaylistRegistry.hxx"
|
#include "playlist/PlaylistRegistry.hxx"
|
||||||
@@ -48,16 +47,19 @@
|
|||||||
#include "AudioParser.hxx"
|
#include "AudioParser.hxx"
|
||||||
#include "pcm/PcmConvert.hxx"
|
#include "pcm/PcmConvert.hxx"
|
||||||
#include "unix/SignalHandlers.hxx"
|
#include "unix/SignalHandlers.hxx"
|
||||||
#include "system/FatalError.hxx"
|
|
||||||
#include "thread/Slack.hxx"
|
#include "thread/Slack.hxx"
|
||||||
#include "net/Init.hxx"
|
#include "net/Init.hxx"
|
||||||
#include "lib/icu/Init.hxx"
|
#include "lib/icu/Init.hxx"
|
||||||
#include "config/ConfigGlobal.hxx"
|
#include "config/File.hxx"
|
||||||
|
#include "config/Check.hxx"
|
||||||
|
#include "config/Data.hxx"
|
||||||
#include "config/Param.hxx"
|
#include "config/Param.hxx"
|
||||||
#include "config/ConfigDefaults.hxx"
|
#include "config/Path.hxx"
|
||||||
#include "config/ConfigOption.hxx"
|
#include "config/Defaults.hxx"
|
||||||
#include "config/ConfigError.hxx"
|
#include "config/Option.hxx"
|
||||||
|
#include "config/Domain.hxx"
|
||||||
#include "util/RuntimeError.hxx"
|
#include "util/RuntimeError.hxx"
|
||||||
|
#include "util/ScopeExit.hxx"
|
||||||
|
|
||||||
#ifdef ENABLE_DAEMON
|
#ifdef ENABLE_DAEMON
|
||||||
#include "unix/Daemon.hxx"
|
#include "unix/Daemon.hxx"
|
||||||
@@ -93,11 +95,14 @@
|
|||||||
#include "android/Environment.hxx"
|
#include "android/Environment.hxx"
|
||||||
#include "android/Context.hxx"
|
#include "android/Context.hxx"
|
||||||
#include "android/LogListener.hxx"
|
#include "android/LogListener.hxx"
|
||||||
#include "fs/StandardDirectory.hxx"
|
|
||||||
#include "fs/FileSystem.hxx"
|
#include "fs/FileSystem.hxx"
|
||||||
#include "org_musicpd_Bridge.h"
|
#include "org_musicpd_Bridge.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef ENABLE_DBUS
|
||||||
|
#include "lib/dbus/Init.hxx"
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_SYSTEMD_DAEMON
|
#ifdef ENABLE_SYSTEMD_DAEMON
|
||||||
#include <systemd/sd-daemon.h>
|
#include <systemd/sd-daemon.h>
|
||||||
#endif
|
#endif
|
||||||
@@ -115,18 +120,10 @@ static constexpr size_t MEGABYTE = 1024 * KILOBYTE;
|
|||||||
|
|
||||||
static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE;
|
static constexpr size_t DEFAULT_BUFFER_SIZE = 4 * MEGABYTE;
|
||||||
|
|
||||||
static
|
static constexpr
|
||||||
#if GCC_OLDER_THAN(5,0)
|
|
||||||
/* gcc 4.x has no "constexpr" for std::max() */
|
|
||||||
const
|
|
||||||
#else
|
|
||||||
constexpr
|
|
||||||
#endif
|
|
||||||
size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32,
|
size_t MIN_BUFFER_SIZE = std::max(CHUNK_SIZE * 32,
|
||||||
64 * KILOBYTE);
|
64 * KILOBYTE);
|
||||||
|
|
||||||
static constexpr unsigned DEFAULT_BUFFER_BEFORE_PLAY = 10;
|
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
Context *context;
|
Context *context;
|
||||||
LogListener *logListener;
|
LogListener *logListener;
|
||||||
@@ -139,19 +136,20 @@ struct Config {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static Config
|
static Config
|
||||||
LoadConfig()
|
LoadConfig(const ConfigData &config)
|
||||||
{
|
{
|
||||||
return {LoadReplayGainConfig()};
|
return {LoadReplayGainConfig(config)};
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DAEMON
|
#ifdef ENABLE_DAEMON
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue_daemonize_init(const struct options *options)
|
glue_daemonize_init(const struct options *options,
|
||||||
|
const ConfigData &config)
|
||||||
{
|
{
|
||||||
daemonize_init(config_get_string(ConfigOption::USER, nullptr),
|
daemonize_init(config.GetString(ConfigOption::USER),
|
||||||
config_get_string(ConfigOption::GROUP, nullptr),
|
config.GetString(ConfigOption::GROUP),
|
||||||
config_get_path(ConfigOption::PID_FILE));
|
config.GetPath(ConfigOption::PID_FILE));
|
||||||
|
|
||||||
if (options->kill)
|
if (options->kill)
|
||||||
daemonize_kill();
|
daemonize_kill();
|
||||||
@@ -160,23 +158,23 @@ glue_daemonize_init(const struct options *options)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue_mapper_init()
|
glue_mapper_init(const ConfigData &config)
|
||||||
{
|
{
|
||||||
mapper_init(config_get_path(ConfigOption::PLAYLIST_DIR));
|
mapper_init(config.GetPath(ConfigOption::PLAYLIST_DIR));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
|
|
||||||
static void
|
static void
|
||||||
InitStorage()
|
InitStorage(const ConfigData &config, EventLoop &event_loop)
|
||||||
{
|
{
|
||||||
Storage *storage = CreateConfiguredStorage(io_thread_get());
|
auto storage = CreateConfiguredStorage(config, event_loop);
|
||||||
if (storage == nullptr)
|
if (storage == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CompositeStorage *composite = new CompositeStorage();
|
CompositeStorage *composite = new CompositeStorage();
|
||||||
instance->storage = composite;
|
instance->storage = composite;
|
||||||
composite->Mount("", storage);
|
composite->Mount("", std::move(storage));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -185,15 +183,17 @@ InitStorage()
|
|||||||
* process has been daemonized.
|
* process has been daemonized.
|
||||||
*/
|
*/
|
||||||
static bool
|
static bool
|
||||||
glue_db_init_and_load(void)
|
glue_db_init_and_load(const ConfigData &config)
|
||||||
{
|
{
|
||||||
instance->database =
|
instance->database =
|
||||||
CreateConfiguredDatabase(instance->event_loop, *instance);
|
CreateConfiguredDatabase(config, instance->event_loop,
|
||||||
|
instance->io_thread.GetEventLoop(),
|
||||||
|
*instance);
|
||||||
if (instance->database == nullptr)
|
if (instance->database == nullptr)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if (instance->database->GetPlugin().flags & DatabasePlugin::FLAG_REQUIRE_STORAGE) {
|
if (instance->database->GetPlugin().RequireStorage()) {
|
||||||
InitStorage();
|
InitStorage(config, instance->io_thread.GetEventLoop());
|
||||||
|
|
||||||
if (instance->storage == nullptr) {
|
if (instance->storage == nullptr) {
|
||||||
delete instance->database;
|
delete instance->database;
|
||||||
@@ -204,7 +204,7 @@ glue_db_init_and_load(void)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (IsStorageConfigured())
|
if (IsStorageConfigured(config))
|
||||||
LogDefault(config_domain,
|
LogDefault(config_domain,
|
||||||
"Ignoring the storage configuration "
|
"Ignoring the storage configuration "
|
||||||
"because the database does not need it");
|
"because the database does not need it");
|
||||||
@@ -216,22 +216,23 @@ glue_db_init_and_load(void)
|
|||||||
std::throw_with_nested(std::runtime_error("Failed to open database plugin"));
|
std::throw_with_nested(std::runtime_error("Failed to open database plugin"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!instance->database->IsPlugin(simple_db_plugin))
|
auto *db = dynamic_cast<SimpleDatabase *>(instance->database);
|
||||||
|
if (db == nullptr)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
SimpleDatabase &db = *(SimpleDatabase *)instance->database;
|
instance->update = new UpdateService(config,
|
||||||
instance->update = new UpdateService(instance->event_loop, db,
|
instance->event_loop, *db,
|
||||||
static_cast<CompositeStorage &>(*instance->storage),
|
static_cast<CompositeStorage &>(*instance->storage),
|
||||||
*instance);
|
*instance);
|
||||||
|
|
||||||
/* run database update after daemonization? */
|
/* run database update after daemonization? */
|
||||||
return db.FileExists();
|
return db->FileExists();
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool
|
static bool
|
||||||
InitDatabaseAndStorage()
|
InitDatabaseAndStorage(const ConfigData &config)
|
||||||
{
|
{
|
||||||
const bool create_db = !glue_db_init_and_load();
|
const bool create_db = !glue_db_init_and_load(config);
|
||||||
return create_db;
|
return create_db;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,39 +242,28 @@ InitDatabaseAndStorage()
|
|||||||
* Configure and initialize the sticker subsystem.
|
* Configure and initialize the sticker subsystem.
|
||||||
*/
|
*/
|
||||||
static void
|
static void
|
||||||
glue_sticker_init()
|
glue_sticker_init(const ConfigData &config)
|
||||||
{
|
{
|
||||||
#ifdef ENABLE_SQLITE
|
#ifdef ENABLE_SQLITE
|
||||||
auto sticker_file = config_get_path(ConfigOption::STICKER_FILE);
|
auto sticker_file = config.GetPath(ConfigOption::STICKER_FILE);
|
||||||
if (sticker_file.IsNull())
|
if (sticker_file.IsNull())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
sticker_global_init(std::move(sticker_file));
|
sticker_global_init(std::move(sticker_file));
|
||||||
|
#else
|
||||||
|
(void)config;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glue_state_file_init()
|
glue_state_file_init(const ConfigData &raw_config)
|
||||||
{
|
{
|
||||||
auto path_fs = config_get_path(ConfigOption::STATE_FILE);
|
StateFileConfig config(raw_config);
|
||||||
if (path_fs.IsNull()) {
|
if (!config.IsEnabled())
|
||||||
#ifdef ANDROID
|
|
||||||
const auto cache_dir = GetUserCacheDir();
|
|
||||||
if (cache_dir.IsNull())
|
|
||||||
return;
|
|
||||||
|
|
||||||
path_fs = AllocatedPath::Build(cache_dir, "state");
|
|
||||||
#else
|
|
||||||
return;
|
return;
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto interval =
|
instance->state_file = new StateFile(std::move(config),
|
||||||
config_get_unsigned(ConfigOption::STATE_FILE_INTERVAL,
|
instance->partitions.front(),
|
||||||
StateFile::DEFAULT_INTERVAL);
|
|
||||||
|
|
||||||
instance->state_file = new StateFile(std::move(path_fs), interval,
|
|
||||||
*instance->partition,
|
|
||||||
instance->event_loop);
|
instance->event_loop);
|
||||||
instance->state_file->Read();
|
instance->state_file->Read();
|
||||||
}
|
}
|
||||||
@@ -282,19 +272,20 @@ glue_state_file_init()
|
|||||||
* 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(const ReplayGainConfig &replay_gain_config)
|
initialize_decoder_and_player(const ConfigData &config,
|
||||||
|
const ReplayGainConfig &replay_gain_config)
|
||||||
{
|
{
|
||||||
const ConfigParam *param;
|
const ConfigParam *param;
|
||||||
|
|
||||||
size_t buffer_size;
|
size_t buffer_size;
|
||||||
param = config_get_param(ConfigOption::AUDIO_BUFFER_SIZE);
|
param = config.GetParam(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);
|
||||||
if (*test != '\0' || tmp <= 0 || tmp == LONG_MAX)
|
if (*test != '\0' || tmp <= 0 || tmp == LONG_MAX)
|
||||||
FormatFatalError("buffer size \"%s\" is not a "
|
throw FormatRuntimeError("buffer size \"%s\" is not a "
|
||||||
"positive integer, line %i",
|
"positive integer, line %i",
|
||||||
param->value.c_str(), param->line);
|
param->value.c_str(), param->line);
|
||||||
buffer_size = tmp * KILOBYTE;
|
buffer_size = tmp * KILOBYTE;
|
||||||
|
|
||||||
if (buffer_size < MIN_BUFFER_SIZE) {
|
if (buffer_size < MIN_BUFFER_SIZE) {
|
||||||
@@ -309,67 +300,37 @@ initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config)
|
|||||||
const unsigned buffered_chunks = buffer_size / CHUNK_SIZE;
|
const unsigned buffered_chunks = buffer_size / CHUNK_SIZE;
|
||||||
|
|
||||||
if (buffered_chunks >= 1 << 15)
|
if (buffered_chunks >= 1 << 15)
|
||||||
FormatFatalError("buffer size \"%lu\" is too big",
|
throw FormatRuntimeError("buffer size \"%lu\" is too big",
|
||||||
(unsigned long)buffer_size);
|
(unsigned long)buffer_size);
|
||||||
|
|
||||||
float perc;
|
|
||||||
param = config_get_param(ConfigOption::BUFFER_BEFORE_PLAY);
|
|
||||||
if (param != nullptr) {
|
|
||||||
char *test;
|
|
||||||
perc = strtod(param->value.c_str(), &test);
|
|
||||||
if (*test != '%' || perc < 0 || perc > 100) {
|
|
||||||
FormatFatalError("buffered before play \"%s\" is not "
|
|
||||||
"a positive percentage and less "
|
|
||||||
"than 100 percent, line %i",
|
|
||||||
param->value.c_str(), param->line);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (perc > 80) {
|
|
||||||
/* this upper limit should avoid deadlocks
|
|
||||||
which can occur because the DecoderThread
|
|
||||||
cannot ever fill the music buffer to
|
|
||||||
exactly 100%; a few chunks always need to
|
|
||||||
be available to generate silence in
|
|
||||||
Player::SendSilence() */
|
|
||||||
FormatError(config_domain,
|
|
||||||
"buffer_before_play is too large (%f%%), capping at 80%%; please fix your configuration",
|
|
||||||
perc);
|
|
||||||
perc = 80;
|
|
||||||
}
|
|
||||||
} else
|
|
||||||
perc = DEFAULT_BUFFER_BEFORE_PLAY;
|
|
||||||
|
|
||||||
unsigned buffered_before_play = (perc / 100) * buffered_chunks;
|
|
||||||
if (buffered_before_play > buffered_chunks)
|
|
||||||
buffered_before_play = buffered_chunks;
|
|
||||||
|
|
||||||
const unsigned max_length =
|
const unsigned max_length =
|
||||||
config_get_positive(ConfigOption::MAX_PLAYLIST_LENGTH,
|
config.GetPositive(ConfigOption::MAX_PLAYLIST_LENGTH,
|
||||||
DEFAULT_PLAYLIST_MAX_LENGTH);
|
DEFAULT_PLAYLIST_MAX_LENGTH);
|
||||||
|
|
||||||
AudioFormat configured_audio_format = AudioFormat::Undefined();
|
AudioFormat configured_audio_format = AudioFormat::Undefined();
|
||||||
param = config_get_param(ConfigOption::AUDIO_OUTPUT_FORMAT);
|
param = config.GetParam(ConfigOption::AUDIO_OUTPUT_FORMAT);
|
||||||
if (param != nullptr) {
|
if (param != nullptr) {
|
||||||
try {
|
try {
|
||||||
configured_audio_format = ParseAudioFormat(param->value.c_str(),
|
configured_audio_format = ParseAudioFormat(param->value.c_str(),
|
||||||
true);
|
true);
|
||||||
} catch (const std::runtime_error &) {
|
} catch (...) {
|
||||||
std::throw_with_nested(FormatRuntimeError("error parsing line %i",
|
std::throw_with_nested(FormatRuntimeError("error parsing line %i",
|
||||||
param->line));
|
param->line));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->partition = new Partition(*instance,
|
instance->partitions.emplace_back(*instance,
|
||||||
max_length,
|
"default",
|
||||||
buffered_chunks,
|
max_length,
|
||||||
buffered_before_play,
|
buffered_chunks,
|
||||||
configured_audio_format,
|
configured_audio_format,
|
||||||
replay_gain_config);
|
replay_gain_config);
|
||||||
|
auto &partition = instance->partitions.back();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
param = config_get_param(ConfigOption::REPLAYGAIN);
|
param = config.GetParam(ConfigOption::REPLAYGAIN);
|
||||||
if (param != nullptr)
|
if (param != nullptr)
|
||||||
instance->partition->replay_gain_mode =
|
partition.replay_gain_mode =
|
||||||
FromString(param->value.c_str());
|
FromString(param->value.c_str());
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
std::throw_with_nested(FormatRuntimeError("Failed to parse line %i",
|
std::throw_with_nested(FormatRuntimeError("Failed to parse line %i",
|
||||||
@@ -377,6 +338,55 @@ initialize_decoder_and_player(const ReplayGainConfig &replay_gain_config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
Instance::BeginShutdownUpdate() noexcept
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
#ifdef ENABLE_INOTIFY
|
||||||
|
mpd_inotify_finish();
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (update != nullptr)
|
||||||
|
update->CancelAllAsync();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
Instance::FinishShutdownUpdate() noexcept
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
delete update;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
Instance::ShutdownDatabase() noexcept
|
||||||
|
{
|
||||||
|
#ifdef ENABLE_DATABASE
|
||||||
|
if (instance->database != nullptr) {
|
||||||
|
instance->database->Close();
|
||||||
|
delete instance->database;
|
||||||
|
}
|
||||||
|
|
||||||
|
delete instance->storage;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
Instance::BeginShutdownPartitions() noexcept
|
||||||
|
{
|
||||||
|
for (auto &partition : partitions) {
|
||||||
|
partition.pc.Kill();
|
||||||
|
partition.listener.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void
|
||||||
|
Instance::FinishShutdownPartitions() noexcept
|
||||||
|
{
|
||||||
|
partitions.clear();
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Instance::OnIdle(unsigned flags)
|
Instance::OnIdle(unsigned flags)
|
||||||
{
|
{
|
||||||
@@ -391,7 +401,8 @@ Instance::OnIdle(unsigned flags)
|
|||||||
|
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int
|
||||||
|
main(int argc, char *argv[]) noexcept
|
||||||
{
|
{
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
return win32_main(argc, argv);
|
return win32_main(argc, argv);
|
||||||
@@ -403,13 +414,12 @@ int main(int argc, char *argv[])
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mpd_main_after_fork(const Config &config);
|
mpd_main_after_fork(const ConfigData &raw_config,
|
||||||
|
const Config &config);
|
||||||
|
|
||||||
#ifdef ANDROID
|
static inline int
|
||||||
static inline
|
MainOrThrow(int argc, char *argv[])
|
||||||
#endif
|
{
|
||||||
int mpd_main(int argc, char *argv[])
|
|
||||||
try {
|
|
||||||
struct options options;
|
struct options options;
|
||||||
|
|
||||||
#ifdef ENABLE_DAEMON
|
#ifdef ENABLE_DAEMON
|
||||||
@@ -424,12 +434,14 @@ try {
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IcuInit();
|
const ScopeIcuInit icu_init;
|
||||||
|
|
||||||
const ScopeNetInit net_init;
|
const ScopeNetInit net_init;
|
||||||
|
|
||||||
io_thread_init();
|
#ifdef ENABLE_DBUS
|
||||||
config_global_init();
|
const ODBus::ScopeInit dbus_init;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
ConfigData raw_config;
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
(void)argc;
|
(void)argc;
|
||||||
@@ -438,29 +450,36 @@ try {
|
|||||||
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");
|
sdcard / Path::FromFS("mpd.conf");
|
||||||
if (FileExists(config_path))
|
if (FileExists(config_path))
|
||||||
ReadConfigFile(config_path);
|
ReadConfigFile(raw_config, config_path);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ParseCommandLine(argc, argv, &options);
|
ParseCommandLine(argc, argv, options, raw_config);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const auto config = LoadConfig();
|
InitPathParser(raw_config);
|
||||||
|
const auto config = LoadConfig(raw_config);
|
||||||
|
|
||||||
#ifdef ENABLE_DAEMON
|
#ifdef ENABLE_DAEMON
|
||||||
glue_daemonize_init(&options);
|
glue_daemonize_init(&options, raw_config);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
TagLoadConfig();
|
TagLoadConfig(raw_config);
|
||||||
|
|
||||||
log_init(options.verbose, options.log_stderr);
|
log_init(raw_config, options.verbose, options.log_stderr);
|
||||||
|
|
||||||
instance = new Instance();
|
instance = new Instance();
|
||||||
|
AtScopeExit() {
|
||||||
|
delete instance;
|
||||||
|
instance = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
instance->neighbors = new NeighborGlue();
|
instance->neighbors = new NeighborGlue();
|
||||||
instance->neighbors->Init(io_thread_get(), *instance);
|
instance->neighbors->Init(raw_config,
|
||||||
|
instance->io_thread.GetEventLoop(),
|
||||||
|
*instance);
|
||||||
|
|
||||||
if (instance->neighbors->IsEmpty()) {
|
if (instance->neighbors->IsEmpty()) {
|
||||||
delete instance->neighbors;
|
delete instance->neighbors;
|
||||||
@@ -469,58 +488,74 @@ try {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
const unsigned max_clients =
|
const unsigned max_clients =
|
||||||
config_get_positive(ConfigOption::MAX_CONN, 10);
|
raw_config.GetPositive(ConfigOption::MAX_CONN, 10);
|
||||||
instance->client_list = new ClientList(max_clients);
|
instance->client_list = new ClientList(max_clients);
|
||||||
|
|
||||||
initialize_decoder_and_player(config.replay_gain);
|
initialize_decoder_and_player(raw_config, config.replay_gain);
|
||||||
|
|
||||||
listen_global_init(instance->event_loop, *instance->partition);
|
listen_global_init(raw_config, *instance->partitions.front().listener);
|
||||||
|
|
||||||
#ifdef ENABLE_DAEMON
|
#ifdef ENABLE_DAEMON
|
||||||
daemonize_set_user();
|
daemonize_set_user();
|
||||||
daemonize_begin(options.daemon);
|
daemonize_begin(options.daemon);
|
||||||
|
AtScopeExit() { daemonize_finish(); };
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return mpd_main_after_fork(config);
|
return mpd_main_after_fork(raw_config, config);
|
||||||
|
}
|
||||||
|
|
||||||
} catch (const std::exception &e) {
|
#ifdef ANDROID
|
||||||
LogError(e);
|
static inline
|
||||||
return EXIT_FAILURE;
|
#endif
|
||||||
|
int mpd_main(int argc, char *argv[]) noexcept
|
||||||
|
{
|
||||||
|
AtScopeExit() { log_deinit(); };
|
||||||
|
|
||||||
|
try {
|
||||||
|
return MainOrThrow(argc, argv);
|
||||||
|
} catch (...) {
|
||||||
|
LogError(std::current_exception());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
mpd_main_after_fork(const Config &config)
|
mpd_main_after_fork(const ConfigData &raw_config, const Config &config)
|
||||||
try {
|
{
|
||||||
ConfigureFS();
|
ConfigureFS(raw_config);
|
||||||
|
|
||||||
glue_mapper_init();
|
glue_mapper_init(raw_config);
|
||||||
|
|
||||||
initPermissions();
|
initPermissions(raw_config);
|
||||||
spl_global_init();
|
spl_global_init(raw_config);
|
||||||
#ifdef ENABLE_ARCHIVE
|
#ifdef ENABLE_ARCHIVE
|
||||||
archive_plugin_init_all();
|
archive_plugin_init_all();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
pcm_convert_global_init();
|
pcm_convert_global_init(raw_config);
|
||||||
|
|
||||||
decoder_plugin_init_all();
|
decoder_plugin_init_all(raw_config);
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
const bool create_db = InitDatabaseAndStorage();
|
const bool create_db = InitDatabaseAndStorage(raw_config);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glue_sticker_init();
|
glue_sticker_init(raw_config);
|
||||||
|
|
||||||
command_init();
|
command_init();
|
||||||
|
|
||||||
instance->partition->outputs.Configure(instance->event_loop,
|
for (auto &partition : instance->partitions) {
|
||||||
config.replay_gain,
|
partition.outputs.Configure(instance->rtio_thread.GetEventLoop(),
|
||||||
instance->partition->pc);
|
raw_config,
|
||||||
instance->partition->UpdateEffectiveReplayGainMode();
|
config.replay_gain,
|
||||||
|
partition.pc);
|
||||||
|
partition.UpdateEffectiveReplayGainMode();
|
||||||
|
}
|
||||||
|
|
||||||
client_manager_init();
|
client_manager_init(raw_config);
|
||||||
input_stream_global_init();
|
input_stream_global_init(raw_config,
|
||||||
playlist_list_global_init();
|
instance->io_thread.GetEventLoop());
|
||||||
|
playlist_list_global_init(raw_config);
|
||||||
|
|
||||||
#ifdef ENABLE_DAEMON
|
#ifdef ENABLE_DAEMON
|
||||||
daemonize_commit();
|
daemonize_commit();
|
||||||
@@ -532,39 +567,36 @@ try {
|
|||||||
SignalHandlersInit(instance->event_loop);
|
SignalHandlersInit(instance->event_loop);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
io_thread_start();
|
instance->io_thread.Start();
|
||||||
|
instance->rtio_thread.Start();
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
if (instance->neighbors != nullptr)
|
if (instance->neighbors != nullptr)
|
||||||
instance->neighbors->Open();
|
instance->neighbors->Open();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
ZeroconfInit(instance->event_loop);
|
ZeroconfInit(raw_config, instance->event_loop);
|
||||||
|
|
||||||
StartPlayerThread(instance->partition->pc);
|
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
if (create_db) {
|
if (create_db) {
|
||||||
/* the database failed to load: recreate the
|
/* the database failed to load: recreate the
|
||||||
database */
|
database */
|
||||||
unsigned job = instance->update->Enqueue("", true);
|
instance->update->Enqueue("", true);
|
||||||
if (job == 0)
|
|
||||||
FatalError("directory update failed");
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
glue_state_file_init();
|
glue_state_file_init(raw_config);
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
#ifdef ENABLE_DATABASE
|
||||||
if (config_get_bool(ConfigOption::AUTO_UPDATE, false)) {
|
if (raw_config.GetBool(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(ConfigOption::AUTO_UPDATE_DEPTH,
|
raw_config.GetUnsigned(ConfigOption::AUTO_UPDATE_DEPTH,
|
||||||
INT_MAX));
|
INT_MAX));
|
||||||
#else
|
#else
|
||||||
FormatWarning(config_domain,
|
FormatWarning(config_domain,
|
||||||
"inotify: auto_update was disabled. enable during compilation phase");
|
"inotify: auto_update was disabled. enable during compilation phase");
|
||||||
@@ -572,11 +604,12 @@ try {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
config_global_check();
|
Check(raw_config);
|
||||||
|
|
||||||
/* 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.LockUpdateAudio();
|
for (auto &partition : instance->partitions)
|
||||||
|
partition.pc.LockUpdateAudio();
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
win32_app_started();
|
win32_app_started();
|
||||||
@@ -599,21 +632,17 @@ try {
|
|||||||
|
|
||||||
/* cleanup */
|
/* cleanup */
|
||||||
|
|
||||||
#if defined(ENABLE_DATABASE) && defined(ENABLE_INOTIFY)
|
instance->BeginShutdownUpdate();
|
||||||
mpd_inotify_finish();
|
|
||||||
|
|
||||||
if (instance->update != nullptr)
|
|
||||||
instance->update->CancelAllAsync();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (instance->state_file != nullptr) {
|
if (instance->state_file != nullptr) {
|
||||||
instance->state_file->Write();
|
instance->state_file->Write();
|
||||||
delete instance->state_file;
|
delete instance->state_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
instance->partition->pc.Kill();
|
|
||||||
ZeroconfDeinit();
|
ZeroconfDeinit();
|
||||||
listen_global_finish();
|
|
||||||
|
instance->BeginShutdownPartitions();
|
||||||
|
|
||||||
delete instance->client_list;
|
delete instance->client_list;
|
||||||
|
|
||||||
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
#ifdef ENABLE_NEIGHBOR_PLUGINS
|
||||||
@@ -623,16 +652,8 @@ try {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ENABLE_DATABASE
|
instance->FinishShutdownUpdate();
|
||||||
delete instance->update;
|
instance->ShutdownDatabase();
|
||||||
|
|
||||||
if (instance->database != nullptr) {
|
|
||||||
instance->database->Close();
|
|
||||||
delete instance->database;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete instance->storage;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef ENABLE_SQLITE
|
#ifdef ENABLE_SQLITE
|
||||||
sticker_global_finish();
|
sticker_global_finish();
|
||||||
@@ -647,31 +668,19 @@ try {
|
|||||||
|
|
||||||
DeinitFS();
|
DeinitFS();
|
||||||
|
|
||||||
delete instance->partition;
|
instance->FinishShutdownPartitions();
|
||||||
command_finish();
|
command_finish();
|
||||||
decoder_plugin_deinit_all();
|
decoder_plugin_deinit_all();
|
||||||
#ifdef ENABLE_ARCHIVE
|
#ifdef ENABLE_ARCHIVE
|
||||||
archive_plugin_deinit_all();
|
archive_plugin_deinit_all();
|
||||||
#endif
|
#endif
|
||||||
config_global_finish();
|
instance->rtio_thread.Stop();
|
||||||
io_thread_deinit();
|
instance->io_thread.Stop();
|
||||||
#ifndef ANDROID
|
#ifndef ANDROID
|
||||||
SignalHandlersFinish();
|
SignalHandlersFinish();
|
||||||
#endif
|
#endif
|
||||||
delete instance;
|
|
||||||
instance = nullptr;
|
|
||||||
|
|
||||||
#ifdef ENABLE_DAEMON
|
|
||||||
daemonize_finish();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
IcuFinish();
|
|
||||||
|
|
||||||
log_deinit();
|
|
||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
} catch (const std::exception &e) {
|
|
||||||
LogError(e);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef ANDROID
|
#ifdef ANDROID
|
||||||
@@ -700,7 +709,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->Shutdown();
|
instance->Break();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -41,7 +41,8 @@ extern Instance *instance;
|
|||||||
* On Windows platform this is called from win32_main()
|
* On Windows platform this is called from win32_main()
|
||||||
* after doing some initialization.
|
* after doing some initialization.
|
||||||
*/
|
*/
|
||||||
int mpd_main(int argc, char *argv[]);
|
int
|
||||||
|
mpd_main(int argc, char *argv[]) noexcept;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
* The absolute path of the playlist directory encoded in the
|
* The absolute path of the playlist directory encoded in the
|
||||||
* filesystem character set.
|
* filesystem character set.
|
||||||
*/
|
*/
|
||||||
static AllocatedPath playlist_dir_fs = AllocatedPath::Null();
|
static AllocatedPath playlist_dir_fs = nullptr;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
mapper_set_playlist_dir(AllocatedPath &&path)
|
mapper_set_playlist_dir(AllocatedPath &&path)
|
||||||
@@ -72,17 +72,17 @@ map_uri_fs(const char *uri) noexcept
|
|||||||
assert(*uri != '/');
|
assert(*uri != '/');
|
||||||
|
|
||||||
if (instance->storage == nullptr)
|
if (instance->storage == nullptr)
|
||||||
return AllocatedPath::Null();
|
return nullptr;
|
||||||
|
|
||||||
const auto music_dir_fs = instance->storage->MapFS("");
|
const auto music_dir_fs = instance->storage->MapFS("");
|
||||||
if (music_dir_fs.IsNull())
|
if (music_dir_fs.IsNull())
|
||||||
return AllocatedPath::Null();
|
return nullptr;
|
||||||
|
|
||||||
const auto uri_fs = AllocatedPath::FromUTF8(uri);
|
const auto uri_fs = AllocatedPath::FromUTF8(uri);
|
||||||
if (uri_fs.IsNull())
|
if (uri_fs.IsNull())
|
||||||
return AllocatedPath::Null();
|
return nullptr;
|
||||||
|
|
||||||
return AllocatedPath::Build(music_dir_fs, uri_fs);
|
return music_dir_fs / uri_fs;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
@@ -118,7 +118,7 @@ AllocatedPath
|
|||||||
map_spl_utf8_to_fs(const char *name) noexcept
|
map_spl_utf8_to_fs(const char *name) noexcept
|
||||||
{
|
{
|
||||||
if (playlist_dir_fs.IsNull())
|
if (playlist_dir_fs.IsNull())
|
||||||
return AllocatedPath::Null();
|
return nullptr;
|
||||||
|
|
||||||
std::string filename_utf8 = name;
|
std::string filename_utf8 = name;
|
||||||
filename_utf8.append(PLAYLIST_FILE_SUFFIX);
|
filename_utf8.append(PLAYLIST_FILE_SUFFIX);
|
||||||
@@ -126,7 +126,7 @@ map_spl_utf8_to_fs(const char *name) noexcept
|
|||||||
const auto filename_fs =
|
const auto filename_fs =
|
||||||
AllocatedPath::FromUTF8(filename_utf8.c_str());
|
AllocatedPath::FromUTF8(filename_utf8.c_str());
|
||||||
if (filename_fs.IsNull())
|
if (filename_fs.IsNull())
|
||||||
return AllocatedPath::Null();
|
return nullptr;
|
||||||
|
|
||||||
return AllocatedPath::Build(playlist_dir_fs, filename_fs);
|
return playlist_dir_fs / filename_fs;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,10 @@
|
|||||||
#ifndef MPD_MAPPER_HXX
|
#ifndef MPD_MAPPER_HXX
|
||||||
#define MPD_MAPPER_HXX
|
#define MPD_MAPPER_HXX
|
||||||
|
|
||||||
#include <string>
|
#include "util/Compiler.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
#include "Compiler.h"
|
#include <string>
|
||||||
|
|
||||||
#define PLAYLIST_FILE_SUFFIX ".m3u"
|
#define PLAYLIST_FILE_SUFFIX ".m3u"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,7 @@
|
|||||||
#ifndef MPD_MIX_RAMP_INFO_HXX
|
#ifndef MPD_MIX_RAMP_INFO_HXX
|
||||||
#define MPD_MIX_RAMP_INFO_HXX
|
#define MPD_MIX_RAMP_INFO_HXX
|
||||||
|
|
||||||
#include "check.h"
|
#include "util/Compiler.h"
|
||||||
#include "Compiler.h"
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -17,21 +17,20 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "MusicBuffer.hxx"
|
#include "MusicBuffer.hxx"
|
||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
MusicBuffer::MusicBuffer(unsigned num_chunks) noexcept
|
MusicBuffer::MusicBuffer(unsigned num_chunks)
|
||||||
:buffer(num_chunks) {
|
:buffer(num_chunks) {
|
||||||
}
|
}
|
||||||
|
|
||||||
MusicChunk *
|
MusicChunkPtr
|
||||||
MusicBuffer::Allocate() noexcept
|
MusicBuffer::Allocate() noexcept
|
||||||
{
|
{
|
||||||
const std::lock_guard<Mutex> protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
return buffer.Allocate();
|
return MusicChunkPtr(buffer.Allocate(), MusicChunkDeleter(*this));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -39,12 +38,15 @@ MusicBuffer::Return(MusicChunk *chunk) noexcept
|
|||||||
{
|
{
|
||||||
assert(chunk != nullptr);
|
assert(chunk != nullptr);
|
||||||
|
|
||||||
|
/* these attributes need to be cleared before locking the
|
||||||
|
mutex, because they might recursively call this method,
|
||||||
|
causing a deadlock */
|
||||||
|
chunk->next.reset();
|
||||||
|
chunk->other.reset();
|
||||||
|
|
||||||
const std::lock_guard<Mutex> protect(mutex);
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
|
||||||
if (chunk->other != nullptr) {
|
assert(!chunk->other || !chunk->other->other);
|
||||||
assert(chunk->other->other == nullptr);
|
|
||||||
buffer.Free(chunk->other);
|
|
||||||
}
|
|
||||||
|
|
||||||
buffer.Free(chunk);
|
buffer.Free(chunk);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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,17 +20,16 @@
|
|||||||
#ifndef MPD_MUSIC_BUFFER_HXX
|
#ifndef MPD_MUSIC_BUFFER_HXX
|
||||||
#define MPD_MUSIC_BUFFER_HXX
|
#define MPD_MUSIC_BUFFER_HXX
|
||||||
|
|
||||||
|
#include "MusicChunkPtr.hxx"
|
||||||
#include "util/SliceBuffer.hxx"
|
#include "util/SliceBuffer.hxx"
|
||||||
#include "thread/Mutex.hxx"
|
#include "thread/Mutex.hxx"
|
||||||
|
|
||||||
struct MusicChunk;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An allocator for #MusicChunk objects.
|
* An allocator for #MusicChunk objects.
|
||||||
*/
|
*/
|
||||||
class MusicBuffer {
|
class MusicBuffer {
|
||||||
/** a mutex which protects #buffer */
|
/** a mutex which protects #buffer */
|
||||||
Mutex mutex;
|
mutable Mutex mutex;
|
||||||
|
|
||||||
SliceBuffer<MusicChunk> buffer;
|
SliceBuffer<MusicChunk> buffer;
|
||||||
|
|
||||||
@@ -41,7 +40,7 @@ public:
|
|||||||
* @param num_chunks the number of #MusicChunk reserved in
|
* @param num_chunks the number of #MusicChunk reserved in
|
||||||
* this buffer
|
* this buffer
|
||||||
*/
|
*/
|
||||||
MusicBuffer(unsigned num_chunks) noexcept;
|
explicit MusicBuffer(unsigned num_chunks);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
/**
|
/**
|
||||||
@@ -50,10 +49,15 @@ public:
|
|||||||
* object is inaccessible to other threads.
|
* object is inaccessible to other threads.
|
||||||
*/
|
*/
|
||||||
bool IsEmptyUnsafe() const {
|
bool IsEmptyUnsafe() const {
|
||||||
return buffer.IsEmpty();
|
return buffer.empty();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
bool IsFull() const noexcept {
|
||||||
|
const std::lock_guard<Mutex> protect(mutex);
|
||||||
|
return buffer.IsFull();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the total number of reserved chunks in this buffer. This
|
* Returns the total number of reserved chunks in this buffer. This
|
||||||
* is the same value which was passed to the constructor
|
* is the same value which was passed to the constructor
|
||||||
@@ -71,7 +75,7 @@ public:
|
|||||||
* @return an empty chunk or nullptr if there are no chunks
|
* @return an empty chunk or nullptr if there are no chunks
|
||||||
* available
|
* available
|
||||||
*/
|
*/
|
||||||
MusicChunk *Allocate() noexcept;
|
MusicChunkPtr Allocate() noexcept;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a chunk to the buffer. It can be reused by
|
* Returns a chunk to the buffer. It can be reused by
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright 2003-2017 The Music Player Daemon Project
|
* Copyright 2003-2018 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
|
||||||
@@ -17,21 +17,18 @@
|
|||||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "MusicChunk.hxx"
|
#include "MusicChunk.hxx"
|
||||||
#include "AudioFormat.hxx"
|
#include "AudioFormat.hxx"
|
||||||
#include "tag/Tag.hxx"
|
#include "tag/Tag.hxx"
|
||||||
|
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
|
|
||||||
MusicChunk::~MusicChunk()
|
MusicChunkInfo::MusicChunkInfo() noexcept = default;
|
||||||
{
|
MusicChunkInfo::~MusicChunkInfo() noexcept = default;
|
||||||
delete tag;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
bool
|
bool
|
||||||
MusicChunk::CheckFormat(const AudioFormat other_format) const noexcept
|
MusicChunkInfo::CheckFormat(const AudioFormat other_format) const noexcept
|
||||||
{
|
{
|
||||||
assert(other_format.IsValid());
|
assert(other_format.IsValid());
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user