Compare commits
953 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6d8725f268 | ||
|
|
373c7cdbc4 | ||
|
|
a4855bb33b | ||
|
|
57c1358ded | ||
|
|
eb4ce1feab | ||
|
|
838c17e144 | ||
|
|
4499cbca3c | ||
|
|
a835a4a2f7 | ||
|
|
9cc6a94353 | ||
|
|
5ed9d9c4a0 | ||
|
|
9c5ac7080d | ||
|
|
6346370e86 | ||
|
|
80697f8f30 | ||
|
|
18b8b56367 | ||
|
|
760aacca26 | ||
|
|
1a4f0dcf5a | ||
|
|
947484a71c | ||
|
|
a74439d038 | ||
|
|
c338618593 | ||
|
|
011897da53 | ||
|
|
3fcaa58947 | ||
|
|
ef8bd4362a | ||
|
|
627a2ef6dd | ||
|
|
2732536d6e | ||
|
|
5a1b4b3ff8 | ||
|
|
d93ec82e4f | ||
|
|
15080972f3 | ||
|
|
171b58f737 | ||
|
|
c008ab6141 | ||
|
|
f14c3654dc | ||
|
|
ae05a61551 | ||
|
|
8e1def225b | ||
|
|
6e061764ee | ||
|
|
ac55b22839 | ||
|
|
49f77d3b75 | ||
|
|
4abc650edf | ||
|
|
5ba00b61be | ||
|
|
bc16a6c4cb | ||
|
|
ea4dc6f040 | ||
|
|
749ae8d5eb | ||
|
|
7a56ffb7c3 | ||
|
|
e62ab23de2 | ||
|
|
c6f6118506 | ||
|
|
8a5d5ad952 | ||
|
|
49e2615d14 | ||
|
|
9289394261 | ||
|
|
8da4c88fd3 | ||
|
|
a303850341 | ||
|
|
fb33610672 | ||
|
|
d024dd6563 | ||
|
|
0be48f9f59 | ||
|
|
df9292bafe | ||
|
|
c1dcef3477 | ||
|
|
48bc1f8361 | ||
|
|
2b2b4dbcf4 | ||
|
|
a1eadecdef | ||
|
|
f0b529952d | ||
|
|
c1ac2debb8 | ||
|
|
ac40094d37 | ||
|
|
cb2bb4cb67 | ||
|
|
f2965940cc | ||
|
|
c9ca147898 | ||
|
|
c379d7f846 | ||
|
|
45ae1ed265 | ||
|
|
9bf00eff40 | ||
|
|
1677b3d5b9 | ||
|
|
2a6806004a | ||
|
|
39347d69df | ||
|
|
a2c0e4d4b1 | ||
|
|
ab2ffd9ac1 | ||
|
|
c69fff52cc | ||
|
|
1cfe61dc72 | ||
|
|
a23f39d81e | ||
|
|
b7724ff583 | ||
|
|
e5dba60fab | ||
|
|
2ccf489a83 | ||
|
|
068939ca0b | ||
|
|
94ba8614ec | ||
|
|
f12a0c2379 | ||
|
|
8ab257645b | ||
|
|
6331a0615f | ||
|
|
a21855fa20 | ||
|
|
12150c2180 | ||
|
|
d90aecb164 | ||
|
|
e738f2bc9f | ||
|
|
2f72c41cda | ||
|
|
aa43d42cdb | ||
|
|
be8228e33c | ||
|
|
5591472dbd | ||
|
|
30e6ced4e9 | ||
|
|
5f4c2bae89 | ||
|
|
0f036d9a43 | ||
|
|
1695ac3a32 | ||
|
|
07a19ba619 | ||
|
|
4dd78d89a0 | ||
|
|
8f4056faa6 | ||
|
|
7b40c33892 | ||
|
|
b06bb5142f | ||
|
|
d576156ee1 | ||
|
|
77079968a5 | ||
|
|
e12aca6214 | ||
|
|
2a72891f28 | ||
|
|
6fe47e78f1 | ||
|
|
0094894b52 | ||
|
|
0951bfb7ac | ||
|
|
60e8519b65 | ||
|
|
78df0ed707 | ||
|
|
e3da0d6c9f | ||
|
|
5df30580a6 | ||
|
|
4816b7dcd8 | ||
|
|
75bced198b | ||
|
|
b500813617 | ||
|
|
a80037f7fc | ||
|
|
1a6345342f | ||
|
|
21b2193cd0 | ||
|
|
3efc496c41 | ||
|
|
16340fbb78 | ||
|
|
a858b28bc4 | ||
|
|
307961cc7e | ||
|
|
3074377b55 | ||
|
|
5a3edc00ac | ||
|
|
5a5f50e1e4 | ||
|
|
7f39a38d6c | ||
|
|
8321a48af7 | ||
|
|
7e613f032e | ||
|
|
1c38c39db2 | ||
|
|
4a0235c2ed | ||
|
|
b92961fda0 | ||
|
|
a2a06be62f | ||
|
|
c0956ed3b0 | ||
|
|
3705e4e4d4 | ||
|
|
3fdbe84573 | ||
|
|
fb8e7d803f | ||
|
|
b01821aa03 | ||
|
|
69f974c9d0 | ||
|
|
5db8b743fe | ||
|
|
c424b0c888 | ||
|
|
d035c7d3b8 | ||
|
|
144ffbc428 | ||
|
|
afa8486d40 | ||
|
|
a4cd42c448 | ||
|
|
853f4b75fa | ||
|
|
b95612287f | ||
|
|
64e779172c | ||
|
|
10a136b4a3 | ||
|
|
ddc3af28ab | ||
|
|
f602948dcf | ||
|
|
973229cf4e | ||
|
|
d1f5cbea4a | ||
|
|
49fe670ddb | ||
|
|
d6d87675c9 | ||
|
|
1ca1927904 | ||
|
|
454c3d1a3c | ||
|
|
11f5004112 | ||
|
|
625343f698 | ||
|
|
89d96a3ec1 | ||
|
|
c4c47fa196 | ||
|
|
ca35894b82 | ||
|
|
0213b6556b | ||
|
|
4edfd9be30 | ||
|
|
e55d9cafb6 | ||
|
|
8deb0ed556 | ||
|
|
82f995f243 | ||
|
|
b41c2ca724 | ||
|
|
06ddbaf2cc | ||
|
|
2adbfe1fbd | ||
|
|
7ae049b559 | ||
|
|
72913ceb1a | ||
|
|
6a2be22fa1 | ||
|
|
eaf20ce8d2 | ||
|
|
97f9e142b4 | ||
|
|
2e0f7b367f | ||
|
|
7312e3f452 | ||
|
|
8faa9f075b | ||
|
|
584dcae075 | ||
|
|
910e869b8d | ||
|
|
469e00b396 | ||
|
|
ec46c758ba | ||
|
|
8970e46bce | ||
|
|
3a4107d903 | ||
|
|
52ee21d550 | ||
|
|
cdda4826cb | ||
|
|
6745df5041 | ||
|
|
3d3efe1117 | ||
|
|
82e5ae05ce | ||
|
|
0dbdd55a6a | ||
|
|
424b0e61cb | ||
|
|
533da8f89c | ||
|
|
31506662db | ||
|
|
7ff1a88ca8 | ||
|
|
1851f26e3f | ||
|
|
84cd65dd6c | ||
|
|
8e0d792bf0 | ||
|
|
e74548b991 | ||
|
|
2356ff5ebb | ||
|
|
691f5d99ca | ||
|
|
ab7b65a30b | ||
|
|
814bb3006c | ||
|
|
4bd4d3ae03 | ||
|
|
af1b0ace19 | ||
|
|
fb54febe03 | ||
|
|
28faae5a4a | ||
|
|
624a920aec | ||
|
|
2bf8187bff | ||
|
|
cf06bf91e3 | ||
|
|
e96f0504c0 | ||
|
|
5fd61725bd | ||
|
|
3fddfa075b | ||
|
|
d712e5c409 | ||
|
|
6287afae6c | ||
|
|
925540055a | ||
|
|
d4373aae93 | ||
|
|
c4be310081 | ||
|
|
d1aa276465 | ||
|
|
2af6fc7452 | ||
|
|
ed15394a96 | ||
|
|
3791d11162 | ||
|
|
032ddabc06 | ||
|
|
bfb93ac6ed | ||
|
|
f6d889d752 | ||
|
|
a7053f4269 | ||
|
|
233a6d06be | ||
|
|
853224148f | ||
|
|
c5c8c27b2e | ||
|
|
d352d5fcff | ||
|
|
0003de9320 | ||
|
|
04f43e77af | ||
|
|
be7cc55488 | ||
|
|
c8f3379a48 | ||
|
|
b5a7945e49 | ||
|
|
0bdac2e97d | ||
|
|
1468a821fb | ||
|
|
3cdc8dc4b6 | ||
|
|
aa255aa7e6 | ||
|
|
66e5ccb9cc | ||
|
|
2215f300bf | ||
|
|
eec767406b | ||
|
|
31aa42c2fa | ||
|
|
e912c59402 | ||
|
|
c9988976f3 | ||
|
|
443be1c2c8 | ||
|
|
7f442cff3b | ||
|
|
3696ae44ad | ||
|
|
fc2d601424 | ||
|
|
8818f24114 | ||
|
|
0e12c8249e | ||
|
|
06d62a70a9 | ||
|
|
76d8018ca2 | ||
|
|
4123b41a5e | ||
|
|
5930257fed | ||
|
|
d3d60327ab | ||
|
|
5080ffb9fc | ||
|
|
9b688a5179 | ||
|
|
a603dc5227 | ||
|
|
c25f682caf | ||
|
|
27a2fd298d | ||
|
|
bb38053cb3 | ||
|
|
5e82ee8695 | ||
|
|
6c691ff9a8 | ||
|
|
ac5a14fe4a | ||
|
|
00402d13ef | ||
|
|
079a559247 | ||
|
|
a19ea8fdba | ||
|
|
c6e172f942 | ||
|
|
bdc9f3e8bf | ||
|
|
8ec5a587fc | ||
|
|
9caf46f2fb | ||
|
|
13fdbfc5e8 | ||
|
|
882c94110e | ||
|
|
97bc980611 | ||
|
|
be9bf5c173 | ||
|
|
6df38c389c | ||
|
|
6c6bceb8cc | ||
|
|
b5a897bb4d | ||
|
|
ab85b716bb | ||
|
|
8e256e6d5c | ||
|
|
288036a63b | ||
|
|
f2005c3343 | ||
|
|
79d516b899 | ||
|
|
28b2f6eae3 | ||
|
|
09ed2b945c | ||
|
|
74aec89ef0 | ||
|
|
4faa23d099 | ||
|
|
5c4997ab20 | ||
|
|
cd490ca946 | ||
|
|
793f6b00e6 | ||
|
|
c1ec568fda | ||
|
|
4e2b52975e | ||
|
|
c141df6b86 | ||
|
|
63b781765a | ||
|
|
c121e141e7 | ||
|
|
7544c9a9f5 | ||
|
|
722a088515 | ||
|
|
0ce75bff58 | ||
|
|
3744b6d3de | ||
|
|
a4ebd91e8d | ||
|
|
3bb0ee916d | ||
|
|
fd6afdf5f3 | ||
|
|
47c13a840e | ||
|
|
5b61992b3c | ||
|
|
36331dc253 | ||
|
|
4265cf31b2 | ||
|
|
337e47269f | ||
|
|
7039234471 | ||
|
|
f7f9333d91 | ||
|
|
bf35665932 | ||
|
|
089a2271c2 | ||
|
|
f8e83e3631 | ||
|
|
46fd329913 | ||
|
|
6b9ba96e77 | ||
|
|
b7d360d850 | ||
|
|
8e226302ab | ||
|
|
7795b9edaf | ||
|
|
9375d9699a | ||
|
|
cf0442d5b8 | ||
|
|
b386ca14df | ||
|
|
ea47fae31e | ||
|
|
e0fed07b10 | ||
|
|
779d5ff7b6 | ||
|
|
eb6fbd03ec | ||
|
|
95409d1b0e | ||
|
|
49599c8731 | ||
|
|
572f94e000 | ||
|
|
c0a2ad5f50 | ||
|
|
71fa5acc74 | ||
|
|
bac5b7679d | ||
|
|
93ade821a5 | ||
|
|
a718e19979 | ||
|
|
8ac83a46f5 | ||
|
|
1b65dcd7df | ||
|
|
bbad45f1e7 | ||
|
|
331b9cca18 | ||
|
|
a9accb7d85 | ||
|
|
1862e70628 | ||
|
|
c4f7054ca6 | ||
|
|
175e568a28 | ||
|
|
c8d580e7de | ||
|
|
bc0c50ee65 | ||
|
|
45e9dd96d1 | ||
|
|
1cc73562a3 | ||
|
|
d870ef0bd5 | ||
|
|
53d308dac5 | ||
|
|
89b06ae7c7 | ||
|
|
d38485a8ad | ||
|
|
834877c503 | ||
|
|
d033b79af4 | ||
|
|
daec2cc203 | ||
|
|
4e593cebab | ||
|
|
73d7701e94 | ||
|
|
24f1d7a72f | ||
|
|
6387a01d7b | ||
|
|
e838840548 | ||
|
|
6a430b441e | ||
|
|
7b977ea839 | ||
|
|
62b8521cbe | ||
|
|
308244d901 | ||
|
|
6f521183f9 | ||
|
|
76c6f7e733 | ||
|
|
80ebfbeb6b | ||
|
|
793901b319 | ||
|
|
3950df8ec9 | ||
|
|
e800b236aa | ||
|
|
4ab7871106 | ||
|
|
3de85549b6 | ||
|
|
73164f7182 | ||
|
|
004b000890 | ||
|
|
d9c703d944 | ||
|
|
364b650033 | ||
|
|
156eb874db | ||
|
|
1a28dd0311 | ||
|
|
e29b4b8609 | ||
|
|
c02997e6d9 | ||
|
|
7c9fc91af9 | ||
|
|
cf5198ac64 | ||
|
|
e76ddd6dd2 | ||
|
|
e3a4cf1cf5 | ||
|
|
5844616ea8 | ||
|
|
abeb580228 | ||
|
|
4d888dfce8 | ||
|
|
08ff6f0ede | ||
|
|
c458c27231 | ||
|
|
9821b70c38 | ||
|
|
8ab8401110 | ||
|
|
4f798c85cf | ||
|
|
1949bdb43f | ||
|
|
8cf2e6b31b | ||
|
|
b1069f9f18 | ||
|
|
fb8dfa9ae9 | ||
|
|
4402a56e94 | ||
|
|
f449808ba3 | ||
|
|
5599739433 | ||
|
|
197cf85f56 | ||
|
|
8c039c9c8b | ||
|
|
c1d9bc046d | ||
|
|
cd99fac7ed | ||
|
|
f4489e6807 | ||
|
|
f2078271b6 | ||
|
|
a3ae9acebb | ||
|
|
b0580265ca | ||
|
|
b4f012392a | ||
|
|
1598809f55 | ||
|
|
6d4f7aa61f | ||
|
|
382080ae4e | ||
|
|
66ac529bca | ||
|
|
ab72207027 | ||
|
|
e3aebf1ca2 | ||
|
|
0e5820c038 | ||
|
|
780e4d34df | ||
|
|
a8700572b7 | ||
|
|
055516312a | ||
|
|
76b4a6585e | ||
|
|
b57535c5ad | ||
|
|
eb10a15eee | ||
|
|
30ed362a8c | ||
|
|
34f071ed1d | ||
|
|
3d3d641e1c | ||
|
|
10c11f2c3d | ||
|
|
cec2745dc0 | ||
|
|
8d15edb063 | ||
|
|
38cf3dc141 | ||
|
|
c146290e07 | ||
|
|
a1745289be | ||
|
|
5a7dbfc87a | ||
|
|
f645950a8f | ||
|
|
b273da0b5e | ||
|
|
689f1eb0c5 | ||
|
|
b0a2edf5fa | ||
|
|
e7b5e02657 | ||
|
|
2d4efd6cf0 | ||
|
|
defc0ada78 | ||
|
|
2f3f4f609c | ||
|
|
4a9c9f8cd4 | ||
|
|
bdc089290d | ||
|
|
cf9f48d8da | ||
|
|
2d67279180 | ||
|
|
83e10aac27 | ||
|
|
9972124aa1 | ||
|
|
d0eb1ba96e | ||
|
|
f5d2910638 | ||
|
|
1cafaf3a79 | ||
|
|
fccc133cb2 | ||
|
|
9fb50b8a73 | ||
|
|
c66c1e17d3 | ||
|
|
4496760340 | ||
|
|
506200d2ee | ||
|
|
04898a3b01 | ||
|
|
f67fb53308 | ||
|
|
c5b78dde04 | ||
|
|
57d9c87de6 | ||
|
|
795f95d855 | ||
|
|
c0ebbc8e2f | ||
|
|
fb377c32ea | ||
|
|
e13faff2d7 | ||
|
|
b0c5348116 | ||
|
|
b462ec022a | ||
|
|
e45a0bf24b | ||
|
|
8962644ba8 | ||
|
|
ad5e04bbcc | ||
|
|
6fc7baec39 | ||
|
|
acd49a9c40 | ||
|
|
bf04358a47 | ||
|
|
b7e13c7b86 | ||
|
|
9b45f0661e | ||
|
|
2a61b1202b | ||
|
|
114f862ea4 | ||
|
|
5a490a8b5a | ||
|
|
8fdc1c1b21 | ||
|
|
32cac90720 | ||
|
|
b2160255d3 | ||
|
|
7fe1f4de93 | ||
|
|
1fbb1b1524 | ||
|
|
0105a53765 | ||
|
|
bd5ab80276 | ||
|
|
387d790228 | ||
|
|
d199a2be0d | ||
|
|
f81ecffda6 | ||
|
|
882f80de1e | ||
|
|
4359f2a0ce | ||
|
|
9c485c4d94 | ||
|
|
1330197036 | ||
|
|
0b0d5fa227 | ||
|
|
45424b8a52 | ||
|
|
0956acbdfb | ||
|
|
654f553d8f | ||
|
|
e4b6e20db6 | ||
|
|
b4f6c6f869 | ||
|
|
16edc52bae | ||
|
|
a33e6c03e4 | ||
|
|
4dccb40bf9 | ||
|
|
9ce1981f93 | ||
|
|
6374c77aa8 | ||
|
|
871bb391d6 | ||
|
|
c3903a7b35 | ||
|
|
6aabf82c11 | ||
|
|
89b624aadf | ||
|
|
67317292ee | ||
|
|
42e7f64856 | ||
|
|
79d963fd65 | ||
|
|
44649fd950 | ||
|
|
0e97f99f93 | ||
|
|
4f52ceb3e0 | ||
|
|
61253b5551 | ||
|
|
12bd6f0d9b | ||
|
|
a32010e03b | ||
|
|
4a934c9dab | ||
|
|
20766c1feb | ||
|
|
6cd4de548f | ||
|
|
8ac4dea8f1 | ||
|
|
e8af3e8d3c | ||
|
|
cd05b10168 | ||
|
|
140935bd8c | ||
|
|
ecb122d93c | ||
|
|
c6e08e0039 | ||
|
|
be1e14df81 | ||
|
|
28bca261fb | ||
|
|
2ab5bc1ad2 | ||
|
|
10c57cf6da | ||
|
|
e65c5eeab1 | ||
|
|
85fad35dc2 | ||
|
|
c992768efe | ||
|
|
7b13c0d059 | ||
|
|
2d3f41da6f | ||
|
|
43b9941dc8 | ||
|
|
dcf27f54aa | ||
|
|
fbf6b69e75 | ||
|
|
0bfebd90da | ||
|
|
e7c3dafa36 | ||
|
|
e90a36da79 | ||
|
|
93f33615ad | ||
|
|
99569081c9 | ||
|
|
588a0b3c41 | ||
|
|
4a1118ceb3 | ||
|
|
a65415bc10 | ||
|
|
8a0e66bf11 | ||
|
|
02cda47c28 | ||
|
|
d34a323a81 | ||
|
|
4166ae8db0 | ||
|
|
955b906b52 | ||
|
|
0d424aa81e | ||
|
|
80acbfa56a | ||
|
|
a7cac24004 | ||
|
|
2927bcf09d | ||
|
|
08dee6bb4f | ||
|
|
08c92f906a | ||
|
|
8e9c9802d1 | ||
|
|
138df66d5e | ||
|
|
0a71347e9a | ||
|
|
2a541a7b9c | ||
|
|
705c12e8da | ||
|
|
cf33df1339 | ||
|
|
87e543b5ef | ||
|
|
81caec99b7 | ||
|
|
41484f8673 | ||
|
|
da0d61f36a | ||
|
|
6f3bc74db0 | ||
|
|
af3bd6ec2f | ||
|
|
b5eb13449b | ||
|
|
bd78e8c275 | ||
|
|
2df21081a1 | ||
|
|
ffebff4ea9 | ||
|
|
2885bc99ca | ||
|
|
2657b80adb | ||
|
|
ebfc106701 | ||
|
|
4d60ca951d | ||
|
|
acf5c57599 | ||
|
|
927df5ff39 | ||
|
|
31fc031267 | ||
|
|
02794e0ebd | ||
|
|
ea6cce7068 | ||
|
|
e4cefeaa8f | ||
|
|
d12d5fd8ae | ||
|
|
0617c3fdc0 | ||
|
|
f00eedf57e | ||
|
|
6d36ae6197 | ||
|
|
45125abb8f | ||
|
|
045b0cd075 | ||
|
|
ff3333e1bf | ||
|
|
7663c5e149 | ||
|
|
4d4748a0a8 | ||
|
|
f8f84ed09e | ||
|
|
e7de7ebbfa | ||
|
|
c9f01f4bc4 | ||
|
|
f2675adc05 | ||
|
|
75beaa3684 | ||
|
|
079495cc32 | ||
|
|
c8bd89e56f | ||
|
|
b089ba2e04 | ||
|
|
adbf8495c6 | ||
|
|
ad062862d8 | ||
|
|
3a86a93154 | ||
|
|
dcf0d6f72d | ||
|
|
83d3725240 | ||
|
|
ce1dd69557 | ||
|
|
4081bdd752 | ||
|
|
c3f1e312b3 | ||
|
|
d820878b89 | ||
|
|
7fa1461d5e | ||
|
|
f4b1ef4d04 | ||
|
|
656130a739 | ||
|
|
aa8679dff5 | ||
|
|
f94a3095fd | ||
|
|
e11958dd58 | ||
|
|
a5a251a964 | ||
|
|
8cb1015a35 | ||
|
|
b5dd90b2d5 | ||
|
|
5f7efee00e | ||
|
|
4150e3efde | ||
|
|
8ebcb71e6e | ||
|
|
f3e852c042 | ||
|
|
5e2a07d144 | ||
|
|
25f6231e9d | ||
|
|
beeba88ea5 | ||
|
|
cc3d454d60 | ||
|
|
afb583cff4 | ||
|
|
561fa66393 | ||
|
|
870dc0d36f | ||
|
|
51462dee1e | ||
|
|
c752d28c6a | ||
|
|
d5ca0ca283 | ||
|
|
f371b3a338 | ||
|
|
93fc4a2c86 | ||
|
|
f10d3f86cc | ||
|
|
af17b0015b | ||
|
|
61af1d1c72 | ||
|
|
65780e1672 | ||
|
|
c92a7967ea | ||
|
|
60aed593b3 | ||
|
|
044f347729 | ||
|
|
aec9df1882 | ||
|
|
4f0a2515f8 | ||
|
|
5cde33711e | ||
|
|
64750025f6 | ||
|
|
cd1cbfdffe | ||
|
|
d413f2c3a7 | ||
|
|
ba314dd734 | ||
|
|
9105b7615c | ||
|
|
a9c162476c | ||
|
|
732b37aca0 | ||
|
|
291b5fad7f | ||
|
|
c2a6def8b9 | ||
|
|
9083c578cc | ||
|
|
bcfd1d39bb | ||
|
|
1185b910c4 | ||
|
|
540b6eba04 | ||
|
|
47f4287e64 | ||
|
|
264c6e259b | ||
|
|
0bbe9838c4 | ||
|
|
2fe337eac3 | ||
|
|
5d7caafdf7 | ||
|
|
f416ef925b | ||
|
|
60bd90848b | ||
|
|
b9f4407815 | ||
|
|
f9cd2639ff | ||
|
|
aeb36e8665 | ||
|
|
057482a3e5 | ||
|
|
15721da46e | ||
|
|
f12b82b5ce | ||
|
|
10dc725942 | ||
|
|
5bd5cdf435 | ||
|
|
84b3603c08 | ||
|
|
8f59b96731 | ||
|
|
e1de110dd7 | ||
|
|
8b6fd3d594 | ||
|
|
d7761e8d79 | ||
|
|
751d652a2f | ||
|
|
647e7e708a | ||
|
|
505c0eeae2 | ||
|
|
bf4001968e | ||
|
|
9d222e2c57 | ||
|
|
033300d659 | ||
|
|
4f2b04bd8f | ||
|
|
f8b9bb4b0f | ||
|
|
8ce8e320c3 | ||
|
|
7c0ab4212b | ||
|
|
26633e0982 | ||
|
|
d27a3f1f33 | ||
|
|
89252d0dba | ||
|
|
dbd2edf442 | ||
|
|
dabd6f8284 | ||
|
|
beb3ab463f | ||
|
|
1d67b623e0 | ||
|
|
2c8cde4d91 | ||
|
|
8cc1d48115 | ||
|
|
ec2468fb8d | ||
|
|
7b54cef23b | ||
|
|
a9da8811fc | ||
|
|
60e86b9881 | ||
|
|
a6766f3c99 | ||
|
|
e59c3c6f70 | ||
|
|
49aa344d8b | ||
|
|
4fed6ab298 | ||
|
|
58eab4d3bc | ||
|
|
5ef5da687d | ||
|
|
4875d319dc | ||
|
|
fb5a53435e | ||
|
|
4f805d65b3 | ||
|
|
56ffb0deb1 | ||
|
|
c0c1457073 | ||
|
|
85a0748ad9 | ||
|
|
c1939a36dd | ||
|
|
b7c394b7a5 | ||
|
|
a070681f89 | ||
|
|
d5e424eec8 | ||
|
|
e0366d38f1 | ||
|
|
cbf1d96b16 | ||
|
|
7cc0d6bb5a | ||
|
|
e19b840ee6 | ||
|
|
5c2ca1e3d9 | ||
|
|
059c4beb30 | ||
|
|
427808226f | ||
|
|
5448245942 | ||
|
|
34ab907007 | ||
|
|
e5fde27859 | ||
|
|
699e8e3ddb | ||
|
|
28ee967371 | ||
|
|
1b0b5f2554 | ||
|
|
1bcc86f989 | ||
|
|
f26f932fd7 | ||
|
|
2b7d48ce77 | ||
|
|
111712fd6d | ||
|
|
7609bc181e | ||
|
|
8b05af7ca3 | ||
|
|
20f9108ebf | ||
|
|
cecae7cdc3 | ||
|
|
e5f3123567 | ||
|
|
27b0e27cfd | ||
|
|
890fba0f61 | ||
|
|
c4b732ff93 | ||
|
|
b8fa2985d5 | ||
|
|
ba741fbce8 | ||
|
|
67d070c334 | ||
|
|
8576afe6f5 | ||
|
|
36807fd376 | ||
|
|
2ad1d27a59 | ||
|
|
7cc9c75d15 | ||
|
|
f33609bbf8 | ||
|
|
69eeb4b0f8 | ||
|
|
aa583ec1aa | ||
|
|
2b9f153257 | ||
|
|
cb9b7fc917 | ||
|
|
74b36c8884 | ||
|
|
89ff7d6dae | ||
|
|
91df420cb4 | ||
|
|
fc25c9f0bc | ||
|
|
12a27e3a8d | ||
|
|
125e32ff00 | ||
|
|
4a110633e8 | ||
|
|
65648f8abd | ||
|
|
50174861dc | ||
|
|
486eb1722e | ||
|
|
740ead4059 | ||
|
|
96424be0da | ||
|
|
cd9d659672 | ||
|
|
ca140388d9 | ||
|
|
8fe0229a2c | ||
|
|
1f43de9458 | ||
|
|
2793f38c2d | ||
|
|
42de7de21d | ||
|
|
1072dc0a41 | ||
|
|
9d8f310e30 | ||
|
|
170adfd00c | ||
|
|
d0135a5ff7 | ||
|
|
1c926cca45 | ||
|
|
ace8ecbb4e | ||
|
|
193fa176dc | ||
|
|
054db62cfa | ||
|
|
fe549cf4c5 | ||
|
|
d347e49b6a | ||
|
|
d6a3f7b329 | ||
|
|
4171bc4c70 | ||
|
|
deca5e5021 | ||
|
|
e0923a0494 | ||
|
|
0a1dfeb860 | ||
|
|
1c911575fa | ||
|
|
d2ef0a996f | ||
|
|
1e886cb12c | ||
|
|
984abc89a8 | ||
|
|
3c6c9741ff | ||
|
|
247a11146c | ||
|
|
d1108c533f | ||
|
|
881339848f | ||
|
|
c44638dcbe | ||
|
|
4887b85b8a | ||
|
|
239f58e290 | ||
|
|
560000f69d | ||
|
|
2d3509ae56 | ||
|
|
4cc926a627 | ||
|
|
a499a70633 | ||
|
|
60a9154326 | ||
|
|
f761b8d4e1 | ||
|
|
7a0f6684e5 | ||
|
|
3ed6817ac9 | ||
|
|
ba76385a2f | ||
|
|
7bcd5ba14c | ||
|
|
40db9f7020 | ||
|
|
dffc46551e | ||
|
|
cf92852bb3 | ||
|
|
844c4a28f4 | ||
|
|
d2fc5a6228 | ||
|
|
006da837aa | ||
|
|
d920e27ab3 | ||
|
|
27bafa8ab2 | ||
|
|
907d18a83a | ||
|
|
37b923bea3 | ||
|
|
91e597bbdd | ||
|
|
a0d697bf6f | ||
|
|
63d5018ad6 | ||
|
|
ca928bdacb | ||
|
|
f7e7791b8b | ||
|
|
80c2e5b141 | ||
|
|
63c171e3b4 | ||
|
|
b0bfb0fdd4 | ||
|
|
31b24d9a09 | ||
|
|
8b04a3b16a | ||
|
|
b88d35d7cb | ||
|
|
e00dcf1af0 | ||
|
|
7f23b9b424 | ||
|
|
e9bf04031b | ||
|
|
c8f2334003 | ||
|
|
380b84195f | ||
|
|
fd26137ad2 | ||
|
|
1ad163aac3 | ||
|
|
36dccc8157 | ||
|
|
6dcdf5bf92 | ||
|
|
0b460017b8 | ||
|
|
061b06cd08 | ||
|
|
86272e1788 | ||
|
|
86f3e011d8 | ||
|
|
0367c5bd1c | ||
|
|
eed008de4b | ||
|
|
74f713ee35 | ||
|
|
6dbb8751b2 | ||
|
|
368bb54870 | ||
|
|
77903a5ecd | ||
|
|
9be161d165 | ||
|
|
0ce5b50950 | ||
|
|
9dded5203e | ||
|
|
d1c2188e5c | ||
|
|
c4285a14b2 | ||
|
|
cf0a47e836 | ||
|
|
c38639afcb | ||
|
|
5863593c65 | ||
|
|
c2fa7f9a57 | ||
|
|
41f5cf6bee | ||
|
|
ea508e9c35 | ||
|
|
5ebf7cd273 | ||
|
|
9986088dc4 | ||
|
|
bfe0b2c634 | ||
|
|
cd2af6974c | ||
|
|
c452486573 | ||
|
|
79406b20f2 | ||
|
|
1226bc214d | ||
|
|
7da79dabdf | ||
|
|
b51026a2ee | ||
|
|
67d01f48a3 | ||
|
|
9fd5c5fc1c | ||
|
|
70bc5b83fa | ||
|
|
b380db51fa | ||
|
|
fab598ebff | ||
|
|
6f6d087fa2 | ||
|
|
6e463d1de3 | ||
|
|
21970f3065 | ||
|
|
9d7e44be2d | ||
|
|
9085fb8285 | ||
|
|
dd79d089f6 | ||
|
|
7aaad124d0 | ||
|
|
0025cb9f53 | ||
|
|
15c8f2a3ee | ||
|
|
fc1a2dac90 | ||
|
|
f698b860f7 | ||
|
|
86b057a301 | ||
|
|
b066158a4b | ||
|
|
046c822604 | ||
|
|
d427733bfc | ||
|
|
04d34a06c7 | ||
|
|
69d86513ae | ||
|
|
019b49a219 | ||
|
|
d9e787784a | ||
|
|
71969b88e3 | ||
|
|
7ae0f5e246 | ||
|
|
1ea7da4bb5 | ||
|
|
8b96bb5f27 | ||
|
|
aefce3ccd0 | ||
|
|
4e599e2aba | ||
|
|
4148c289af | ||
|
|
d575ab0b2b | ||
|
|
d09af19d3f | ||
|
|
a2dff17db9 | ||
|
|
c0fecb935f | ||
|
|
28249b7e99 | ||
|
|
eb63e2257f | ||
|
|
2211716d04 | ||
|
|
242137a50c | ||
|
|
c41311bf76 | ||
|
|
e0d959e3c5 | ||
|
|
f0a5c4b2c2 | ||
|
|
e10a50fdc1 | ||
|
|
380f2509ac | ||
|
|
c0fb35f6b9 | ||
|
|
3e658845d2 | ||
|
|
384209ba70 | ||
|
|
835b589894 | ||
|
|
76e684ee75 | ||
|
|
d0d2c83768 | ||
|
|
b476bc3168 | ||
|
|
5a2ad145e8 | ||
|
|
27233d2549 | ||
|
|
1a0bc75629 | ||
|
|
dc04961699 | ||
|
|
e594cf299e | ||
|
|
096c995a91 | ||
|
|
f64b175cd8 | ||
|
|
954e0e8a59 | ||
|
|
034b032cfa | ||
|
|
e33590bff9 | ||
|
|
55f610f3b2 | ||
|
|
87fd93a1cf | ||
|
|
2db77a248a | ||
|
|
f600274592 | ||
|
|
bc37d00a81 | ||
|
|
1956ea95ee | ||
|
|
a56e3b91e1 | ||
|
|
6bcc9d61e1 | ||
|
|
3ef34191a3 | ||
|
|
60de36aff9 | ||
|
|
b019dd1c51 | ||
|
|
3a083d5527 | ||
|
|
8006241a81 | ||
|
|
b05e3d24ee | ||
|
|
b78c0a4979 | ||
|
|
d3b3c309fa | ||
|
|
65615495d9 | ||
|
|
35f448c34f | ||
|
|
e1abd28a88 | ||
|
|
a109d8be64 | ||
|
|
333a0bc05a | ||
|
|
a831519b54 | ||
|
|
a25052ed96 | ||
|
|
676f8dc8be | ||
|
|
9c3cb82fca | ||
|
|
9b827f58ad | ||
|
|
22e327d391 | ||
|
|
451de4d72d | ||
|
|
0679b78c1d | ||
|
|
ad7084b897 | ||
|
|
3c068eaba9 | ||
|
|
819ae08c6a | ||
|
|
38414ad8de | ||
|
|
f0422f7634 | ||
|
|
2a004dadf3 | ||
|
|
b7ea586e44 | ||
|
|
2a5f286d07 | ||
|
|
0bc14671ec |
544
.circleci/config.yml
Normal file
544
.circleci/config.yml
Normal file
@@ -0,0 +1,544 @@
|
|||||||
|
version: 2.1
|
||||||
|
commands:
|
||||||
|
|
||||||
|
cmake:
|
||||||
|
description: Configure build
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Configure build
|
||||||
|
command: cmake ..
|
||||||
|
working_directory: build
|
||||||
|
|
||||||
|
|
||||||
|
build_source:
|
||||||
|
description: Create source tarball
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Create source tarball
|
||||||
|
command: ../dist/scripts/maketarball.sh
|
||||||
|
working_directory: build
|
||||||
|
|
||||||
|
|
||||||
|
build_rpm:
|
||||||
|
description: Build RPM
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Create RPM build sources directories
|
||||||
|
command: mkdir -p ~/rpmbuild/SOURCES /usr/src/packages/SOURCES
|
||||||
|
- run:
|
||||||
|
name: Copy source tarball 1
|
||||||
|
command: cp strawberry-*.tar.xz ~/rpmbuild/SOURCES/
|
||||||
|
working_directory: build
|
||||||
|
- run:
|
||||||
|
name: Copy source tarball 2
|
||||||
|
command: cp strawberry-*.tar.xz /usr/src/packages/SOURCES/
|
||||||
|
working_directory: build
|
||||||
|
- run:
|
||||||
|
name: Build RPM
|
||||||
|
command: rpmbuild -ba ../dist/unix/strawberry.spec
|
||||||
|
working_directory: build
|
||||||
|
|
||||||
|
|
||||||
|
build_deb:
|
||||||
|
description: Build Deb
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: make deb
|
||||||
|
command: dpkg-buildpackage -b -d -uc -us -nc -j2
|
||||||
|
|
||||||
|
|
||||||
|
install_opensuse_dependencies:
|
||||||
|
description: Install openSUSE dependencies
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Update packages
|
||||||
|
command: zypper --non-interactive --gpg-auto-import-keys ref
|
||||||
|
- run:
|
||||||
|
name: Install openSUSE dependencies
|
||||||
|
command: >
|
||||||
|
zypper --non-interactive --gpg-auto-import-keys install
|
||||||
|
lsb-release
|
||||||
|
rpm-build
|
||||||
|
git
|
||||||
|
tar
|
||||||
|
make
|
||||||
|
cmake
|
||||||
|
gcc
|
||||||
|
gcc-c++
|
||||||
|
gettext-tools
|
||||||
|
glibc-devel
|
||||||
|
libboost_headers-devel
|
||||||
|
boost-devel
|
||||||
|
glib2-devel
|
||||||
|
glib2-tools
|
||||||
|
dbus-1-devel
|
||||||
|
alsa-devel
|
||||||
|
libnotify-devel
|
||||||
|
libgnutls-devel
|
||||||
|
protobuf-devel
|
||||||
|
sqlite3-devel
|
||||||
|
libpulse-devel
|
||||||
|
gstreamer-devel
|
||||||
|
gstreamer-plugins-base-devel
|
||||||
|
libxine-devel
|
||||||
|
vlc-devel
|
||||||
|
libQt5Core-devel
|
||||||
|
libQt5Gui-devel
|
||||||
|
libQt5Widgets-devel
|
||||||
|
libQt5Concurrent-devel
|
||||||
|
libQt5Network-devel
|
||||||
|
libQt5Sql-devel
|
||||||
|
libQt5DBus-devel
|
||||||
|
libQt5Test-devel
|
||||||
|
libqt5-qtx11extras-devel
|
||||||
|
libqt5-qtbase-common-devel
|
||||||
|
libQt5Sql5-sqlite
|
||||||
|
libqt5-linguist-devel
|
||||||
|
libcdio-devel
|
||||||
|
libgpod-devel
|
||||||
|
libplist-devel
|
||||||
|
libmtp-devel
|
||||||
|
libusbmuxd-devel
|
||||||
|
libchromaprint-devel
|
||||||
|
desktop-file-utils
|
||||||
|
update-desktop-files
|
||||||
|
appstream-glib
|
||||||
|
hicolor-icon-theme
|
||||||
|
|
||||||
|
|
||||||
|
install_fedora_dependencies:
|
||||||
|
description: Install Fedora dependencies
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Update packages
|
||||||
|
command: yum update --assumeyes
|
||||||
|
- run:
|
||||||
|
name: Upgrade packages
|
||||||
|
command: yum upgrade --assumeyes
|
||||||
|
- run:
|
||||||
|
name: Install Fedora dependencies
|
||||||
|
command: >
|
||||||
|
dnf install --assumeyes
|
||||||
|
@development-tools
|
||||||
|
redhat-lsb-core
|
||||||
|
git
|
||||||
|
glibc
|
||||||
|
gcc-c++
|
||||||
|
rpmdevtools
|
||||||
|
make
|
||||||
|
cmake
|
||||||
|
pkgconfig
|
||||||
|
glib
|
||||||
|
man
|
||||||
|
tar
|
||||||
|
gettext
|
||||||
|
openssh
|
||||||
|
boost-devel
|
||||||
|
dbus-devel
|
||||||
|
protobuf-devel
|
||||||
|
protobuf-compiler
|
||||||
|
sqlite-devel
|
||||||
|
alsa-lib-devel
|
||||||
|
pulseaudio-libs-devel
|
||||||
|
libnotify-devel
|
||||||
|
gnutls-devel
|
||||||
|
qt5-devel
|
||||||
|
qt5-qtbase-devel
|
||||||
|
qt5-qtx11extras-devel
|
||||||
|
qt5-qttools-devel
|
||||||
|
gstreamer1-devel
|
||||||
|
gstreamer1-plugins-base-devel
|
||||||
|
taglib-devel
|
||||||
|
libcdio-devel
|
||||||
|
libgpod-devel
|
||||||
|
libplist-devel
|
||||||
|
libusbmuxd-devel
|
||||||
|
libmtp-devel
|
||||||
|
libchromaprint-devel
|
||||||
|
fftw-devel
|
||||||
|
desktop-file-utils
|
||||||
|
libappstream-glib
|
||||||
|
hicolor-icon-theme
|
||||||
|
|
||||||
|
|
||||||
|
install_mageia_dependencies:
|
||||||
|
description: Install Mageia dependencies
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Add extra media
|
||||||
|
command: urpmi.addmedia --distrib http://www.mirrorservice.org/sites/mageia.org/pub/mageia/distrib/7/x86_64
|
||||||
|
- run:
|
||||||
|
name: Update packages
|
||||||
|
command: urpmi.update -a
|
||||||
|
- run:
|
||||||
|
name: Configure auto update
|
||||||
|
command: urpmi --auto-update
|
||||||
|
- run:
|
||||||
|
name: Install dependencies
|
||||||
|
command: >
|
||||||
|
urpmi --force
|
||||||
|
urpmi-debuginfo-install
|
||||||
|
git
|
||||||
|
tar
|
||||||
|
rpmdevtools
|
||||||
|
make
|
||||||
|
cmake
|
||||||
|
glibc
|
||||||
|
binutils
|
||||||
|
gcc-c++
|
||||||
|
man
|
||||||
|
gettext
|
||||||
|
notification-daemon
|
||||||
|
dbus-devel
|
||||||
|
libgnutls-devel
|
||||||
|
lib64boost-devel
|
||||||
|
lib64protobuf-devel
|
||||||
|
protobuf-compiler
|
||||||
|
lib64sqlite3-devel
|
||||||
|
lib64alsa2-devel
|
||||||
|
lib64pulseaudio-devel
|
||||||
|
lib64notify-devel
|
||||||
|
lib64qt5core-devel
|
||||||
|
lib64qt5gui-devel
|
||||||
|
lib64qt5widgets-devel
|
||||||
|
lib64qt5network-devel
|
||||||
|
lib64qt5concurrent-devel
|
||||||
|
lib64qt5sql-devel
|
||||||
|
lib64qt5dbus-devel
|
||||||
|
lib64qt5x11extras-devel
|
||||||
|
lib64qt5help-devel
|
||||||
|
libqt5test-devel
|
||||||
|
lib64gstreamer1.0-devel
|
||||||
|
lib64gstreamer-plugins-base1.0-devel
|
||||||
|
lib64cdio-devel
|
||||||
|
lib64gpod-devel
|
||||||
|
lib64plist-devel
|
||||||
|
lib64usbmuxd-devel
|
||||||
|
lib64mtp-devel
|
||||||
|
lib64raw1394-devel
|
||||||
|
lib64chromaprint-devel
|
||||||
|
libfftw-devel
|
||||||
|
desktop-file-utils
|
||||||
|
appstream-util
|
||||||
|
libappstream-glib8
|
||||||
|
hicolor-icon-theme
|
||||||
|
qt5ct
|
||||||
|
lib64mesaegl1
|
||||||
|
|
||||||
|
|
||||||
|
install_debian_dependencies:
|
||||||
|
description: Install Debian dependencies
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Install Debian dependencies
|
||||||
|
command: >
|
||||||
|
apt-get update && apt-get install -y
|
||||||
|
build-essential
|
||||||
|
ssh
|
||||||
|
git
|
||||||
|
make
|
||||||
|
cmake
|
||||||
|
gcc
|
||||||
|
pkg-config
|
||||||
|
fakeroot
|
||||||
|
gettext
|
||||||
|
lsb-release
|
||||||
|
libglib2.0-dev
|
||||||
|
dpkg-dev
|
||||||
|
libdbus-1-dev
|
||||||
|
libboost-dev
|
||||||
|
libprotobuf-dev
|
||||||
|
protobuf-compiler
|
||||||
|
libsqlite3-dev
|
||||||
|
libgnutls28-dev
|
||||||
|
libasound2-dev
|
||||||
|
libpulse-dev
|
||||||
|
qtbase5-dev
|
||||||
|
qtbase5-dev-tools
|
||||||
|
qtbase5-private-dev
|
||||||
|
libqt5x11extras5-dev
|
||||||
|
qttools5-dev
|
||||||
|
libgstreamer1.0-dev
|
||||||
|
libgstreamer-plugins-base1.0-dev
|
||||||
|
gstreamer1.0-alsa
|
||||||
|
gstreamer1.0-pulseaudio
|
||||||
|
libchromaprint-dev
|
||||||
|
libfftw3-dev
|
||||||
|
libcdio-dev
|
||||||
|
libmtp-dev
|
||||||
|
libgpod-dev
|
||||||
|
libimobiledevice-dev
|
||||||
|
libplist-dev
|
||||||
|
libusbmuxd-dev
|
||||||
|
|
||||||
|
|
||||||
|
install_ubuntu_dependencies:
|
||||||
|
description: Install Ubuntu dependencies
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Setup environment
|
||||||
|
command: |
|
||||||
|
echo 'export DEBIAN_FRONTEND=noninteractive' >> $BASH_ENV
|
||||||
|
source $BASH_ENV
|
||||||
|
- run:
|
||||||
|
name: Install Ubuntu dependencies
|
||||||
|
command: >
|
||||||
|
apt-get update && apt-get install -y
|
||||||
|
build-essential
|
||||||
|
ssh
|
||||||
|
git
|
||||||
|
make
|
||||||
|
cmake
|
||||||
|
pkg-config
|
||||||
|
gcc
|
||||||
|
fakeroot
|
||||||
|
wget
|
||||||
|
curl
|
||||||
|
gettext
|
||||||
|
lsb-release
|
||||||
|
dpkg-dev
|
||||||
|
libglib2.0-dev
|
||||||
|
libboost-dev
|
||||||
|
libdbus-1-dev
|
||||||
|
libprotobuf-dev
|
||||||
|
protobuf-compiler
|
||||||
|
libsqlite3-dev
|
||||||
|
libgnutls28-dev
|
||||||
|
libasound2-dev
|
||||||
|
libpulse-dev
|
||||||
|
qtbase5-dev
|
||||||
|
qtbase5-dev-tools
|
||||||
|
qtbase5-private-dev
|
||||||
|
libqt5x11extras5-dev
|
||||||
|
qttools5-dev
|
||||||
|
libgstreamer1.0-dev
|
||||||
|
libgstreamer-plugins-base1.0-dev
|
||||||
|
libgstreamer-plugins-good1.0-dev
|
||||||
|
gstreamer1.0-alsa
|
||||||
|
gstreamer1.0-pulseaudio
|
||||||
|
libchromaprint-dev
|
||||||
|
libfftw3-dev
|
||||||
|
libcdio-dev
|
||||||
|
libmtp-dev
|
||||||
|
libgpod-dev
|
||||||
|
libimobiledevice-dev
|
||||||
|
libplist-dev
|
||||||
|
libusbmuxd-dev
|
||||||
|
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build_source:
|
||||||
|
docker:
|
||||||
|
- image: opensuse/leap:15.1
|
||||||
|
steps:
|
||||||
|
- install_opensuse_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_source
|
||||||
|
|
||||||
|
|
||||||
|
build_opensuse_tumbleweed:
|
||||||
|
docker:
|
||||||
|
- image: opensuse/tumbleweed
|
||||||
|
environment:
|
||||||
|
RPM_BUILD_NCPUS: "2"
|
||||||
|
steps:
|
||||||
|
- run:
|
||||||
|
name: Update packages
|
||||||
|
command: zypper --non-interactive --gpg-auto-import-keys ref
|
||||||
|
- run:
|
||||||
|
name: Upgrade packages
|
||||||
|
command: zypper --non-interactive --gpg-auto-import-keys dup
|
||||||
|
- install_opensuse_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_source
|
||||||
|
- build_rpm
|
||||||
|
|
||||||
|
build_opensuse_lp151:
|
||||||
|
docker:
|
||||||
|
- image: opensuse/leap:15.1
|
||||||
|
environment:
|
||||||
|
RPM_BUILD_NCPUS: "2"
|
||||||
|
steps:
|
||||||
|
- install_opensuse_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_source
|
||||||
|
- build_rpm
|
||||||
|
|
||||||
|
build_opensuse_lp152:
|
||||||
|
docker:
|
||||||
|
- image: opensuse/leap:15.2
|
||||||
|
environment:
|
||||||
|
RPM_BUILD_NCPUS: "2"
|
||||||
|
steps:
|
||||||
|
- install_opensuse_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_source
|
||||||
|
- build_rpm
|
||||||
|
|
||||||
|
|
||||||
|
build_fedora_30:
|
||||||
|
docker:
|
||||||
|
- image: fedora:30
|
||||||
|
environment:
|
||||||
|
RPM_BUILD_NCPUS: "2"
|
||||||
|
steps:
|
||||||
|
- install_fedora_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_source
|
||||||
|
- build_rpm
|
||||||
|
|
||||||
|
build_fedora_31:
|
||||||
|
docker:
|
||||||
|
- image: fedora:31
|
||||||
|
environment:
|
||||||
|
RPM_BUILD_NCPUS: "2"
|
||||||
|
steps:
|
||||||
|
- install_fedora_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_source
|
||||||
|
- build_rpm
|
||||||
|
|
||||||
|
|
||||||
|
build_mageia_7:
|
||||||
|
docker:
|
||||||
|
- image: mageia:7
|
||||||
|
environment:
|
||||||
|
RPM_BUILD_NCPUS: "2"
|
||||||
|
steps:
|
||||||
|
- install_mageia_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_source
|
||||||
|
- build_rpm
|
||||||
|
|
||||||
|
|
||||||
|
build_debian_stretch:
|
||||||
|
docker:
|
||||||
|
- image: debian:stretch
|
||||||
|
steps:
|
||||||
|
- install_debian_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_deb
|
||||||
|
|
||||||
|
build_debian_buster:
|
||||||
|
docker:
|
||||||
|
- image: debian:buster
|
||||||
|
steps:
|
||||||
|
- install_debian_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_deb
|
||||||
|
|
||||||
|
build_debian_bullseye:
|
||||||
|
docker:
|
||||||
|
- image: debian:bullseye
|
||||||
|
steps:
|
||||||
|
- install_debian_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_deb
|
||||||
|
|
||||||
|
|
||||||
|
build_ubuntu_bionic:
|
||||||
|
docker:
|
||||||
|
- image: ubuntu:bionic
|
||||||
|
|
||||||
|
steps:
|
||||||
|
- install_ubuntu_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_deb
|
||||||
|
|
||||||
|
build_ubuntu_eoan:
|
||||||
|
docker:
|
||||||
|
- image: ubuntu:eoan
|
||||||
|
steps:
|
||||||
|
- install_ubuntu_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_deb
|
||||||
|
|
||||||
|
build_ubuntu_focal:
|
||||||
|
docker:
|
||||||
|
- image: ubuntu:focal
|
||||||
|
steps:
|
||||||
|
- install_ubuntu_dependencies
|
||||||
|
- checkout
|
||||||
|
- cmake
|
||||||
|
- build_deb
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2
|
||||||
|
build_all:
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
- build_source:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
|
||||||
|
|
||||||
|
- build_opensuse_tumbleweed:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
- build_opensuse_lp151:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
- build_opensuse_lp152:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
|
||||||
|
|
||||||
|
- build_fedora_30:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
- build_fedora_31:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
|
||||||
|
|
||||||
|
- build_mageia_7:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
|
||||||
|
|
||||||
|
- build_debian_stretch:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
- build_debian_buster:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
- build_debian_bullseye:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
|
||||||
|
|
||||||
|
- build_ubuntu_eoan:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
- build_ubuntu_bionic:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
|
- build_ubuntu_focal:
|
||||||
|
filters:
|
||||||
|
tags:
|
||||||
|
only: /.*/
|
||||||
1
.github/FUNDING.yml
vendored
Normal file
1
.github/FUNDING.yml
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
github: jonaski
|
||||||
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
For general technical questions and help with technical issues please use the forum on https://forum.strawberrymusicplayer.org/
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior.
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots:**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**System Information:**
|
||||||
|
- Operating system:
|
||||||
|
- Strawberry Version:
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
||||||
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
||||||
51
.github/workflows/ccpp.yml
vendored
Normal file
51
.github/workflows/ccpp.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
name: C/C++ CI
|
||||||
|
on: [push, pull_request]
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
|
||||||
|
build-linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: opensuse/leap:15.1
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Update Packages
|
||||||
|
run: zypper ref
|
||||||
|
- name: Install Packages
|
||||||
|
run: zypper --non-interactive --gpg-auto-import-keys install lsb-release rpm-build git tar make cmake gcc gcc-c++ gettext-tools glibc-devel libboost_headers-devel boost-devel glib2-devel glib2-tools dbus-1-devel alsa-devel libnotify-devel libgnutls-devel protobuf-devel sqlite3-devel libpulse-devel gstreamer-devel gstreamer-plugins-base-devel libxine-devel vlc-devel taglib-devel libQt5Core-devel libQt5Gui-devel libQt5Widgets-devel libQt5Concurrent-devel libQt5Network-devel libQt5Sql-devel libQt5DBus-devel libQt5Test-devel libqt5-qtx11extras-devel libqt5-qtbase-common-devel libQt5Sql5-sqlite libqt5-linguist-devel libcdio-devel libgpod-devel libplist-devel libmtp-devel libusbmuxd-devel libchromaprint-devel desktop-file-utils update-desktop-files appstream-glib hicolor-icon-theme
|
||||||
|
- name: Create Build Environment
|
||||||
|
run: mkdir -p build
|
||||||
|
- name: Configure CMake
|
||||||
|
working-directory: build
|
||||||
|
shell: bash
|
||||||
|
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE
|
||||||
|
- name: Build
|
||||||
|
working-directory: build
|
||||||
|
shell: bash
|
||||||
|
run: cmake --build . --config $BUILD_TYPE
|
||||||
|
|
||||||
|
build-macos:
|
||||||
|
runs-on: macos-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v1
|
||||||
|
- name: Unlink python
|
||||||
|
run: brew unlink python@2
|
||||||
|
- name: Install Packages
|
||||||
|
run: brew install glib pkgconfig boost libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav libcdio libmtp libimobiledevice libplist create-dmg taglib
|
||||||
|
- name: Create Build Environment
|
||||||
|
run: cmake -E make_directory ${{runner.workspace}}/build
|
||||||
|
- name: Configure CMake
|
||||||
|
env:
|
||||||
|
Qt5_DIR: /usr/local/opt/qt5/lib/cmake
|
||||||
|
Qt5LinguistTools_DIR: /usr/local/opt/qt5/lib/cmake/Qt5LinguistTools
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
shell: bash
|
||||||
|
run: cmake $GITHUB_WORKSPACE -DCMAKE_BUILD_TYPE=$BUILD_TYPE -DUSE_BUNDLE=ON -DUSE_SYSTEM_TAGLIB=ON
|
||||||
|
- name: Build
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
shell: bash
|
||||||
|
run: cmake --build . --config $BUILD_TYPE
|
||||||
|
- name: Install
|
||||||
|
working-directory: ${{runner.workspace}}/build
|
||||||
|
shell: bash
|
||||||
|
run: make install
|
||||||
160
.gitignore
vendored
160
.gitignore
vendored
@@ -1,80 +1,122 @@
|
|||||||
# This file is used to ignore files which are generated
|
# This file is used to ignore files which are generated
|
||||||
# ----------------------------------------------------------------------------
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
*~
|
# Build
|
||||||
*.autosave
|
build/
|
||||||
*.a
|
bin/
|
||||||
*.core
|
|
||||||
*.moc
|
# CMake
|
||||||
|
CMakeLists.txt.user
|
||||||
|
CMakeCache.txt
|
||||||
|
CMakeFiles
|
||||||
|
CMakeScripts
|
||||||
|
Makefile*
|
||||||
|
Testing
|
||||||
|
cmake_install.cmake
|
||||||
|
install_manifest.txt
|
||||||
|
compile_commands.json
|
||||||
|
CTestTestfile.cmake
|
||||||
|
_deps
|
||||||
|
|
||||||
|
# Prerequisites
|
||||||
|
*.d
|
||||||
|
|
||||||
|
# Compiled Object files
|
||||||
|
*.slo
|
||||||
|
*.lo
|
||||||
*.o
|
*.o
|
||||||
*.obj
|
*.obj
|
||||||
*.orig
|
|
||||||
*.rej
|
# Precompiled Headers
|
||||||
|
*.gch
|
||||||
|
*.pch
|
||||||
|
|
||||||
|
# Compiled Dynamic libraries
|
||||||
*.so
|
*.so
|
||||||
*.so.*
|
*.so.*
|
||||||
*_pch.h.cpp
|
*.dylib
|
||||||
*_resource.rc
|
*.dll
|
||||||
*.qm
|
|
||||||
.#*
|
# Fortran module files
|
||||||
*.*#
|
*.mod
|
||||||
core
|
*.smod
|
||||||
!core/
|
|
||||||
tags
|
# Compiled Static libraries
|
||||||
.DS_Store
|
*.lai
|
||||||
.directory
|
*.la
|
||||||
*.debug
|
*.a
|
||||||
Makefile*
|
*.lib
|
||||||
*.prl
|
|
||||||
|
# Executables
|
||||||
|
*.exe
|
||||||
|
*.out
|
||||||
*.app
|
*.app
|
||||||
|
|
||||||
|
# Dump files
|
||||||
|
*.core
|
||||||
|
*.stackdump
|
||||||
|
|
||||||
|
# Qt
|
||||||
|
*build-*
|
||||||
moc_*.cpp
|
moc_*.cpp
|
||||||
ui_*.h
|
moc_*.h
|
||||||
qrc_*.cpp
|
qrc_*.cpp
|
||||||
Thumbs.db
|
ui_*.h
|
||||||
*.res
|
*.moc
|
||||||
*.rc
|
*.qm
|
||||||
/.qmake.cache
|
|
||||||
/.qmake.stash
|
|
||||||
*.spec
|
|
||||||
*.nsi
|
|
||||||
*.plist
|
|
||||||
maketarball.sh
|
|
||||||
dist/macos/create-dmg.sh
|
|
||||||
dist/debian/changelog
|
|
||||||
dist/pacman/PKGBUILD
|
|
||||||
|
|
||||||
# qtcreator generated files
|
# QtCreator
|
||||||
*.pro.user*
|
CMakeLists.txt.user*
|
||||||
|
*.pro.user
|
||||||
|
*.pro.user.*
|
||||||
|
*creator.user*
|
||||||
|
target_wrapper.*
|
||||||
|
compile_commands.json
|
||||||
|
|
||||||
# xemacs temporary files
|
*.kdev4
|
||||||
|
*.vscode
|
||||||
|
*.code-workspace
|
||||||
|
*.sublime-workspace
|
||||||
|
|
||||||
|
# Temporary files
|
||||||
|
*~
|
||||||
|
*.autosave
|
||||||
|
*.orig
|
||||||
|
*.rej
|
||||||
|
.*.kate-swp
|
||||||
|
.swp.*
|
||||||
|
.*.swp
|
||||||
*.flc
|
*.flc
|
||||||
|
|
||||||
# Vim temporary files
|
# Directory files
|
||||||
.*.swp
|
.directory
|
||||||
|
.DS_Store
|
||||||
# Visual Studio generated files
|
Thumbs.db
|
||||||
*.ib_pdb_index
|
|
||||||
*.idb
|
|
||||||
*.ilk
|
|
||||||
*.pdb
|
|
||||||
*.sln
|
|
||||||
*.suo
|
|
||||||
*.vcproj
|
|
||||||
*vcproj.*.*.user
|
|
||||||
*.ncb
|
|
||||||
*.sdf
|
|
||||||
*.opensdf
|
|
||||||
*.vcxproj
|
|
||||||
*vcxproj.*
|
|
||||||
|
|
||||||
# MinGW generated files
|
# MinGW generated files
|
||||||
*.Debug
|
*.Debug
|
||||||
*.Release
|
*.Release
|
||||||
|
|
||||||
# Python byte code
|
# Package files
|
||||||
*.pyc
|
*.spec
|
||||||
|
*.nsi
|
||||||
|
*.plist
|
||||||
|
|
||||||
# Binaries
|
# Stuff in dist
|
||||||
# --------
|
maketarball.sh
|
||||||
*.dll
|
create-dmg.sh
|
||||||
*.exe
|
changelog
|
||||||
|
PKGBUILD
|
||||||
|
|
||||||
|
# Translations
|
||||||
|
translations.pot
|
||||||
|
zanata.xml
|
||||||
|
.zanata-cache/
|
||||||
|
|
||||||
|
# Snap
|
||||||
|
parts/
|
||||||
|
prime/
|
||||||
|
stage/
|
||||||
|
*.snap
|
||||||
|
/snap/.snapcraft/
|
||||||
|
/*_source.tar.bz2
|
||||||
|
|||||||
54
.travis.yml
54
.travis.yml
@@ -1,51 +1,55 @@
|
|||||||
sudo: required
|
sudo: required
|
||||||
language: C++
|
language: C++
|
||||||
os:
|
os:
|
||||||
- linux
|
|
||||||
- osx
|
- osx
|
||||||
services:
|
services:
|
||||||
- docker
|
- docker
|
||||||
compiler:
|
compiler:
|
||||||
- gcc
|
- gcc
|
||||||
- clang
|
|
||||||
|
|
||||||
before_install:
|
before_install:
|
||||||
- echo $DEPLOY_KEY_ENC | base64 --decode | openssl aes-256-cbc -K $encrypted_83a41ac424a6_key -iv $encrypted_83a41ac424a6_iv -out ~/.ssh/id_rsa -d
|
- if ! [ "$DEPLOY_KEY_ENC" == "" ]; then
|
||||||
- chmod 600 ~/.ssh/id_rsa
|
echo $DEPLOY_KEY_ENC | base64 --decode | openssl aes-256-cbc -K $encrypted_83a41ac424a6_key -iv $encrypted_83a41ac424a6_iv -out ~/.ssh/id_rsa -d ;
|
||||||
|
chmod 600 ~/.ssh/id_rsa ;
|
||||||
|
fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then
|
||||||
docker build -f Dockerfile -t strawberry-build .;
|
docker build -f Dockerfile -t strawberry-build . || travis_terminate 1;
|
||||||
docker run --name build -itd strawberry-build /bin/bash;
|
docker run --name build -itd strawberry-build /bin/bash || travis_terminate 1;
|
||||||
docker exec build git clone https://github.com/jonaski/strawberry;
|
docker exec build git clone https://github.com/strawberrymusicplayer/strawberry;
|
||||||
fi
|
fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
git fetch --unshallow;
|
git fetch --unshallow || travis_terminate 1;
|
||||||
git pull;
|
git pull || travis_terminate 1;
|
||||||
brew update;
|
brew unlink python@2 || travis_terminate 1;
|
||||||
brew unlink python;
|
brew install glib pkgconfig libffi protobuf protobuf-c qt gettext gnutls fftw sqlite chromaprint zlib taglib;
|
||||||
brew install glib pkgconfig protobuf protobuf-c qt;
|
brew install gstreamer gst-plugins-base gst-plugins-good gst-plugins-bad gst-plugins-ugly gst-libav;
|
||||||
brew install sqlite --with-fts;
|
|
||||||
brew install gstreamer gst-plugins-base;
|
|
||||||
brew install gst-plugins-good --with-flac;
|
|
||||||
brew install gst-plugins-bad gst-plugins-ugly gst-libav;
|
|
||||||
brew install chromaprint;
|
|
||||||
brew install libcdio libmtp libimobiledevice libplist;
|
brew install libcdio libmtp libimobiledevice libplist;
|
||||||
|
brew install create-dmg;
|
||||||
export Qt5_DIR=/usr/local/opt/qt5/lib/cmake;
|
export Qt5_DIR=/usr/local/opt/qt5/lib/cmake;
|
||||||
|
export Qt5LinguistTools_DIR=/usr/local/opt/qt5/lib/cmake/Qt5LinguistTools;
|
||||||
|
export PATH="/usr/local/opt/gettext/bin:$PATH";
|
||||||
|
export PKG_CONFIG_PATH="/usr/local/opt/libffi/lib/pkgconfig/:/usr/local/opt/zlib/lib/pkgconfig:$PKG_CONFIG_PATH";
|
||||||
ls /usr/local/lib/gstreamer-1.0;
|
ls /usr/local/lib/gstreamer-1.0;
|
||||||
fi
|
fi
|
||||||
before_script:
|
before_script:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild -DENABLE_STREAM_DEEZER=ON ; fi
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build cmake -Hstrawberry -Bbuild ; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON -DENABLE_STREAM_DEEZER=ON ; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then mkdir build; cd build; cmake .. -DUSE_BUNDLE=ON -DUSE_SYSTEM_TAGLIB=ON ; fi
|
||||||
script:
|
script:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
|
- if [[ "$TRAVIS_OS_NAME" == "linux" ]]; then docker exec build make -C build -j8 ; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then
|
||||||
make -j8;
|
make -j8 || travis_terminate 1;
|
||||||
sudo make install;
|
make install || travis_terminate 1;
|
||||||
sudo ../dist/macos/macdeploy.py strawberry.app;
|
make dmg;
|
||||||
../dist/macos/create-dmg.sh strawberry.app;
|
|
||||||
fi
|
fi
|
||||||
after_success:
|
after_success:
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ls -lh strawberry.dmg; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then ls -lh strawberry*.dmg; fi
|
||||||
- if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$TRAVIS_BRANCH" == "master" ]]; then rsync -e "ssh -o StrictHostKeyChecking=no" -va strawberry*.dmg travis@echoes.jkvinge.net:/home/travis/builds/macos; fi
|
- if [[ "$TRAVIS_OS_NAME" == "osx" ]] && [[ "$CC_FOR_BUILD" == "gcc" ]] && [ -f ~/.ssh/id_rsa ]; then
|
||||||
|
if [[ "$TRAVIS_BRANCH" == "master" ]]; then
|
||||||
|
rsync -e "ssh -o StrictHostKeyChecking=no" -va strawberry*.dmg travis@echoes.jkvinge.net:/home/travis/builds/macos;
|
||||||
|
elif [[ "$TRAVIS_BRANCH" == "macos" ]]; then
|
||||||
|
rsync -e "ssh -o StrictHostKeyChecking=no" -va strawberry*.dmg travis@echoes.jkvinge.net:/home/travis/builds/macos;
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
branches:
|
branches:
|
||||||
except:
|
except:
|
||||||
|
|||||||
27
3rdparty/README.md
vendored
27
3rdparty/README.md
vendored
@@ -7,28 +7,11 @@ This is a small static library used by Strawberry to prevent it from starting tw
|
|||||||
If the user tries to start strawberry twice, the main window will maximize instead of starting another instance.
|
If the user tries to start strawberry twice, the main window will maximize instead of starting another instance.
|
||||||
If you dynamically link to your systems version, you'll need two versions, one defined as QApplication and
|
If you dynamically link to your systems version, you'll need two versions, one defined as QApplication and
|
||||||
one as a QCoreApplication.
|
one as a QCoreApplication.
|
||||||
It is included here because it is normally not packaged by distros, and is also used on macOS and Windows.
|
It is included here because it is not packed by distros and is also used on macOS and Windows.
|
||||||
|
|
||||||
URL: https://github.com/itay-grudev/SingleApplication
|
URL: https://github.com/itay-grudev/SingleApplication
|
||||||
|
|
||||||
|
|
||||||
qocoa
|
|
||||||
-----
|
|
||||||
This is a small static library currently used for the search fields above the collection, playlist and in
|
|
||||||
the cover manager. It is slightly modified from original version, so it should not be used as a dynamic
|
|
||||||
library.
|
|
||||||
The plan in the long run is to replace it with something else.
|
|
||||||
|
|
||||||
URL: https://github.com/mikemcquaid/Qocoa
|
|
||||||
|
|
||||||
|
|
||||||
SPMediaKeyTap
|
|
||||||
-------------
|
|
||||||
|
|
||||||
This is used for macOS only to enable strawberry to grab global shortcuts and can safely be deleted on other
|
|
||||||
platforms.
|
|
||||||
|
|
||||||
|
|
||||||
taglib
|
taglib
|
||||||
------
|
------
|
||||||
|
|
||||||
@@ -36,11 +19,11 @@ TagLib is a library for reading and editing the meta-data of several popular aud
|
|||||||
by Strawberry to identify audio files. It is important that it is kept up-to-date for Strawberry to function
|
by Strawberry to identify audio files. It is important that it is kept up-to-date for Strawberry to function
|
||||||
correctly.
|
correctly.
|
||||||
|
|
||||||
It is kept in 3rdparty because there currently is no offical release of TagLib with the features and bugfixes
|
It is kept in 3rdparty because there currently is no official release of TagLib with the features and bugfixes
|
||||||
that are in the official repository. And also because some distros use older, or unpatched versions.
|
that are in the official repository. And also because some distros use older, or unpatched versions.
|
||||||
This version is a unmodified copy of commit 5cb589a (sha: 5cb589a5b82c13ba8f0542e5e79629da7645cb3c).
|
|
||||||
|
|
||||||
Also, there is a bug in version 1.11.1 corrupting Ogg files, see: https://github.com/taglib/taglib/issues/864
|
There is a bug in the latest version (1.11.1) corrupting Ogg files,
|
||||||
|
see: https://github.com/taglib/taglib/issues/864
|
||||||
If you decide to use the systems taglib, make sure it has been patched with the following commit:
|
If you decide to use the systems taglib, make sure it has been patched with the following commit:
|
||||||
https://github.com/taglib/taglib/commit/9336c82da3a04552168f208cd7a5fa4646701ea4
|
https://github.com/taglib/taglib/commit/9336c82da3a04552168f208cd7a5fa4646701ea4
|
||||||
|
|
||||||
@@ -54,6 +37,6 @@ URL: https://github.com/taglib/taglib
|
|||||||
utf8-cpp
|
utf8-cpp
|
||||||
--------
|
--------
|
||||||
|
|
||||||
This is 2 header files used by taglib, but kept in a seperate directory because it is maintained by others.
|
This is 2 header files used by taglib, but kept in a separate directory because it is maintained by others.
|
||||||
|
|
||||||
URL: http://utfcpp.sourceforge.net/
|
URL: http://utfcpp.sourceforge.net/
|
||||||
|
|||||||
13
3rdparty/SPMediaKeyTap/CMakeLists.txt
vendored
13
3rdparty/SPMediaKeyTap/CMakeLists.txt
vendored
@@ -1,13 +0,0 @@
|
|||||||
set(SPMEDIAKEY-SOURCES
|
|
||||||
SPMediaKeyTap.m
|
|
||||||
SPInvocationGrabbing/NSObject+SPInvocationGrabbing.m
|
|
||||||
)
|
|
||||||
|
|
||||||
set(SPMEDIAKEY-HEADERS
|
|
||||||
SPMediaKeyTap.h
|
|
||||||
SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h
|
|
||||||
)
|
|
||||||
|
|
||||||
ADD_LIBRARY(SPMediaKeyTap STATIC
|
|
||||||
${SPMEDIAKEY-SOURCES}
|
|
||||||
)
|
|
||||||
8
3rdparty/SPMediaKeyTap/LICENSE
vendored
8
3rdparty/SPMediaKeyTap/LICENSE
vendored
@@ -1,8 +0,0 @@
|
|||||||
Copyright (c) 2011, Joachim Bengtsson
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
|
||||||
|
|
||||||
* Neither the name of the organization nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
12
3rdparty/SPMediaKeyTap/README.md
vendored
12
3rdparty/SPMediaKeyTap/README.md
vendored
@@ -1,12 +0,0 @@
|
|||||||
SPMediaKeyTap
|
|
||||||
=============
|
|
||||||
|
|
||||||
`SPMediaKeyTap` abstracts a `CGEventHook` and other nastiness in order to give you a relatively simple API to receive media key events (prev/next/playpause, on F7 to F9 on modern MacBook Pros) exclusively, without them reaching other applications like iTunes. `SPMediaKeyTap` is clever enough to resign its exclusive lock on media keys by looking for which application was active most recently: if that application is in `SPMediaKeyTap`'s whitelist, it will resign the keys. This is similar to the behavior of Apple's applications collaborating on media key handling exclusivity, but unfortunately, Apple are not exposing any APIs allowing third-parties to join in on this collaboration.
|
|
||||||
|
|
||||||
For now, the whitelist is just a hardcoded array in `+[SPMediaKeyTap defaultMediaKeyUserBundleIdentifiers]`. If your app starts using `SPMediaKeyTap`, please [mail me](mailto:nevyn@spotify.com) your bundle ID, and I'll include it in the canonical repository. This is a bad solution; a better solution would be to use distributed notifications to collaborate in creating this whitelist at runtime. Hopefully someone'll have the time and energy to write this soon.
|
|
||||||
|
|
||||||
In `Example/SPMediaKeyTapExampleAppDelegate.m` is an example of both how you use `SPMediaKeyTap`, and how you handle the semi-private `NSEvent` subtypes involved in media keys, including on how to fall back to non-event tap handling of these events.
|
|
||||||
|
|
||||||
`SPMediaKeyTap` and other `CGEventHook`s on the event type `NSSystemDefined` is known to interfere with each other and applications doing weird stuff with mouse input, because mouse clicks are also part of the `NSSystemDefined` category. The single issue we have had reported here at Spotify is Adobe Fireworks, in which item selection stops working with `SPMediaKeyTap` is active.
|
|
||||||
|
|
||||||
`SPMediaKeyTap` requires 10.5 to work, and disables itself on 10.4.
|
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
#import <Foundation/Foundation.h>
|
|
||||||
|
|
||||||
@interface SPInvocationGrabber : NSObject {
|
|
||||||
id _object;
|
|
||||||
NSInvocation *_invocation;
|
|
||||||
int frameCount;
|
|
||||||
char **frameStrings;
|
|
||||||
BOOL backgroundAfterForward;
|
|
||||||
BOOL onMainAfterForward;
|
|
||||||
BOOL waitUntilDone;
|
|
||||||
}
|
|
||||||
-(id)initWithObject:(id)obj;
|
|
||||||
-(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack;
|
|
||||||
@property (readonly, retain, nonatomic) id object;
|
|
||||||
@property (readonly, retain, nonatomic) NSInvocation *invocation;
|
|
||||||
@property BOOL backgroundAfterForward;
|
|
||||||
@property BOOL onMainAfterForward;
|
|
||||||
@property BOOL waitUntilDone;
|
|
||||||
-(void)invoke; // will release object and invocation
|
|
||||||
-(void)printBacktrace;
|
|
||||||
-(void)saveBacktrace;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSObject (SPInvocationGrabbing)
|
|
||||||
-(id)grab;
|
|
||||||
-(id)invokeAfter:(NSTimeInterval)delta;
|
|
||||||
-(id)nextRunloop;
|
|
||||||
-(id)inBackground;
|
|
||||||
-(id)onMainAsync:(BOOL)async;
|
|
||||||
@end
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
#import "NSObject+SPInvocationGrabbing.h"
|
|
||||||
#import <execinfo.h>
|
|
||||||
|
|
||||||
#pragma mark Invocation grabbing
|
|
||||||
@interface SPInvocationGrabber ()
|
|
||||||
@property (readwrite, retain, nonatomic) id object;
|
|
||||||
@property (readwrite, retain, nonatomic) NSInvocation *invocation;
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation SPInvocationGrabber
|
|
||||||
- (id)initWithObject:(id)obj;
|
|
||||||
{
|
|
||||||
return [self initWithObject:obj stacktraceSaving:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
-(id)initWithObject:(id)obj stacktraceSaving:(BOOL)saveStack;
|
|
||||||
{
|
|
||||||
self.object = obj;
|
|
||||||
|
|
||||||
if(saveStack)
|
|
||||||
[self saveBacktrace];
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
-(void)dealloc;
|
|
||||||
{
|
|
||||||
free(frameStrings);
|
|
||||||
self.object = nil;
|
|
||||||
self.invocation = nil;
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
@synthesize invocation = _invocation, object = _object;
|
|
||||||
|
|
||||||
@synthesize backgroundAfterForward, onMainAfterForward, waitUntilDone;
|
|
||||||
- (void)runInBackground;
|
|
||||||
{
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
@try {
|
|
||||||
[self invoke];
|
|
||||||
}
|
|
||||||
@finally {
|
|
||||||
[pool drain];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
- (void)forwardInvocation:(NSInvocation *)anInvocation {
|
|
||||||
[anInvocation retainArguments];
|
|
||||||
anInvocation.target = _object;
|
|
||||||
self.invocation = anInvocation;
|
|
||||||
|
|
||||||
if(backgroundAfterForward)
|
|
||||||
[NSThread detachNewThreadSelector:@selector(runInBackground) toTarget:self withObject:nil];
|
|
||||||
else if(onMainAfterForward)
|
|
||||||
[self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:waitUntilDone];
|
|
||||||
}
|
|
||||||
- (NSMethodSignature *)methodSignatureForSelector:(SEL)inSelector {
|
|
||||||
NSMethodSignature *signature = [super methodSignatureForSelector:inSelector];
|
|
||||||
if (signature == NULL)
|
|
||||||
signature = [_object methodSignatureForSelector:inSelector];
|
|
||||||
|
|
||||||
return signature;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)invoke;
|
|
||||||
{
|
|
||||||
|
|
||||||
@try {
|
|
||||||
[_invocation invoke];
|
|
||||||
}
|
|
||||||
@catch (NSException * e) {
|
|
||||||
NSLog(@"SPInvocationGrabber's target raised %@:\n\t%@\nInvocation was originally scheduled at:", e.name, e);
|
|
||||||
[self printBacktrace];
|
|
||||||
printf("\n");
|
|
||||||
[e raise];
|
|
||||||
}
|
|
||||||
|
|
||||||
self.invocation = nil;
|
|
||||||
self.object = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)saveBacktrace;
|
|
||||||
{
|
|
||||||
void *backtraceFrames[128];
|
|
||||||
frameCount = backtrace(&backtraceFrames[0], 128);
|
|
||||||
frameStrings = backtrace_symbols(&backtraceFrames[0], frameCount);
|
|
||||||
}
|
|
||||||
-(void)printBacktrace;
|
|
||||||
{
|
|
||||||
int x;
|
|
||||||
for(x = 3; x < frameCount; x++) {
|
|
||||||
if(frameStrings[x] == NULL) { break; }
|
|
||||||
printf("%s\n", frameStrings[x]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation NSObject (SPInvocationGrabbing)
|
|
||||||
-(id)grab;
|
|
||||||
{
|
|
||||||
return [[[SPInvocationGrabber alloc] initWithObject:self] autorelease];
|
|
||||||
}
|
|
||||||
-(id)invokeAfter:(NSTimeInterval)delta;
|
|
||||||
{
|
|
||||||
id grabber = [self grab];
|
|
||||||
[NSTimer scheduledTimerWithTimeInterval:delta target:grabber selector:@selector(invoke) userInfo:nil repeats:NO];
|
|
||||||
return grabber;
|
|
||||||
}
|
|
||||||
- (id)nextRunloop;
|
|
||||||
{
|
|
||||||
return [self invokeAfter:0];
|
|
||||||
}
|
|
||||||
-(id)inBackground;
|
|
||||||
{
|
|
||||||
SPInvocationGrabber *grabber = [self grab];
|
|
||||||
grabber.backgroundAfterForward = YES;
|
|
||||||
return grabber;
|
|
||||||
}
|
|
||||||
-(id)onMainAsync:(BOOL)async;
|
|
||||||
{
|
|
||||||
SPInvocationGrabber *grabber = [self grab];
|
|
||||||
grabber.onMainAfterForward = YES;
|
|
||||||
grabber.waitUntilDone = !async;
|
|
||||||
return grabber;
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// A
|
|
||||||
+(UIView*)flashAt:(CGRect)r in:(UIView*)parent color:(UIColor*)color;
|
|
||||||
{
|
|
||||||
float duration = 0.5;
|
|
||||||
UIView *flash = [[[UIView alloc] initWithFrame:r] autorelease];
|
|
||||||
flash.backgroundColor = color;
|
|
||||||
[parent addSubview:flash];
|
|
||||||
[[flash invokeAfter:duration+0.1] removeFromSuperview];
|
|
||||||
|
|
||||||
[UIView beginAnimations:@"SPFlash" context:NULL];
|
|
||||||
[UIView setAnimationDuration:duration];
|
|
||||||
flash.alpha = 0.0;
|
|
||||||
[UIView commitAnimations];
|
|
||||||
return flash;
|
|
||||||
}
|
|
||||||
|
|
||||||
// B
|
|
||||||
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
|
|
||||||
|
|
||||||
// Force the animation to happen by calling this method again after a small
|
|
||||||
// delay - see http://blog.instapaper.com/post/53568356
|
|
||||||
[[self nextRunloop] delayedTableViewDidSelectRowAtIndexPath: indexPath];
|
|
||||||
}
|
|
||||||
|
|
||||||
// C
|
|
||||||
[[tableView invokeAfter:0.15] selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
|
|
||||||
[[tableView invokeAfter:0.30] deselectRowAtIndexPath:indexPath animated:YES];
|
|
||||||
[[tableView invokeAfter:0.45] selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
@interface MyClass : NSObject
|
|
||||||
-(BOOL)areTheNewViewersGoneYet:(Duck*)duck;
|
|
||||||
@end
|
|
||||||
...
|
|
||||||
MyClass *myInstance = [[MyClass alloc] init];
|
|
||||||
id invocationGrabber = [[[SPInvocationGrabber alloc] initWithTarget:myInstance] autorelease];
|
|
||||||
|
|
||||||
|
|
||||||
[invocationGrabber areTheNewViewersGoneYet:[Duck yellowDuck]]; // line 9
|
|
||||||
|
|
||||||
|
|
||||||
NSInvocation *invocationForAreTheNewViewersGoneYet = [invocationGrabber invocation];
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
#import <Cocoa/Cocoa.h>
|
|
||||||
#import "NSObject+SPInvocationGrabbing.h"
|
|
||||||
|
|
||||||
@interface Foo : NSObject {
|
|
||||||
int a;
|
|
||||||
}
|
|
||||||
-(void)startIt;
|
|
||||||
-(void)theBackgroundStuff;
|
|
||||||
-(void)theForegroundStuff;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation Foo
|
|
||||||
-(void)startIt;
|
|
||||||
{
|
|
||||||
NSLog(@"Starting out on the main thread...");
|
|
||||||
a = 3;
|
|
||||||
[[self inBackground] theBackgroundStuff];
|
|
||||||
}
|
|
||||||
-(void)theBackgroundStuff;
|
|
||||||
{
|
|
||||||
NSLog(@"Woah, this is a background thread!");
|
|
||||||
a += 6;
|
|
||||||
[[self onMainAsync:YES] theForegroundStuff];
|
|
||||||
}
|
|
||||||
-(void)theForegroundStuff;
|
|
||||||
{
|
|
||||||
NSLog(@"Hey presto: %d", a);
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
int main() {
|
|
||||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
|
||||||
Foo *foo = [Foo new];
|
|
||||||
[foo startIt];
|
|
||||||
[[NSRunLoop currentRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]];
|
|
||||||
[pool release];
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
34
3rdparty/SPMediaKeyTap/SPMediaKeyTap.h
vendored
34
3rdparty/SPMediaKeyTap/SPMediaKeyTap.h
vendored
@@ -1,34 +0,0 @@
|
|||||||
#include <Cocoa/Cocoa.h>
|
|
||||||
#import <IOKit/hidsystem/ev_keymap.h>
|
|
||||||
#import <Carbon/Carbon.h>
|
|
||||||
|
|
||||||
// http://overooped.com/post/2593597587/mediakeys
|
|
||||||
|
|
||||||
#define SPSystemDefinedEventMediaKeys 8
|
|
||||||
|
|
||||||
@interface SPMediaKeyTap : NSObject {
|
|
||||||
EventHandlerRef _app_switching_ref;
|
|
||||||
EventHandlerRef _app_terminating_ref;
|
|
||||||
CFMachPortRef _eventPort;
|
|
||||||
CFRunLoopSourceRef _eventPortSource;
|
|
||||||
CFRunLoopRef _tapThreadRL;
|
|
||||||
BOOL _shouldInterceptMediaKeyEvents;
|
|
||||||
id _delegate;
|
|
||||||
// The app that is frontmost in this list owns media keys
|
|
||||||
NSMutableArray *_mediaKeyAppList;
|
|
||||||
}
|
|
||||||
+ (NSArray*)defaultMediaKeyUserBundleIdentifiers;
|
|
||||||
|
|
||||||
-(id)initWithDelegate:(id)delegate;
|
|
||||||
|
|
||||||
+(BOOL)usesGlobalMediaKeyTap;
|
|
||||||
-(void)startWatchingMediaKeys;
|
|
||||||
-(void)stopWatchingMediaKeys;
|
|
||||||
-(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@interface NSObject (SPMediaKeyTapDelegate)
|
|
||||||
-(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event;
|
|
||||||
@end
|
|
||||||
|
|
||||||
extern NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey;
|
|
||||||
300
3rdparty/SPMediaKeyTap/SPMediaKeyTap.m
vendored
300
3rdparty/SPMediaKeyTap/SPMediaKeyTap.m
vendored
@@ -1,300 +0,0 @@
|
|||||||
// Copyright (c) 2010 Spotify AB
|
|
||||||
#import "SPMediaKeyTap.h"
|
|
||||||
#import "SPInvocationGrabbing/NSObject+SPInvocationGrabbing.h" // https://gist.github.com/511181, in submodule
|
|
||||||
|
|
||||||
@interface SPMediaKeyTap ()
|
|
||||||
-(BOOL)shouldInterceptMediaKeyEvents;
|
|
||||||
-(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting;
|
|
||||||
-(void)startWatchingAppSwitching;
|
|
||||||
-(void)stopWatchingAppSwitching;
|
|
||||||
-(void)eventTapThread;
|
|
||||||
@end
|
|
||||||
static SPMediaKeyTap *singleton = nil;
|
|
||||||
|
|
||||||
static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData);
|
|
||||||
static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData);
|
|
||||||
static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon);
|
|
||||||
|
|
||||||
|
|
||||||
// Inspired by http://gist.github.com/546311
|
|
||||||
|
|
||||||
@implementation SPMediaKeyTap
|
|
||||||
|
|
||||||
#pragma mark -
|
|
||||||
#pragma mark Setup and teardown
|
|
||||||
-(id)initWithDelegate:(id)delegate;
|
|
||||||
{
|
|
||||||
_delegate = delegate;
|
|
||||||
[self startWatchingAppSwitching];
|
|
||||||
singleton = self;
|
|
||||||
_mediaKeyAppList = [NSMutableArray new];
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
-(void)dealloc;
|
|
||||||
{
|
|
||||||
[self stopWatchingMediaKeys];
|
|
||||||
[self stopWatchingAppSwitching];
|
|
||||||
[_mediaKeyAppList release];
|
|
||||||
[super dealloc];
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)startWatchingAppSwitching;
|
|
||||||
{
|
|
||||||
// Listen to "app switched" event, so that we don't intercept media keys if we
|
|
||||||
// weren't the last "media key listening" app to be active
|
|
||||||
EventTypeSpec eventType = { kEventClassApplication, kEventAppFrontSwitched };
|
|
||||||
OSStatus err = InstallApplicationEventHandler(NewEventHandlerUPP(appSwitched), 1, &eventType, self, &_app_switching_ref);
|
|
||||||
assert(err == noErr);
|
|
||||||
|
|
||||||
eventType.eventKind = kEventAppTerminated;
|
|
||||||
err = InstallApplicationEventHandler(NewEventHandlerUPP(appTerminated), 1, &eventType, self, &_app_terminating_ref);
|
|
||||||
assert(err == noErr);
|
|
||||||
}
|
|
||||||
-(void)stopWatchingAppSwitching;
|
|
||||||
{
|
|
||||||
if(!_app_switching_ref) return;
|
|
||||||
RemoveEventHandler(_app_switching_ref);
|
|
||||||
_app_switching_ref = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)startWatchingMediaKeys;{
|
|
||||||
[self setShouldInterceptMediaKeyEvents:YES];
|
|
||||||
|
|
||||||
// Add an event tap to intercept the system defined media key events
|
|
||||||
_eventPort = CGEventTapCreate(kCGSessionEventTap,
|
|
||||||
kCGHeadInsertEventTap,
|
|
||||||
kCGEventTapOptionDefault,
|
|
||||||
CGEventMaskBit(NX_SYSDEFINED),
|
|
||||||
tapEventCallback,
|
|
||||||
self);
|
|
||||||
assert(_eventPort != NULL);
|
|
||||||
|
|
||||||
_eventPortSource = CFMachPortCreateRunLoopSource(kCFAllocatorSystemDefault, _eventPort, 0);
|
|
||||||
assert(_eventPortSource != NULL);
|
|
||||||
|
|
||||||
// Let's do this in a separate thread so that a slow app doesn't lag the event tap
|
|
||||||
[NSThread detachNewThreadSelector:@selector(eventTapThread) toTarget:self withObject:nil];
|
|
||||||
}
|
|
||||||
-(void)stopWatchingMediaKeys;
|
|
||||||
{
|
|
||||||
// TODO<nevyn>: Shut down thread, remove event tap port and source
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark -
|
|
||||||
#pragma mark Accessors
|
|
||||||
|
|
||||||
+(BOOL)usesGlobalMediaKeyTap
|
|
||||||
{
|
|
||||||
#ifdef _DEBUG
|
|
||||||
// breaking in gdb with a key tap inserted sometimes locks up all mouse and keyboard input forever, forcing reboot
|
|
||||||
return NO;
|
|
||||||
#else
|
|
||||||
// XXX(nevyn): MediaKey event tap doesn't work on 10.4, feel free to figure out why if you have the energy.
|
|
||||||
return floor(NSAppKitVersionNumber) >= 949/*NSAppKitVersionNumber10_5*/;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
+ (NSArray*)defaultMediaKeyUserBundleIdentifiers;
|
|
||||||
{
|
|
||||||
return [NSArray arrayWithObjects:
|
|
||||||
[[NSBundle mainBundle] bundleIdentifier], // your app
|
|
||||||
@"com.spotify.client",
|
|
||||||
@"com.apple.iTunes",
|
|
||||||
@"com.apple.QuickTimePlayerX",
|
|
||||||
@"com.apple.quicktimeplayer",
|
|
||||||
@"com.apple.iWork.Keynote",
|
|
||||||
@"com.apple.iPhoto",
|
|
||||||
@"org.videolan.vlc",
|
|
||||||
@"com.apple.Aperture",
|
|
||||||
@"com.plexsquared.Plex",
|
|
||||||
@"com.soundcloud.desktop",
|
|
||||||
@"com.macromedia.fireworks", // the tap messes up their mouse input
|
|
||||||
nil
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-(BOOL)shouldInterceptMediaKeyEvents;
|
|
||||||
{
|
|
||||||
BOOL shouldIntercept = NO;
|
|
||||||
@synchronized(self) {
|
|
||||||
shouldIntercept = _shouldInterceptMediaKeyEvents;
|
|
||||||
}
|
|
||||||
return shouldIntercept;
|
|
||||||
}
|
|
||||||
|
|
||||||
-(void)pauseTapOnTapThread:(BOOL)yeahno;
|
|
||||||
{
|
|
||||||
CGEventTapEnable(self->_eventPort, yeahno);
|
|
||||||
}
|
|
||||||
-(void)setShouldInterceptMediaKeyEvents:(BOOL)newSetting;
|
|
||||||
{
|
|
||||||
BOOL oldSetting;
|
|
||||||
@synchronized(self) {
|
|
||||||
oldSetting = _shouldInterceptMediaKeyEvents;
|
|
||||||
_shouldInterceptMediaKeyEvents = newSetting;
|
|
||||||
}
|
|
||||||
if(_tapThreadRL && oldSetting != newSetting) {
|
|
||||||
id grab = [self grab];
|
|
||||||
[grab pauseTapOnTapThread:newSetting];
|
|
||||||
NSTimer *timer = [NSTimer timerWithTimeInterval:0 invocation:[grab invocation] repeats:NO];
|
|
||||||
CFRunLoopAddTimer(_tapThreadRL, (CFRunLoopTimerRef)timer, kCFRunLoopCommonModes);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark
|
|
||||||
#pragma mark -
|
|
||||||
#pragma mark Event tap callbacks
|
|
||||||
|
|
||||||
// Note: method called on background thread
|
|
||||||
|
|
||||||
static CGEventRef tapEventCallback2(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
|
|
||||||
{
|
|
||||||
SPMediaKeyTap *self = refcon;
|
|
||||||
|
|
||||||
if(type == kCGEventTapDisabledByTimeout) {
|
|
||||||
NSLog(@"Media key event tap was disabled by timeout");
|
|
||||||
CGEventTapEnable(self->_eventPort, TRUE);
|
|
||||||
return event;
|
|
||||||
} else if(type == kCGEventTapDisabledByUserInput) {
|
|
||||||
// Was disabled manually by -[pauseTapOnTapThread]
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
NSEvent *nsEvent = nil;
|
|
||||||
@try {
|
|
||||||
nsEvent = [NSEvent eventWithCGEvent:event];
|
|
||||||
}
|
|
||||||
@catch (NSException * e) {
|
|
||||||
NSLog(@"Strange CGEventType: %d: %@", type, e);
|
|
||||||
assert(0);
|
|
||||||
return event;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (type != NX_SYSDEFINED || [nsEvent subtype] != SPSystemDefinedEventMediaKeys)
|
|
||||||
return event;
|
|
||||||
|
|
||||||
int keyCode = (([nsEvent data1] & 0xFFFF0000) >> 16);
|
|
||||||
if (keyCode != NX_KEYTYPE_PLAY && keyCode != NX_KEYTYPE_FAST && keyCode != NX_KEYTYPE_REWIND)
|
|
||||||
return event;
|
|
||||||
|
|
||||||
if (![self shouldInterceptMediaKeyEvents])
|
|
||||||
return event;
|
|
||||||
|
|
||||||
[nsEvent retain]; // matched in handleAndReleaseMediaKeyEvent:
|
|
||||||
[self performSelectorOnMainThread:@selector(handleAndReleaseMediaKeyEvent:) withObject:nsEvent waitUntilDone:NO];
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static CGEventRef tapEventCallback(CGEventTapProxy proxy, CGEventType type, CGEventRef event, void *refcon)
|
|
||||||
{
|
|
||||||
NSAutoreleasePool *pool = [NSAutoreleasePool new];
|
|
||||||
CGEventRef ret = tapEventCallback2(proxy, type, event, refcon);
|
|
||||||
[pool drain];
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// event will have been retained in the other thread
|
|
||||||
-(void)handleAndReleaseMediaKeyEvent:(NSEvent *)event {
|
|
||||||
[event autorelease];
|
|
||||||
|
|
||||||
[_delegate mediaKeyTap:self receivedMediaKeyEvent:event];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
-(void)eventTapThread;
|
|
||||||
{
|
|
||||||
_tapThreadRL = CFRunLoopGetCurrent();
|
|
||||||
CFRunLoopAddSource(_tapThreadRL, _eventPortSource, kCFRunLoopCommonModes);
|
|
||||||
CFRunLoopRun();
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark Task switching callbacks
|
|
||||||
|
|
||||||
NSString *kMediaKeyUsingBundleIdentifiersDefaultsKey = @"SPApplicationsNeedingMediaKeys";
|
|
||||||
|
|
||||||
|
|
||||||
-(void)mediaKeyAppListChanged;
|
|
||||||
{
|
|
||||||
if([_mediaKeyAppList count] == 0) return;
|
|
||||||
|
|
||||||
/*NSLog(@"--");
|
|
||||||
int i = 0;
|
|
||||||
for (NSValue *psnv in _mediaKeyAppList) {
|
|
||||||
ProcessSerialNumber psn; [psnv getValue:&psn];
|
|
||||||
NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary(
|
|
||||||
&psn,
|
|
||||||
kProcessDictionaryIncludeAllInformationMask
|
|
||||||
) autorelease];
|
|
||||||
NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey];
|
|
||||||
NSLog(@"%d: %@", i++, bundleIdentifier);
|
|
||||||
}*/
|
|
||||||
|
|
||||||
ProcessSerialNumber mySerial, topSerial;
|
|
||||||
GetCurrentProcess(&mySerial);
|
|
||||||
[[_mediaKeyAppList objectAtIndex:0] getValue:&topSerial];
|
|
||||||
|
|
||||||
Boolean same;
|
|
||||||
OSErr err = SameProcess(&mySerial, &topSerial, &same);
|
|
||||||
[self setShouldInterceptMediaKeyEvents:(err == noErr && same)];
|
|
||||||
|
|
||||||
}
|
|
||||||
-(void)appIsNowFrontmost:(ProcessSerialNumber)psn;
|
|
||||||
{
|
|
||||||
NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)];
|
|
||||||
|
|
||||||
NSDictionary *processInfo = [(id)ProcessInformationCopyDictionary(
|
|
||||||
&psn,
|
|
||||||
kProcessDictionaryIncludeAllInformationMask
|
|
||||||
) autorelease];
|
|
||||||
NSString *bundleIdentifier = [processInfo objectForKey:(id)kCFBundleIdentifierKey];
|
|
||||||
|
|
||||||
NSArray *whitelistIdentifiers = [[NSUserDefaults standardUserDefaults] arrayForKey:kMediaKeyUsingBundleIdentifiersDefaultsKey];
|
|
||||||
if(![whitelistIdentifiers containsObject:bundleIdentifier]) return;
|
|
||||||
|
|
||||||
[_mediaKeyAppList removeObject:psnv];
|
|
||||||
[_mediaKeyAppList insertObject:psnv atIndex:0];
|
|
||||||
[self mediaKeyAppListChanged];
|
|
||||||
}
|
|
||||||
-(void)appTerminated:(ProcessSerialNumber)psn;
|
|
||||||
{
|
|
||||||
NSValue *psnv = [NSValue valueWithBytes:&psn objCType:@encode(ProcessSerialNumber)];
|
|
||||||
[_mediaKeyAppList removeObject:psnv];
|
|
||||||
[self mediaKeyAppListChanged];
|
|
||||||
}
|
|
||||||
|
|
||||||
static pascal OSStatus appSwitched (EventHandlerCallRef nextHandler, EventRef evt, void* userData)
|
|
||||||
{
|
|
||||||
SPMediaKeyTap *self = (id)userData;
|
|
||||||
|
|
||||||
ProcessSerialNumber newSerial;
|
|
||||||
GetFrontProcess(&newSerial);
|
|
||||||
|
|
||||||
[self appIsNowFrontmost:newSerial];
|
|
||||||
|
|
||||||
return CallNextEventHandler(nextHandler, evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
static pascal OSStatus appTerminated (EventHandlerCallRef nextHandler, EventRef evt, void* userData)
|
|
||||||
{
|
|
||||||
SPMediaKeyTap *self = (id)userData;
|
|
||||||
|
|
||||||
ProcessSerialNumber deadPSN;
|
|
||||||
|
|
||||||
GetEventParameter(
|
|
||||||
evt,
|
|
||||||
kEventParamProcessID,
|
|
||||||
typeProcessSerialNumber,
|
|
||||||
NULL,
|
|
||||||
sizeof(deadPSN),
|
|
||||||
NULL,
|
|
||||||
&deadPSN
|
|
||||||
);
|
|
||||||
|
|
||||||
|
|
||||||
[self appTerminated:deadPSN];
|
|
||||||
return CallNextEventHandler(nextHandler, evt);
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
25
3rdparty/SPMediaKeyTap/SPMediaKeyTapDelegate.m
vendored
25
3rdparty/SPMediaKeyTap/SPMediaKeyTapDelegate.m
vendored
@@ -1,25 +0,0 @@
|
|||||||
-(void)mediaKeyTap:(SPMediaKeyTap*)keyTap receivedMediaKeyEvent:(NSEvent*)event;
|
|
||||||
{
|
|
||||||
assert([event type] == NSSystemDefined && [event subtype] == SPSystemDefinedEventMediaKeys);
|
|
||||||
|
|
||||||
int keyCode = (([event data1] & 0xFFFF0000) >> 16);
|
|
||||||
int keyFlags = ([event data1] & 0x0000FFFF);
|
|
||||||
int keyState = (((keyFlags & 0xFF00) >> 8)) == 0xA;
|
|
||||||
int keyRepeat = (keyFlags & 0x1);
|
|
||||||
|
|
||||||
if (keyState == 1 && windowController != NULL) {
|
|
||||||
|
|
||||||
|
|
||||||
switch (keyCode) {
|
|
||||||
|
|
||||||
case NX_KEYTYPE_PLAY:
|
|
||||||
... return;
|
|
||||||
|
|
||||||
case NX_KEYTYPE_FAST:
|
|
||||||
... return;
|
|
||||||
|
|
||||||
case NX_KEYTYPE_REWIND:
|
|
||||||
... return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
35
3rdparty/qocoa/CMakeLists.txt
vendored
35
3rdparty/qocoa/CMakeLists.txt
vendored
@@ -1,35 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.11)
|
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
|
|
||||||
set(SOURCES)
|
|
||||||
|
|
||||||
set(HEADERS
|
|
||||||
qsearchfield.h
|
|
||||||
qbutton.h
|
|
||||||
qprogressindicatorspinning.h
|
|
||||||
)
|
|
||||||
|
|
||||||
qt5_wrap_cpp(MOC_SOURCES ${HEADERS})
|
|
||||||
|
|
||||||
if(APPLE)
|
|
||||||
list(APPEND SOURCES
|
|
||||||
qsearchfield_mac.mm
|
|
||||||
qbutton_mac.mm
|
|
||||||
qprogressindicatorspinning_mac.mm
|
|
||||||
)
|
|
||||||
else()
|
|
||||||
list(APPEND SOURCES
|
|
||||||
qsearchfield_nonmac.cpp
|
|
||||||
qbutton_nonmac.cpp
|
|
||||||
qprogressindicatorspinning_nonmac.cpp
|
|
||||||
)
|
|
||||||
set(RESOURCES
|
|
||||||
qsearchfield_nonmac.qrc
|
|
||||||
qprogressindicatorspinning_nonmac.qrc
|
|
||||||
)
|
|
||||||
qt5_add_resources(RESOURCES_SOURCES ${RESOURCES})
|
|
||||||
endif()
|
|
||||||
|
|
||||||
add_library(Qocoa STATIC ${SOURCES} ${MOC_SOURCES} ${RESOURCES_SOURCES})
|
|
||||||
target_link_libraries(Qocoa ${QT_LIBRARIES})
|
|
||||||
|
|
||||||
19
3rdparty/qocoa/LICENSE.txt
vendored
19
3rdparty/qocoa/LICENSE.txt
vendored
@@ -1,19 +0,0 @@
|
|||||||
Copyright (C) 2011 by Mike McQuaid
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
38
3rdparty/qocoa/README.md
vendored
38
3rdparty/qocoa/README.md
vendored
@@ -1,38 +0,0 @@
|
|||||||
# Qocoa
|
|
||||||
Qocoa is a collection of Qt wrappers for OSX's Cocoa widgets.
|
|
||||||
|
|
||||||
## Features
|
|
||||||
- basic fallback to sensible Qt types on non-OSX platforms
|
|
||||||
- shared class headers which expose no implementation details
|
|
||||||
- typical Qt signal/slot-based API
|
|
||||||
- trivial to import into projects (class header/implementation, [single shared global header](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h))
|
|
||||||
|
|
||||||
## Building
|
|
||||||
```
|
|
||||||
git clone git://github.com/mikemcquaid/Qocoa.git
|
|
||||||
cd Qocoa
|
|
||||||
qmake # or cmake .
|
|
||||||
make
|
|
||||||
```
|
|
||||||
|
|
||||||
## Status
|
|
||||||
I'm not personally working on this any more but will accept pull-requests.
|
|
||||||
|
|
||||||
[](https://travis-ci.org/MikeMcQuaid/Qocoa)
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
For each class you want to use copy the [`qocoa_mac.h`](https://github.com/mikemcquaid/Qocoa/blob/master/qocoa_mac.h), `$CLASS.h`, `$CLASS_mac.*` and `$CLASS_nonmac.*` files into your source tree and add them to your buildsystem. Examples are provided for [CMake](https://github.com/mikemcquaid/Qocoa/blob/master/CMakeLists.txt) and [QMake](https://github.com/mikemcquaid/Qocoa/blob/master/Qocoa.pro).
|
|
||||||
|
|
||||||
## Contact
|
|
||||||
[Mike McQuaid](mailto:mike@mikemcquaid.com)
|
|
||||||
|
|
||||||
## License
|
|
||||||
Qocoa is licensed under the [MIT License](http://en.wikipedia.org/wiki/MIT_License).
|
|
||||||
The full license text is available in [LICENSE.txt](https://github.com/mikemcquaid/Qocoa/blob/master/LICENSE.txt).
|
|
||||||
|
|
||||||
Magnifier and EditClear icons taken from [QtCreator](http://qt-project.org/) and are licensed under the [LGPL](http://www.gnu.org/copyleft/lesser.html).
|
|
||||||
|
|
||||||
Other icons are taken from the [Oxygen Project](http://www.oxygen-icons.org/) and are licensed under the [Creative Commons Attribution-ShareAlike 3.0 License](http://creativecommons.org/licenses/by-sa/3.0/).
|
|
||||||
|
|
||||||
## Gallery
|
|
||||||

|
|
||||||
13
3rdparty/qocoa/TODO.md
vendored
13
3rdparty/qocoa/TODO.md
vendored
@@ -1,13 +0,0 @@
|
|||||||
Widgets I hope to implement (or at least investigate):
|
|
||||||
|
|
||||||
- NSTokenField
|
|
||||||
- NSSegmentedControl
|
|
||||||
- NSLevelIndicator
|
|
||||||
- NSPathControl
|
|
||||||
- NSSlider (Circular)
|
|
||||||
- NSSplitView
|
|
||||||
- NSTextFinder
|
|
||||||
- NSOutlineView in an NSScrollView (Source List)
|
|
||||||
- NSDrawer
|
|
||||||
- PDFView
|
|
||||||
- WebView
|
|
||||||
49
3rdparty/qocoa/qbutton.h
vendored
49
3rdparty/qocoa/qbutton.h
vendored
@@ -1,49 +0,0 @@
|
|||||||
#ifndef QBUTTON_H
|
|
||||||
#define QBUTTON_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
class QButtonPrivate;
|
|
||||||
class QButton : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
// Matches NSBezelStyle
|
|
||||||
enum BezelStyle {
|
|
||||||
Rounded = 1,
|
|
||||||
RegularSquare = 2,
|
|
||||||
Disclosure = 5,
|
|
||||||
ShadowlessSquare = 6,
|
|
||||||
Circular = 7,
|
|
||||||
TexturedSquare = 8,
|
|
||||||
HelpButton = 9,
|
|
||||||
SmallSquare = 10,
|
|
||||||
TexturedRounded = 11,
|
|
||||||
RoundRect = 12,
|
|
||||||
Recessed = 13,
|
|
||||||
RoundedDisclosure = 14,
|
|
||||||
#ifdef __MAC_10_7
|
|
||||||
Inline = 15
|
|
||||||
#endif
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit QButton(QWidget *parent, BezelStyle bezelStyle = Rounded);
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void setText(const QString &text);
|
|
||||||
void setImage(const QPixmap &image);
|
|
||||||
void setChecked(bool checked);
|
|
||||||
|
|
||||||
public:
|
|
||||||
void setCheckable(bool checkable);
|
|
||||||
bool isChecked();
|
|
||||||
|
|
||||||
signals:
|
|
||||||
void clicked(bool checked = false);
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend class QButtonPrivate;
|
|
||||||
QPointer<QButtonPrivate> pimpl;
|
|
||||||
};
|
|
||||||
#endif // QBUTTON_H
|
|
||||||
229
3rdparty/qocoa/qbutton_mac.mm
vendored
229
3rdparty/qocoa/qbutton_mac.mm
vendored
@@ -1,229 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2011 by Mike McQuaid
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qbutton.h"
|
|
||||||
|
|
||||||
#include "qocoa_mac.h"
|
|
||||||
|
|
||||||
#import "Foundation/NSAutoreleasePool.h"
|
|
||||||
#import "AppKit/NSButton.h"
|
|
||||||
#import "AppKit/NSFont.h"
|
|
||||||
|
|
||||||
class QButtonPrivate : public QObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QButtonPrivate(QButton *qButton, NSButton *nsButton, QButton::BezelStyle bezelStyle)
|
|
||||||
: QObject(qButton), qButton(qButton), nsButton(nsButton)
|
|
||||||
{
|
|
||||||
switch(bezelStyle) {
|
|
||||||
case QButton::Disclosure:
|
|
||||||
case QButton::Circular:
|
|
||||||
#ifdef __MAC_10_7
|
|
||||||
case QButton::Inline:
|
|
||||||
#endif
|
|
||||||
case QButton::RoundedDisclosure:
|
|
||||||
case QButton::HelpButton:
|
|
||||||
[nsButton setTitle:@""];
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
NSFont* font = 0;
|
|
||||||
switch(bezelStyle) {
|
|
||||||
case QButton::RoundRect:
|
|
||||||
font = [NSFont fontWithName:@"Lucida Grande" size:12];
|
|
||||||
break;
|
|
||||||
|
|
||||||
case QButton::Recessed:
|
|
||||||
font = [NSFont fontWithName:@"Lucida Grande Bold" size:12];
|
|
||||||
break;
|
|
||||||
|
|
||||||
#ifdef __MAC_10_7
|
|
||||||
case QButton::Inline:
|
|
||||||
font = [NSFont boldSystemFontOfSize:[NSFont systemFontSizeForControlSize:NSSmallControlSize]];
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
default:
|
|
||||||
font = [NSFont systemFontOfSize:[NSFont systemFontSizeForControlSize:NSRegularControlSize]];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
[nsButton setFont:font];
|
|
||||||
|
|
||||||
switch(bezelStyle) {
|
|
||||||
case QButton::Rounded:
|
|
||||||
qButton->setMinimumWidth(40);
|
|
||||||
qButton->setFixedHeight(24);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
|
||||||
break;
|
|
||||||
case QButton::RegularSquare:
|
|
||||||
case QButton::TexturedSquare:
|
|
||||||
qButton->setMinimumSize(14, 23);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
||||||
break;
|
|
||||||
case QButton::ShadowlessSquare:
|
|
||||||
qButton->setMinimumSize(5, 25);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
||||||
break;
|
|
||||||
case QButton::SmallSquare:
|
|
||||||
qButton->setMinimumSize(4, 21);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
||||||
break;
|
|
||||||
case QButton::TexturedRounded:
|
|
||||||
qButton->setMinimumSize(10, 22);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
||||||
break;
|
|
||||||
case QButton::RoundRect:
|
|
||||||
case QButton::Recessed:
|
|
||||||
qButton->setMinimumWidth(16);
|
|
||||||
qButton->setFixedHeight(18);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
|
||||||
break;
|
|
||||||
case QButton::Disclosure:
|
|
||||||
qButton->setMinimumWidth(13);
|
|
||||||
qButton->setFixedHeight(13);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
|
||||||
break;
|
|
||||||
case QButton::Circular:
|
|
||||||
qButton->setMinimumSize(16, 16);
|
|
||||||
qButton->setMaximumHeight(40);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
|
|
||||||
break;
|
|
||||||
case QButton::HelpButton:
|
|
||||||
case QButton::RoundedDisclosure:
|
|
||||||
qButton->setMinimumWidth(22);
|
|
||||||
qButton->setFixedHeight(22);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
|
||||||
break;
|
|
||||||
#ifdef __MAC_10_7
|
|
||||||
case QButton::Inline:
|
|
||||||
qButton->setMinimumWidth(10);
|
|
||||||
qButton->setFixedHeight(16);
|
|
||||||
qButton->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
|
||||||
break;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
switch(bezelStyle) {
|
|
||||||
case QButton::Recessed:
|
|
||||||
[nsButton setButtonType:NSPushOnPushOffButton];
|
|
||||||
case QButton::Disclosure:
|
|
||||||
[nsButton setButtonType:NSOnOffButton];
|
|
||||||
default:
|
|
||||||
[nsButton setButtonType:NSMomentaryPushInButton];
|
|
||||||
}
|
|
||||||
|
|
||||||
[nsButton setBezelStyle:(__bridge NSBezelStyle)bezelStyle];
|
|
||||||
}
|
|
||||||
|
|
||||||
void clicked()
|
|
||||||
{
|
|
||||||
emit qButton->clicked(qButton->isChecked());
|
|
||||||
}
|
|
||||||
|
|
||||||
~QButtonPrivate() {
|
|
||||||
[[nsButton target] release];
|
|
||||||
[nsButton setTarget:nil];
|
|
||||||
}
|
|
||||||
|
|
||||||
QButton *qButton;
|
|
||||||
NSButton *nsButton;
|
|
||||||
};
|
|
||||||
|
|
||||||
@interface QButtonTarget : NSObject
|
|
||||||
{
|
|
||||||
@public
|
|
||||||
QPointer<QButtonPrivate> pimpl;
|
|
||||||
}
|
|
||||||
-(void)clicked;
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation QButtonTarget
|
|
||||||
-(void)clicked {
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
pimpl->clicked();
|
|
||||||
}
|
|
||||||
@end
|
|
||||||
|
|
||||||
QButton::QButton(QWidget *parent, BezelStyle bezelStyle) : QWidget(parent)
|
|
||||||
{
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
NSButton *button = [[NSButton alloc] init];
|
|
||||||
pimpl = new QButtonPrivate(this, button, bezelStyle);
|
|
||||||
|
|
||||||
QButtonTarget *target = [[QButtonTarget alloc] init];
|
|
||||||
target->pimpl = pimpl;
|
|
||||||
[button setTarget:target];
|
|
||||||
|
|
||||||
[button setAction:@selector(clicked)];
|
|
||||||
|
|
||||||
setupLayout(button, this);
|
|
||||||
|
|
||||||
[button release];
|
|
||||||
|
|
||||||
[pool drain];
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setText(const QString &text)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (!pimpl)
|
|
||||||
return;
|
|
||||||
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
[pimpl->nsButton setTitle:fromQString(text)];
|
|
||||||
[pool drain];
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setImage(const QPixmap &image)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
[pimpl->nsButton setImage:fromQPixmap(image)];
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setChecked(bool checked)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
[pimpl->nsButton setState:checked];
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setCheckable(bool checkable)
|
|
||||||
{
|
|
||||||
const NSInteger cellMask = checkable ? NSChangeBackgroundCellMask : NSNoCellMask;
|
|
||||||
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
[[pimpl->nsButton cell] setShowsStateBy:cellMask];
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QButton::isChecked()
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (!pimpl)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return [pimpl->nsButton state];
|
|
||||||
}
|
|
||||||
89
3rdparty/qocoa/qbutton_nonmac.cpp
vendored
89
3rdparty/qocoa/qbutton_nonmac.cpp
vendored
@@ -1,89 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2011 by Mike McQuaid
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qbutton.h"
|
|
||||||
|
|
||||||
#include <QToolBar>
|
|
||||||
#include <QToolButton>
|
|
||||||
#include <QPushButton>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
class QButtonPrivate : public QObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QButtonPrivate(QButton *button, QAbstractButton *abstractButton)
|
|
||||||
: QObject(button), abstractButton(abstractButton) {}
|
|
||||||
QPointer<QAbstractButton> abstractButton;
|
|
||||||
};
|
|
||||||
|
|
||||||
QButton::QButton(QWidget *parent, BezelStyle) : QWidget(parent)
|
|
||||||
{
|
|
||||||
QAbstractButton *button = 0;
|
|
||||||
if (qobject_cast<QToolBar*>(parent))
|
|
||||||
button = new QToolButton(this);
|
|
||||||
else
|
|
||||||
button = new QPushButton(this);
|
|
||||||
connect(button, SIGNAL(clicked()),
|
|
||||||
this, SIGNAL(clicked()));
|
|
||||||
pimpl = new QButtonPrivate(this, button);
|
|
||||||
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
|
||||||
layout->setMargin(0);
|
|
||||||
layout->addWidget(button);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setText(const QString &text)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
pimpl->abstractButton->setText(text);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setImage(const QPixmap &image)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
pimpl->abstractButton->setIcon(image);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setChecked(bool checked)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
pimpl->abstractButton->setChecked(checked);
|
|
||||||
}
|
|
||||||
|
|
||||||
void QButton::setCheckable(bool checkable)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (pimpl)
|
|
||||||
pimpl->abstractButton->setCheckable(checkable);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool QButton::isChecked()
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (!pimpl)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return pimpl->abstractButton->isChecked();
|
|
||||||
}
|
|
||||||
29
3rdparty/qocoa/qprogressindicatorspinning.h
vendored
29
3rdparty/qocoa/qprogressindicatorspinning.h
vendored
@@ -1,29 +0,0 @@
|
|||||||
#ifndef QPROGRESSINDICATORSPINNING_H
|
|
||||||
#define QPROGRESSINDICATORSPINNING_H
|
|
||||||
|
|
||||||
#include <QWidget>
|
|
||||||
#include <QPointer>
|
|
||||||
|
|
||||||
class QProgressIndicatorSpinningPrivate;
|
|
||||||
class QProgressIndicatorSpinning : public QWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
// Matches NSProgressIndicatorThickness
|
|
||||||
enum Thickness {
|
|
||||||
Default = 14,
|
|
||||||
Small = 10,
|
|
||||||
Large = 18,
|
|
||||||
Aqua = 12
|
|
||||||
};
|
|
||||||
|
|
||||||
explicit QProgressIndicatorSpinning(QWidget *parent,
|
|
||||||
Thickness thickness = Default);
|
|
||||||
public slots:
|
|
||||||
void animate(bool animate = true);
|
|
||||||
private:
|
|
||||||
friend class QProgressIndicatorSpinningPrivate;
|
|
||||||
QPointer<QProgressIndicatorSpinningPrivate> pimpl;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // QPROGRESSINDICATORSPINNING_H
|
|
||||||
70
3rdparty/qocoa/qprogressindicatorspinning_mac.mm
vendored
70
3rdparty/qocoa/qprogressindicatorspinning_mac.mm
vendored
@@ -1,70 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2011 by Mike McQuaid
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qprogressindicatorspinning.h"
|
|
||||||
|
|
||||||
#include "qocoa_mac.h"
|
|
||||||
|
|
||||||
#import "Foundation/NSAutoreleasePool.h"
|
|
||||||
#import "AppKit/NSProgressIndicator.h"
|
|
||||||
|
|
||||||
class QProgressIndicatorSpinningPrivate : public QObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning,
|
|
||||||
NSProgressIndicator *nsProgressIndicator)
|
|
||||||
: QObject(qProgressIndicatorSpinning), nsProgressIndicator(nsProgressIndicator) {}
|
|
||||||
|
|
||||||
NSProgressIndicator *nsProgressIndicator;
|
|
||||||
};
|
|
||||||
|
|
||||||
QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent,
|
|
||||||
Thickness thickness)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
|
|
||||||
|
|
||||||
NSProgressIndicator *progress = [[NSProgressIndicator alloc] init];
|
|
||||||
[progress setStyle:NSProgressIndicatorSpinningStyle];
|
|
||||||
|
|
||||||
pimpl = new QProgressIndicatorSpinningPrivate(this, progress);
|
|
||||||
|
|
||||||
setupLayout(progress, this);
|
|
||||||
|
|
||||||
setFixedSize(thickness, thickness);
|
|
||||||
|
|
||||||
[progress release];
|
|
||||||
|
|
||||||
[pool drain];
|
|
||||||
}
|
|
||||||
|
|
||||||
void QProgressIndicatorSpinning::animate(bool animate)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl);
|
|
||||||
if (!pimpl)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (animate)
|
|
||||||
[pimpl->nsProgressIndicator startAnimation:nil];
|
|
||||||
else
|
|
||||||
[pimpl->nsProgressIndicator stopAnimation:nil];
|
|
||||||
}
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (C) 2011 by Mike McQuaid
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in
|
|
||||||
all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
||||||
THE SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "qprogressindicatorspinning.h"
|
|
||||||
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
#include <QMovie>
|
|
||||||
#include <QLabel>
|
|
||||||
|
|
||||||
class QProgressIndicatorSpinningPrivate : public QObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
QProgressIndicatorSpinningPrivate(QProgressIndicatorSpinning *qProgressIndicatorSpinning,
|
|
||||||
QMovie *movie)
|
|
||||||
: QObject(qProgressIndicatorSpinning), movie(movie) {}
|
|
||||||
|
|
||||||
QPointer<QMovie> movie;
|
|
||||||
};
|
|
||||||
|
|
||||||
QProgressIndicatorSpinning::QProgressIndicatorSpinning(QWidget *parent,
|
|
||||||
Thickness thickness)
|
|
||||||
: QWidget(parent)
|
|
||||||
{
|
|
||||||
QVBoxLayout *layout = new QVBoxLayout(this);
|
|
||||||
layout->setMargin(0);
|
|
||||||
|
|
||||||
QSize size(thickness, thickness);
|
|
||||||
QMovie *movie = new QMovie(this);
|
|
||||||
movie->setFileName(":/Qocoa/qprogressindicatorspinning_nonmac.gif");
|
|
||||||
movie->setScaledSize(size);
|
|
||||||
// Roughly match OSX speed.
|
|
||||||
movie->setSpeed(200);
|
|
||||||
pimpl = new QProgressIndicatorSpinningPrivate(this, movie);
|
|
||||||
|
|
||||||
QLabel *label = new QLabel(this);
|
|
||||||
label->setMovie(movie);
|
|
||||||
|
|
||||||
layout->addWidget(label);
|
|
||||||
setFixedSize(size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void QProgressIndicatorSpinning::animate(bool animate)
|
|
||||||
{
|
|
||||||
Q_ASSERT(pimpl && pimpl->movie);
|
|
||||||
if (!(pimpl && pimpl->movie))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (animate)
|
|
||||||
pimpl->movie->start();
|
|
||||||
else
|
|
||||||
pimpl->movie->stop();
|
|
||||||
}
|
|
||||||
BIN
3rdparty/qocoa/qprogressindicatorspinning_nonmac.gif
vendored
BIN
3rdparty/qocoa/qprogressindicatorspinning_nonmac.gif
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 3.1 KiB |
@@ -1,5 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/Qocoa">
|
|
||||||
<file>qprogressindicatorspinning_nonmac.gif</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
7
3rdparty/qocoa/qsearchfield_nonmac.qrc
vendored
7
3rdparty/qocoa/qsearchfield_nonmac.qrc
vendored
@@ -1,7 +0,0 @@
|
|||||||
<RCC>
|
|
||||||
<qresource prefix="/Qocoa">
|
|
||||||
<file>qsearchfield_nonmac_clear.png</file>
|
|
||||||
<file>qsearchfield_nonmac_magnifier_menu.png</file>
|
|
||||||
<file>qsearchfield_nonmac_magnifier.png</file>
|
|
||||||
</qresource>
|
|
||||||
</RCC>
|
|
||||||
BIN
3rdparty/qocoa/qsearchfield_nonmac_clear.png
vendored
BIN
3rdparty/qocoa/qsearchfield_nonmac_clear.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 736 B |
BIN
3rdparty/qocoa/qsearchfield_nonmac_magnifier.png
vendored
BIN
3rdparty/qocoa/qsearchfield_nonmac_magnifier.png
vendored
Binary file not shown.
|
Before Width: | Height: | Size: 300 B |
Binary file not shown.
|
Before Width: | Height: | Size: 439 B |
19
3rdparty/singleapplication/CMakeLists.txt
vendored
19
3rdparty/singleapplication/CMakeLists.txt
vendored
@@ -1,14 +1,25 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.11)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
|
include(CheckIncludeFiles)
|
||||||
|
include(CheckFunctionExists)
|
||||||
|
|
||||||
|
if(CMAKE_VERSION VERSION_GREATER 3.0)
|
||||||
|
check_function_exists(geteuid HAVE_GETEUID)
|
||||||
|
check_function_exists(getpwuid HAVE_GETPWUID)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(SINGLEAPP-SOURCES singleapplication.cpp singleapplication_p.cpp)
|
set(SINGLEAPP-SOURCES singleapplication.cpp singleapplication_p.cpp)
|
||||||
set(SINGLEAPP-MOC-HEADERS singleapplication.h singleapplication_p.h)
|
set(SINGLEAPP-MOC-HEADERS singleapplication.h singleapplication_p.h)
|
||||||
QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})
|
QT5_WRAP_CPP(SINGLEAPP-SOURCES-MOC ${SINGLEAPP-MOC-HEADERS})
|
||||||
ADD_LIBRARY(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
|
add_library(singleapplication STATIC ${SINGLEAPP-SOURCES} ${SINGLEAPP-SOURCES-MOC})
|
||||||
target_link_libraries(singleapplication Qt5::Core Qt5::Widgets Qt5::Network)
|
target_link_libraries(singleapplication Qt5::Core Qt5::Widgets Qt5::Network)
|
||||||
|
|
||||||
set(SINGLECOREAPP-SOURCES singlecoreapplication.cpp singlecoreapplication_p.cpp)
|
set(SINGLECOREAPP-SOURCES singlecoreapplication.cpp singlecoreapplication_p.cpp)
|
||||||
set(SINGLECOREAPP-MOC-HEADERS singlecoreapplication.h singlecoreapplication_p.h)
|
set(SINGLECOREAPP-MOC-HEADERS singlecoreapplication.h singlecoreapplication_p.h)
|
||||||
QT5_WRAP_CPP(SINGLECOREAPP-SOURCES-MOC ${SINGLECOREAPP-MOC-HEADERS})
|
QT5_WRAP_CPP(SINGLECOREAPP-SOURCES-MOC ${SINGLECOREAPP-MOC-HEADERS})
|
||||||
ADD_LIBRARY(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
|
add_library(singlecoreapplication STATIC ${SINGLECOREAPP-SOURCES} ${SINGLECOREAPP-SOURCES-MOC})
|
||||||
target_link_libraries(singlecoreapplication Qt5::Core Qt5::Widgets Qt5::Network)
|
target_link_libraries(singlecoreapplication Qt5::Core Qt5::Widgets Qt5::Network)
|
||||||
|
|
||||||
|
configure_file(config.h.in "${CMAKE_CURRENT_BINARY_DIR}/config.h")
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR})
|
||||||
|
|||||||
2
3rdparty/singleapplication/config.h.in
vendored
Normal file
2
3rdparty/singleapplication/config.h.in
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
#cmakedefine HAVE_GETEUID
|
||||||
|
#cmakedefine HAVE_GETPWUID
|
||||||
230
3rdparty/singleapplication/singleapplication.cpp
vendored
230
3rdparty/singleapplication/singleapplication.cpp
vendored
@@ -20,156 +20,170 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
#include <QApplication>
|
//
|
||||||
#include <QtCore/QTime>
|
// W A R N I N G !!!
|
||||||
#include <QtCore/QThread>
|
// -----------------
|
||||||
#include <QtCore/QDateTime>
|
//
|
||||||
#include <QtCore/QByteArray>
|
// This is a modified version of SingleApplication,
|
||||||
#include <QtCore/QSharedMemory>
|
// The original version is at:
|
||||||
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
#include <QCoreApplication>
|
||||||
|
#include <QThread>
|
||||||
|
#include <QSharedMemory>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QDateTime>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
#include "singleapplication_p.h"
|
#include "singleapplication_p.h"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Constructor. Checks and fires up LocalServer or closes the program
|
* @brief Constructor.
|
||||||
* if another instance already exists
|
* Checks and fires up LocalServer or closes the program if another instance already exists
|
||||||
* @param argc
|
* @param argc
|
||||||
* @param argv
|
* @param argv
|
||||||
* @param {bool} allowSecondaryInstances
|
* @param {bool} allowSecondaryInstances
|
||||||
*/
|
*/
|
||||||
SingleApplication::SingleApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout )
|
SingleApplication::SingleApplication(int &argc, char *argv[], bool allowSecondary, Options options, int timeout)
|
||||||
: app_t( argc, argv ), d_ptr( new SingleApplicationPrivate( this ) )
|
: app_t(argc, argv), d_ptr(new SingleApplicationPrivate(this)) {
|
||||||
{
|
|
||||||
Q_D(SingleApplication);
|
|
||||||
|
|
||||||
// Store the current mode of the program
|
Q_D(SingleApplication);
|
||||||
d->options = options;
|
|
||||||
|
|
||||||
// Generating an application ID used for identifying the shared memory
|
// Store the current mode of the program
|
||||||
// block and QLocalServer
|
d->options = options;
|
||||||
d->genBlockServerName();
|
|
||||||
|
// Generating an application ID used for identifying the shared memory block and QLocalServer
|
||||||
|
d->genBlockServerName();
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
// By explicitly attaching it and then deleting it we make sure that the
|
// By explicitly attaching it and then deleting it we make sure that the
|
||||||
// memory is deleted even after the process has crashed on Unix.
|
// memory is deleted even after the process has crashed on Unix.
|
||||||
d->memory = new QSharedMemory( d->blockServerName );
|
d->memory = new QSharedMemory(d->blockServerName);
|
||||||
d->memory->attach();
|
d->memory->attach();
|
||||||
delete d->memory;
|
delete d->memory;
|
||||||
#endif
|
#endif
|
||||||
// Guarantee thread safe behaviour with a shared memory block.
|
// Guarantee thread safe behaviour with a shared memory block.
|
||||||
d->memory = new QSharedMemory( d->blockServerName );
|
d->memory = new QSharedMemory(d->blockServerName);
|
||||||
|
|
||||||
// Create a shared memory block
|
// Create a shared memory block
|
||||||
if( d->memory->create( sizeof( InstancesInfo ) ) ) {
|
if (d->memory->create(sizeof(InstancesInfo))) {
|
||||||
// Initialize the shared memory block
|
// Initialize the shared memory block
|
||||||
d->memory->lock();
|
d->memory->lock();
|
||||||
d->initializeMemoryBlock();
|
d->initializeMemoryBlock();
|
||||||
d->memory->unlock();
|
d->memory->unlock();
|
||||||
} else {
|
}
|
||||||
// Attempt to attach to the memory segment
|
else {
|
||||||
if( ! d->memory->attach() ) {
|
// Attempt to attach to the memory segment
|
||||||
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
|
if (! d->memory->attach()) {
|
||||||
qCritical() << d->memory->errorString();
|
qCritical() << "SingleApplication: Unable to attach to shared memory block.";
|
||||||
delete d;
|
qCritical() << d->memory->errorString();
|
||||||
::exit( EXIT_FAILURE );
|
delete d;
|
||||||
}
|
::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( d->memory->data() );
|
InstancesInfo* inst = static_cast<InstancesInfo*>(d->memory->data());
|
||||||
QTime time;
|
QElapsedTimer time;
|
||||||
time.start();
|
time.start();
|
||||||
|
|
||||||
// Make sure the shared memory block is initialised and in consistent state
|
// Make sure the shared memory block is initialised and in consistent state
|
||||||
while( true ) {
|
while (true) {
|
||||||
d->memory->lock();
|
d->memory->lock();
|
||||||
|
|
||||||
if( d->blockChecksum() == inst->checksum ) break;
|
if (d->blockChecksum() == inst->checksum) break;
|
||||||
|
|
||||||
if( time.elapsed() > 5000 ) {
|
if (time.elapsed() > 5000) {
|
||||||
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
|
qWarning() << "SingleApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
|
||||||
d->initializeMemoryBlock();
|
d->initializeMemoryBlock();
|
||||||
}
|
|
||||||
|
|
||||||
d->memory->unlock();
|
|
||||||
|
|
||||||
// Random sleep here limits the probability of a collision between two racing apps
|
|
||||||
qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max() );
|
|
||||||
QThread::sleep( 8 + static_cast <unsigned long>( static_cast <float>( qrand() ) / RAND_MAX * 10 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( inst->primary == false) {
|
|
||||||
d->startPrimary();
|
|
||||||
d->memory->unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if another instance can be started
|
|
||||||
if( allowSecondary ) {
|
|
||||||
inst->secondary += 1;
|
|
||||||
inst->checksum = d->blockChecksum();
|
|
||||||
d->instanceNumber = inst->secondary;
|
|
||||||
d->startSecondary();
|
|
||||||
if( d->options & Mode::SecondaryNotification ) {
|
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::SecondaryInstance );
|
|
||||||
}
|
|
||||||
d->memory->unlock();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d->memory->unlock();
|
d->memory->unlock();
|
||||||
|
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::NewInstance );
|
// Random sleep here limits the probability of a collision between two racing apps
|
||||||
|
qsrand(QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max());
|
||||||
|
QThread::sleep(8 + static_cast <unsigned long>(static_cast <float>(qrand()) / RAND_MAX * 10));
|
||||||
|
}
|
||||||
|
|
||||||
delete d;
|
if (inst->primary == false) {
|
||||||
|
d->startPrimary();
|
||||||
|
d->memory->unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if another instance can be started
|
||||||
|
if (allowSecondary) {
|
||||||
|
inst->secondary += 1;
|
||||||
|
inst->checksum = d->blockChecksum();
|
||||||
|
d->instanceNumber = inst->secondary;
|
||||||
|
d->startSecondary();
|
||||||
|
if (d->options & Mode::SecondaryNotification) {
|
||||||
|
d->connectToPrimary(timeout, SingleApplicationPrivate::SecondaryInstance);
|
||||||
|
}
|
||||||
|
d->memory->unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->memory->unlock();
|
||||||
|
|
||||||
|
d->connectToPrimary(timeout, SingleApplicationPrivate::NewInstance);
|
||||||
|
|
||||||
|
delete d;
|
||||||
|
|
||||||
|
::exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
::exit( EXIT_SUCCESS );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructor
|
* @brief Destructor
|
||||||
*/
|
*/
|
||||||
SingleApplication::~SingleApplication()
|
SingleApplication::~SingleApplication() {
|
||||||
{
|
Q_D(SingleApplication);
|
||||||
Q_D(SingleApplication);
|
delete d;
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleApplication::isPrimary()
|
bool SingleApplication::isPrimary() {
|
||||||
{
|
Q_D(SingleApplication);
|
||||||
Q_D(SingleApplication);
|
return d->server != nullptr;
|
||||||
return d->server != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleApplication::isSecondary()
|
bool SingleApplication::isSecondary() {
|
||||||
{
|
Q_D(SingleApplication);
|
||||||
Q_D(SingleApplication);
|
return d->server == nullptr;
|
||||||
return d->server == nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 SingleApplication::instanceId()
|
quint32 SingleApplication::instanceId() {
|
||||||
{
|
Q_D(SingleApplication);
|
||||||
Q_D(SingleApplication);
|
return d->instanceNumber;
|
||||||
return d->instanceNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 SingleApplication::primaryPid()
|
qint64 SingleApplication::primaryPid() {
|
||||||
{
|
Q_D(SingleApplication);
|
||||||
Q_D(SingleApplication);
|
return d->primaryPid();
|
||||||
return d->primaryPid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleApplication::sendMessage( QByteArray message, int timeout )
|
bool SingleApplication::sendMessage(QByteArray message, int timeout) {
|
||||||
{
|
|
||||||
Q_D(SingleApplication);
|
|
||||||
|
|
||||||
// Nobody to connect to
|
Q_D(SingleApplication);
|
||||||
if( isPrimary() ) return false;
|
|
||||||
|
|
||||||
// Make sure the socket is connected
|
// Nobody to connect to
|
||||||
d->connectToPrimary( timeout, SingleApplicationPrivate::Reconnect );
|
if (isPrimary()) return false;
|
||||||
|
|
||||||
|
// Make sure the socket is connected
|
||||||
|
d->connectToPrimary(timeout, SingleApplicationPrivate::Reconnect);
|
||||||
|
|
||||||
|
d->socket->write(message);
|
||||||
|
bool dataWritten = d->socket->waitForBytesWritten(timeout);
|
||||||
|
d->socket->flush();
|
||||||
|
return dataWritten;
|
||||||
|
|
||||||
d->socket->write( message );
|
|
||||||
bool dataWritten = d->socket->flush();
|
|
||||||
d->socket->waitForBytesWritten( timeout );
|
|
||||||
return dataWritten;
|
|
||||||
}
|
}
|
||||||
|
|||||||
172
3rdparty/singleapplication/singleapplication.h
vendored
172
3rdparty/singleapplication/singleapplication.h
vendored
@@ -20,12 +20,24 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G !!!
|
||||||
|
// -----------------
|
||||||
|
//
|
||||||
|
// This is a modified version of SingleApplication,
|
||||||
|
// The original version is at:
|
||||||
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
#ifndef SINGLEAPPLICATION_H
|
#ifndef SINGLEAPPLICATION_H
|
||||||
#define SINGLEAPPLICATION_H
|
#define SINGLEAPPLICATION_H
|
||||||
|
|
||||||
#include <QtCore/QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QFlags>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
class SingleApplicationPrivate;
|
class SingleApplicationPrivate;
|
||||||
|
|
||||||
@@ -34,95 +46,95 @@ class SingleApplicationPrivate;
|
|||||||
* Application
|
* Application
|
||||||
* @see QCoreApplication
|
* @see QCoreApplication
|
||||||
*/
|
*/
|
||||||
class SingleApplication : public QApplication
|
class SingleApplication : public QApplication {
|
||||||
{
|
Q_OBJECT
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
typedef QApplication app_t;
|
typedef QApplication app_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Mode of operation of SingleApplication.
|
* @brief Mode of operation of SingleApplication.
|
||||||
* Whether the block should be user-wide or system-wide and whether the
|
* Whether the block should be user-wide or system-wide and whether the
|
||||||
* primary instance should be notified when a secondary instance had been
|
* primary instance should be notified when a secondary instance had been
|
||||||
* started.
|
* started.
|
||||||
* @note Operating system can restrict the shared memory blocks to the same
|
* @note Operating system can restrict the shared memory blocks to the same
|
||||||
* user, in which case the User/System modes will have no effect and the
|
* user, in which case the User/System modes will have no effect and the
|
||||||
* block will be user wide.
|
* block will be user wide.
|
||||||
* @enum
|
* @enum
|
||||||
*/
|
*/
|
||||||
enum Mode {
|
enum Mode {
|
||||||
User = 1 << 0,
|
User = 1 << 0,
|
||||||
System = 1 << 1,
|
System = 1 << 1,
|
||||||
SecondaryNotification = 1 << 2,
|
SecondaryNotification = 1 << 2,
|
||||||
ExcludeAppVersion = 1 << 3,
|
ExcludeAppVersion = 1 << 3,
|
||||||
ExcludeAppPath = 1 << 4
|
ExcludeAppPath = 1 << 4
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Options, Mode)
|
Q_DECLARE_FLAGS(Options, Mode)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Intitializes a SingleApplication instance with argc command line
|
* @brief Intitializes a SingleApplication instance with argc command line
|
||||||
* arguments in argv
|
* arguments in argv
|
||||||
* @arg {int &} argc - Number of arguments in argv
|
* @arg {int &} argc - Number of arguments in argv
|
||||||
* @arg {const char *[]} argv - Supplied command line arguments
|
* @arg {const char *[]} argv - Supplied command line arguments
|
||||||
* @arg {bool} allowSecondary - Whether to start the instance as secondary
|
* @arg {bool} allowSecondary - Whether to start the instance as secondary
|
||||||
* if there is already a primary instance.
|
* if there is already a primary instance.
|
||||||
* @arg {Mode} mode - Whether for the SingleApplication block to be applied
|
* @arg {Mode} mode - Whether for the SingleApplication block to be applied
|
||||||
* User wide or System wide.
|
* User wide or System wide.
|
||||||
* @arg {int} timeout - Timeout to wait in miliseconds.
|
* @arg {int} timeout - Timeout to wait in milliseconds.
|
||||||
* @note argc and argv may be changed as Qt removes arguments that it
|
* @note argc and argv may be changed as Qt removes arguments that it
|
||||||
* recognizes
|
* recognizes
|
||||||
* @note Mode::SecondaryNotification only works if set on both the primary
|
* @note Mode::SecondaryNotification only works if set on both the primary
|
||||||
* instance and the secondary instance.
|
* instance and the secondary instance.
|
||||||
* @note The timeout is just a hint for the maximum time of blocking
|
* @note The timeout is just a hint for the maximum time of blocking
|
||||||
* operations. It does not guarantee that the SingleApplication
|
* operations. It does not guarantee that the SingleApplication
|
||||||
* initialisation will be completed in given time, though is a good hint.
|
* initialisation will be completed in given time, though is a good hint.
|
||||||
* Usually 4*timeout would be the worst case (fail) scenario.
|
* Usually 4*timeout would be the worst case (fail) scenario.
|
||||||
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
|
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
|
||||||
*/
|
*/
|
||||||
explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 );
|
explicit SingleApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 );
|
||||||
~SingleApplication();
|
~SingleApplication();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns if the instance is the primary instance
|
* @brief Returns if the instance is the primary instance
|
||||||
* @returns {bool}
|
* @returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isPrimary();
|
bool isPrimary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns if the instance is a secondary instance
|
* @brief Returns if the instance is a secondary instance
|
||||||
* @returns {bool}
|
* @returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isSecondary();
|
bool isSecondary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a unique identifier for the current instance
|
* @brief Returns a unique identifier for the current instance
|
||||||
* @returns {qint32}
|
* @returns {qint32}
|
||||||
*/
|
*/
|
||||||
quint32 instanceId();
|
quint32 instanceId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the process ID (PID) of the primary instance
|
* @brief Returns the process ID (PID) of the primary instance
|
||||||
* @returns {qint64}
|
* @returns {qint64}
|
||||||
*/
|
*/
|
||||||
qint64 primaryPid();
|
qint64 primaryPid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends a message to the primary instance. Returns true on success.
|
* @brief Sends a message to the primary instance. Returns true on success.
|
||||||
* @param {int} timeout - Timeout for connecting
|
* @param {int} timeout - Timeout for connecting
|
||||||
* @returns {bool}
|
* @returns {bool}
|
||||||
* @note sendMessage() will return false if invoked from the primary
|
* @note sendMessage() will return false if invoked from the primary
|
||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
bool sendMessage( QByteArray message, int timeout = 100 );
|
bool sendMessage( QByteArray message, int timeout = 1000 );
|
||||||
|
|
||||||
Q_SIGNALS:
|
signals:
|
||||||
void instanceStarted();
|
void instanceStarted();
|
||||||
void receivedMessage( quint32 instanceId, QByteArray message );
|
void receivedMessage( quint32 instanceId, QByteArray message );
|
||||||
|
|
||||||
|
private:
|
||||||
|
SingleApplicationPrivate *d_ptr;
|
||||||
|
Q_DECLARE_PRIVATE(SingleApplication)
|
||||||
|
|
||||||
private:
|
|
||||||
SingleApplicationPrivate *d_ptr;
|
|
||||||
Q_DECLARE_PRIVATE(SingleApplication)
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleApplication::Options)
|
||||||
|
|||||||
617
3rdparty/singleapplication/singleapplication_p.cpp
vendored
617
3rdparty/singleapplication/singleapplication_p.cpp
vendored
@@ -24,381 +24,378 @@
|
|||||||
// W A R N I N G !!!
|
// W A R N I N G !!!
|
||||||
// -----------------
|
// -----------------
|
||||||
//
|
//
|
||||||
// This file is not part of the SingleApplication API. It is used purely as an
|
// This is a modified version of SingleApplication,
|
||||||
// implementation detail. This header file may change from version to
|
// The original version is at:
|
||||||
// version without notice, or may even be removed.
|
|
||||||
//
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include <QtCore/QDir>
|
#ifdef Q_OS_UNIX
|
||||||
#include <QtCore/QProcess>
|
# include <unistd.h>
|
||||||
#include <QtCore/QByteArray>
|
# include <sys/types.h>
|
||||||
#include <QtCore/QSemaphore>
|
# include <pwd.h>
|
||||||
#include <QtCore/QDataStream>
|
#endif
|
||||||
#include <QtCore/QStandardPaths>
|
|
||||||
#include <QtCore/QCryptographicHash>
|
#include <QIODevice>
|
||||||
#include <QtNetwork/QLocalServer>
|
#include <QSharedMemory>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QByteArray>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
#include "singleapplication_p.h"
|
#include "singleapplication_p.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
#include <lmcons.h>
|
# include <lmcons.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SingleApplicationPrivate::SingleApplicationPrivate( SingleApplication *q_ptr )
|
SingleApplicationPrivate::SingleApplicationPrivate(SingleApplication *_q_ptr)
|
||||||
: q_ptr( q_ptr )
|
: q_ptr(_q_ptr),
|
||||||
{
|
memory(nullptr),
|
||||||
server = nullptr;
|
socket(nullptr),
|
||||||
socket = nullptr;
|
server(nullptr),
|
||||||
memory = nullptr;
|
instanceNumber(-1)
|
||||||
instanceNumber = -1;
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
SingleApplicationPrivate::~SingleApplicationPrivate()
|
SingleApplicationPrivate::~SingleApplicationPrivate() {
|
||||||
{
|
|
||||||
if( socket != nullptr ) {
|
|
||||||
socket->close();
|
|
||||||
delete socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->lock();
|
if (socket != nullptr) {
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
socket->close();
|
||||||
if( server != nullptr ) {
|
delete socket;
|
||||||
server->close();
|
}
|
||||||
delete server;
|
|
||||||
inst->primary = false;
|
|
||||||
inst->primaryPid = -1;
|
|
||||||
inst->checksum = blockChecksum();
|
|
||||||
}
|
|
||||||
memory->unlock();
|
|
||||||
|
|
||||||
delete memory;
|
memory->lock();
|
||||||
}
|
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
|
if (server != nullptr) {
|
||||||
void SingleApplicationPrivate::genBlockServerName()
|
server->close();
|
||||||
{
|
delete server;
|
||||||
QCryptographicHash appData( QCryptographicHash::Sha256 );
|
|
||||||
appData.addData( "SingleApplication", 17 );
|
|
||||||
appData.addData( SingleApplication::app_t::applicationName().toUtf8() );
|
|
||||||
appData.addData( SingleApplication::app_t::organizationName().toUtf8() );
|
|
||||||
appData.addData( SingleApplication::app_t::organizationDomain().toUtf8() );
|
|
||||||
|
|
||||||
if( ! (options & SingleApplication::Mode::ExcludeAppVersion) ) {
|
|
||||||
appData.addData( SingleApplication::app_t::applicationVersion().toUtf8() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ! (options & SingleApplication::Mode::ExcludeAppPath) ) {
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
appData.addData( SingleApplication::app_t::applicationFilePath().toLower().toUtf8() );
|
|
||||||
#else
|
|
||||||
appData.addData( SingleApplication::app_t::applicationFilePath().toUtf8() );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// User level block requires a user specific data in the hash
|
|
||||||
if( options & SingleApplication::Mode::User ) {
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
wchar_t username [ UNLEN + 1 ];
|
|
||||||
// Specifies size of the buffer on input
|
|
||||||
DWORD usernameLength = UNLEN + 1;
|
|
||||||
if( GetUserNameW( username, &usernameLength ) ) {
|
|
||||||
appData.addData( QString::fromWCharArray(username).toUtf8() );
|
|
||||||
} else {
|
|
||||||
appData.addData( QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).join("").toUtf8() );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_UNIX
|
|
||||||
QProcess process;
|
|
||||||
process.start( "whoami" );
|
|
||||||
if( process.waitForFinished( 100 ) &&
|
|
||||||
process.exitCode() == QProcess::NormalExit) {
|
|
||||||
appData.addData( process.readLine() );
|
|
||||||
} else {
|
|
||||||
appData.addData(
|
|
||||||
QDir(
|
|
||||||
QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).first()
|
|
||||||
).absolutePath().toUtf8()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
|
|
||||||
// server naming requirements.
|
|
||||||
blockServerName = appData.result().toBase64().replace("/", "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleApplicationPrivate::initializeMemoryBlock()
|
|
||||||
{
|
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
|
|
||||||
inst->primary = false;
|
inst->primary = false;
|
||||||
inst->secondary = 0;
|
|
||||||
inst->primaryPid = -1;
|
inst->primaryPid = -1;
|
||||||
inst->checksum = blockChecksum();
|
inst->checksum = blockChecksum();
|
||||||
|
}
|
||||||
|
memory->unlock();
|
||||||
|
|
||||||
|
delete memory;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::startPrimary()
|
void SingleApplicationPrivate::genBlockServerName() {
|
||||||
{
|
|
||||||
Q_Q(SingleApplication);
|
|
||||||
|
|
||||||
// Successful creation means that no main process exists
|
QCryptographicHash appData(QCryptographicHash::Sha256);
|
||||||
// So we start a QLocalServer to listen for connections
|
appData.addData("SingleApplication", 17);
|
||||||
QLocalServer::removeServer( blockServerName );
|
appData.addData(SingleApplication::app_t::applicationName().toUtf8());
|
||||||
server = new QLocalServer();
|
appData.addData(SingleApplication::app_t::organizationName().toUtf8());
|
||||||
|
appData.addData(SingleApplication::app_t::organizationDomain().toUtf8());
|
||||||
|
|
||||||
// Restrict access to the socket according to the
|
if (!(options & SingleApplication::Mode::ExcludeAppVersion)) {
|
||||||
// SingleApplication::Mode::User flag on User level or no restrictions
|
appData.addData(SingleApplication::app_t::applicationVersion().toUtf8());
|
||||||
if( options & SingleApplication::Mode::User ) {
|
}
|
||||||
server->setSocketOptions( QLocalServer::UserAccessOption );
|
|
||||||
} else {
|
|
||||||
server->setSocketOptions( QLocalServer::WorldAccessOption );
|
|
||||||
}
|
|
||||||
|
|
||||||
server->listen( blockServerName );
|
if (! (options & SingleApplication::Mode::ExcludeAppPath)) {
|
||||||
QObject::connect(
|
#ifdef Q_OS_WIN
|
||||||
server,
|
appData.addData(SingleApplication::app_t::applicationFilePath().toLower().toUtf8());
|
||||||
&QLocalServer::newConnection,
|
#else
|
||||||
this,
|
appData.addData(SingleApplication::app_t::applicationFilePath().toUtf8());
|
||||||
&SingleApplicationPrivate::slotConnectionEstablished
|
|
||||||
);
|
|
||||||
|
|
||||||
// Reset the number of connections
|
|
||||||
InstancesInfo* inst = static_cast <InstancesInfo*>( memory->data() );
|
|
||||||
|
|
||||||
inst->primary = true;
|
|
||||||
inst->primaryPid = q->applicationPid();
|
|
||||||
inst->checksum = blockChecksum();
|
|
||||||
|
|
||||||
instanceNumber = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleApplicationPrivate::startSecondary()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
|
|
||||||
{
|
|
||||||
// Connect to the Local Server of the Primary Instance if not already
|
|
||||||
// connected.
|
|
||||||
if( socket == nullptr ) {
|
|
||||||
socket = new QLocalSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If already connected - we are done;
|
|
||||||
if( socket->state() == QLocalSocket::ConnectedState )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If not connect
|
|
||||||
if( socket->state() == QLocalSocket::UnconnectedState ||
|
|
||||||
socket->state() == QLocalSocket::ClosingState ) {
|
|
||||||
socket->connectToServer( blockServerName );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for being connected
|
|
||||||
if( socket->state() == QLocalSocket::ConnectingState ) {
|
|
||||||
socket->waitForConnected( msecs );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialisation message according to the SingleApplication protocol
|
|
||||||
if( socket->state() == QLocalSocket::ConnectedState ) {
|
|
||||||
// Notify the parent that a new instance had been started;
|
|
||||||
QByteArray initMsg;
|
|
||||||
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
|
||||||
writeStream.setVersion(QDataStream::Qt_5_6);
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
writeStream << blockServerName.toLatin1();
|
// User level block requires a user specific data in the hash
|
||||||
writeStream << static_cast<quint8>(connectionType);
|
if (options & SingleApplication::Mode::User) {
|
||||||
writeStream << instanceNumber;
|
#ifdef Q_OS_UNIX
|
||||||
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
QByteArray username;
|
||||||
writeStream << checksum;
|
#if defined(HAVE_GETEUID) && defined(HAVE_GETPWUID)
|
||||||
|
struct passwd *pw = getpwuid(geteuid());
|
||||||
// The header indicates the message length that follows
|
if (pw) {
|
||||||
QByteArray header;
|
username = pw->pw_name;
|
||||||
QDataStream headerStream(&header, QIODevice::WriteOnly);
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
|
||||||
headerStream.setVersion(QDataStream::Qt_5_6);
|
|
||||||
#endif
|
|
||||||
headerStream << static_cast <quint64>( initMsg.length() );
|
|
||||||
|
|
||||||
socket->write( header );
|
|
||||||
socket->write( initMsg );
|
|
||||||
socket->flush();
|
|
||||||
socket->waitForBytesWritten( msecs );
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
if (username.isEmpty()) username = qgetenv("USER");
|
||||||
|
appData.addData(username);
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
wchar_t username [ UNLEN + 1 ];
|
||||||
|
// Specifies size of the buffer on input
|
||||||
|
DWORD usernameLength = UNLEN + 1;
|
||||||
|
if (GetUserNameW(username, &usernameLength)) {
|
||||||
|
appData.addData(QString::fromWCharArray(username).toUtf8());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appData.addData(qgetenv("USERNAME"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with server naming requirements.
|
||||||
|
blockServerName = appData.result().toBase64().replace("/", "_");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 SingleApplicationPrivate::blockChecksum()
|
void SingleApplicationPrivate::initializeMemoryBlock() {
|
||||||
{
|
|
||||||
return qChecksum(
|
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
static_cast <const char *>( memory->data() ),
|
inst->primary = false;
|
||||||
offsetof( InstancesInfo, checksum )
|
inst->secondary = 0;
|
||||||
);
|
inst->primaryPid = -1;
|
||||||
|
inst->checksum = blockChecksum();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 SingleApplicationPrivate::primaryPid()
|
void SingleApplicationPrivate::startPrimary() {
|
||||||
{
|
|
||||||
qint64 pid;
|
|
||||||
|
|
||||||
memory->lock();
|
Q_Q(SingleApplication);
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
|
|
||||||
pid = inst->primaryPid;
|
// Successful creation means that no main process exists
|
||||||
memory->unlock();
|
// So we start a QLocalServer to listen for connections
|
||||||
|
QLocalServer::removeServer(blockServerName);
|
||||||
|
server = new QLocalServer();
|
||||||
|
|
||||||
|
// Restrict access to the socket according to the
|
||||||
|
// SingleApplication::Mode::User flag on User level or no restrictions
|
||||||
|
if (options & SingleApplication::Mode::User) {
|
||||||
|
server->setSocketOptions(QLocalServer::UserAccessOption);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
server->listen(blockServerName);
|
||||||
|
QObject::connect(server, &QLocalServer::newConnection, this, &SingleApplicationPrivate::slotConnectionEstablished);
|
||||||
|
|
||||||
|
// Reset the number of connections
|
||||||
|
InstancesInfo* inst = static_cast <InstancesInfo*>(memory->data());
|
||||||
|
|
||||||
|
inst->primary = true;
|
||||||
|
inst->primaryPid = q->applicationPid();
|
||||||
|
inst->checksum = blockChecksum();
|
||||||
|
|
||||||
|
instanceNumber = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleApplicationPrivate::startSecondary() {}
|
||||||
|
|
||||||
|
void SingleApplicationPrivate::connectToPrimary(const int msecs, const ConnectionType connectionType) {
|
||||||
|
|
||||||
|
// Connect to the Local Server of the Primary Instance if not already connected.
|
||||||
|
if (socket == nullptr) {
|
||||||
|
socket = new QLocalSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If already connected - we are done;
|
||||||
|
if (socket->state() == QLocalSocket::ConnectedState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If not connect
|
||||||
|
if (socket->state() == QLocalSocket::UnconnectedState ||
|
||||||
|
socket->state() == QLocalSocket::ClosingState) {
|
||||||
|
socket->connectToServer(blockServerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for being connected
|
||||||
|
if (socket->state() == QLocalSocket::ConnectingState) {
|
||||||
|
socket->waitForConnected(msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialisation message according to the SingleApplication protocol
|
||||||
|
if (socket->state() == QLocalSocket::ConnectedState) {
|
||||||
|
// Notify the parent that a new instance had been started;
|
||||||
|
QByteArray initMsg;
|
||||||
|
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
writeStream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
|
||||||
|
writeStream << blockServerName.toLatin1();
|
||||||
|
writeStream << static_cast<quint8>(connectionType);
|
||||||
|
writeStream << instanceNumber;
|
||||||
|
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
||||||
|
writeStream << checksum;
|
||||||
|
|
||||||
|
// The header indicates the message length that follows
|
||||||
|
QByteArray header;
|
||||||
|
QDataStream headerStream(&header, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
headerStream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
|
||||||
|
headerStream << static_cast <quint64>(initMsg.length());
|
||||||
|
|
||||||
|
socket->write(header);
|
||||||
|
socket->write(initMsg);
|
||||||
|
socket->flush();
|
||||||
|
socket->waitForBytesWritten(msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 SingleApplicationPrivate::blockChecksum() {
|
||||||
|
|
||||||
|
return qChecksum(static_cast <const char *>(memory->data()), offsetof(InstancesInfo, checksum));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 SingleApplicationPrivate::primaryPid() {
|
||||||
|
|
||||||
|
qint64 pid;
|
||||||
|
|
||||||
|
memory->lock();
|
||||||
|
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
|
pid = inst->primaryPid;
|
||||||
|
memory->unlock();
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Executed when a connection has been made to the LocalServer
|
* @brief Executed when a connection has been made to the LocalServer
|
||||||
*/
|
*/
|
||||||
void SingleApplicationPrivate::slotConnectionEstablished()
|
void SingleApplicationPrivate::slotConnectionEstablished() {
|
||||||
{
|
|
||||||
QLocalSocket *nextConnSocket = server->nextPendingConnection();
|
|
||||||
connectionMap.insert(nextConnSocket, ConnectionInfo());
|
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
|
QLocalSocket *nextConnSocket = server->nextPendingConnection();
|
||||||
[nextConnSocket, this]() {
|
connectionMap.insert(nextConnSocket, ConnectionInfo());
|
||||||
auto &info = connectionMap[nextConnSocket];
|
|
||||||
Q_EMIT this->slotClientConnectionClosed( nextConnSocket, info.instanceId );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::disconnected,
|
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
|
||||||
[nextConnSocket, this](){
|
[nextConnSocket, this]() {
|
||||||
connectionMap.remove(nextConnSocket);
|
auto &info = connectionMap[nextConnSocket];
|
||||||
nextConnSocket->deleteLater();
|
Q_EMIT this->slotClientConnectionClosed(nextConnSocket, info.instanceId);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QObject::connect(nextConnSocket, &QLocalSocket::disconnected,
|
||||||
|
[nextConnSocket, this](){
|
||||||
|
connectionMap.remove(nextConnSocket);
|
||||||
|
nextConnSocket->deleteLater();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
||||||
|
[nextConnSocket, this]() {
|
||||||
|
auto &info = connectionMap[nextConnSocket];
|
||||||
|
switch(info.stage) {
|
||||||
|
case StageHeader:
|
||||||
|
readInitMessageHeader(nextConnSocket);
|
||||||
|
break;
|
||||||
|
case StageBody:
|
||||||
|
readInitMessageBody(nextConnSocket);
|
||||||
|
break;
|
||||||
|
case StageConnected:
|
||||||
|
Q_EMIT this->slotDataAvailable(nextConnSocket, info.instanceId);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
|
||||||
[nextConnSocket, this]() {
|
|
||||||
auto &info = connectionMap[nextConnSocket];
|
|
||||||
switch(info.stage) {
|
|
||||||
case StageHeader:
|
|
||||||
readInitMessageHeader(nextConnSocket);
|
|
||||||
break;
|
|
||||||
case StageBody:
|
|
||||||
readInitMessageBody(nextConnSocket);
|
|
||||||
break;
|
|
||||||
case StageConnected:
|
|
||||||
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::readInitMessageHeader( QLocalSocket *sock )
|
void SingleApplicationPrivate::readInitMessageHeader(QLocalSocket *sock) {
|
||||||
{
|
|
||||||
if (!connectionMap.contains( sock )) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ) {
|
if (!connectionMap.contains(sock)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream headerStream( sock );
|
if (sock->bytesAvailable() < (qint64) sizeof(quint64)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
QDataStream headerStream(sock);
|
||||||
headerStream.setVersion( QDataStream::Qt_5_6 );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Read the header to know the message length
|
headerStream.setVersion(QDataStream::Qt_5_6);
|
||||||
quint64 msgLen = 0;
|
|
||||||
headerStream >> msgLen;
|
// Read the header to know the message length
|
||||||
ConnectionInfo &info = connectionMap[sock];
|
quint64 msgLen = 0;
|
||||||
info.stage = StageBody;
|
headerStream >> msgLen;
|
||||||
info.msgLen = msgLen;
|
ConnectionInfo &info = connectionMap[sock];
|
||||||
|
info.stage = StageBody;
|
||||||
|
info.msgLen = msgLen;
|
||||||
|
|
||||||
|
if (sock->bytesAvailable() >= (qint64) msgLen) {
|
||||||
|
readInitMessageBody(sock);
|
||||||
|
}
|
||||||
|
|
||||||
if ( sock->bytesAvailable() >= (qint64) msgLen ) {
|
|
||||||
readInitMessageBody( sock );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
|
void SingleApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
|
||||||
{
|
|
||||||
Q_Q(SingleApplication);
|
|
||||||
|
|
||||||
if (!connectionMap.contains( sock )) {
|
Q_Q(SingleApplication);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionInfo &info = connectionMap[sock];
|
if (!connectionMap.contains(sock)) {
|
||||||
if( sock->bytesAvailable() < ( qint64 )info.msgLen ) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Read the message body
|
ConnectionInfo &info = connectionMap[sock];
|
||||||
QByteArray msgBytes = sock->read(info.msgLen);
|
if (sock->bytesAvailable() < (qint64)info.msgLen) {
|
||||||
QDataStream readStream(msgBytes);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
// Read the message body
|
||||||
readStream.setVersion( QDataStream::Qt_5_6 );
|
QByteArray msgBytes = sock->read(info.msgLen);
|
||||||
#endif
|
QDataStream readStream(msgBytes);
|
||||||
|
|
||||||
// server name
|
readStream.setVersion(QDataStream::Qt_5_6);
|
||||||
QByteArray latin1Name;
|
|
||||||
readStream >> latin1Name;
|
|
||||||
|
|
||||||
// connection type
|
// server name
|
||||||
ConnectionType connectionType = InvalidConnection;
|
QByteArray latin1Name;
|
||||||
quint8 connTypeVal = InvalidConnection;
|
readStream >> latin1Name;
|
||||||
readStream >> connTypeVal;
|
|
||||||
connectionType = static_cast <ConnectionType>( connTypeVal );
|
|
||||||
|
|
||||||
// instance id
|
// connection type
|
||||||
quint32 instanceId = 0;
|
ConnectionType connectionType = InvalidConnection;
|
||||||
readStream >> instanceId;
|
quint8 connTypeVal = InvalidConnection;
|
||||||
|
readStream >> connTypeVal;
|
||||||
|
connectionType = static_cast <ConnectionType>(connTypeVal);
|
||||||
|
|
||||||
// checksum
|
// instance id
|
||||||
quint16 msgChecksum = 0;
|
quint32 instanceId = 0;
|
||||||
readStream >> msgChecksum;
|
readStream >> instanceId;
|
||||||
|
|
||||||
const quint16 actualChecksum = qChecksum( msgBytes.constData(), static_cast<quint32>( msgBytes.length() - sizeof( quint16 ) ) );
|
// checksum
|
||||||
|
quint16 msgChecksum = 0;
|
||||||
|
readStream >> msgChecksum;
|
||||||
|
|
||||||
bool isValid = readStream.status() == QDataStream::Ok &&
|
const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length() - sizeof(quint16)));
|
||||||
QLatin1String(latin1Name) == blockServerName &&
|
|
||||||
msgChecksum == actualChecksum;
|
|
||||||
|
|
||||||
if( !isValid ) {
|
bool isValid = readStream.status() == QDataStream::Ok && QLatin1String(latin1Name) == blockServerName && msgChecksum == actualChecksum;
|
||||||
sock->close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.instanceId = instanceId;
|
if (!isValid) {
|
||||||
info.stage = StageConnected;
|
sock->close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( connectionType == NewInstance ||
|
info.instanceId = instanceId;
|
||||||
( connectionType == SecondaryInstance &&
|
info.stage = StageConnected;
|
||||||
options & SingleApplication::Mode::SecondaryNotification ) )
|
|
||||||
{
|
if (connectionType == NewInstance || (connectionType == SecondaryInstance && options & SingleApplication::Mode::SecondaryNotification)) {
|
||||||
Q_EMIT q->instanceStarted();
|
Q_EMIT q->instanceStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->bytesAvailable() > 0) {
|
||||||
|
Q_EMIT this->slotDataAvailable(sock, instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
if (sock->bytesAvailable() > 0) {
|
|
||||||
Q_EMIT this->slotDataAvailable( sock, instanceId );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
|
void SingleApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, const quint32 instanceId) {
|
||||||
{
|
|
||||||
Q_Q(SingleApplication);
|
Q_Q(SingleApplication);
|
||||||
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
|
Q_EMIT q->receivedMessage(instanceId, dataSocket->readAll());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
|
void SingleApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
|
||||||
{
|
|
||||||
if( closedSocket->bytesAvailable() > 0 )
|
if (closedSocket->bytesAvailable() > 0)
|
||||||
Q_EMIT slotDataAvailable( closedSocket, instanceId );
|
Q_EMIT slotDataAvailable(closedSocket, instanceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
112
3rdparty/singleapplication/singleapplication_p.h
vendored
112
3rdparty/singleapplication/singleapplication_p.h
vendored
@@ -24,76 +24,82 @@
|
|||||||
// W A R N I N G !!!
|
// W A R N I N G !!!
|
||||||
// -----------------
|
// -----------------
|
||||||
//
|
//
|
||||||
// This file is not part of the SingleApplication API. It is used purely as an
|
// This is a modified version of SingleApplication,
|
||||||
// implementation detail. This header file may change from version to
|
// The original version is at:
|
||||||
// version without notice, or may even be removed.
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef SINGLEAPPLICATION_P_H
|
#ifndef SINGLEAPPLICATION_P_H
|
||||||
#define SINGLEAPPLICATION_P_H
|
#define SINGLEAPPLICATION_P_H
|
||||||
|
|
||||||
#include <QtCore/QSharedMemory>
|
#include <QtGlobal>
|
||||||
#include <QtNetwork/QLocalServer>
|
#include <QObject>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QMap>
|
||||||
|
|
||||||
#include "singleapplication.h"
|
#include "singleapplication.h"
|
||||||
|
|
||||||
|
class QLocalServer;
|
||||||
|
class QLocalSocket;
|
||||||
|
class QSharedMemory;
|
||||||
|
|
||||||
struct InstancesInfo {
|
struct InstancesInfo {
|
||||||
bool primary;
|
bool primary;
|
||||||
quint32 secondary;
|
quint32 secondary;
|
||||||
qint64 primaryPid;
|
qint64 primaryPid;
|
||||||
quint16 checksum;
|
quint16 checksum;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionInfo {
|
struct ConnectionInfo {
|
||||||
explicit ConnectionInfo() :
|
explicit ConnectionInfo() : msgLen(0), instanceId(0), stage(0) {}
|
||||||
msgLen(0), instanceId(0), stage(0) {}
|
qint64 msgLen;
|
||||||
qint64 msgLen;
|
quint32 instanceId;
|
||||||
quint32 instanceId;
|
quint8 stage;
|
||||||
quint8 stage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SingleApplicationPrivate : public QObject {
|
class SingleApplicationPrivate : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum ConnectionType : quint8 {
|
enum ConnectionType : quint8 {
|
||||||
InvalidConnection = 0,
|
InvalidConnection = 0,
|
||||||
NewInstance = 1,
|
NewInstance = 1,
|
||||||
SecondaryInstance = 2,
|
SecondaryInstance = 2,
|
||||||
Reconnect = 3
|
Reconnect = 3
|
||||||
};
|
};
|
||||||
enum ConnectionStage : quint8 {
|
enum ConnectionStage : quint8 {
|
||||||
StageHeader = 0,
|
StageHeader = 0,
|
||||||
StageBody = 1,
|
StageBody = 1,
|
||||||
StageConnected = 2,
|
StageConnected = 2,
|
||||||
};
|
};
|
||||||
Q_DECLARE_PUBLIC(SingleApplication)
|
Q_DECLARE_PUBLIC(SingleApplication)
|
||||||
|
|
||||||
SingleApplicationPrivate( SingleApplication *q_ptr );
|
SingleApplicationPrivate(SingleApplication *_q_ptr);
|
||||||
~SingleApplicationPrivate();
|
~SingleApplicationPrivate();
|
||||||
|
|
||||||
void genBlockServerName();
|
void genBlockServerName();
|
||||||
void initializeMemoryBlock();
|
void initializeMemoryBlock();
|
||||||
void startPrimary();
|
void startPrimary();
|
||||||
void startSecondary();
|
void startSecondary();
|
||||||
void connectToPrimary(int msecs, ConnectionType connectionType );
|
void connectToPrimary(const int msecs, const ConnectionType connectionType);
|
||||||
quint16 blockChecksum();
|
quint16 blockChecksum();
|
||||||
qint64 primaryPid();
|
qint64 primaryPid();
|
||||||
void readInitMessageHeader(QLocalSocket *socket);
|
void readInitMessageHeader(QLocalSocket *socket);
|
||||||
void readInitMessageBody(QLocalSocket *socket);
|
void readInitMessageBody(QLocalSocket *socket);
|
||||||
|
|
||||||
SingleApplication *q_ptr;
|
SingleApplication *q_ptr;
|
||||||
QSharedMemory *memory;
|
QSharedMemory *memory;
|
||||||
QLocalSocket *socket;
|
QLocalSocket *socket;
|
||||||
QLocalServer *server;
|
QLocalServer *server;
|
||||||
quint32 instanceNumber;
|
quint32 instanceNumber;
|
||||||
QString blockServerName;
|
QString blockServerName;
|
||||||
SingleApplication::Options options;
|
SingleApplication::Options options;
|
||||||
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public slots:
|
||||||
void slotConnectionEstablished();
|
void slotConnectionEstablished();
|
||||||
void slotDataAvailable( QLocalSocket*, quint32 );
|
void slotDataAvailable(QLocalSocket*, const quint32);
|
||||||
void slotClientConnectionClosed( QLocalSocket*, quint32 );
|
void slotClientConnectionClosed(QLocalSocket*, const quint32);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SINGLEAPPLICATION_P_H
|
#endif // SINGLEAPPLICATION_P_H
|
||||||
|
|||||||
225
3rdparty/singleapplication/singlecoreapplication.cpp
vendored
225
3rdparty/singleapplication/singlecoreapplication.cpp
vendored
@@ -20,12 +20,29 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G !!!
|
||||||
|
// -----------------
|
||||||
|
//
|
||||||
|
// This is a modified version of SingleApplication,
|
||||||
|
// The original version is at:
|
||||||
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QtCore/QTime>
|
#include <QThread>
|
||||||
#include <QtCore/QThread>
|
#include <QSharedMemory>
|
||||||
#include <QtCore/QDateTime>
|
#include <QLocalSocket>
|
||||||
#include <QtCore/QByteArray>
|
#include <QByteArray>
|
||||||
#include <QtCore/QSharedMemory>
|
#include <QDateTime>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include <QtDebug>
|
||||||
|
|
||||||
#include "singlecoreapplication.h"
|
#include "singlecoreapplication.h"
|
||||||
#include "singlecoreapplication_p.h"
|
#include "singlecoreapplication_p.h"
|
||||||
@@ -37,139 +54,137 @@
|
|||||||
* @param argv
|
* @param argv
|
||||||
* @param {bool} allowSecondaryInstances
|
* @param {bool} allowSecondaryInstances
|
||||||
*/
|
*/
|
||||||
SingleCoreApplication::SingleCoreApplication( int &argc, char *argv[], bool allowSecondary, Options options, int timeout )
|
SingleCoreApplication::SingleCoreApplication(int &argc, char *argv[], bool allowSecondary, Options options, int timeout)
|
||||||
: app_t( argc, argv ), d_ptr( new SingleCoreApplicationPrivate( this ) )
|
: app_t(argc, argv), d_ptr(new SingleCoreApplicationPrivate(this)) {
|
||||||
{
|
|
||||||
Q_D(SingleCoreApplication);
|
|
||||||
|
|
||||||
// Store the current mode of the program
|
Q_D(SingleCoreApplication);
|
||||||
d->options = options;
|
|
||||||
|
|
||||||
// Generating an application ID used for identifying the shared memory
|
// Store the current mode of the program
|
||||||
// block and QLocalServer
|
d->options = options;
|
||||||
d->genBlockServerName();
|
|
||||||
|
// Generating an application ID used for identifying the shared memory
|
||||||
|
// block and QLocalServer
|
||||||
|
d->genBlockServerName();
|
||||||
|
|
||||||
#ifdef Q_OS_UNIX
|
#ifdef Q_OS_UNIX
|
||||||
// By explicitly attaching it and then deleting it we make sure that the
|
// By explicitly attaching it and then deleting it we make sure that the
|
||||||
// memory is deleted even after the process has crashed on Unix.
|
// memory is deleted even after the process has crashed on Unix.
|
||||||
d->memory = new QSharedMemory( d->blockServerName );
|
d->memory = new QSharedMemory(d->blockServerName);
|
||||||
d->memory->attach();
|
d->memory->attach();
|
||||||
delete d->memory;
|
delete d->memory;
|
||||||
#endif
|
#endif
|
||||||
// Guarantee thread safe behaviour with a shared memory block.
|
// Guarantee thread safe behaviour with a shared memory block.
|
||||||
d->memory = new QSharedMemory( d->blockServerName );
|
d->memory = new QSharedMemory(d->blockServerName);
|
||||||
|
|
||||||
// Create a shared memory block
|
// Create a shared memory block
|
||||||
if( d->memory->create( sizeof( InstancesInfo ) ) ) {
|
if (d->memory->create(sizeof(InstancesInfo))) {
|
||||||
// Initialize the shared memory block
|
// Initialize the shared memory block
|
||||||
d->memory->lock();
|
d->memory->lock();
|
||||||
d->initializeMemoryBlock();
|
d->initializeMemoryBlock();
|
||||||
d->memory->unlock();
|
d->memory->unlock();
|
||||||
} else {
|
}
|
||||||
// Attempt to attach to the memory segment
|
else {
|
||||||
if( ! d->memory->attach() ) {
|
// Attempt to attach to the memory segment
|
||||||
qCritical() << "SingleCoreApplication: Unable to attach to shared memory block.";
|
if (!d->memory->attach()) {
|
||||||
qCritical() << d->memory->errorString();
|
qCritical() << "SingleCoreApplication: Unable to attach to shared memory block.";
|
||||||
delete d;
|
qCritical() << d->memory->errorString();
|
||||||
::exit( EXIT_FAILURE );
|
delete d;
|
||||||
}
|
::exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( d->memory->data() );
|
InstancesInfo* inst = static_cast<InstancesInfo*>(d->memory->data());
|
||||||
QTime time;
|
QElapsedTimer time;
|
||||||
time.start();
|
time.start();
|
||||||
|
|
||||||
// Make sure the shared memory block is initialised and in consistent state
|
// Make sure the shared memory block is initialised and in consistent state
|
||||||
while( true ) {
|
while (true) {
|
||||||
d->memory->lock();
|
d->memory->lock();
|
||||||
|
|
||||||
if( d->blockChecksum() == inst->checksum ) break;
|
if(d->blockChecksum() == inst->checksum) break;
|
||||||
|
|
||||||
if( time.elapsed() > 5000 ) {
|
if (time.elapsed() > 5000) {
|
||||||
qWarning() << "SingleCoreApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
|
qWarning() << "SingleCoreApplication: Shared memory block has been in an inconsistent state from more than 5s. Assuming primary instance failure.";
|
||||||
d->initializeMemoryBlock();
|
d->initializeMemoryBlock();
|
||||||
}
|
|
||||||
|
|
||||||
d->memory->unlock();
|
|
||||||
|
|
||||||
// Random sleep here limits the probability of a collision between two racing apps
|
|
||||||
qsrand( QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max() );
|
|
||||||
QThread::sleep( 8 + static_cast <unsigned long>( static_cast <float>( qrand() ) / RAND_MAX * 10 ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( inst->primary == false) {
|
|
||||||
d->startPrimary();
|
|
||||||
d->memory->unlock();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if another instance can be started
|
|
||||||
if( allowSecondary ) {
|
|
||||||
inst->secondary += 1;
|
|
||||||
inst->checksum = d->blockChecksum();
|
|
||||||
d->instanceNumber = inst->secondary;
|
|
||||||
d->startSecondary();
|
|
||||||
if( d->options & Mode::SecondaryNotification ) {
|
|
||||||
d->connectToPrimary( timeout, SingleCoreApplicationPrivate::SecondaryInstance );
|
|
||||||
}
|
|
||||||
d->memory->unlock();
|
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
d->memory->unlock();
|
d->memory->unlock();
|
||||||
|
|
||||||
d->connectToPrimary( timeout, SingleCoreApplicationPrivate::NewInstance );
|
// Random sleep here limits the probability of a collision between two racing apps
|
||||||
|
qsrand(QDateTime::currentMSecsSinceEpoch() % std::numeric_limits<uint>::max());
|
||||||
|
QThread::sleep(8 + static_cast <unsigned long>(static_cast <float>(qrand()) / RAND_MAX * 10));
|
||||||
|
}
|
||||||
|
|
||||||
delete d;
|
if (inst->primary == false) {
|
||||||
|
d->startPrimary();
|
||||||
|
d->memory->unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if another instance can be started
|
||||||
|
if (allowSecondary) {
|
||||||
|
inst->secondary += 1;
|
||||||
|
inst->checksum = d->blockChecksum();
|
||||||
|
d->instanceNumber = inst->secondary;
|
||||||
|
d->startSecondary();
|
||||||
|
if(d->options & Mode::SecondaryNotification) {
|
||||||
|
d->connectToPrimary(timeout, SingleCoreApplicationPrivate::SecondaryInstance);
|
||||||
|
}
|
||||||
|
d->memory->unlock();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->memory->unlock();
|
||||||
|
|
||||||
|
d->connectToPrimary(timeout, SingleCoreApplicationPrivate::NewInstance);
|
||||||
|
|
||||||
|
delete d;
|
||||||
|
|
||||||
|
::exit(EXIT_SUCCESS);
|
||||||
|
|
||||||
::exit( EXIT_SUCCESS );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Destructor
|
* @brief Destructor
|
||||||
*/
|
*/
|
||||||
SingleCoreApplication::~SingleCoreApplication()
|
SingleCoreApplication::~SingleCoreApplication() {
|
||||||
{
|
Q_D(SingleCoreApplication);
|
||||||
Q_D(SingleCoreApplication);
|
delete d;
|
||||||
delete d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleCoreApplication::isPrimary()
|
bool SingleCoreApplication::isPrimary() {
|
||||||
{
|
Q_D(SingleCoreApplication);
|
||||||
Q_D(SingleCoreApplication);
|
return d->server != nullptr;
|
||||||
return d->server != nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleCoreApplication::isSecondary()
|
bool SingleCoreApplication::isSecondary() {
|
||||||
{
|
Q_D(SingleCoreApplication);
|
||||||
Q_D(SingleCoreApplication);
|
return d->server == nullptr;
|
||||||
return d->server == nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint32 SingleCoreApplication::instanceId()
|
quint32 SingleCoreApplication::instanceId() {
|
||||||
{
|
Q_D(SingleCoreApplication);
|
||||||
Q_D(SingleCoreApplication);
|
return d->instanceNumber;
|
||||||
return d->instanceNumber;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 SingleCoreApplication::primaryPid()
|
qint64 SingleCoreApplication::primaryPid() {
|
||||||
{
|
Q_D(SingleCoreApplication);
|
||||||
Q_D(SingleCoreApplication);
|
return d->primaryPid();
|
||||||
return d->primaryPid();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SingleCoreApplication::sendMessage( QByteArray message, int timeout )
|
bool SingleCoreApplication::sendMessage(QByteArray message, int timeout) {
|
||||||
{
|
|
||||||
Q_D(SingleCoreApplication);
|
|
||||||
|
|
||||||
// Nobody to connect to
|
Q_D(SingleCoreApplication);
|
||||||
if( isPrimary() ) return false;
|
|
||||||
|
|
||||||
// Make sure the socket is connected
|
// Nobody to connect to
|
||||||
d->connectToPrimary( timeout, SingleCoreApplicationPrivate::Reconnect );
|
if(isPrimary()) return false;
|
||||||
|
|
||||||
|
// Make sure the socket is connected
|
||||||
|
d->connectToPrimary(timeout, SingleCoreApplicationPrivate::Reconnect);
|
||||||
|
|
||||||
|
d->socket->write(message);
|
||||||
|
bool dataWritten = d->socket->waitForBytesWritten(timeout);
|
||||||
|
d->socket->flush();
|
||||||
|
return dataWritten;
|
||||||
|
|
||||||
d->socket->write( message );
|
|
||||||
bool dataWritten = d->socket->flush();
|
|
||||||
d->socket->waitForBytesWritten( timeout );
|
|
||||||
return dataWritten;
|
|
||||||
}
|
}
|
||||||
|
|||||||
171
3rdparty/singleapplication/singlecoreapplication.h
vendored
171
3rdparty/singleapplication/singlecoreapplication.h
vendored
@@ -20,109 +20,120 @@
|
|||||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
// THE SOFTWARE.
|
// THE SOFTWARE.
|
||||||
|
|
||||||
|
//
|
||||||
|
// W A R N I N G !!!
|
||||||
|
// -----------------
|
||||||
|
//
|
||||||
|
// This is a modified version of SingleApplication,
|
||||||
|
// The original version is at:
|
||||||
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
#ifndef SINGLECOREAPPLICATION_H
|
#ifndef SINGLECOREAPPLICATION_H
|
||||||
#define SINGLECOREAPPLICATION_H
|
#define SINGLECOREAPPLICATION_H
|
||||||
|
|
||||||
#include <QtCore/QtGlobal>
|
#include <QtGlobal>
|
||||||
#include <QCoreApplication>
|
#include <QCoreApplication>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QFlags>
|
||||||
|
#include <QByteArray>
|
||||||
|
|
||||||
class SingleCoreApplicationPrivate;
|
class SingleCoreApplicationPrivate;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief The SingleCoreApplication class handles multipe instances of the same
|
* @brief The SingleCoreApplication class handles multiple instances of the same
|
||||||
* Application
|
* Application
|
||||||
* @see QCoreApplication
|
* @see QCoreApplication
|
||||||
*/
|
*/
|
||||||
class SingleCoreApplication : public QCoreApplication
|
class SingleCoreApplication : public QCoreApplication {
|
||||||
{
|
Q_OBJECT
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
typedef QCoreApplication app_t;
|
typedef QCoreApplication app_t;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/**
|
/**
|
||||||
* @brief Mode of operation of SingleCoreApplication.
|
* @brief Mode of operation of SingleCoreApplication.
|
||||||
* Whether the block should be user-wide or system-wide and whether the
|
* Whether the block should be user-wide or system-wide and whether the
|
||||||
* primary instance should be notified when a secondary instance had been
|
* primary instance should be notified when a secondary instance had been
|
||||||
* started.
|
* started.
|
||||||
* @note Operating system can restrict the shared memory blocks to the same
|
* @note Operating system can restrict the shared memory blocks to the same
|
||||||
* user, in which case the User/System modes will have no effect and the
|
* user, in which case the User/System modes will have no effect and the
|
||||||
* block will be user wide.
|
* block will be user wide.
|
||||||
* @enum
|
* @enum
|
||||||
*/
|
*/
|
||||||
enum Mode {
|
enum Mode {
|
||||||
User = 1 << 0,
|
User = 1 << 0,
|
||||||
System = 1 << 1,
|
System = 1 << 1,
|
||||||
SecondaryNotification = 1 << 2,
|
SecondaryNotification = 1 << 2,
|
||||||
ExcludeAppVersion = 1 << 3,
|
ExcludeAppVersion = 1 << 3,
|
||||||
ExcludeAppPath = 1 << 4
|
ExcludeAppPath = 1 << 4
|
||||||
};
|
};
|
||||||
Q_DECLARE_FLAGS(Options, Mode)
|
Q_DECLARE_FLAGS(Options, Mode)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Intitializes a SingleCoreApplication instance with argc command line
|
* @brief Intitializes a SingleCoreApplication instance with argc command line
|
||||||
* arguments in argv
|
* arguments in argv
|
||||||
* @arg {int &} argc - Number of arguments in argv
|
* @arg {int &} argc - Number of arguments in argv
|
||||||
* @arg {const char *[]} argv - Supplied command line arguments
|
* @arg {const char *[]} argv - Supplied command line arguments
|
||||||
* @arg {bool} allowSecondary - Whether to start the instance as secondary
|
* @arg {bool} allowSecondary - Whether to start the instance as secondary
|
||||||
* if there is already a primary instance.
|
* if there is already a primary instance.
|
||||||
* @arg {Mode} mode - Whether for the SingleCoreApplication block to be applied
|
* @arg {Mode} mode - Whether for the SingleCoreApplication block to be applied
|
||||||
* User wide or System wide.
|
* User wide or System wide.
|
||||||
* @arg {int} timeout - Timeout to wait in miliseconds.
|
* @arg {int} timeout - Timeout to wait in milliseconds.
|
||||||
* @note argc and argv may be changed as Qt removes arguments that it
|
* @note argc and argv may be changed as Qt removes arguments that it
|
||||||
* recognizes
|
* recognizes
|
||||||
* @note Mode::SecondaryNotification only works if set on both the primary
|
* @note Mode::SecondaryNotification only works if set on both the primary
|
||||||
* instance and the secondary instance.
|
* instance and the secondary instance.
|
||||||
* @note The timeout is just a hint for the maximum time of blocking
|
* @note The timeout is just a hint for the maximum time of blocking
|
||||||
* operations. It does not guarantee that the SingleCoreApplication
|
* operations. It does not guarantee that the SingleCoreApplication
|
||||||
* initialisation will be completed in given time, though is a good hint.
|
* initialisation will be completed in given time, though is a good hint.
|
||||||
* Usually 4*timeout would be the worst case (fail) scenario.
|
* Usually 4*timeout would be the worst case (fail) scenario.
|
||||||
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
|
* @see See the corresponding QAPPLICATION_CLASS constructor for reference
|
||||||
*/
|
*/
|
||||||
explicit SingleCoreApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 );
|
explicit SingleCoreApplication( int &argc, char *argv[], bool allowSecondary = false, Options options = Mode::User, int timeout = 1000 );
|
||||||
~SingleCoreApplication();
|
~SingleCoreApplication();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns if the instance is the primary instance
|
* @brief Returns if the instance is the primary instance
|
||||||
* @returns {bool}
|
* @returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isPrimary();
|
bool isPrimary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns if the instance is a secondary instance
|
* @brief Returns if the instance is a secondary instance
|
||||||
* @returns {bool}
|
* @returns {bool}
|
||||||
*/
|
*/
|
||||||
bool isSecondary();
|
bool isSecondary();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns a unique identifier for the current instance
|
* @brief Returns a unique identifier for the current instance
|
||||||
* @returns {qint32}
|
* @returns {qint32}
|
||||||
*/
|
*/
|
||||||
quint32 instanceId();
|
quint32 instanceId();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Returns the process ID (PID) of the primary instance
|
* @brief Returns the process ID (PID) of the primary instance
|
||||||
* @returns {qint64}
|
* @returns {qint64}
|
||||||
*/
|
*/
|
||||||
qint64 primaryPid();
|
qint64 primaryPid();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Sends a message to the primary instance. Returns true on success.
|
* @brief Sends a message to the primary instance. Returns true on success.
|
||||||
* @param {int} timeout - Timeout for connecting
|
* @param {int} timeout - Timeout for connecting
|
||||||
* @returns {bool}
|
* @returns {bool}
|
||||||
* @note sendMessage() will return false if invoked from the primary
|
* @note sendMessage() will return false if invoked from the primary
|
||||||
* instance.
|
* instance.
|
||||||
*/
|
*/
|
||||||
bool sendMessage( QByteArray message, int timeout = 100 );
|
bool sendMessage( QByteArray message, int timeout = 1000 );
|
||||||
|
|
||||||
Q_SIGNALS:
|
signals:
|
||||||
void instanceStarted();
|
void instanceStarted();
|
||||||
void receivedMessage( quint32 instanceId, QByteArray message );
|
void receivedMessage( quint32 instanceId, QByteArray message );
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SingleCoreApplicationPrivate *d_ptr;
|
SingleCoreApplicationPrivate *d_ptr;
|
||||||
Q_DECLARE_PRIVATE(SingleCoreApplication)
|
Q_DECLARE_PRIVATE(SingleCoreApplication)
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleCoreApplication::Options)
|
Q_DECLARE_OPERATORS_FOR_FLAGS(SingleCoreApplication::Options)
|
||||||
|
|||||||
@@ -24,381 +24,378 @@
|
|||||||
// W A R N I N G !!!
|
// W A R N I N G !!!
|
||||||
// -----------------
|
// -----------------
|
||||||
//
|
//
|
||||||
// This file is not part of the SingleCoreApplication API. It is used purely as an
|
// This is a modified version of SingleApplication,
|
||||||
// implementation detail. This header file may change from version to
|
// The original version is at:
|
||||||
// version without notice, or may even be removed.
|
|
||||||
//
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#include <QtGlobal>
|
||||||
|
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
|
|
||||||
#include <QtCore/QDir>
|
#ifdef Q_OS_UNIX
|
||||||
#include <QtCore/QProcess>
|
# include <unistd.h>
|
||||||
#include <QtCore/QByteArray>
|
# include <sys/types.h>
|
||||||
#include <QtCore/QSemaphore>
|
# include <pwd.h>
|
||||||
#include <QtCore/QDataStream>
|
#endif
|
||||||
#include <QtCore/QStandardPaths>
|
|
||||||
#include <QtCore/QCryptographicHash>
|
#include <QIODevice>
|
||||||
#include <QtNetwork/QLocalServer>
|
#include <QSharedMemory>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QByteArray>
|
||||||
|
#include <QDataStream>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QLocalServer>
|
||||||
|
#include <QLocalSocket>
|
||||||
|
#include <QDir>
|
||||||
|
|
||||||
#include "singlecoreapplication.h"
|
#include "singlecoreapplication.h"
|
||||||
#include "singlecoreapplication_p.h"
|
#include "singlecoreapplication_p.h"
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
#include <windows.h>
|
# include <windows.h>
|
||||||
#include <lmcons.h>
|
# include <lmcons.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SingleCoreApplicationPrivate::SingleCoreApplicationPrivate( SingleCoreApplication *q_ptr )
|
SingleCoreApplicationPrivate::SingleCoreApplicationPrivate(SingleCoreApplication *_q_ptr)
|
||||||
: q_ptr( q_ptr )
|
: q_ptr(_q_ptr),
|
||||||
{
|
memory(nullptr),
|
||||||
server = nullptr;
|
socket(nullptr),
|
||||||
socket = nullptr;
|
server(nullptr),
|
||||||
memory = nullptr;
|
instanceNumber(-1)
|
||||||
instanceNumber = -1;
|
{}
|
||||||
}
|
|
||||||
|
|
||||||
SingleCoreApplicationPrivate::~SingleCoreApplicationPrivate()
|
SingleCoreApplicationPrivate::~SingleCoreApplicationPrivate() {
|
||||||
{
|
|
||||||
if( socket != nullptr ) {
|
|
||||||
socket->close();
|
|
||||||
delete socket;
|
|
||||||
}
|
|
||||||
|
|
||||||
memory->lock();
|
if (socket != nullptr) {
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
socket->close();
|
||||||
if( server != nullptr ) {
|
delete socket;
|
||||||
server->close();
|
}
|
||||||
delete server;
|
|
||||||
inst->primary = false;
|
|
||||||
inst->primaryPid = -1;
|
|
||||||
inst->checksum = blockChecksum();
|
|
||||||
}
|
|
||||||
memory->unlock();
|
|
||||||
|
|
||||||
delete memory;
|
memory->lock();
|
||||||
}
|
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
|
if (server != nullptr) {
|
||||||
void SingleCoreApplicationPrivate::genBlockServerName()
|
server->close();
|
||||||
{
|
delete server;
|
||||||
QCryptographicHash appData( QCryptographicHash::Sha256 );
|
|
||||||
appData.addData( "SingleApplication", 17 );
|
|
||||||
appData.addData( SingleCoreApplication::app_t::applicationName().toUtf8() );
|
|
||||||
appData.addData( SingleCoreApplication::app_t::organizationName().toUtf8() );
|
|
||||||
appData.addData( SingleCoreApplication::app_t::organizationDomain().toUtf8() );
|
|
||||||
|
|
||||||
if( ! (options & SingleCoreApplication::Mode::ExcludeAppVersion) ) {
|
|
||||||
appData.addData( SingleCoreApplication::app_t::applicationVersion().toUtf8() );
|
|
||||||
}
|
|
||||||
|
|
||||||
if( ! (options & SingleCoreApplication::Mode::ExcludeAppPath) ) {
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
appData.addData( SingleCoreApplication::app_t::applicationFilePath().toLower().toUtf8() );
|
|
||||||
#else
|
|
||||||
appData.addData( SingleCoreApplication::app_t::applicationFilePath().toUtf8() );
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// User level block requires a user specific data in the hash
|
|
||||||
if( options & SingleCoreApplication::Mode::User ) {
|
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
wchar_t username [ UNLEN + 1 ];
|
|
||||||
// Specifies size of the buffer on input
|
|
||||||
DWORD usernameLength = UNLEN + 1;
|
|
||||||
if( GetUserNameW( username, &usernameLength ) ) {
|
|
||||||
appData.addData( QString::fromWCharArray(username).toUtf8() );
|
|
||||||
} else {
|
|
||||||
appData.addData( QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).join("").toUtf8() );
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef Q_OS_UNIX
|
|
||||||
QProcess process;
|
|
||||||
process.start( "whoami" );
|
|
||||||
if( process.waitForFinished( 100 ) &&
|
|
||||||
process.exitCode() == QProcess::NormalExit) {
|
|
||||||
appData.addData( process.readLine() );
|
|
||||||
} else {
|
|
||||||
appData.addData(
|
|
||||||
QDir(
|
|
||||||
QStandardPaths::standardLocations( QStandardPaths::HomeLocation ).first()
|
|
||||||
).absolutePath().toUtf8()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with
|
|
||||||
// server naming requirements.
|
|
||||||
blockServerName = appData.result().toBase64().replace("/", "_");
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::initializeMemoryBlock()
|
|
||||||
{
|
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
|
|
||||||
inst->primary = false;
|
inst->primary = false;
|
||||||
inst->secondary = 0;
|
|
||||||
inst->primaryPid = -1;
|
inst->primaryPid = -1;
|
||||||
inst->checksum = blockChecksum();
|
inst->checksum = blockChecksum();
|
||||||
|
}
|
||||||
|
memory->unlock();
|
||||||
|
|
||||||
|
delete memory;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::startPrimary()
|
void SingleCoreApplicationPrivate::genBlockServerName() {
|
||||||
{
|
|
||||||
Q_Q(SingleCoreApplication);
|
|
||||||
|
|
||||||
// Successful creation means that no main process exists
|
QCryptographicHash appData(QCryptographicHash::Sha256);
|
||||||
// So we start a QLocalServer to listen for connections
|
appData.addData("SingleApplication", 17);
|
||||||
QLocalServer::removeServer( blockServerName );
|
appData.addData(SingleCoreApplication::app_t::applicationName().toUtf8());
|
||||||
server = new QLocalServer();
|
appData.addData(SingleCoreApplication::app_t::organizationName().toUtf8());
|
||||||
|
appData.addData(SingleCoreApplication::app_t::organizationDomain().toUtf8());
|
||||||
|
|
||||||
// Restrict access to the socket according to the
|
if (!(options & SingleCoreApplication::Mode::ExcludeAppVersion)) {
|
||||||
// SingleCoreApplication::Mode::User flag on User level or no restrictions
|
appData.addData(SingleCoreApplication::app_t::applicationVersion().toUtf8());
|
||||||
if( options & SingleCoreApplication::Mode::User ) {
|
}
|
||||||
server->setSocketOptions( QLocalServer::UserAccessOption );
|
|
||||||
} else {
|
|
||||||
server->setSocketOptions( QLocalServer::WorldAccessOption );
|
|
||||||
}
|
|
||||||
|
|
||||||
server->listen( blockServerName );
|
if (!(options & SingleCoreApplication::Mode::ExcludeAppPath)) {
|
||||||
QObject::connect(
|
#ifdef Q_OS_WIN
|
||||||
server,
|
appData.addData(SingleCoreApplication::app_t::applicationFilePath().toLower().toUtf8());
|
||||||
&QLocalServer::newConnection,
|
#else
|
||||||
this,
|
appData.addData(SingleCoreApplication::app_t::applicationFilePath().toUtf8());
|
||||||
&SingleCoreApplicationPrivate::slotConnectionEstablished
|
|
||||||
);
|
|
||||||
|
|
||||||
// Reset the number of connections
|
|
||||||
InstancesInfo* inst = static_cast <InstancesInfo*>( memory->data() );
|
|
||||||
|
|
||||||
inst->primary = true;
|
|
||||||
inst->primaryPid = q->applicationPid();
|
|
||||||
inst->checksum = blockChecksum();
|
|
||||||
|
|
||||||
instanceNumber = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::startSecondary()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::connectToPrimary( int msecs, ConnectionType connectionType )
|
|
||||||
{
|
|
||||||
// Connect to the Local Server of the Primary Instance if not already
|
|
||||||
// connected.
|
|
||||||
if( socket == nullptr ) {
|
|
||||||
socket = new QLocalSocket();
|
|
||||||
}
|
|
||||||
|
|
||||||
// If already connected - we are done;
|
|
||||||
if( socket->state() == QLocalSocket::ConnectedState )
|
|
||||||
return;
|
|
||||||
|
|
||||||
// If not connect
|
|
||||||
if( socket->state() == QLocalSocket::UnconnectedState ||
|
|
||||||
socket->state() == QLocalSocket::ClosingState ) {
|
|
||||||
socket->connectToServer( blockServerName );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for being connected
|
|
||||||
if( socket->state() == QLocalSocket::ConnectingState ) {
|
|
||||||
socket->waitForConnected( msecs );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Initialisation message according to the SingleCoreApplication protocol
|
|
||||||
if( socket->state() == QLocalSocket::ConnectedState ) {
|
|
||||||
// Notify the parent that a new instance had been started;
|
|
||||||
QByteArray initMsg;
|
|
||||||
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
|
||||||
writeStream.setVersion(QDataStream::Qt_5_6);
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
writeStream << blockServerName.toLatin1();
|
// User level block requires a user specific data in the hash
|
||||||
writeStream << static_cast<quint8>(connectionType);
|
if (options & SingleCoreApplication::Mode::User) {
|
||||||
writeStream << instanceNumber;
|
#ifdef Q_OS_UNIX
|
||||||
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
QByteArray username;
|
||||||
writeStream << checksum;
|
#if defined(HAVE_GETEUID) && defined(HAVE_GETPWUID)
|
||||||
|
struct passwd *pw = getpwuid(geteuid());
|
||||||
// The header indicates the message length that follows
|
if (pw) {
|
||||||
QByteArray header;
|
username = pw->pw_name;
|
||||||
QDataStream headerStream(&header, QIODevice::WriteOnly);
|
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
|
||||||
headerStream.setVersion(QDataStream::Qt_5_6);
|
|
||||||
#endif
|
|
||||||
headerStream << static_cast <quint64>( initMsg.length() );
|
|
||||||
|
|
||||||
socket->write( header );
|
|
||||||
socket->write( initMsg );
|
|
||||||
socket->flush();
|
|
||||||
socket->waitForBytesWritten( msecs );
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
if (username.isEmpty()) username = qgetenv("USER");
|
||||||
|
appData.addData(username);
|
||||||
|
#endif
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
wchar_t username [ UNLEN + 1 ];
|
||||||
|
// Specifies size of the buffer on input
|
||||||
|
DWORD usernameLength = UNLEN + 1;
|
||||||
|
if (GetUserNameW(username, &usernameLength)) {
|
||||||
|
appData.addData(QString::fromWCharArray(username).toUtf8());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
appData.addData(qgetenv("USERNAME"));
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// Replace the backslash in RFC 2045 Base64 [a-zA-Z0-9+/=] to comply with server naming requirements.
|
||||||
|
blockServerName = appData.result().toBase64().replace("/", "_");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
quint16 SingleCoreApplicationPrivate::blockChecksum()
|
void SingleCoreApplicationPrivate::initializeMemoryBlock() {
|
||||||
{
|
|
||||||
return qChecksum(
|
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
static_cast <const char *>( memory->data() ),
|
inst->primary = false;
|
||||||
offsetof( InstancesInfo, checksum )
|
inst->secondary = 0;
|
||||||
);
|
inst->primaryPid = -1;
|
||||||
|
inst->checksum = blockChecksum();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
qint64 SingleCoreApplicationPrivate::primaryPid()
|
void SingleCoreApplicationPrivate::startPrimary() {
|
||||||
{
|
|
||||||
qint64 pid;
|
|
||||||
|
|
||||||
memory->lock();
|
Q_Q(SingleCoreApplication);
|
||||||
InstancesInfo* inst = static_cast<InstancesInfo*>( memory->data() );
|
|
||||||
pid = inst->primaryPid;
|
// Successful creation means that no main process exists
|
||||||
memory->unlock();
|
// So we start a QLocalServer to listen for connections
|
||||||
|
QLocalServer::removeServer(blockServerName);
|
||||||
|
server = new QLocalServer();
|
||||||
|
|
||||||
|
// Restrict access to the socket according to the
|
||||||
|
// SingleCoreApplication::Mode::User flag on User level or no restrictions
|
||||||
|
if (options & SingleCoreApplication::Mode::User) {
|
||||||
|
server->setSocketOptions(QLocalServer::UserAccessOption);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
server->setSocketOptions(QLocalServer::WorldAccessOption);
|
||||||
|
}
|
||||||
|
|
||||||
|
server->listen(blockServerName);
|
||||||
|
QObject::connect(server, &QLocalServer::newConnection, this, &SingleCoreApplicationPrivate::slotConnectionEstablished);
|
||||||
|
|
||||||
|
// Reset the number of connections
|
||||||
|
InstancesInfo* inst = static_cast <InstancesInfo*>(memory->data());
|
||||||
|
|
||||||
|
inst->primary = true;
|
||||||
|
inst->primaryPid = q->applicationPid();
|
||||||
|
inst->checksum = blockChecksum();
|
||||||
|
|
||||||
|
instanceNumber = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void SingleCoreApplicationPrivate::startSecondary() {}
|
||||||
|
|
||||||
|
void SingleCoreApplicationPrivate::connectToPrimary(const int msecs, const ConnectionType connectionType) {
|
||||||
|
|
||||||
|
// Connect to the Local Server of the Primary Instance if not already connected.
|
||||||
|
if (socket == nullptr) {
|
||||||
|
socket = new QLocalSocket();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If already connected - we are done;
|
||||||
|
if (socket->state() == QLocalSocket::ConnectedState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// If not connect
|
||||||
|
if (socket->state() == QLocalSocket::UnconnectedState ||
|
||||||
|
socket->state() == QLocalSocket::ClosingState) {
|
||||||
|
socket->connectToServer(blockServerName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wait for being connected
|
||||||
|
if (socket->state() == QLocalSocket::ConnectingState) {
|
||||||
|
socket->waitForConnected(msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Initialisation message according to the SingleCoreApplication protocol
|
||||||
|
if (socket->state() == QLocalSocket::ConnectedState) {
|
||||||
|
// Notify the parent that a new instance had been started;
|
||||||
|
QByteArray initMsg;
|
||||||
|
QDataStream writeStream(&initMsg, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
writeStream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
|
||||||
|
writeStream << blockServerName.toLatin1();
|
||||||
|
writeStream << static_cast<quint8>(connectionType);
|
||||||
|
writeStream << instanceNumber;
|
||||||
|
quint16 checksum = qChecksum(initMsg.constData(), static_cast<quint32>(initMsg.length()));
|
||||||
|
writeStream << checksum;
|
||||||
|
|
||||||
|
// The header indicates the message length that follows
|
||||||
|
QByteArray header;
|
||||||
|
QDataStream headerStream(&header, QIODevice::WriteOnly);
|
||||||
|
|
||||||
|
headerStream.setVersion(QDataStream::Qt_5_6);
|
||||||
|
|
||||||
|
headerStream << static_cast <quint64>(initMsg.length());
|
||||||
|
|
||||||
|
socket->write(header);
|
||||||
|
socket->write(initMsg);
|
||||||
|
socket->flush();
|
||||||
|
socket->waitForBytesWritten(msecs);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
quint16 SingleCoreApplicationPrivate::blockChecksum() {
|
||||||
|
|
||||||
|
return qChecksum(static_cast <const char*> (memory->data()), offsetof(InstancesInfo, checksum));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
qint64 SingleCoreApplicationPrivate::primaryPid() {
|
||||||
|
|
||||||
|
qint64 pid;
|
||||||
|
|
||||||
|
memory->lock();
|
||||||
|
InstancesInfo* inst = static_cast<InstancesInfo*>(memory->data());
|
||||||
|
pid = inst->primaryPid;
|
||||||
|
memory->unlock();
|
||||||
|
|
||||||
|
return pid;
|
||||||
|
|
||||||
return pid;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Executed when a connection has been made to the LocalServer
|
* @brief Executed when a connection has been made to the LocalServer
|
||||||
*/
|
*/
|
||||||
void SingleCoreApplicationPrivate::slotConnectionEstablished()
|
void SingleCoreApplicationPrivate::slotConnectionEstablished() {
|
||||||
{
|
|
||||||
QLocalSocket *nextConnSocket = server->nextPendingConnection();
|
|
||||||
connectionMap.insert(nextConnSocket, ConnectionInfo());
|
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
|
QLocalSocket *nextConnSocket = server->nextPendingConnection();
|
||||||
[nextConnSocket, this]() {
|
connectionMap.insert(nextConnSocket, ConnectionInfo());
|
||||||
auto &info = connectionMap[nextConnSocket];
|
|
||||||
Q_EMIT this->slotClientConnectionClosed( nextConnSocket, info.instanceId );
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::disconnected,
|
QObject::connect(nextConnSocket, &QLocalSocket::aboutToClose,
|
||||||
[nextConnSocket, this](){
|
[nextConnSocket, this]() {
|
||||||
connectionMap.remove(nextConnSocket);
|
auto &info = connectionMap[nextConnSocket];
|
||||||
nextConnSocket->deleteLater();
|
Q_EMIT this->slotClientConnectionClosed(nextConnSocket, info.instanceId);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QObject::connect(nextConnSocket, &QLocalSocket::disconnected,
|
||||||
|
[nextConnSocket, this](){
|
||||||
|
connectionMap.remove(nextConnSocket);
|
||||||
|
nextConnSocket->deleteLater();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
||||||
|
[nextConnSocket, this]() {
|
||||||
|
auto &info = connectionMap[nextConnSocket];
|
||||||
|
switch(info.stage) {
|
||||||
|
case StageHeader:
|
||||||
|
readInitMessageHeader(nextConnSocket);
|
||||||
|
break;
|
||||||
|
case StageBody:
|
||||||
|
readInitMessageBody(nextConnSocket);
|
||||||
|
break;
|
||||||
|
case StageConnected:
|
||||||
|
Q_EMIT this->slotDataAvailable(nextConnSocket, info.instanceId);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
QObject::connect(nextConnSocket, &QLocalSocket::readyRead,
|
|
||||||
[nextConnSocket, this]() {
|
|
||||||
auto &info = connectionMap[nextConnSocket];
|
|
||||||
switch(info.stage) {
|
|
||||||
case StageHeader:
|
|
||||||
readInitMessageHeader(nextConnSocket);
|
|
||||||
break;
|
|
||||||
case StageBody:
|
|
||||||
readInitMessageBody(nextConnSocket);
|
|
||||||
break;
|
|
||||||
case StageConnected:
|
|
||||||
Q_EMIT this->slotDataAvailable( nextConnSocket, info.instanceId );
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::readInitMessageHeader( QLocalSocket *sock )
|
void SingleCoreApplicationPrivate::readInitMessageHeader(QLocalSocket *sock) {
|
||||||
{
|
|
||||||
if (!connectionMap.contains( sock )) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if( sock->bytesAvailable() < ( qint64 )sizeof( quint64 ) ) {
|
if (!connectionMap.contains(sock)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDataStream headerStream( sock );
|
if (sock->bytesAvailable() < (qint64)sizeof(quint64)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
QDataStream headerStream(sock);
|
||||||
headerStream.setVersion( QDataStream::Qt_5_6 );
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Read the header to know the message length
|
headerStream.setVersion(QDataStream::Qt_5_6);
|
||||||
quint64 msgLen = 0;
|
|
||||||
headerStream >> msgLen;
|
// Read the header to know the message length
|
||||||
ConnectionInfo &info = connectionMap[sock];
|
quint64 msgLen = 0;
|
||||||
info.stage = StageBody;
|
headerStream >> msgLen;
|
||||||
info.msgLen = msgLen;
|
ConnectionInfo &info = connectionMap[sock];
|
||||||
|
info.stage = StageBody;
|
||||||
|
info.msgLen = msgLen;
|
||||||
|
|
||||||
|
if (sock->bytesAvailable() >= (qint64) msgLen) {
|
||||||
|
readInitMessageBody(sock);
|
||||||
|
}
|
||||||
|
|
||||||
if ( sock->bytesAvailable() >= (qint64) msgLen ) {
|
|
||||||
readInitMessageBody( sock );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::readInitMessageBody( QLocalSocket *sock )
|
void SingleCoreApplicationPrivate::readInitMessageBody(QLocalSocket *sock) {
|
||||||
{
|
|
||||||
Q_Q(SingleCoreApplication);
|
|
||||||
|
|
||||||
if (!connectionMap.contains( sock )) {
|
Q_Q(SingleCoreApplication);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ConnectionInfo &info = connectionMap[sock];
|
if (!connectionMap.contains(sock)) {
|
||||||
if( sock->bytesAvailable() < ( qint64 )info.msgLen ) {
|
return;
|
||||||
return;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Read the message body
|
ConnectionInfo &info = connectionMap[sock];
|
||||||
QByteArray msgBytes = sock->read(info.msgLen);
|
if (sock->bytesAvailable() < (qint64)info.msgLen) {
|
||||||
QDataStream readStream(msgBytes);
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
#if (QT_VERSION >= QT_VERSION_CHECK(5, 6, 0))
|
// Read the message body
|
||||||
readStream.setVersion( QDataStream::Qt_5_6 );
|
QByteArray msgBytes = sock->read(info.msgLen);
|
||||||
#endif
|
QDataStream readStream(msgBytes);
|
||||||
|
|
||||||
// server name
|
readStream.setVersion(QDataStream::Qt_5_6);
|
||||||
QByteArray latin1Name;
|
|
||||||
readStream >> latin1Name;
|
|
||||||
|
|
||||||
// connection type
|
// server name
|
||||||
ConnectionType connectionType = InvalidConnection;
|
QByteArray latin1Name;
|
||||||
quint8 connTypeVal = InvalidConnection;
|
readStream >> latin1Name;
|
||||||
readStream >> connTypeVal;
|
|
||||||
connectionType = static_cast <ConnectionType>( connTypeVal );
|
|
||||||
|
|
||||||
// instance id
|
// connection type
|
||||||
quint32 instanceId = 0;
|
ConnectionType connectionType = InvalidConnection;
|
||||||
readStream >> instanceId;
|
quint8 connTypeVal = InvalidConnection;
|
||||||
|
readStream >> connTypeVal;
|
||||||
|
connectionType = static_cast <ConnectionType>(connTypeVal);
|
||||||
|
|
||||||
// checksum
|
// instance id
|
||||||
quint16 msgChecksum = 0;
|
quint32 instanceId = 0;
|
||||||
readStream >> msgChecksum;
|
readStream >> instanceId;
|
||||||
|
|
||||||
const quint16 actualChecksum = qChecksum( msgBytes.constData(), static_cast<quint32>( msgBytes.length() - sizeof( quint16 ) ) );
|
// checksum
|
||||||
|
quint16 msgChecksum = 0;
|
||||||
|
readStream >> msgChecksum;
|
||||||
|
|
||||||
bool isValid = readStream.status() == QDataStream::Ok &&
|
const quint16 actualChecksum = qChecksum(msgBytes.constData(), static_cast<quint32>(msgBytes.length() - sizeof(quint16)));
|
||||||
QLatin1String(latin1Name) == blockServerName &&
|
|
||||||
msgChecksum == actualChecksum;
|
|
||||||
|
|
||||||
if( !isValid ) {
|
bool isValid = readStream.status() == QDataStream::Ok && QLatin1String(latin1Name) == blockServerName && msgChecksum == actualChecksum;
|
||||||
sock->close();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.instanceId = instanceId;
|
if (!isValid) {
|
||||||
info.stage = StageConnected;
|
sock->close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if( connectionType == NewInstance ||
|
info.instanceId = instanceId;
|
||||||
( connectionType == SecondaryInstance &&
|
info.stage = StageConnected;
|
||||||
options & SingleCoreApplication::Mode::SecondaryNotification ) )
|
|
||||||
{
|
if (connectionType == NewInstance || (connectionType == SecondaryInstance && options & SingleCoreApplication::Mode::SecondaryNotification)) {
|
||||||
Q_EMIT q->instanceStarted();
|
Q_EMIT q->instanceStarted();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sock->bytesAvailable() > 0) {
|
||||||
|
Q_EMIT this->slotDataAvailable(sock, instanceId);
|
||||||
|
}
|
||||||
|
|
||||||
if (sock->bytesAvailable() > 0) {
|
|
||||||
Q_EMIT this->slotDataAvailable( sock, instanceId );
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::slotDataAvailable( QLocalSocket *dataSocket, quint32 instanceId )
|
void SingleCoreApplicationPrivate::slotDataAvailable(QLocalSocket *dataSocket, const quint32 instanceId) {
|
||||||
{
|
|
||||||
Q_Q(SingleCoreApplication);
|
Q_Q(SingleCoreApplication);
|
||||||
Q_EMIT q->receivedMessage( instanceId, dataSocket->readAll() );
|
Q_EMIT q->receivedMessage(instanceId, dataSocket->readAll());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SingleCoreApplicationPrivate::slotClientConnectionClosed( QLocalSocket *closedSocket, quint32 instanceId )
|
void SingleCoreApplicationPrivate::slotClientConnectionClosed(QLocalSocket *closedSocket, const quint32 instanceId) {
|
||||||
{
|
|
||||||
if( closedSocket->bytesAvailable() > 0 )
|
if (closedSocket->bytesAvailable() > 0)
|
||||||
Q_EMIT slotDataAvailable( closedSocket, instanceId );
|
Q_EMIT slotDataAvailable(closedSocket, instanceId);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
112
3rdparty/singleapplication/singlecoreapplication_p.h
vendored
112
3rdparty/singleapplication/singlecoreapplication_p.h
vendored
@@ -24,76 +24,82 @@
|
|||||||
// W A R N I N G !!!
|
// W A R N I N G !!!
|
||||||
// -----------------
|
// -----------------
|
||||||
//
|
//
|
||||||
// This file is not part of the SingleCoreApplication API. It is used purely as an
|
// This is a modified version of SingleApplication,
|
||||||
// implementation detail. This header file may change from version to
|
// The original version is at:
|
||||||
// version without notice, or may even be removed.
|
//
|
||||||
|
// https://github.com/itay-grudev/SingleApplication
|
||||||
|
//
|
||||||
//
|
//
|
||||||
|
|
||||||
#ifndef SINGLECOREAPPLICATION_P_H
|
#ifndef SINGLECOREAPPLICATION_P_H
|
||||||
#define SINGLECOREAPPLICATION_P_H
|
#define SINGLECOREAPPLICATION_P_H
|
||||||
|
|
||||||
#include <QtCore/QSharedMemory>
|
#include <QtGlobal>
|
||||||
#include <QtNetwork/QLocalServer>
|
#include <QObject>
|
||||||
#include <QtNetwork/QLocalSocket>
|
#include <QMap>
|
||||||
|
|
||||||
#include "singlecoreapplication.h"
|
#include "singlecoreapplication.h"
|
||||||
|
|
||||||
|
class QLocalServer;
|
||||||
|
class QLocalSocket;
|
||||||
|
class QSharedMemory;
|
||||||
|
|
||||||
struct InstancesInfo {
|
struct InstancesInfo {
|
||||||
bool primary;
|
bool primary;
|
||||||
quint32 secondary;
|
quint32 secondary;
|
||||||
qint64 primaryPid;
|
qint64 primaryPid;
|
||||||
quint16 checksum;
|
quint16 checksum;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ConnectionInfo {
|
struct ConnectionInfo {
|
||||||
explicit ConnectionInfo() :
|
explicit ConnectionInfo() : msgLen(0), instanceId(0), stage(0) {}
|
||||||
msgLen(0), instanceId(0), stage(0) {}
|
qint64 msgLen;
|
||||||
qint64 msgLen;
|
quint32 instanceId;
|
||||||
quint32 instanceId;
|
quint8 stage;
|
||||||
quint8 stage;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class SingleCoreApplicationPrivate : public QObject {
|
class SingleCoreApplicationPrivate : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
enum ConnectionType : quint8 {
|
enum ConnectionType : quint8 {
|
||||||
InvalidConnection = 0,
|
InvalidConnection = 0,
|
||||||
NewInstance = 1,
|
NewInstance = 1,
|
||||||
SecondaryInstance = 2,
|
SecondaryInstance = 2,
|
||||||
Reconnect = 3
|
Reconnect = 3
|
||||||
};
|
};
|
||||||
enum ConnectionStage : quint8 {
|
enum ConnectionStage : quint8 {
|
||||||
StageHeader = 0,
|
StageHeader = 0,
|
||||||
StageBody = 1,
|
StageBody = 1,
|
||||||
StageConnected = 2,
|
StageConnected = 2,
|
||||||
};
|
};
|
||||||
Q_DECLARE_PUBLIC(SingleCoreApplication)
|
Q_DECLARE_PUBLIC(SingleCoreApplication)
|
||||||
|
|
||||||
SingleCoreApplicationPrivate( SingleCoreApplication *q_ptr );
|
SingleCoreApplicationPrivate(SingleCoreApplication *_q_ptr);
|
||||||
~SingleCoreApplicationPrivate();
|
~SingleCoreApplicationPrivate();
|
||||||
|
|
||||||
void genBlockServerName();
|
void genBlockServerName();
|
||||||
void initializeMemoryBlock();
|
void initializeMemoryBlock();
|
||||||
void startPrimary();
|
void startPrimary();
|
||||||
void startSecondary();
|
void startSecondary();
|
||||||
void connectToPrimary(int msecs, ConnectionType connectionType );
|
void connectToPrimary(const int msecs, const ConnectionType connectionType);
|
||||||
quint16 blockChecksum();
|
quint16 blockChecksum();
|
||||||
qint64 primaryPid();
|
qint64 primaryPid();
|
||||||
void readInitMessageHeader(QLocalSocket *socket);
|
void readInitMessageHeader(QLocalSocket *socket);
|
||||||
void readInitMessageBody(QLocalSocket *socket);
|
void readInitMessageBody(QLocalSocket *socket);
|
||||||
|
|
||||||
SingleCoreApplication *q_ptr;
|
SingleCoreApplication *q_ptr;
|
||||||
QSharedMemory *memory;
|
QSharedMemory *memory;
|
||||||
QLocalSocket *socket;
|
QLocalSocket *socket;
|
||||||
QLocalServer *server;
|
QLocalServer *server;
|
||||||
quint32 instanceNumber;
|
quint32 instanceNumber;
|
||||||
QString blockServerName;
|
QString blockServerName;
|
||||||
SingleCoreApplication::Options options;
|
SingleCoreApplication::Options options;
|
||||||
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
QMap<QLocalSocket*, ConnectionInfo> connectionMap;
|
||||||
|
|
||||||
public Q_SLOTS:
|
public slots:
|
||||||
void slotConnectionEstablished();
|
void slotConnectionEstablished();
|
||||||
void slotDataAvailable( QLocalSocket*, quint32 );
|
void slotDataAvailable(QLocalSocket*, const quint32);
|
||||||
void slotClientConnectionClosed( QLocalSocket*, quint32 );
|
void slotClientConnectionClosed(QLocalSocket*, const quint32);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SINGLECOREAPPLICATION_P_H
|
#endif // SINGLECOREAPPLICATION_P_H
|
||||||
|
|||||||
10
3rdparty/taglib/CMakeLists.txt
vendored
10
3rdparty/taglib/CMakeLists.txt
vendored
@@ -1,6 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 2.8.11)
|
cmake_minimum_required(VERSION 3.0)
|
||||||
set(CMAKE_CXX_STANDARD 11)
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-delete-non-virtual-dtor")
|
|
||||||
|
|
||||||
set(TAGLIB_SOVERSION_CURRENT 17)
|
set(TAGLIB_SOVERSION_CURRENT 17)
|
||||||
set(TAGLIB_SOVERSION_REVISION 0)
|
set(TAGLIB_SOVERSION_REVISION 0)
|
||||||
@@ -19,8 +17,13 @@ else()
|
|||||||
add_definitions(-DSYSTEM_BYTEORDER=2)
|
add_definitions(-DSYSTEM_BYTEORDER=2)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
include(ConfigureChecks.cmake)
|
||||||
|
configure_file(config.h.cmake "${CMAKE_CURRENT_BINARY_DIR}/config.h")
|
||||||
configure_file(taglib_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h)
|
configure_file(taglib_config.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/taglib_config.h)
|
||||||
|
|
||||||
|
add_definitions(-DHAVE_CONFIG_H)
|
||||||
|
add_definitions(-DTAGLIB_STATIC)
|
||||||
|
|
||||||
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
set(CMAKE_INCLUDE_CURRENT_DIR ON)
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}/toolkit
|
${CMAKE_CURRENT_SOURCE_DIR}/toolkit
|
||||||
@@ -86,6 +89,7 @@ set(tag_HDRS
|
|||||||
mpeg/xingheader.h
|
mpeg/xingheader.h
|
||||||
mpeg/id3v1/id3v1tag.h
|
mpeg/id3v1/id3v1tag.h
|
||||||
mpeg/id3v1/id3v1genres.h
|
mpeg/id3v1/id3v1genres.h
|
||||||
|
mpeg/id3v2/id3v2.h
|
||||||
mpeg/id3v2/id3v2extendedheader.h
|
mpeg/id3v2/id3v2extendedheader.h
|
||||||
mpeg/id3v2/id3v2frame.h
|
mpeg/id3v2/id3v2frame.h
|
||||||
mpeg/id3v2/id3v2header.h
|
mpeg/id3v2/id3v2header.h
|
||||||
|
|||||||
215
3rdparty/taglib/ConfigureChecks.cmake
vendored
Normal file
215
3rdparty/taglib/ConfigureChecks.cmake
vendored
Normal file
@@ -0,0 +1,215 @@
|
|||||||
|
include(CheckLibraryExists)
|
||||||
|
include(CheckTypeSize)
|
||||||
|
include(CheckCXXSourceCompiles)
|
||||||
|
|
||||||
|
# Check if the size of numeric types are suitable.
|
||||||
|
|
||||||
|
check_type_size("short" SIZEOF_SHORT)
|
||||||
|
if(NOT ${SIZEOF_SHORT} EQUAL 2)
|
||||||
|
message(FATAL_ERROR "TagLib requires that short is 16-bit wide.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_type_size("int" SIZEOF_INT)
|
||||||
|
if(NOT ${SIZEOF_INT} EQUAL 4)
|
||||||
|
message(FATAL_ERROR "TagLib requires that int is 32-bit wide.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_type_size("long long" SIZEOF_LONGLONG)
|
||||||
|
if(NOT ${SIZEOF_LONGLONG} EQUAL 8)
|
||||||
|
message(FATAL_ERROR "TagLib requires that long long is 64-bit wide.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_type_size("wchar_t" SIZEOF_WCHAR_T)
|
||||||
|
if(${SIZEOF_WCHAR_T} LESS 2)
|
||||||
|
message(FATAL_ERROR "TagLib requires that wchar_t is sufficient to store a UTF-16 char.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_type_size("float" SIZEOF_FLOAT)
|
||||||
|
if(NOT ${SIZEOF_FLOAT} EQUAL 4)
|
||||||
|
message(FATAL_ERROR "TagLib requires that float is 32-bit wide.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
check_type_size("double" SIZEOF_DOUBLE)
|
||||||
|
if(NOT ${SIZEOF_DOUBLE} EQUAL 8)
|
||||||
|
message(FATAL_ERROR "TagLib requires that double is 64-bit wide.")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine which kind of atomic operations your compiler supports.
|
||||||
|
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <atomic>
|
||||||
|
int main() {
|
||||||
|
std::atomic_int x(1);
|
||||||
|
++x;
|
||||||
|
--x;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_STD_ATOMIC)
|
||||||
|
|
||||||
|
if(NOT HAVE_STD_ATOMIC)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
int main() {
|
||||||
|
volatile int x;
|
||||||
|
__sync_add_and_fetch(&x, 1);
|
||||||
|
int y = __sync_sub_and_fetch(&x, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_GCC_ATOMIC)
|
||||||
|
|
||||||
|
if(NOT HAVE_GCC_ATOMIC)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <libkern/OSAtomic.h>
|
||||||
|
int main() {
|
||||||
|
volatile int32_t x;
|
||||||
|
OSAtomicIncrement32Barrier(&x);
|
||||||
|
int32_t y = OSAtomicDecrement32Barrier(&x);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_MAC_ATOMIC)
|
||||||
|
|
||||||
|
if(NOT HAVE_MAC_ATOMIC)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <windows.h>
|
||||||
|
int main() {
|
||||||
|
volatile LONG x;
|
||||||
|
InterlockedIncrement(&x);
|
||||||
|
LONG y = InterlockedDecrement(&x);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_WIN_ATOMIC)
|
||||||
|
|
||||||
|
if(NOT HAVE_WIN_ATOMIC)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <ia64intrin.h>
|
||||||
|
int main() {
|
||||||
|
volatile int x;
|
||||||
|
__sync_add_and_fetch(&x, 1);
|
||||||
|
int y = __sync_sub_and_fetch(&x, 1);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_IA64_ATOMIC)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine which kind of byte swap functions your compiler supports.
|
||||||
|
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
int main() {
|
||||||
|
__builtin_bswap16(0);
|
||||||
|
__builtin_bswap32(0);
|
||||||
|
__builtin_bswap64(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_GCC_BYTESWAP)
|
||||||
|
|
||||||
|
if(NOT HAVE_GCC_BYTESWAP)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <byteswap.h>
|
||||||
|
int main() {
|
||||||
|
__bswap_16(0);
|
||||||
|
__bswap_32(0);
|
||||||
|
__bswap_64(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_GLIBC_BYTESWAP)
|
||||||
|
|
||||||
|
if(NOT HAVE_GLIBC_BYTESWAP)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <stdlib.h>
|
||||||
|
int main() {
|
||||||
|
_byteswap_ushort(0);
|
||||||
|
_byteswap_ulong(0);
|
||||||
|
_byteswap_uint64(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_MSC_BYTESWAP)
|
||||||
|
|
||||||
|
if(NOT HAVE_MSC_BYTESWAP)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <libkern/OSByteOrder.h>
|
||||||
|
int main() {
|
||||||
|
OSSwapInt16(0);
|
||||||
|
OSSwapInt32(0);
|
||||||
|
OSSwapInt64(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_MAC_BYTESWAP)
|
||||||
|
|
||||||
|
if(NOT HAVE_MAC_BYTESWAP)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <sys/endian.h>
|
||||||
|
int main() {
|
||||||
|
swap16(0);
|
||||||
|
swap32(0);
|
||||||
|
swap64(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_OPENBSD_BYTESWAP)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine whether your compiler supports some safer version of vsprintf.
|
||||||
|
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
int main() {
|
||||||
|
char buf[20];
|
||||||
|
va_list args;
|
||||||
|
vsnprintf(buf, 20, \"%d\", args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_VSNPRINTF)
|
||||||
|
|
||||||
|
if(NOT HAVE_VSNPRINTF)
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <cstdio>
|
||||||
|
#include <cstdarg>
|
||||||
|
int main() {
|
||||||
|
char buf[20];
|
||||||
|
va_list args;
|
||||||
|
vsprintf_s(buf, \"%d\", args);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_VSPRINTF_S)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine whether your compiler supports ISO _strdup.
|
||||||
|
|
||||||
|
check_cxx_source_compiles("
|
||||||
|
#include <cstring>
|
||||||
|
int main() {
|
||||||
|
_strdup(0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
" HAVE_ISO_STRDUP)
|
||||||
|
|
||||||
|
# Determine whether zlib is installed.
|
||||||
|
|
||||||
|
if(NOT ZLIB_SOURCE)
|
||||||
|
find_package(ZLIB)
|
||||||
|
if(ZLIB_FOUND)
|
||||||
|
set(HAVE_ZLIB 1)
|
||||||
|
else()
|
||||||
|
set(HAVE_ZLIB 0)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Determine whether CppUnit is installed.
|
||||||
|
|
||||||
|
if(BUILD_TESTS AND NOT BUILD_SHARED_LIBS)
|
||||||
|
find_package(CppUnit)
|
||||||
|
if(NOT CppUnit_FOUND)
|
||||||
|
message(STATUS "CppUnit not found, disabling tests.")
|
||||||
|
set(BUILD_TESTS OFF)
|
||||||
|
endif()
|
||||||
|
endif()
|
||||||
|
|
||||||
|
# Detect WinRT mode
|
||||||
|
if(CMAKE_SYSTEM_NAME STREQUAL "WindowsStore")
|
||||||
|
set(PLATFORM WINRT 1)
|
||||||
|
endif()
|
||||||
17
3rdparty/taglib/ape/apefile.cpp
vendored
17
3rdparty/taglib/ape/apefile.cpp
vendored
@@ -44,7 +44,7 @@
|
|||||||
#include "apetag.h"
|
#include "apetag.h"
|
||||||
#include "apefooter.h"
|
#include "apefooter.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -87,12 +87,15 @@ public:
|
|||||||
// static members
|
// static members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
bool APE::File::isSupported(IOStream *stream)
|
bool APE::File::isSupported(IOStream*)
|
||||||
{
|
{
|
||||||
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
|
// An APE file has an ID "MAC " somewhere. An ID3v2 tag may precede.
|
||||||
|
|
||||||
const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
// FIXME:
|
||||||
return (buffer.find("MAC ") >= 0);
|
//const ByteVector buffer = Utils::readHeader(stream, bufferSize(), true);
|
||||||
|
//return (buffer.find("MAC ") >= 0);
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
@@ -100,7 +103,7 @@ bool APE::File::isSupported(IOStream *stream)
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
||||||
TagLib::File(file),
|
Strawberry_TagLib::TagLib::File(file),
|
||||||
d(new FilePrivate())
|
d(new FilePrivate())
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -108,7 +111,7 @@ APE::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
|
APE::File::File(IOStream *stream, bool readProperties, Properties::ReadStyle) :
|
||||||
TagLib::File(stream),
|
Strawberry_TagLib::TagLib::File(stream),
|
||||||
d(new FilePrivate())
|
d(new FilePrivate())
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -120,7 +123,7 @@ APE::File::~File()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagLib::Tag *APE::File::tag() const
|
Strawberry_TagLib::TagLib::Tag *APE::File::tag() const
|
||||||
{
|
{
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|||||||
6
3rdparty/taglib/ape/apefile.h
vendored
6
3rdparty/taglib/ape/apefile.h
vendored
@@ -38,6 +38,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "apeproperties.h"
|
#include "apeproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
class Tag;
|
class Tag;
|
||||||
@@ -65,7 +66,7 @@ namespace TagLib {
|
|||||||
* information specific to APE files.
|
* information specific to APE files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@@ -113,7 +114,7 @@ namespace TagLib {
|
|||||||
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
* Returns the Tag for this file. This will be an APE tag, an ID3v1 tag
|
||||||
* or a combination of the two.
|
* or a combination of the two.
|
||||||
*/
|
*/
|
||||||
virtual TagLib::Tag *tag() const;
|
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
@@ -231,5 +232,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/ape/apefooter.cpp
vendored
2
3rdparty/taglib/ape/apefooter.cpp
vendored
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include "apefooter.h"
|
#include "apefooter.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace APE;
|
using namespace APE;
|
||||||
|
|
||||||
class APE::Footer::FooterPrivate
|
class APE::Footer::FooterPrivate
|
||||||
|
|||||||
2
3rdparty/taglib/ape/apefooter.h
vendored
2
3rdparty/taglib/ape/apefooter.h
vendored
@@ -29,6 +29,7 @@
|
|||||||
#include "tbytevector.h"
|
#include "tbytevector.h"
|
||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace APE {
|
namespace APE {
|
||||||
@@ -169,5 +170,6 @@ namespace TagLib {
|
|||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/ape/apeitem.cpp
vendored
2
3rdparty/taglib/ape/apeitem.cpp
vendored
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "apeitem.h"
|
#include "apeitem.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace APE;
|
using namespace APE;
|
||||||
|
|
||||||
class APE::Item::ItemPrivate
|
class APE::Item::ItemPrivate
|
||||||
|
|||||||
2
3rdparty/taglib/ape/apeitem.h
vendored
2
3rdparty/taglib/ape/apeitem.h
vendored
@@ -30,6 +30,7 @@
|
|||||||
#include "tstring.h"
|
#include "tstring.h"
|
||||||
#include "tstringlist.h"
|
#include "tstringlist.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace APE {
|
namespace APE {
|
||||||
@@ -218,6 +219,7 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
2
3rdparty/taglib/ape/apeproperties.cpp
vendored
2
3rdparty/taglib/ape/apeproperties.cpp
vendored
@@ -36,7 +36,7 @@
|
|||||||
#include "apetag.h"
|
#include "apetag.h"
|
||||||
#include "apefooter.h"
|
#include "apefooter.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class APE::Properties::PropertiesPrivate
|
class APE::Properties::PropertiesPrivate
|
||||||
{
|
{
|
||||||
|
|||||||
6
3rdparty/taglib/ape/apeproperties.h
vendored
6
3rdparty/taglib/ape/apeproperties.h
vendored
@@ -33,6 +33,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace APE {
|
namespace APE {
|
||||||
@@ -55,7 +56,7 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
Properties(File *file, ReadStyle style = Average);
|
TAGLIB_DEPRECATED Properties(File *file, ReadStyle style = Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Create an instance of APE::Properties with the data read from the
|
* Create an instance of APE::Properties with the data read from the
|
||||||
@@ -76,7 +77,7 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
virtual int length() const;
|
TAGLIB_DEPRECATED virtual int length() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
@@ -139,5 +140,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
8
3rdparty/taglib/ape/apetag.cpp
vendored
8
3rdparty/taglib/ape/apetag.cpp
vendored
@@ -42,7 +42,7 @@
|
|||||||
#include "apefooter.h"
|
#include "apefooter.h"
|
||||||
#include "apeitem.h"
|
#include "apeitem.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace APE;
|
using namespace APE;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
@@ -91,13 +91,13 @@ public:
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
APE::Tag::Tag() :
|
APE::Tag::Tag() :
|
||||||
TagLib::Tag(),
|
Strawberry_TagLib::TagLib::Tag(),
|
||||||
d(new TagPrivate())
|
d(new TagPrivate())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
APE::Tag::Tag(TagLib::File *file, long footerLocation) :
|
APE::Tag::Tag(Strawberry_TagLib::TagLib::File *file, long footerLocation) :
|
||||||
TagLib::Tag(),
|
Strawberry_TagLib::TagLib::Tag(),
|
||||||
d(new TagPrivate())
|
d(new TagPrivate())
|
||||||
{
|
{
|
||||||
d->file = file;
|
d->file = file;
|
||||||
|
|||||||
6
3rdparty/taglib/ape/apetag.h
vendored
6
3rdparty/taglib/ape/apetag.h
vendored
@@ -34,6 +34,7 @@
|
|||||||
|
|
||||||
#include "apeitem.h"
|
#include "apeitem.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
class File;
|
class File;
|
||||||
@@ -54,7 +55,7 @@ namespace TagLib {
|
|||||||
|
|
||||||
//! An APE tag implementation
|
//! An APE tag implementation
|
||||||
|
|
||||||
class TAGLIB_EXPORT Tag : public TagLib::Tag
|
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@@ -66,7 +67,7 @@ namespace TagLib {
|
|||||||
* Create an APE tag and parse the data in \a file with APE footer at
|
* Create an APE tag and parse the data in \a file with APE footer at
|
||||||
* \a tagOffset.
|
* \a tagOffset.
|
||||||
*/
|
*/
|
||||||
Tag(TagLib::File *file, long footerLocation);
|
Tag(Strawberry_TagLib::TagLib::File *file, long footerLocation);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Destroys this Tag instance.
|
* Destroys this Tag instance.
|
||||||
@@ -204,5 +205,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
4
3rdparty/taglib/asf/asfattribute.cpp
vendored
4
3rdparty/taglib/asf/asfattribute.cpp
vendored
@@ -31,7 +31,7 @@
|
|||||||
#include "asffile.h"
|
#include "asffile.h"
|
||||||
#include "asfutils.h"
|
#include "asfutils.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Attribute::AttributePrivate : public RefCounter
|
class ASF::Attribute::AttributePrivate : public RefCounter
|
||||||
{
|
{
|
||||||
@@ -264,6 +264,7 @@ int ASF::Attribute::dataSize() const
|
|||||||
case BytesType:
|
case BytesType:
|
||||||
if(d->pictureValue.isValid())
|
if(d->pictureValue.isValid())
|
||||||
return d->pictureValue.dataSize();
|
return d->pictureValue.dataSize();
|
||||||
|
break;
|
||||||
case GuidType:
|
case GuidType:
|
||||||
return d->byteVectorValue.size();
|
return d->byteVectorValue.size();
|
||||||
}
|
}
|
||||||
@@ -305,6 +306,7 @@ ByteVector ASF::Attribute::render(const String &name, int kind) const
|
|||||||
data.append(d->pictureValue.render());
|
data.append(d->pictureValue.render());
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
case GuidType:
|
case GuidType:
|
||||||
data.append(d->byteVectorValue);
|
data.append(d->byteVectorValue);
|
||||||
break;
|
break;
|
||||||
|
|||||||
2
3rdparty/taglib/asf/asfattribute.h
vendored
2
3rdparty/taglib/asf/asfattribute.h
vendored
@@ -31,6 +31,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "asfpicture.h"
|
#include "asfpicture.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib
|
namespace TagLib
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -204,5 +205,6 @@ namespace TagLib
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
8
3rdparty/taglib/asf/asffile.cpp
vendored
8
3rdparty/taglib/asf/asffile.cpp
vendored
@@ -34,7 +34,7 @@
|
|||||||
#include "asfproperties.h"
|
#include "asfproperties.h"
|
||||||
#include "asfutils.h"
|
#include "asfutils.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::File::FilePrivate
|
class ASF::File::FilePrivate
|
||||||
{
|
{
|
||||||
@@ -113,7 +113,7 @@ class ASF::File::FilePrivate::UnknownObject : public ASF::File::FilePrivate::Bas
|
|||||||
{
|
{
|
||||||
ByteVector myGuid;
|
ByteVector myGuid;
|
||||||
public:
|
public:
|
||||||
UnknownObject(const ByteVector &guid);
|
explicit UnknownObject(const ByteVector &guid);
|
||||||
ByteVector guid() const;
|
ByteVector guid() const;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -488,7 +488,7 @@ bool ASF::File::isSupported(IOStream *stream)
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
ASF::File::File(FileName file, bool, Properties::ReadStyle) :
|
ASF::File::File(FileName file, bool, Properties::ReadStyle) :
|
||||||
TagLib::File(file),
|
Strawberry_TagLib::TagLib::File(file),
|
||||||
d(new FilePrivate())
|
d(new FilePrivate())
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -496,7 +496,7 @@ ASF::File::File(FileName file, bool, Properties::ReadStyle) :
|
|||||||
}
|
}
|
||||||
|
|
||||||
ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) :
|
ASF::File::File(IOStream *stream, bool, Properties::ReadStyle) :
|
||||||
TagLib::File(stream),
|
Strawberry_TagLib::TagLib::File(stream),
|
||||||
d(new FilePrivate())
|
d(new FilePrivate())
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
|
|||||||
4
3rdparty/taglib/asf/asffile.h
vendored
4
3rdparty/taglib/asf/asffile.h
vendored
@@ -32,6 +32,7 @@
|
|||||||
#include "asfproperties.h"
|
#include "asfproperties.h"
|
||||||
#include "asftag.h"
|
#include "asftag.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! An implementation of ASF (WMA) metadata
|
//! An implementation of ASF (WMA) metadata
|
||||||
@@ -43,7 +44,7 @@ namespace TagLib {
|
|||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract TagLib::File API as well as providing some additional
|
||||||
* information specific to ASF files.
|
* information specific to ASF files.
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT File : public TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@@ -134,5 +135,6 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/asf/asfpicture.cpp
vendored
2
3rdparty/taglib/asf/asfpicture.cpp
vendored
@@ -32,7 +32,7 @@
|
|||||||
#include "asfpicture.h"
|
#include "asfpicture.h"
|
||||||
#include "asfutils.h"
|
#include "asfutils.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Picture::PicturePrivate : public RefCounter
|
class ASF::Picture::PicturePrivate : public RefCounter
|
||||||
{
|
{
|
||||||
|
|||||||
2
3rdparty/taglib/asf/asfpicture.h
vendored
2
3rdparty/taglib/asf/asfpicture.h
vendored
@@ -31,6 +31,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "attachedpictureframe.h"
|
#include "attachedpictureframe.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib
|
namespace TagLib
|
||||||
{
|
{
|
||||||
namespace ASF
|
namespace ASF
|
||||||
@@ -218,5 +219,6 @@ namespace TagLib
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif // ASFPICTURE_H
|
#endif // ASFPICTURE_H
|
||||||
|
|||||||
2
3rdparty/taglib/asf/asfproperties.cpp
vendored
2
3rdparty/taglib/asf/asfproperties.cpp
vendored
@@ -27,7 +27,7 @@
|
|||||||
#include <tstring.h>
|
#include <tstring.h>
|
||||||
#include "asfproperties.h"
|
#include "asfproperties.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Properties::PropertiesPrivate
|
class ASF::Properties::PropertiesPrivate
|
||||||
{
|
{
|
||||||
|
|||||||
2
3rdparty/taglib/asf/asfproperties.h
vendored
2
3rdparty/taglib/asf/asfproperties.h
vendored
@@ -30,6 +30,7 @@
|
|||||||
#include "tstring.h"
|
#include "tstring.h"
|
||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace ASF {
|
namespace ASF {
|
||||||
@@ -182,5 +183,6 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
6
3rdparty/taglib/asf/asftag.cpp
vendored
6
3rdparty/taglib/asf/asftag.cpp
vendored
@@ -26,7 +26,7 @@
|
|||||||
#include <tpropertymap.h>
|
#include <tpropertymap.h>
|
||||||
#include "asftag.h"
|
#include "asftag.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class ASF::Tag::TagPrivate
|
class ASF::Tag::TagPrivate
|
||||||
{
|
{
|
||||||
@@ -40,7 +40,7 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
ASF::Tag::Tag() :
|
ASF::Tag::Tag() :
|
||||||
TagLib::Tag(),
|
Strawberry_TagLib::TagLib::Tag(),
|
||||||
d(new TagPrivate())
|
d(new TagPrivate())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -204,7 +204,7 @@ void ASF::Tag::addAttribute(const String &name, const Attribute &attribute)
|
|||||||
|
|
||||||
bool ASF::Tag::isEmpty() const
|
bool ASF::Tag::isEmpty() const
|
||||||
{
|
{
|
||||||
return TagLib::Tag::isEmpty() &&
|
return Strawberry_TagLib::TagLib::Tag::isEmpty() &&
|
||||||
copyright().isEmpty() &&
|
copyright().isEmpty() &&
|
||||||
rating().isEmpty() &&
|
rating().isEmpty() &&
|
||||||
d->attributeListMap.isEmpty();
|
d->attributeListMap.isEmpty();
|
||||||
|
|||||||
5
3rdparty/taglib/asf/asftag.h
vendored
5
3rdparty/taglib/asf/asftag.h
vendored
@@ -32,6 +32,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "asfattribute.h"
|
#include "asfattribute.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace ASF {
|
namespace ASF {
|
||||||
@@ -39,7 +40,7 @@ namespace TagLib {
|
|||||||
typedef List<Attribute> AttributeList;
|
typedef List<Attribute> AttributeList;
|
||||||
typedef Map<String, AttributeList> AttributeListMap;
|
typedef Map<String, AttributeList> AttributeListMap;
|
||||||
|
|
||||||
class TAGLIB_EXPORT Tag : public TagLib::Tag {
|
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag {
|
||||||
|
|
||||||
friend class File;
|
friend class File;
|
||||||
|
|
||||||
@@ -160,6 +161,7 @@ namespace TagLib {
|
|||||||
* Returns a reference to the item list map. This is an AttributeListMap of
|
* Returns a reference to the item list map. This is an AttributeListMap of
|
||||||
* all of the items in the tag.
|
* all of the items in the tag.
|
||||||
*/
|
*/
|
||||||
|
// BIC: return by value
|
||||||
const AttributeListMap &attributeListMap() const;
|
const AttributeListMap &attributeListMap() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@@ -206,4 +208,5 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/asf/asfutils.h
vendored
2
3rdparty/taglib/asf/asfutils.h
vendored
@@ -30,6 +30,7 @@
|
|||||||
|
|
||||||
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
#ifndef DO_NOT_DOCUMENT // tell Doxygen not to document this header
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib
|
namespace TagLib
|
||||||
{
|
{
|
||||||
namespace ASF
|
namespace ASF
|
||||||
@@ -98,6 +99,7 @@ namespace TagLib
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
2
3rdparty/taglib/audioproperties.cpp
vendored
2
3rdparty/taglib/audioproperties.cpp
vendored
@@ -43,7 +43,7 @@
|
|||||||
|
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
// This macro is a workaround for the fact that we can't add virtual functions.
|
// This macro is a workaround for the fact that we can't add virtual functions.
|
||||||
// Should be true virtual functions in taglib2.
|
// Should be true virtual functions in taglib2.
|
||||||
|
|||||||
2
3rdparty/taglib/audioproperties.h
vendored
2
3rdparty/taglib/audioproperties.h
vendored
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! A simple, abstract interface to common audio properties
|
//! A simple, abstract interface to common audio properties
|
||||||
@@ -123,5 +124,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
35
3rdparty/taglib/config.h.cmake
vendored
Normal file
35
3rdparty/taglib/config.h.cmake
vendored
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
/* config.h. Generated by cmake from config.h.cmake */
|
||||||
|
|
||||||
|
#ifndef TAGLIB_CONFIG_H
|
||||||
|
#define TAGLIB_CONFIG_H
|
||||||
|
|
||||||
|
/* Defined if your compiler supports some byte swap functions */
|
||||||
|
#cmakedefine HAVE_GCC_BYTESWAP 1
|
||||||
|
#cmakedefine HAVE_GLIBC_BYTESWAP 1
|
||||||
|
#cmakedefine HAVE_MSC_BYTESWAP 1
|
||||||
|
#cmakedefine HAVE_MAC_BYTESWAP 1
|
||||||
|
#cmakedefine HAVE_OPENBSD_BYTESWAP 1
|
||||||
|
|
||||||
|
/* Defined if your compiler supports some atomic operations */
|
||||||
|
#cmakedefine HAVE_STD_ATOMIC 1
|
||||||
|
#cmakedefine HAVE_GCC_ATOMIC 1
|
||||||
|
#cmakedefine HAVE_MAC_ATOMIC 1
|
||||||
|
#cmakedefine HAVE_WIN_ATOMIC 1
|
||||||
|
#cmakedefine HAVE_IA64_ATOMIC 1
|
||||||
|
|
||||||
|
/* Defined if your compiler supports some safer version of vsprintf */
|
||||||
|
#cmakedefine HAVE_VSNPRINTF 1
|
||||||
|
#cmakedefine HAVE_VSPRINTF_S 1
|
||||||
|
|
||||||
|
/* Defined if your compiler supports ISO _strdup */
|
||||||
|
#cmakedefine HAVE_ISO_STRDUP 1
|
||||||
|
|
||||||
|
/* Defined if zlib is installed */
|
||||||
|
#cmakedefine HAVE_ZLIB 1
|
||||||
|
|
||||||
|
/* Indicates whether debug messages are shown even in release mode */
|
||||||
|
#cmakedefine TRACE_IN_RELEASE 1
|
||||||
|
|
||||||
|
#cmakedefine TESTS_DIR "@TESTS_DIR@"
|
||||||
|
|
||||||
|
#endif
|
||||||
4
3rdparty/taglib/dsdiff/dsdiffdiintag.cpp
vendored
4
3rdparty/taglib/dsdiff/dsdiffdiintag.cpp
vendored
@@ -27,7 +27,7 @@
|
|||||||
#include "tstringlist.h"
|
#include "tstringlist.h"
|
||||||
#include "tpropertymap.h"
|
#include "tpropertymap.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace DSDIFF::DIIN;
|
using namespace DSDIFF::DIIN;
|
||||||
|
|
||||||
class DSDIFF::DIIN::Tag::TagPrivate
|
class DSDIFF::DIIN::Tag::TagPrivate
|
||||||
@@ -41,7 +41,7 @@ public:
|
|||||||
String artist;
|
String artist;
|
||||||
};
|
};
|
||||||
|
|
||||||
DSDIFF::DIIN::Tag::Tag() : TagLib::Tag()
|
DSDIFF::DIIN::Tag::Tag() : Strawberry_TagLib::TagLib::Tag()
|
||||||
{
|
{
|
||||||
d = new TagPrivate;
|
d = new TagPrivate;
|
||||||
}
|
}
|
||||||
|
|||||||
4
3rdparty/taglib/dsdiff/dsdiffdiintag.h
vendored
4
3rdparty/taglib/dsdiff/dsdiffdiintag.h
vendored
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "tag.h"
|
#include "tag.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace DSDIFF {
|
namespace DSDIFF {
|
||||||
@@ -39,7 +40,7 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* Only Title and Artist tags are supported
|
* Only Title and Artist tags are supported
|
||||||
*/
|
*/
|
||||||
class TAGLIB_EXPORT Tag : public TagLib::Tag
|
class TAGLIB_EXPORT Tag : public Strawberry_TagLib::TagLib::Tag
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Tag();
|
Tag();
|
||||||
@@ -145,6 +146,7 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
393
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
393
3rdparty/taglib/dsdiff/dsdifffile.cpp
vendored
@@ -33,18 +33,45 @@
|
|||||||
#include "tagunion.h"
|
#include "tagunion.h"
|
||||||
#include "dsdifffile.h"
|
#include "dsdifffile.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
#include <array>
|
||||||
|
|
||||||
struct Chunk64
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
{
|
|
||||||
ByteVector name;
|
|
||||||
unsigned long long offset;
|
|
||||||
unsigned long long size;
|
|
||||||
char padding;
|
|
||||||
};
|
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
struct Chunk64
|
||||||
|
{
|
||||||
|
ByteVector name;
|
||||||
|
unsigned long long offset;
|
||||||
|
unsigned long long size;
|
||||||
|
char padding;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef std::vector<Chunk64> ChunkList;
|
||||||
|
|
||||||
|
int chunkIndex(const ChunkList &chunks, const ByteVector &id)
|
||||||
|
{
|
||||||
|
for (unsigned long int i = 0 ; i < chunks.size() ; i++) {
|
||||||
|
if(chunks[i].name == id)
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isValidChunkID(const ByteVector &name)
|
||||||
|
{
|
||||||
|
if(name.size() != 4)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for (int i = 0 ; i < 4 ; i++) {
|
||||||
|
if (name[i] < 32)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
ID3v2Index = 0,
|
ID3v2Index = 0,
|
||||||
DIINIndex = 1
|
DIINIndex = 1
|
||||||
@@ -59,14 +86,14 @@ class DSDIFF::File::FilePrivate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FilePrivate() :
|
FilePrivate() :
|
||||||
endianness(BigEndian),
|
endianness(BigEndian),
|
||||||
size(0),
|
size(0),
|
||||||
isID3InPropChunk(false),
|
isID3InPropChunk(false),
|
||||||
duplicateID3V2chunkIndex(-1),
|
duplicateID3V2chunkIndex(-1),
|
||||||
properties(0),
|
properties(0),
|
||||||
id3v2TagChunkID("ID3 "),
|
id3v2TagChunkID("ID3 "),
|
||||||
hasID3v2(false),
|
hasID3v2(false),
|
||||||
hasDiin(false)
|
hasDiin(false)
|
||||||
{
|
{
|
||||||
childChunkIndex[ID3v2Index] = -1;
|
childChunkIndex[ID3v2Index] = -1;
|
||||||
childChunkIndex[DIINIndex] = -1;
|
childChunkIndex[DIINIndex] = -1;
|
||||||
@@ -81,12 +108,18 @@ public:
|
|||||||
ByteVector type;
|
ByteVector type;
|
||||||
unsigned long long size;
|
unsigned long long size;
|
||||||
ByteVector format;
|
ByteVector format;
|
||||||
std::vector<Chunk64> chunks;
|
ChunkList chunks;
|
||||||
std::vector<Chunk64> childChunks[2];
|
std::array<ChunkList, 2> childChunks;
|
||||||
int childChunkIndex[2];
|
std::array<int, 2> childChunkIndex;
|
||||||
bool isID3InPropChunk; // Two possibilities can be found: ID3V2 chunk inside PROP chunk or at root level
|
/*
|
||||||
int duplicateID3V2chunkIndex; // 2 ID3 chunks are present. This is then the index of the one in
|
* Two possibilities can be found: ID3V2 chunk inside PROP chunk or at root level
|
||||||
// PROP chunk that will be removed upon next save to remove duplicates.
|
*/
|
||||||
|
bool isID3InPropChunk;
|
||||||
|
/*
|
||||||
|
* ID3 chunks are present. This is then the index of the one in PROP chunk that
|
||||||
|
* will be removed upon next save to remove duplicates.
|
||||||
|
*/
|
||||||
|
int duplicateID3V2chunkIndex;
|
||||||
|
|
||||||
Properties *properties;
|
Properties *properties;
|
||||||
|
|
||||||
@@ -115,7 +148,7 @@ bool DSDIFF::File::isSupported(IOStream *stream)
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DSDIFF::File::File(FileName file, bool readProperties,
|
DSDIFF::File::File(FileName file, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) : TagLib::File(file)
|
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(file)
|
||||||
{
|
{
|
||||||
d = new FilePrivate;
|
d = new FilePrivate;
|
||||||
d->endianness = BigEndian;
|
d->endianness = BigEndian;
|
||||||
@@ -124,7 +157,7 @@ DSDIFF::File::File(FileName file, bool readProperties,
|
|||||||
}
|
}
|
||||||
|
|
||||||
DSDIFF::File::File(IOStream *stream, bool readProperties,
|
DSDIFF::File::File(IOStream *stream, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) : TagLib::File(stream)
|
Properties::ReadStyle propertiesStyle) : Strawberry_TagLib::TagLib::File(stream)
|
||||||
{
|
{
|
||||||
d = new FilePrivate;
|
d = new FilePrivate;
|
||||||
d->endianness = BigEndian;
|
d->endianness = BigEndian;
|
||||||
@@ -137,14 +170,14 @@ DSDIFF::File::~File()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagLib::Tag *DSDIFF::File::tag() const
|
Strawberry_TagLib::TagLib::Tag *DSDIFF::File::tag() const
|
||||||
{
|
{
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|
||||||
ID3v2::Tag *DSDIFF::File::ID3v2Tag() const
|
ID3v2::Tag *DSDIFF::File::ID3v2Tag(bool create) const
|
||||||
{
|
{
|
||||||
return d->tag.access<ID3v2::Tag>(ID3v2Index, false);
|
return d->tag.access<ID3v2::Tag>(ID3v2Index, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSDIFF::File::hasID3v2Tag() const
|
bool DSDIFF::File::hasID3v2Tag() const
|
||||||
@@ -152,9 +185,9 @@ bool DSDIFF::File::hasID3v2Tag() const
|
|||||||
return d->hasID3v2;
|
return d->hasID3v2;
|
||||||
}
|
}
|
||||||
|
|
||||||
DSDIFF::DIIN::Tag *DSDIFF::File::DIINTag() const
|
DSDIFF::DIIN::Tag *DSDIFF::File::DIINTag(bool create) const
|
||||||
{
|
{
|
||||||
return d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
|
return d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSDIFF::File::hasDIINTag() const
|
bool DSDIFF::File::hasDIINTag() const
|
||||||
@@ -190,6 +223,11 @@ DSDIFF::Properties *DSDIFF::File::audioProperties() const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool DSDIFF::File::save()
|
bool DSDIFF::File::save()
|
||||||
|
{
|
||||||
|
return save(AllTags);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DSDIFF::File::save(TagTypes tags, StripTags, ID3v2::Version version)
|
||||||
{
|
{
|
||||||
if(readOnly()) {
|
if(readOnly()) {
|
||||||
debug("DSDIFF::File::save() -- File is read only.");
|
debug("DSDIFF::File::save() -- File is read only.");
|
||||||
@@ -201,36 +239,44 @@ bool DSDIFF::File::save()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if(strip == StripOthers || strip == StripAll)
|
||||||
|
//File::strip(static_cast<TagTypes>(AllTags & ~tags));
|
||||||
|
|
||||||
// First: save ID3V2 chunk
|
// First: save ID3V2 chunk
|
||||||
|
|
||||||
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
|
ID3v2::Tag *id3v2Tag = d->tag.access<ID3v2::Tag>(ID3v2Index, false);
|
||||||
if(d->isID3InPropChunk) {
|
|
||||||
if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
|
if(tags & ID3v2 && id3v2Tag) {
|
||||||
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(), PROPChunk);
|
if(d->isID3InPropChunk) {
|
||||||
d->hasID3v2 = true;
|
if(id3v2Tag && !id3v2Tag->isEmpty()) {
|
||||||
|
setChildChunkData(d->id3v2TagChunkID, id3v2Tag->render(version), PROPChunk);
|
||||||
|
d->hasID3v2 = true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Empty tag: remove it
|
||||||
|
setChildChunkData(d->id3v2TagChunkID, ByteVector(), PROPChunk);
|
||||||
|
d->hasID3v2 = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Empty tag: remove it
|
if(id3v2Tag && !id3v2Tag->isEmpty()) {
|
||||||
setChildChunkData(d->id3v2TagChunkID, ByteVector(), PROPChunk);
|
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render(version));
|
||||||
d->hasID3v2 = false;
|
d->hasID3v2 = true;
|
||||||
}
|
}
|
||||||
}
|
else {
|
||||||
else {
|
// Empty tag: remove it
|
||||||
if(id3v2Tag != NULL && !id3v2Tag->isEmpty()) {
|
setRootChunkData(d->id3v2TagChunkID, ByteVector());
|
||||||
setRootChunkData(d->id3v2TagChunkID, id3v2Tag->render());
|
d->hasID3v2 = false;
|
||||||
d->hasID3v2 = true;
|
}
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Empty tag: remove it
|
|
||||||
setRootChunkData(d->id3v2TagChunkID, ByteVector());
|
|
||||||
d->hasID3v2 = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second: save the DIIN chunk
|
// Second: save the DIIN chunk
|
||||||
if(d->hasDiin) {
|
|
||||||
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
|
|
||||||
|
|
||||||
if(!diinTag->title().isNull() && !diinTag->title().isEmpty()) {
|
DSDIFF::DIIN::Tag *diinTag = d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, false);
|
||||||
|
|
||||||
|
if(tags & DIIN && diinTag) {
|
||||||
|
if(!diinTag->title().isEmpty()) {
|
||||||
ByteVector diinTitle;
|
ByteVector diinTitle;
|
||||||
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
|
diinTitle.append(ByteVector::fromUInt(diinTag->title().size(), d->endianness == BigEndian));
|
||||||
diinTitle.append(ByteVector::fromCString(diinTag->title().toCString()));
|
diinTitle.append(ByteVector::fromCString(diinTag->title().toCString()));
|
||||||
@@ -239,7 +285,7 @@ bool DSDIFF::File::save()
|
|||||||
else
|
else
|
||||||
setChildChunkData("DITI", ByteVector(), DIINChunk);
|
setChildChunkData("DITI", ByteVector(), DIINChunk);
|
||||||
|
|
||||||
if(!diinTag->artist().isNull() && !diinTag->artist().isEmpty()) {
|
if(!diinTag->artist().isEmpty()) {
|
||||||
ByteVector diinArtist;
|
ByteVector diinArtist;
|
||||||
diinArtist.append(ByteVector::fromUInt(diinTag->artist().size(), d->endianness == BigEndian));
|
diinArtist.append(ByteVector::fromUInt(diinTag->artist().size(), d->endianness == BigEndian));
|
||||||
diinArtist.append(ByteVector::fromCString(diinTag->artist().toCString()));
|
diinArtist.append(ByteVector::fromCString(diinTag->artist().toCString()));
|
||||||
@@ -258,46 +304,80 @@ bool DSDIFF::File::save()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DSDIFF::File::strip(TagTypes tags)
|
||||||
|
{
|
||||||
|
if(tags & ID3v2) {
|
||||||
|
removeRootChunk("ID3 ");
|
||||||
|
removeRootChunk("id3 ");
|
||||||
|
d->hasID3v2 = false;
|
||||||
|
d->tag.set(ID3v2Index, new ID3v2::Tag);
|
||||||
|
|
||||||
|
/// TODO: needs to also account for ID3v2 tags under the PROP chunk
|
||||||
|
}
|
||||||
|
if(tags & DIIN) {
|
||||||
|
removeRootChunk("DITI");
|
||||||
|
removeRootChunk("DIAR");
|
||||||
|
d->hasDiin = false;
|
||||||
|
d->tag.set(DIINIndex, new DIIN::Tag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
// private members
|
// private members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
|
void DSDIFF::File::removeRootChunk(unsigned int i)
|
||||||
{
|
{
|
||||||
if(data.isNull() || data.isEmpty()) {
|
unsigned long long chunkSize = d->chunks[i].size + d->chunks[i].padding + 12;
|
||||||
// Null data: remove chunk
|
|
||||||
// Update global size
|
d->size -= chunkSize;
|
||||||
unsigned long long removedChunkTotalSize = d->chunks[i].size + d->chunks[i].padding + 12;
|
|
||||||
d->size -= removedChunkTotalSize;
|
|
||||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||||
|
|
||||||
removeBlock(d->chunks[i].offset - 12, removedChunkTotalSize);
|
removeBlock(d->chunks[i].offset - 12, chunkSize);
|
||||||
|
|
||||||
// Update the internal offsets
|
// Update the internal offsets
|
||||||
|
|
||||||
for(unsigned long r = i + 1; r < d->chunks.size(); r++)
|
for(unsigned long r = i + 1; r < d->chunks.size(); r++)
|
||||||
d->chunks[r].offset = d->chunks[r - 1].offset + 12
|
d->chunks[r].offset = d->chunks[r - 1].offset + 12
|
||||||
+ d->chunks[r - 1].size + d->chunks[r - 1].padding;
|
+ d->chunks[r - 1].size + d->chunks[r - 1].padding;
|
||||||
|
|
||||||
d->chunks.erase(d->chunks.begin() + i);
|
d->chunks.erase(d->chunks.begin() + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSDIFF::File::removeRootChunk(const ByteVector &id)
|
||||||
|
{
|
||||||
|
int i = chunkIndex(d->chunks, id);
|
||||||
|
|
||||||
|
if(i >= 0)
|
||||||
|
removeRootChunk(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSDIFF::File::setRootChunkData(unsigned int i, const ByteVector &data)
|
||||||
|
{
|
||||||
|
if(data.isEmpty()) {
|
||||||
|
removeRootChunk(i);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Non null data: update chunk
|
|
||||||
// First we update the global size
|
|
||||||
d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding);
|
|
||||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
|
||||||
|
|
||||||
// Now update the specific chunk
|
// Non null data: update chunk
|
||||||
writeChunk(d->chunks[i].name,
|
// First we update the global size
|
||||||
data,
|
|
||||||
d->chunks[i].offset - 12,
|
|
||||||
d->chunks[i].size + d->chunks[i].padding + 12);
|
|
||||||
|
|
||||||
d->chunks[i].size = data.size();
|
d->size += ((data.size() + 1) & ~1) - (d->chunks[i].size + d->chunks[i].padding);
|
||||||
d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||||
|
|
||||||
// Finally update the internal offsets
|
// Now update the specific chunk
|
||||||
updateRootChunksStructure(i + 1);
|
|
||||||
}
|
writeChunk(d->chunks[i].name,
|
||||||
|
data,
|
||||||
|
d->chunks[i].offset - 12,
|
||||||
|
d->chunks[i].size + d->chunks[i].padding + 12);
|
||||||
|
|
||||||
|
d->chunks[i].size = data.size();
|
||||||
|
d->chunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
||||||
|
|
||||||
|
// Finally update the internal offsets
|
||||||
|
|
||||||
|
updateRootChunksStructure(i + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data)
|
void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &data)
|
||||||
@@ -307,15 +387,15 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
for(unsigned int i = 0; i < d->chunks.size(); i++) {
|
int i = chunkIndex(d->chunks, name);
|
||||||
if(d->chunks[i].name == name) {
|
|
||||||
setRootChunkData(i, data);
|
if(i >= 0) {
|
||||||
return;
|
setRootChunkData(i, data);
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Couldn't find an existing chunk, so let's create a new one.
|
// Couldn't find an existing chunk, so let's create a new one.
|
||||||
unsigned int i = d->chunks.size() - 1;
|
i = d->chunks.size() - 1;
|
||||||
unsigned long offset = d->chunks[i].offset + d->chunks[i].size + d->chunks[i].padding;
|
unsigned long offset = d->chunks[i].offset + d->chunks[i].size + d->chunks[i].padding;
|
||||||
|
|
||||||
// First we update the global size
|
// First we update the global size
|
||||||
@@ -338,28 +418,29 @@ void DSDIFF::File::setRootChunkData(const ByteVector &name, const ByteVector &da
|
|||||||
d->chunks.push_back(chunk);
|
d->chunks.push_back(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::setChildChunkData(unsigned int i,
|
void DSDIFF::File::removeChildChunk(unsigned int i, unsigned int childChunkNum)
|
||||||
const ByteVector &data,
|
|
||||||
unsigned int childChunkNum)
|
|
||||||
{
|
{
|
||||||
std::vector<Chunk64> &childChunks = d->childChunks[childChunkNum];
|
ChunkList &childChunks = d->childChunks[childChunkNum];
|
||||||
|
|
||||||
if(data.isNull() || data.isEmpty()) {
|
|
||||||
// Null data: remove chunk
|
|
||||||
// Update global size
|
// Update global size
|
||||||
|
|
||||||
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
|
unsigned long long removedChunkTotalSize = childChunks[i].size + childChunks[i].padding + 12;
|
||||||
d->size -= removedChunkTotalSize;
|
d->size -= removedChunkTotalSize;
|
||||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||||
|
|
||||||
// Update child chunk size
|
// Update child chunk size
|
||||||
|
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize;
|
d->chunks[d->childChunkIndex[childChunkNum]].size -= removedChunkTotalSize;
|
||||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||||
d->endianness == BigEndian),
|
d->endianness == BigEndian),
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||||
// Remove the chunk
|
// Remove the chunk
|
||||||
|
|
||||||
removeBlock(childChunks[i].offset - 12, removedChunkTotalSize);
|
removeBlock(childChunks[i].offset - 12, removedChunkTotalSize);
|
||||||
|
|
||||||
// Update the internal offsets
|
// Update the internal offsets
|
||||||
// For child chunks
|
// For child chunks
|
||||||
|
|
||||||
if((i + 1) < childChunks.size()) {
|
if((i + 1) < childChunks.size()) {
|
||||||
childChunks[i + 1].offset = childChunks[i].offset;
|
childChunks[i + 1].offset = childChunks[i].offset;
|
||||||
i++;
|
i++;
|
||||||
@@ -369,49 +450,65 @@ void DSDIFF::File::setChildChunkData(unsigned int i,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// And for root chunks
|
// And for root chunks
|
||||||
|
|
||||||
for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
|
for(i = d->childChunkIndex[childChunkNum] + 1; i < d->chunks.size(); i++)
|
||||||
d->chunks[i].offset = d->chunks[i - 1].offset + 12
|
d->chunks[i].offset = d->chunks[i - 1].offset + 12
|
||||||
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
||||||
|
|
||||||
childChunks.erase(childChunks.begin() + i);
|
childChunks.erase(childChunks.begin() + i);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DSDIFF::File::setChildChunkData(unsigned int i,
|
||||||
|
const ByteVector &data,
|
||||||
|
unsigned int childChunkNum)
|
||||||
|
{
|
||||||
|
ChunkList &childChunks = d->childChunks[childChunkNum];
|
||||||
|
|
||||||
|
if(data.isEmpty()) {
|
||||||
|
removeChildChunk(i, childChunkNum);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
// Non null data: update chunk
|
|
||||||
// First we update the global size
|
|
||||||
d->size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
|
|
||||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
|
||||||
// And the PROP chunk size
|
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].size += ((data.size() + 1) & ~1)
|
|
||||||
- (childChunks[i].size + childChunks[i].padding);
|
|
||||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
|
||||||
d->endianness == BigEndian),
|
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
|
||||||
|
|
||||||
// Now update the specific chunk
|
// Non null data: update chunk
|
||||||
writeChunk(childChunks[i].name,
|
// First we update the global size
|
||||||
data,
|
|
||||||
childChunks[i].offset - 12,
|
|
||||||
childChunks[i].size + childChunks[i].padding + 12);
|
|
||||||
|
|
||||||
childChunks[i].size = data.size();
|
d->size += ((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
|
||||||
childChunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
|
||||||
|
|
||||||
// Now update the internal offsets
|
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||||
// For child Chunks
|
|
||||||
for(i++; i < childChunks.size(); i++)
|
|
||||||
childChunks[i].offset = childChunks[i - 1].offset + 12
|
|
||||||
+ childChunks[i - 1].size + childChunks[i - 1].padding;
|
|
||||||
|
|
||||||
// And for root chunks
|
// And the PROP chunk size
|
||||||
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
|
||||||
}
|
d->chunks[d->childChunkIndex[childChunkNum]].size +=
|
||||||
|
((data.size() + 1) & ~1) - (childChunks[i].size + childChunks[i].padding);
|
||||||
|
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||||
|
d->endianness == BigEndian),
|
||||||
|
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||||
|
|
||||||
|
// Now update the specific chunk
|
||||||
|
|
||||||
|
writeChunk(childChunks[i].name,
|
||||||
|
data,
|
||||||
|
childChunks[i].offset - 12,
|
||||||
|
childChunks[i].size + childChunks[i].padding + 12);
|
||||||
|
|
||||||
|
childChunks[i].size = data.size();
|
||||||
|
childChunks[i].padding = (data.size() & 0x01) ? 1 : 0;
|
||||||
|
|
||||||
|
// Now update the internal offsets
|
||||||
|
// For child Chunks
|
||||||
|
for(i++; i < childChunks.size(); i++)
|
||||||
|
childChunks[i].offset = childChunks[i - 1].offset + 12
|
||||||
|
+ childChunks[i - 1].size + childChunks[i - 1].padding;
|
||||||
|
|
||||||
|
// And for root chunks
|
||||||
|
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
||||||
const ByteVector &data,
|
const ByteVector &data,
|
||||||
unsigned int childChunkNum)
|
unsigned int childChunkNum)
|
||||||
{
|
{
|
||||||
std::vector<Chunk64> &childChunks = d->childChunks[childChunkNum];
|
ChunkList &childChunks = d->childChunks[childChunkNum];
|
||||||
|
|
||||||
if(childChunks.size() == 0) {
|
if(childChunks.size() == 0) {
|
||||||
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
debug("DSDIFF::File::setPropChunkData - No valid chunks found.");
|
||||||
@@ -426,17 +523,22 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do not attempt to remove a non existing chunk
|
// Do not attempt to remove a non existing chunk
|
||||||
if(data.isNull() || data.isEmpty())
|
|
||||||
|
if(data.isEmpty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Couldn't find an existing chunk, so let's create a new one.
|
// Couldn't find an existing chunk, so let's create a new one.
|
||||||
|
|
||||||
unsigned int i = childChunks.size() - 1;
|
unsigned int i = childChunks.size() - 1;
|
||||||
unsigned long offset = childChunks[i].offset + childChunks[i].size + childChunks[i].padding;
|
unsigned long offset = childChunks[i].offset + childChunks[i].size + childChunks[i].padding;
|
||||||
|
|
||||||
// First we update the global size
|
// First we update the global size
|
||||||
|
|
||||||
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
|
d->size += (offset & 1) + ((data.size() + 1) & ~1) + 12;
|
||||||
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
insert(ByteVector::fromLongLong(d->size, d->endianness == BigEndian), 4, 8);
|
||||||
|
|
||||||
// And the child chunk size
|
// And the child chunk size
|
||||||
|
|
||||||
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1)
|
d->chunks[d->childChunkIndex[childChunkNum]].size += (offset & 1)
|
||||||
+ ((data.size() + 1) & ~1) + 12;
|
+ ((data.size() + 1) & ~1) + 12;
|
||||||
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
insert(ByteVector::fromLongLong(d->chunks[d->childChunkIndex[childChunkNum]].size,
|
||||||
@@ -444,6 +546,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
|||||||
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
d->chunks[d->childChunkIndex[childChunkNum]].offset - 8, 8);
|
||||||
|
|
||||||
// Now add the chunk to the file
|
// Now add the chunk to the file
|
||||||
|
|
||||||
unsigned long long nextRootChunkIdx = length();
|
unsigned long long nextRootChunkIdx = length();
|
||||||
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
|
if((d->childChunkIndex[childChunkNum] + 1) < static_cast<int>(d->chunks.size()))
|
||||||
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
|
nextRootChunkIdx = d->chunks[d->childChunkIndex[childChunkNum] + 1].offset - 12;
|
||||||
@@ -453,6 +556,7 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
|||||||
(offset & 1) ? 1 : 0);
|
(offset & 1) ? 1 : 0);
|
||||||
|
|
||||||
// For root chunks
|
// For root chunks
|
||||||
|
|
||||||
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
updateRootChunksStructure(d->childChunkIndex[childChunkNum] + 1);
|
||||||
|
|
||||||
Chunk64 chunk;
|
Chunk64 chunk;
|
||||||
@@ -464,19 +568,6 @@ void DSDIFF::File::setChildChunkData(const ByteVector &name,
|
|||||||
childChunks.push_back(chunk);
|
childChunks.push_back(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool isValidChunkID(const ByteVector &name)
|
|
||||||
{
|
|
||||||
if(name.size() != 4)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
for(int i = 0; i < 4; i++) {
|
|
||||||
if(name[i] < 32 || name[i] > 127)
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
|
void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
|
||||||
{
|
{
|
||||||
for(unsigned int i = startingChunk; i < d->chunks.size(); i++)
|
for(unsigned int i = startingChunk; i < d->chunks.size(); i++)
|
||||||
@@ -484,17 +575,19 @@ void DSDIFF::File::updateRootChunksStructure(unsigned int startingChunk)
|
|||||||
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
+ d->chunks[i - 1].size + d->chunks[i - 1].padding;
|
||||||
|
|
||||||
// Update childchunks structure as well
|
// Update childchunks structure as well
|
||||||
|
|
||||||
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
|
if(d->childChunkIndex[PROPChunk] >= static_cast<int>(startingChunk)) {
|
||||||
std::vector<Chunk64> &childChunksToUpdate = d->childChunks[PROPChunk];
|
ChunkList &childChunksToUpdate = d->childChunks[PROPChunk];
|
||||||
if(childChunksToUpdate.size() > 0) {
|
if(childChunksToUpdate.size() > 0) {
|
||||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
|
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[PROPChunk]].offset + 12;
|
||||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||||
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
childChunksToUpdate[i].offset = childChunksToUpdate[i - 1].offset + 12
|
||||||
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
|
+ childChunksToUpdate[i - 1].size + childChunksToUpdate[i - 1].padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
|
if(d->childChunkIndex[DIINChunk] >= static_cast<int>(startingChunk)) {
|
||||||
std::vector<Chunk64> &childChunksToUpdate = d->childChunks[DIINChunk];
|
ChunkList &childChunksToUpdate = d->childChunks[DIINChunk];
|
||||||
if(childChunksToUpdate.size() > 0) {
|
if(childChunksToUpdate.size() > 0) {
|
||||||
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
|
childChunksToUpdate[0].offset = d->chunks[d->childChunkIndex[DIINChunk]].offset + 12;
|
||||||
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
for(unsigned int i = 1; i < childChunksToUpdate.size(); i++)
|
||||||
@@ -513,6 +606,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
d->format = readBlock(4);
|
d->format = readBlock(4);
|
||||||
|
|
||||||
// + 12: chunk header at least, fix for additional junk bytes
|
// + 12: chunk header at least, fix for additional junk bytes
|
||||||
|
|
||||||
while(tell() + 12 <= length()) {
|
while(tell() + 12 <= length()) {
|
||||||
ByteVector chunkName = readBlock(4);
|
ByteVector chunkName = readBlock(4);
|
||||||
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
|
unsigned long long chunkSize = readBlock(8).toLongLong(bigEndian);
|
||||||
@@ -523,7 +617,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(static_cast<unsigned long long>(tell()) + chunkSize > static_cast<unsigned long long>(length())) {
|
if(static_cast<unsigned long long>(tell()) + chunkSize >
|
||||||
|
static_cast<unsigned long long>(length())) {
|
||||||
debug("DSDIFF::File::read() -- Chunk '" + chunkName
|
debug("DSDIFF::File::read() -- Chunk '" + chunkName
|
||||||
+ "' has invalid size (larger than the file size)");
|
+ "' has invalid size (larger than the file size)");
|
||||||
setValid(false);
|
setValid(false);
|
||||||
@@ -538,6 +633,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
seek(chunk.size, Current);
|
seek(chunk.size, Current);
|
||||||
|
|
||||||
// Check padding
|
// Check padding
|
||||||
|
|
||||||
chunk.padding = 0;
|
chunk.padding = 0;
|
||||||
long uPosNotPadded = tell();
|
long uPosNotPadded = tell();
|
||||||
if((uPosNotPadded & 0x01) != 0) {
|
if((uPosNotPadded & 0x01) != 0) {
|
||||||
@@ -551,10 +647,14 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
d->chunks.push_back(chunk);
|
d->chunks.push_back(chunk);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned long long lengthDSDSamplesTimeChannels = 0; // For DSD uncompressed
|
// For DSD uncompressed
|
||||||
unsigned long long audioDataSizeinBytes = 0; // For computing bitrate
|
unsigned long long lengthDSDSamplesTimeChannels = 0;
|
||||||
unsigned long dstNumFrames = 0; // For DST compressed frames
|
// For computing bitrate
|
||||||
unsigned short dstFrameRate = 0; // For DST compressed frames
|
unsigned long long audioDataSizeinBytes = 0;
|
||||||
|
// For DST compressed frames
|
||||||
|
unsigned long dstNumFrames = 0;
|
||||||
|
// For DST compressed frames
|
||||||
|
unsigned short dstFrameRate = 0;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < d->chunks.size(); i++) {
|
for(unsigned int i = 0; i < d->chunks.size(); i++) {
|
||||||
if(d->chunks[i].name == "DSD ") {
|
if(d->chunks[i].name == "DSD ") {
|
||||||
@@ -589,7 +689,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
// Found the DST frame information chunk
|
// Found the DST frame information chunk
|
||||||
dstNumFrames = readBlock(4).toUInt(bigEndian);
|
dstNumFrames = readBlock(4).toUInt(bigEndian);
|
||||||
dstFrameRate = readBlock(2).toUShort(bigEndian);
|
dstFrameRate = readBlock(2).toUShort(bigEndian);
|
||||||
break; // Found the wanted one, no need to look at the others
|
// Found the wanted one, no need to look at the others
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
seek(dstChunkSize, Current);
|
seek(dstChunkSize, Current);
|
||||||
@@ -608,7 +709,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
d->childChunkIndex[PROPChunk] = i;
|
d->childChunkIndex[PROPChunk] = i;
|
||||||
// Now decodes the chunks inside the PROP chunk
|
// Now decodes the chunks inside the PROP chunk
|
||||||
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
long long propChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||||
seek(d->chunks[i].offset + 4); // +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
|
// +4 to remove the 'SND ' marker at beginning of 'PROP' chunk
|
||||||
|
seek(d->chunks[i].offset + 4);
|
||||||
while(tell() + 12 <= propChunkEnd) {
|
while(tell() + 12 <= propChunkEnd) {
|
||||||
ByteVector propChunkName = readBlock(4);
|
ByteVector propChunkName = readBlock(4);
|
||||||
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
|
long long propChunkSize = readBlock(8).toLongLong(bigEndian);
|
||||||
@@ -650,7 +752,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
else if(d->chunks[i].name == "DIIN") {
|
else if(d->chunks[i].name == "DIIN") {
|
||||||
d->childChunkIndex[DIINChunk] = i;
|
d->childChunkIndex[DIINChunk] = i;
|
||||||
d->hasDiin = true;
|
d->hasDiin = true;
|
||||||
|
|
||||||
// Now decode the chunks inside the DIIN chunk
|
// Now decode the chunks inside the DIIN chunk
|
||||||
|
|
||||||
long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
long long diinChunkEnd = d->chunks[i].offset + d->chunks[i].size;
|
||||||
seek(d->chunks[i].offset);
|
seek(d->chunks[i].offset);
|
||||||
|
|
||||||
@@ -679,8 +783,10 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
seek(chunk.size, Current);
|
seek(chunk.size, Current);
|
||||||
|
|
||||||
// Check padding
|
// Check padding
|
||||||
|
|
||||||
chunk.padding = 0;
|
chunk.padding = 0;
|
||||||
long uPosNotPadded = tell();
|
long uPosNotPadded = tell();
|
||||||
|
|
||||||
if((uPosNotPadded & 0x01) != 0) {
|
if((uPosNotPadded & 0x01) != 0) {
|
||||||
ByteVector iByte = readBlock(1);
|
ByteVector iByte = readBlock(1);
|
||||||
if((iByte.size() != 1) || (iByte[0] != 0))
|
if((iByte.size() != 1) || (iByte[0] != 0))
|
||||||
@@ -715,10 +821,12 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
unsigned short channels=0;
|
unsigned short channels=0;
|
||||||
|
|
||||||
for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
|
for(unsigned int i = 0; i < d->childChunks[PROPChunk].size(); i++) {
|
||||||
if(d->childChunks[PROPChunk][i].name == "ID3 " || d->childChunks[PROPChunk][i].name == "id3 ") {
|
if(d->childChunks[PROPChunk][i].name == "ID3 " ||
|
||||||
|
d->childChunks[PROPChunk][i].name == "id3 ") {
|
||||||
if(d->hasID3v2) {
|
if(d->hasID3v2) {
|
||||||
d->duplicateID3V2chunkIndex = i;
|
d->duplicateID3V2chunkIndex = i;
|
||||||
continue; // ID3V2 tag has already been found at root level
|
// ID3V2 tag has already been found at root level
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
d->id3v2TagChunkID = d->childChunks[PROPChunk][i].name;
|
d->id3v2TagChunkID = d->childChunks[PROPChunk][i].name;
|
||||||
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->childChunks[PROPChunk][i].offset));
|
d->tag.set(ID3v2Index, new ID3v2::Tag(this, d->childChunks[PROPChunk][i].offset));
|
||||||
@@ -738,6 +846,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Read title & artist from DIIN chunk
|
// Read title & artist from DIIN chunk
|
||||||
|
|
||||||
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, true);
|
d->tag.access<DSDIFF::DIIN::Tag>(DIINIndex, true);
|
||||||
|
|
||||||
if(d->hasDiin) {
|
if(d->hasDiin) {
|
||||||
@@ -765,8 +874,9 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
if(lengthDSDSamplesTimeChannels == 0) {
|
if(lengthDSDSamplesTimeChannels == 0) {
|
||||||
// DST compressed signal : need to compute length of DSD uncompressed frames
|
// DST compressed signal : need to compute length of DSD uncompressed frames
|
||||||
if(dstFrameRate > 0)
|
if(dstFrameRate > 0)
|
||||||
lengthDSDSamplesTimeChannels = (unsigned long long)dstNumFrames
|
lengthDSDSamplesTimeChannels = (unsigned long long) dstNumFrames *
|
||||||
* (unsigned long long)sampleRate / (unsigned long long)dstFrameRate;
|
(unsigned long long) sampleRate /
|
||||||
|
(unsigned long long) dstFrameRate;
|
||||||
else
|
else
|
||||||
lengthDSDSamplesTimeChannels = 0;
|
lengthDSDSamplesTimeChannels = 0;
|
||||||
}
|
}
|
||||||
@@ -777,7 +887,7 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
}
|
}
|
||||||
int bitrate = 0;
|
int bitrate = 0;
|
||||||
if(lengthDSDSamplesTimeChannels > 0)
|
if(lengthDSDSamplesTimeChannels > 0)
|
||||||
bitrate = (audioDataSizeinBytes*8*sampleRate) / lengthDSDSamplesTimeChannels / 1000;
|
bitrate = (audioDataSizeinBytes * 8 * sampleRate) / lengthDSDSamplesTimeChannels / 1000;
|
||||||
|
|
||||||
d->properties = new Properties(sampleRate,
|
d->properties = new Properties(sampleRate,
|
||||||
channels,
|
channels,
|
||||||
@@ -788,7 +898,8 @@ void DSDIFF::File::read(bool readProperties, Properties::ReadStyle propertiesSty
|
|||||||
|
|
||||||
if(!ID3v2Tag()) {
|
if(!ID3v2Tag()) {
|
||||||
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
|
d->tag.access<ID3v2::Tag>(ID3v2Index, true);
|
||||||
d->isID3InPropChunk = false; // By default, ID3 chunk is at root level
|
// By default, ID3 chunk is at root level
|
||||||
|
d->isID3InPropChunk = false;
|
||||||
d->hasID3v2 = false;
|
d->hasID3v2 = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
58
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
58
3rdparty/taglib/dsdiff/dsdifffile.h
vendored
@@ -31,6 +31,7 @@
|
|||||||
#include "dsdiffproperties.h"
|
#include "dsdiffproperties.h"
|
||||||
#include "dsdiffdiintag.h"
|
#include "dsdiffdiintag.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! An implementation of DSDIFF metadata
|
//! An implementation of DSDIFF metadata
|
||||||
@@ -40,9 +41,9 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
|
* This supports an ID3v2 tag as well as reading stream from the ID3 RIFF
|
||||||
* chunk as well as properties from the file.
|
* chunk as well as properties from the file.
|
||||||
* Description of the DSDIFF format is available
|
* Description of the DSDIFF format is available
|
||||||
* at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf
|
* at http://dsd-guide.com/sites/default/files/white-papers/DSDIFF_1.5_Spec.pdf
|
||||||
* DSDIFF standard does not explictly specify the ID3V2 chunk
|
* DSDIFF standard does not explicitly specify the ID3V2 chunk
|
||||||
* It can be found at the root level, but also sometimes inside the PROP chunk
|
* It can be found at the root level, but also sometimes inside the PROP chunk
|
||||||
* In addition, title and artist info are stored as part of the standard
|
* In addition, title and artist info are stored as part of the standard
|
||||||
*/
|
*/
|
||||||
@@ -58,9 +59,25 @@ namespace TagLib {
|
|||||||
* information specific to DSDIFF files.
|
* information specific to DSDIFF files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This set of flags is used for various operations and is suitable for
|
||||||
|
* being OR-ed together.
|
||||||
|
*/
|
||||||
|
enum TagTypes {
|
||||||
|
//! Empty set. Matches no tag types.
|
||||||
|
NoTags = 0x0000,
|
||||||
|
//! Matches DIIN tags.
|
||||||
|
DIIN = 0x0002,
|
||||||
|
//! Matches ID3v1 tags.
|
||||||
|
ID3v2 = 0x0002,
|
||||||
|
//! Matches all tag types.
|
||||||
|
AllTags = 0xffff
|
||||||
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Constructs an DSDIFF file from \a file. If \a readProperties is true
|
* Constructs an DSDIFF file from \a file. If \a readProperties is true
|
||||||
* the file's audio properties will also be read.
|
* the file's audio properties will also be read.
|
||||||
@@ -114,13 +131,13 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \see hasID3v2Tag()
|
* \see hasID3v2Tag()
|
||||||
*/
|
*/
|
||||||
virtual ID3v2::Tag *ID3v2Tag() const;
|
ID3v2::Tag *ID3v2Tag(bool create = false) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the DSDIFF DIIN Tag for this file
|
* Returns the DSDIFF DIIN Tag for this file
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
DSDIFF::DIIN::Tag *DIINTag() const;
|
DSDIFF::DIIN::Tag *DIINTag(bool create = false) const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
@@ -160,15 +177,21 @@ namespace TagLib {
|
|||||||
virtual bool save();
|
virtual bool save();
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Save the file. This will attempt to save all of the tag types that are
|
* Save the file. If \a strip is specified, it is possible to choose if
|
||||||
* specified by OR-ing together TagTypes values. The save() method above
|
* tags not specified in \a tags should be stripped from the file or
|
||||||
* uses AllTags. This returns true if saving was successful.
|
* retained. With \a version, it is possible to specify whether ID3v2.4
|
||||||
*
|
* or ID3v2.3 should be used.
|
||||||
* This strips all tags not included in the mask, but does not modify them
|
|
||||||
* in memory, so later calls to save() which make use of these tags will
|
|
||||||
* remain valid. This also strips empty tags.
|
|
||||||
*/
|
*/
|
||||||
bool save(int tags);
|
bool save(TagTypes tags, StripTags strip = StripOthers, ID3v2::Version version = ID3v2::v4);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* This will strip the tags that match the OR-ed together TagTypes from the
|
||||||
|
* file. By default it strips all tags. It returns true if the tags are
|
||||||
|
* successfully stripped.
|
||||||
|
*
|
||||||
|
* \note This will update the file immediately.
|
||||||
|
*/
|
||||||
|
void strip(TagTypes tags = AllTags);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
* Returns whether or not the file on disk actually has an ID3v2 tag.
|
||||||
@@ -178,8 +201,8 @@ namespace TagLib {
|
|||||||
bool hasID3v2Tag() const;
|
bool hasID3v2Tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns whether or not the file on disk actually has the DSDIFF
|
* Returns whether or not the file on disk actually has the DSDIFF
|
||||||
* Title & Artist tag.
|
* title and artist tags.
|
||||||
*
|
*
|
||||||
* \see DIINTag()
|
* \see DIINTag()
|
||||||
*/
|
*/
|
||||||
@@ -204,6 +227,10 @@ namespace TagLib {
|
|||||||
File(const File &);
|
File(const File &);
|
||||||
File &operator=(const File &);
|
File &operator=(const File &);
|
||||||
|
|
||||||
|
void removeRootChunk(const ByteVector &id);
|
||||||
|
void removeRootChunk(unsigned int chunk);
|
||||||
|
void removeChildChunk(unsigned int i, unsigned int chunk);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Sets the data for the the specified chunk at root level to \a data.
|
* Sets the data for the the specified chunk at root level to \a data.
|
||||||
*
|
*
|
||||||
@@ -255,6 +282,7 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
2
3rdparty/taglib/dsdiff/dsdiffproperties.cpp
vendored
2
3rdparty/taglib/dsdiff/dsdiffproperties.cpp
vendored
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "dsdiffproperties.h"
|
#include "dsdiffproperties.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class DSDIFF::Properties::PropertiesPrivate
|
class DSDIFF::Properties::PropertiesPrivate
|
||||||
{
|
{
|
||||||
|
|||||||
2
3rdparty/taglib/dsdiff/dsdiffproperties.h
vendored
2
3rdparty/taglib/dsdiff/dsdiffproperties.h
vendored
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace DSDIFF {
|
namespace DSDIFF {
|
||||||
@@ -78,6 +79,7 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
14
3rdparty/taglib/dsf/dsffile.cpp
vendored
14
3rdparty/taglib/dsf/dsffile.cpp
vendored
@@ -32,7 +32,7 @@
|
|||||||
|
|
||||||
#include "dsffile.h"
|
#include "dsffile.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
// The DSF specification is located at http://dsd-guide.com/sites/default/files/white-papers/DSFFileFormatSpec_E.pdf
|
||||||
|
|
||||||
@@ -40,8 +40,10 @@ class DSF::File::FilePrivate
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FilePrivate() :
|
FilePrivate() :
|
||||||
properties(0),
|
fileSize(0),
|
||||||
tag(0)
|
metadataOffset(0),
|
||||||
|
properties(nullptr),
|
||||||
|
tag(nullptr)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,7 +76,7 @@ bool DSF::File::isSupported(IOStream *stream)
|
|||||||
|
|
||||||
DSF::File::File(FileName file, bool readProperties,
|
DSF::File::File(FileName file, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) :
|
Properties::ReadStyle propertiesStyle) :
|
||||||
TagLib::File(file),
|
Strawberry_TagLib::TagLib::File(file),
|
||||||
d(new FilePrivate())
|
d(new FilePrivate())
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -83,7 +85,7 @@ DSF::File::File(FileName file, bool readProperties,
|
|||||||
|
|
||||||
DSF::File::File(IOStream *stream, bool readProperties,
|
DSF::File::File(IOStream *stream, bool readProperties,
|
||||||
Properties::ReadStyle propertiesStyle) :
|
Properties::ReadStyle propertiesStyle) :
|
||||||
TagLib::File(stream),
|
Strawberry_TagLib::TagLib::File(stream),
|
||||||
d(new FilePrivate())
|
d(new FilePrivate())
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -178,7 +180,7 @@ bool DSF::File::save()
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
|
||||||
void DSF::File::read(bool readProperties, Properties::ReadStyle propertiesStyle)
|
void DSF::File::read(bool, Properties::ReadStyle propertiesStyle)
|
||||||
{
|
{
|
||||||
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
|
// A DSF file consists of four chunks: DSD chunk, format chunk, data chunk, and metadata chunk
|
||||||
// The file format is not chunked in the sense of a RIFF File, though
|
// The file format is not chunked in the sense of a RIFF File, though
|
||||||
|
|||||||
14
3rdparty/taglib/dsf/dsffile.h
vendored
14
3rdparty/taglib/dsf/dsffile.h
vendored
@@ -30,6 +30,7 @@
|
|||||||
#include "id3v2tag.h"
|
#include "id3v2tag.h"
|
||||||
#include "dsfproperties.h"
|
#include "dsfproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
//! An implementation of DSF metadata
|
//! An implementation of DSF metadata
|
||||||
@@ -42,20 +43,20 @@ namespace TagLib {
|
|||||||
|
|
||||||
namespace DSF {
|
namespace DSF {
|
||||||
|
|
||||||
//! An implementation of TagLib::File with DSF specific methods
|
//! An implementation of Strawberry_TagLib::TagLib::File with DSF specific methods
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* This implements and provides an interface for DSF files to the
|
* This implements and provides an interface for DSF files to the
|
||||||
* TagLib::Tag and TagLib::AudioProperties interfaces by way of implementing
|
* Strawberry_TagLib::TagLib::Tag and Strawberry_TagLib::TagLib::AudioProperties interfaces by way of implementing
|
||||||
* the abstract TagLib::File API as well as providing some additional
|
* the abstract Strawberry_TagLib::TagLib::File API as well as providing some additional
|
||||||
* information specific to DSF files.
|
* information specific to DSF files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
* Contructs an DSF file from \a file. If \a readProperties is true the
|
* Constructs an DSF file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
* false, \a propertiesStyle is ignored.
|
* false, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
@@ -63,7 +64,7 @@ namespace TagLib {
|
|||||||
Properties::ReadStyle propertiesStyle = Properties::Average);
|
Properties::ReadStyle propertiesStyle = Properties::Average);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Contructs an DSF file from \a file. If \a readProperties is true the
|
* Constructs an DSF file from \a file. If \a readProperties is true the
|
||||||
* file's audio properties will also be read using \a propertiesStyle. If
|
* file's audio properties will also be read using \a propertiesStyle. If
|
||||||
* false, \a propertiesStyle is ignored.
|
* false, \a propertiesStyle is ignored.
|
||||||
*/
|
*/
|
||||||
@@ -123,6 +124,7 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
4
3rdparty/taglib/dsf/dsfproperties.cpp
vendored
4
3rdparty/taglib/dsf/dsfproperties.cpp
vendored
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "dsfproperties.h"
|
#include "dsfproperties.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class DSF::Properties::PropertiesPrivate
|
class DSF::Properties::PropertiesPrivate
|
||||||
{
|
{
|
||||||
@@ -66,7 +66,7 @@ public:
|
|||||||
// public members
|
// public members
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
DSF::Properties::Properties(const ByteVector &data, ReadStyle style) : TagLib::AudioProperties(style)
|
DSF::Properties::Properties(const ByteVector &data, ReadStyle style) : Strawberry_TagLib::TagLib::AudioProperties(style)
|
||||||
{
|
{
|
||||||
d = new PropertiesPrivate;
|
d = new PropertiesPrivate;
|
||||||
read(data);
|
read(data);
|
||||||
|
|||||||
4
3rdparty/taglib/dsf/dsfproperties.h
vendored
4
3rdparty/taglib/dsf/dsfproperties.h
vendored
@@ -28,6 +28,7 @@
|
|||||||
|
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace DSF {
|
namespace DSF {
|
||||||
@@ -41,7 +42,7 @@ namespace TagLib {
|
|||||||
* API.
|
* API.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT Properties : public TagLib::AudioProperties
|
class TAGLIB_EXPORT Properties : public Strawberry_TagLib::TagLib::AudioProperties
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@@ -87,6 +88,7 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
26
3rdparty/taglib/fileref.cpp
vendored
26
3rdparty/taglib/fileref.cpp
vendored
@@ -55,7 +55,7 @@
|
|||||||
#include "dsffile.h"
|
#include "dsffile.h"
|
||||||
#include "dsdifffile.h"
|
#include "dsdifffile.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -74,7 +74,7 @@ namespace
|
|||||||
return file;
|
return file;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect the file type based on the file extension.
|
// Detect the file type based on the file extension.
|
||||||
@@ -98,7 +98,7 @@ namespace
|
|||||||
// that a default file type resolver is created.
|
// that a default file type resolver is created.
|
||||||
|
|
||||||
if(ext.isEmpty())
|
if(ext.isEmpty())
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
|
// .oga can be any audio in the Ogg container. So leave it to content-based detection.
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ namespace
|
|||||||
if(ext == "DSF")
|
if(ext == "DSF")
|
||||||
return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
return new DSF::File(stream, readAudioProperties, audioPropertiesStyle);
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Detect the file type based on the actual content of the stream.
|
// Detect the file type based on the actual content of the stream.
|
||||||
@@ -194,7 +194,7 @@ namespace
|
|||||||
delete file;
|
delete file;
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Internal function that supports FileRef::create().
|
// Internal function that supports FileRef::create().
|
||||||
@@ -220,7 +220,7 @@ namespace
|
|||||||
ext = s.substr(pos + 1).upper();
|
ext = s.substr(pos + 1).upper();
|
||||||
|
|
||||||
if(ext.isEmpty())
|
if(ext.isEmpty())
|
||||||
return 0;
|
return nullptr;
|
||||||
|
|
||||||
if(ext == "MP3")
|
if(ext == "MP3")
|
||||||
return new MPEG::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
return new MPEG::File(fileName, ID3v2::FrameFactory::instance(), readAudioProperties, audioPropertiesStyle);
|
||||||
@@ -228,10 +228,10 @@ namespace
|
|||||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(ext == "OGA") {
|
if(ext == "OGA") {
|
||||||
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
|
/* .oga can be any audio in the Ogg container. First try FLAC, then Vorbis. */
|
||||||
File *file = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
File *file_flac = new Ogg::FLAC::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
if(file->isValid())
|
if (file_flac->isValid())
|
||||||
return file;
|
return file_flac;
|
||||||
delete file;
|
delete file_flac;
|
||||||
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new Ogg::Vorbis::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
}
|
}
|
||||||
if(ext == "FLAC")
|
if(ext == "FLAC")
|
||||||
@@ -270,7 +270,7 @@ namespace
|
|||||||
if(ext == "DSF")
|
if(ext == "DSF")
|
||||||
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
return new DSF::File(fileName, readAudioProperties, audioPropertiesStyle);
|
||||||
|
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -335,7 +335,7 @@ Tag *FileRef::tag() const
|
|||||||
{
|
{
|
||||||
if(isNull()) {
|
if(isNull()) {
|
||||||
debug("FileRef::tag() - Called without a valid file.");
|
debug("FileRef::tag() - Called without a valid file.");
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return d->file->tag();
|
return d->file->tag();
|
||||||
}
|
}
|
||||||
@@ -344,7 +344,7 @@ AudioProperties *FileRef::audioProperties() const
|
|||||||
{
|
{
|
||||||
if(isNull()) {
|
if(isNull()) {
|
||||||
debug("FileRef::audioProperties() - Called without a valid file.");
|
debug("FileRef::audioProperties() - Called without a valid file.");
|
||||||
return 0;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return d->file->audioProperties();
|
return d->file->audioProperties();
|
||||||
}
|
}
|
||||||
|
|||||||
12
3rdparty/taglib/fileref.h
vendored
12
3rdparty/taglib/fileref.h
vendored
@@ -32,6 +32,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
class Tag;
|
class Tag;
|
||||||
@@ -72,10 +73,10 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* class MyFileTypeResolver : FileTypeResolver
|
* class MyFileTypeResolver : FileTypeResolver
|
||||||
* {
|
* {
|
||||||
* TagLib::File *createFile(TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const
|
* Strawberry_TagLib::TagLib::File *createFile(Strawberry_TagLib::TagLib::FileName *fileName, bool, AudioProperties::ReadStyle) const
|
||||||
* {
|
* {
|
||||||
* if(someCheckForAnMP3File(fileName))
|
* if(someCheckForAnMP3File(fileName))
|
||||||
* return new TagLib::MPEG::File(fileName);
|
* return new Strawberry_TagLib::TagLib::MPEG::File(fileName);
|
||||||
* return 0;
|
* return 0;
|
||||||
* }
|
* }
|
||||||
* }
|
* }
|
||||||
@@ -91,8 +92,8 @@ namespace TagLib {
|
|||||||
|
|
||||||
class TAGLIB_EXPORT FileTypeResolver
|
class TAGLIB_EXPORT FileTypeResolver
|
||||||
{
|
{
|
||||||
TAGLIB_IGNORE_MISSING_DESTRUCTOR
|
|
||||||
public:
|
public:
|
||||||
|
virtual ~FileTypeResolver();
|
||||||
/*!
|
/*!
|
||||||
* This method must be overridden to provide an additional file type
|
* This method must be overridden to provide an additional file type
|
||||||
* resolver. If the resolver is able to determine the file type it should
|
* resolver. If the resolver is able to determine the file type it should
|
||||||
@@ -282,6 +283,7 @@ namespace TagLib {
|
|||||||
FileRefPrivate *d;
|
FileRefPrivate *d;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace TagLib
|
}
|
||||||
|
} // namespace Strawberry_TagLib::TagLib
|
||||||
|
|
||||||
#endif
|
#endif // TAGLIB_FILEREF_H
|
||||||
|
|||||||
12
3rdparty/taglib/flac/flacfile.cpp
vendored
12
3rdparty/taglib/flac/flacfile.cpp
vendored
@@ -41,7 +41,7 @@
|
|||||||
#include "flacmetadatablock.h"
|
#include "flacmetadatablock.h"
|
||||||
#include "flacunknownmetadatablock.h"
|
#include "flacunknownmetadatablock.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
@@ -60,7 +60,7 @@ namespace
|
|||||||
class FLAC::File::FilePrivate
|
class FLAC::File::FilePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
|
explicit FilePrivate(const ID3v2::FrameFactory *frameFactory = ID3v2::FrameFactory::instance()) :
|
||||||
ID3v2FrameFactory(frameFactory),
|
ID3v2FrameFactory(frameFactory),
|
||||||
ID3v2Location(-1),
|
ID3v2Location(-1),
|
||||||
ID3v2OriginalSize(0),
|
ID3v2OriginalSize(0),
|
||||||
@@ -112,7 +112,7 @@ bool FLAC::File::isSupported(IOStream *stream)
|
|||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
||||||
TagLib::File(file),
|
Strawberry_TagLib::TagLib::File(file),
|
||||||
d(new FilePrivate())
|
d(new FilePrivate())
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -121,7 +121,7 @@ FLAC::File::File(FileName file, bool readProperties, Properties::ReadStyle) :
|
|||||||
|
|
||||||
FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
|
FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
|
||||||
bool readProperties, Properties::ReadStyle) :
|
bool readProperties, Properties::ReadStyle) :
|
||||||
TagLib::File(file),
|
Strawberry_TagLib::TagLib::File(file),
|
||||||
d(new FilePrivate(frameFactory))
|
d(new FilePrivate(frameFactory))
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -130,7 +130,7 @@ FLAC::File::File(FileName file, ID3v2::FrameFactory *frameFactory,
|
|||||||
|
|
||||||
FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
FLAC::File::File(IOStream *stream, ID3v2::FrameFactory *frameFactory,
|
||||||
bool readProperties, Properties::ReadStyle) :
|
bool readProperties, Properties::ReadStyle) :
|
||||||
TagLib::File(stream),
|
Strawberry_TagLib::TagLib::File(stream),
|
||||||
d(new FilePrivate(frameFactory))
|
d(new FilePrivate(frameFactory))
|
||||||
{
|
{
|
||||||
if(isOpen())
|
if(isOpen())
|
||||||
@@ -142,7 +142,7 @@ FLAC::File::~File()
|
|||||||
delete d;
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
TagLib::Tag *FLAC::File::tag() const
|
Strawberry_TagLib::TagLib::Tag *FLAC::File::tag() const
|
||||||
{
|
{
|
||||||
return &d->tag;
|
return &d->tag;
|
||||||
}
|
}
|
||||||
|
|||||||
12
3rdparty/taglib/flac/flacfile.h
vendored
12
3rdparty/taglib/flac/flacfile.h
vendored
@@ -34,6 +34,7 @@
|
|||||||
#include "flacpicture.h"
|
#include "flacpicture.h"
|
||||||
#include "flacproperties.h"
|
#include "flacproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
class Tag;
|
class Tag;
|
||||||
@@ -63,7 +64,7 @@ namespace TagLib {
|
|||||||
* information specific to FLAC files.
|
* information specific to FLAC files.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public TagLib::File
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::File
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@@ -139,7 +140,7 @@ namespace TagLib {
|
|||||||
* \see ID3v1Tag()
|
* \see ID3v1Tag()
|
||||||
* \see XiphComment()
|
* \see XiphComment()
|
||||||
*/
|
*/
|
||||||
virtual TagLib::Tag *tag() const;
|
virtual Strawberry_TagLib::TagLib::Tag *tag() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Implements the unified property interface -- export function.
|
* Implements the unified property interface -- export function.
|
||||||
@@ -240,7 +241,7 @@ namespace TagLib {
|
|||||||
* \see ID3v2FrameFactory
|
* \see ID3v2FrameFactory
|
||||||
* \deprecated This value should be passed in via the constructor
|
* \deprecated This value should be passed in via the constructor
|
||||||
*/
|
*/
|
||||||
void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
|
TAGLIB_DEPRECATED void setID3v2FrameFactory(const ID3v2::FrameFactory *factory);
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the block of data used by FLAC::Properties for parsing the
|
* Returns the block of data used by FLAC::Properties for parsing the
|
||||||
@@ -248,7 +249,7 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated Always returns an empty vector.
|
* \deprecated Always returns an empty vector.
|
||||||
*/
|
*/
|
||||||
ByteVector streamInfoData(); // BIC: remove
|
TAGLIB_DEPRECATED ByteVector streamInfoData(); // BIC: remove
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the audio-stream, used by FLAC::Properties for
|
* Returns the length of the audio-stream, used by FLAC::Properties for
|
||||||
@@ -256,7 +257,7 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated Always returns zero.
|
* \deprecated Always returns zero.
|
||||||
*/
|
*/
|
||||||
long streamLength(); // BIC: remove
|
TAGLIB_DEPRECATED long streamLength(); // BIC: remove
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns a list of pictures attached to the FLAC file.
|
* Returns a list of pictures attached to the FLAC file.
|
||||||
@@ -339,5 +340,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/flac/flacmetadatablock.cpp
vendored
2
3rdparty/taglib/flac/flacmetadatablock.cpp
vendored
@@ -27,7 +27,7 @@
|
|||||||
#include <tdebug.h>
|
#include <tdebug.h>
|
||||||
#include "flacmetadatablock.h"
|
#include "flacmetadatablock.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::MetadataBlock::MetadataBlockPrivate
|
class FLAC::MetadataBlock::MetadataBlockPrivate
|
||||||
{
|
{
|
||||||
|
|||||||
2
3rdparty/taglib/flac/flacmetadatablock.h
vendored
2
3rdparty/taglib/flac/flacmetadatablock.h
vendored
@@ -30,6 +30,7 @@
|
|||||||
#include "tbytevector.h"
|
#include "tbytevector.h"
|
||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace FLAC {
|
namespace FLAC {
|
||||||
@@ -71,5 +72,6 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/flac/flacpicture.cpp
vendored
2
3rdparty/taglib/flac/flacpicture.cpp
vendored
@@ -27,7 +27,7 @@
|
|||||||
#include <tdebug.h>
|
#include <tdebug.h>
|
||||||
#include "flacpicture.h"
|
#include "flacpicture.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::Picture::PicturePrivate
|
class FLAC::Picture::PicturePrivate
|
||||||
{
|
{
|
||||||
|
|||||||
2
3rdparty/taglib/flac/flacpicture.h
vendored
2
3rdparty/taglib/flac/flacpicture.h
vendored
@@ -32,6 +32,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "flacmetadatablock.h"
|
#include "flacmetadatablock.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace FLAC {
|
namespace FLAC {
|
||||||
@@ -204,5 +205,6 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/flac/flacproperties.cpp
vendored
2
3rdparty/taglib/flac/flacproperties.cpp
vendored
@@ -29,7 +29,7 @@
|
|||||||
#include "flacproperties.h"
|
#include "flacproperties.h"
|
||||||
#include "flacfile.h"
|
#include "flacfile.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::Properties::PropertiesPrivate
|
class FLAC::Properties::PropertiesPrivate
|
||||||
{
|
{
|
||||||
|
|||||||
6
3rdparty/taglib/flac/flacproperties.h
vendored
6
3rdparty/taglib/flac/flacproperties.h
vendored
@@ -29,6 +29,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace FLAC {
|
namespace FLAC {
|
||||||
@@ -72,7 +73,7 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
virtual int length() const;
|
TAGLIB_DEPRECATED virtual int length() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Returns the length of the file in seconds. The length is rounded down to
|
* Returns the length of the file in seconds. The length is rounded down to
|
||||||
@@ -120,7 +121,7 @@ namespace TagLib {
|
|||||||
*
|
*
|
||||||
* \deprecated
|
* \deprecated
|
||||||
*/
|
*/
|
||||||
int sampleWidth() const;
|
TAGLIB_DEPRECATED int sampleWidth() const;
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
* Return the number of sample frames.
|
* Return the number of sample frames.
|
||||||
@@ -144,5 +145,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
#include <tstring.h>
|
#include <tstring.h>
|
||||||
#include "flacunknownmetadatablock.h"
|
#include "flacunknownmetadatablock.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
|
|
||||||
class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate
|
class FLAC::UnknownMetadataBlock::UnknownMetadataBlockPrivate
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -31,6 +31,7 @@
|
|||||||
#include "taglib_export.h"
|
#include "taglib_export.h"
|
||||||
#include "flacmetadatablock.h"
|
#include "flacmetadatablock.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace FLAC {
|
namespace FLAC {
|
||||||
@@ -77,5 +78,6 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
6
3rdparty/taglib/it/itfile.cpp
vendored
6
3rdparty/taglib/it/itfile.cpp
vendored
@@ -30,13 +30,13 @@
|
|||||||
#include "modfileprivate.h"
|
#include "modfileprivate.h"
|
||||||
#include "tpropertymap.h"
|
#include "tpropertymap.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace IT;
|
using namespace IT;
|
||||||
|
|
||||||
class IT::File::FilePrivate
|
class IT::File::FilePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
||||||
: tag(), properties(propertiesStyle)
|
: tag(), properties(propertiesStyle)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -277,7 +277,7 @@ void IT::File::read(bool)
|
|||||||
// in the instrument/sample names and more characters
|
// in the instrument/sample names and more characters
|
||||||
// afterwards. The spec does not mention such a case.
|
// afterwards. The spec does not mention such a case.
|
||||||
// Currently I just discard anything after a nil, but
|
// Currently I just discard anything after a nil, but
|
||||||
// e.g. VLC seems to interprete a nil as a space. I
|
// e.g. VLC seems to interpret a nil as a space. I
|
||||||
// don't know what is the proper behaviour.
|
// don't know what is the proper behaviour.
|
||||||
for(unsigned short i = 0; i < instrumentCount; ++ i) {
|
for(unsigned short i = 0; i < instrumentCount; ++ i) {
|
||||||
seek(192L + length + ((long)i << 2));
|
seek(192L + length + ((long)i << 2));
|
||||||
|
|||||||
2
3rdparty/taglib/it/itfile.h
vendored
2
3rdparty/taglib/it/itfile.h
vendored
@@ -29,6 +29,7 @@
|
|||||||
#include "modtag.h"
|
#include "modtag.h"
|
||||||
#include "itproperties.h"
|
#include "itproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace IT {
|
namespace IT {
|
||||||
@@ -105,5 +106,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
2
3rdparty/taglib/it/itproperties.cpp
vendored
2
3rdparty/taglib/it/itproperties.cpp
vendored
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include "itproperties.h"
|
#include "itproperties.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace IT;
|
using namespace IT;
|
||||||
|
|
||||||
class IT::Properties::PropertiesPrivate
|
class IT::Properties::PropertiesPrivate
|
||||||
|
|||||||
2
3rdparty/taglib/it/itproperties.h
vendored
2
3rdparty/taglib/it/itproperties.h
vendored
@@ -29,6 +29,7 @@
|
|||||||
#include "taglib.h"
|
#include "taglib.h"
|
||||||
#include "audioproperties.h"
|
#include "audioproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
namespace IT {
|
namespace IT {
|
||||||
class TAGLIB_EXPORT Properties : public AudioProperties {
|
class TAGLIB_EXPORT Properties : public AudioProperties {
|
||||||
@@ -103,5 +104,6 @@ namespace TagLib {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
4
3rdparty/taglib/mod/modfile.cpp
vendored
4
3rdparty/taglib/mod/modfile.cpp
vendored
@@ -30,13 +30,13 @@
|
|||||||
#include "modfileprivate.h"
|
#include "modfileprivate.h"
|
||||||
#include "tpropertymap.h"
|
#include "tpropertymap.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace Mod;
|
using namespace Mod;
|
||||||
|
|
||||||
class Mod::File::FilePrivate
|
class Mod::File::FilePrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
explicit FilePrivate(AudioProperties::ReadStyle propertiesStyle)
|
||||||
: properties(propertiesStyle)
|
: properties(propertiesStyle)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|||||||
4
3rdparty/taglib/mod/modfile.h
vendored
4
3rdparty/taglib/mod/modfile.h
vendored
@@ -33,11 +33,12 @@
|
|||||||
#include "modtag.h"
|
#include "modtag.h"
|
||||||
#include "modproperties.h"
|
#include "modproperties.h"
|
||||||
|
|
||||||
|
namespace Strawberry_TagLib {
|
||||||
namespace TagLib {
|
namespace TagLib {
|
||||||
|
|
||||||
namespace Mod {
|
namespace Mod {
|
||||||
|
|
||||||
class TAGLIB_EXPORT File : public TagLib::Mod::FileBase
|
class TAGLIB_EXPORT File : public Strawberry_TagLib::TagLib::Mod::FileBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
/*!
|
/*!
|
||||||
@@ -110,5 +111,6 @@ namespace TagLib {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
14
3rdparty/taglib/mod/modfilebase.cpp
vendored
14
3rdparty/taglib/mod/modfilebase.cpp
vendored
@@ -27,14 +27,14 @@
|
|||||||
#include "tdebug.h"
|
#include "tdebug.h"
|
||||||
#include "modfilebase.h"
|
#include "modfilebase.h"
|
||||||
|
|
||||||
using namespace TagLib;
|
using namespace Strawberry_TagLib::TagLib;
|
||||||
using namespace Mod;
|
using namespace Mod;
|
||||||
|
|
||||||
Mod::FileBase::FileBase(FileName file) : TagLib::File(file)
|
Mod::FileBase::FileBase(FileName file) : Strawberry_TagLib::TagLib::File(file)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
Mod::FileBase::FileBase(IOStream *stream) : TagLib::File(stream)
|
Mod::FileBase::FileBase(IOStream *stream) : Strawberry_TagLib::TagLib::File(stream)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -60,9 +60,9 @@ bool Mod::FileBase::readString(String &s, unsigned long size)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Mod::FileBase::writeByte(unsigned char byte)
|
void Mod::FileBase::writeByte(unsigned char _byte)
|
||||||
{
|
{
|
||||||
ByteVector data(1, byte);
|
ByteVector data(1, _byte);
|
||||||
writeBlock(data);
|
writeBlock(data);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -86,11 +86,11 @@ void Mod::FileBase::writeU32B(unsigned long number)
|
|||||||
writeBlock(ByteVector::fromUInt(number, true));
|
writeBlock(ByteVector::fromUInt(number, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Mod::FileBase::readByte(unsigned char &byte)
|
bool Mod::FileBase::readByte(unsigned char &_byte)
|
||||||
{
|
{
|
||||||
ByteVector data(readBlock(1));
|
ByteVector data(readBlock(1));
|
||||||
if(data.size() < 1) return false;
|
if(data.size() < 1) return false;
|
||||||
byte = data[0];
|
_byte = data[0];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user