mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-05-09 07:08:10 +02:00
Compare commits
1002 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
08d4e319cf | ||
|
|
6c0a9b31f6 | ||
|
|
0ac3cf3c88 | ||
|
|
b9bae7fdcf | ||
|
|
c8462edf4b | ||
|
|
cfe9c7d6ca | ||
|
|
bba43d4433 | ||
|
|
ff7b996596 | ||
|
|
8caea521d7 | ||
|
|
b5d294eab0 | ||
|
|
57770c7e18 | ||
|
|
c94bbb55bc | ||
|
|
c7f2f0dc73 | ||
|
|
4c8093fa72 | ||
|
|
93b940edef | ||
|
|
136fc59765 | ||
|
|
6d3122c1b1 | ||
|
|
7fd3e13a3e | ||
|
|
753eae9302 | ||
|
|
6cee86e509 | ||
|
|
22243d5ce9 | ||
|
|
5b37b9cf99 | ||
|
|
b3257ae425 | ||
|
|
ddab12a5aa | ||
|
|
97c8a0a5ae | ||
|
|
85decefbef | ||
|
|
a4e2856d06 | ||
|
|
e3f75314be | ||
|
|
143af979ab | ||
|
|
e9aff3040a | ||
|
|
aa36fd5a17 | ||
|
|
e975a44d05 | ||
|
|
9825fb3647 | ||
|
|
c362bca5e9 | ||
|
|
eadaa2608a | ||
|
|
91755950dd | ||
|
|
3e53487c72 | ||
|
|
7254b8288f | ||
|
|
517b6c3778 | ||
|
|
95a4772031 | ||
|
|
ac95f1241e | ||
|
|
51b635cc98 | ||
|
|
2c4dc2d22f | ||
|
|
cc2c7cc591 | ||
|
|
b66614063d | ||
|
|
8276d615ba | ||
|
|
fed4d14ab7 | ||
|
|
f5bbdc403f | ||
|
|
aac0f13487 | ||
|
|
d33466a340 | ||
|
|
195c048d1c | ||
|
|
bceaf1a212 | ||
|
|
59a5392850 | ||
|
|
364436dd31 | ||
|
|
d32a21c4ee | ||
|
|
c4a2f9b480 | ||
|
|
ca46444d13 | ||
|
|
aa29fefbd2 | ||
|
|
8907d0860b | ||
|
|
eec372ba9d | ||
|
|
31f0300c48 | ||
|
|
81470db44f | ||
|
|
620b18e9d8 | ||
|
|
f57a2e9680 | ||
|
|
593b5cf148 | ||
|
|
b9761926df | ||
|
|
c2bf8c920e | ||
|
|
aa6fa6bdc3 | ||
|
|
9124a09482 | ||
|
|
f8a76d9f00 | ||
|
|
ea25c3f2b1 | ||
|
|
6eac1efb20 | ||
|
|
01b2af13c7 | ||
|
|
899051169e | ||
|
|
2ac7c81958 | ||
|
|
67e8da3390 | ||
|
|
3db8038652 | ||
|
|
c8b9b44d40 | ||
|
|
9946f5ec77 | ||
|
|
379b4a8747 | ||
|
|
dd695ee5a7 | ||
|
|
24f9b9a335 | ||
|
|
7bfc820ae8 | ||
|
|
9972df2614 | ||
|
|
06ba2f792d | ||
|
|
96594d6716 | ||
|
|
09dda9e4e0 | ||
|
|
3ef2b77915 | ||
|
|
ccfb61efa4 | ||
|
|
8344117e7b | ||
|
|
f91b98a812 | ||
|
|
49ce385c44 | ||
|
|
96ef2728b8 | ||
|
|
c263a52ab7 | ||
|
|
057ae16504 | ||
|
|
6539c2bf8c | ||
|
|
8cf1164eb6 | ||
|
|
c4b198962c | ||
|
|
bd8eab3ffb | ||
|
|
782986baa1 | ||
|
|
ed33b4d877 | ||
|
|
4cf5acf18d | ||
|
|
7ab2b7d24a | ||
|
|
732df7b978 | ||
|
|
a4d7607a88 | ||
|
|
2993bf1722 | ||
|
|
e423844f9b | ||
|
|
62dbd49f5a | ||
|
|
16ba0ef59b | ||
|
|
7dacdc8cc8 | ||
|
|
cda2e2ee17 | ||
|
|
17723bc00d | ||
|
|
67b70c8d23 | ||
|
|
5a8a3b5a54 | ||
|
|
be6bfba8eb | ||
|
|
32bb568225 | ||
|
|
172f969650 | ||
|
|
47deb75247 | ||
|
|
7a826b1580 | ||
|
|
4da6e39281 | ||
|
|
09b3f0dc34 | ||
|
|
97436efe1e | ||
|
|
ff3367dc05 | ||
|
|
e02a4854de | ||
|
|
55bb0b6a6a | ||
|
|
c877ea4243 | ||
|
|
fc08d2444a | ||
|
|
1b81dbab85 | ||
|
|
4b44c15768 | ||
|
|
21dd14618c | ||
|
|
46f9c5130e | ||
|
|
9f019a061d | ||
|
|
e9a1e50996 | ||
|
|
231b0950c5 | ||
|
|
3f63b51fcc | ||
|
|
0da747fd44 | ||
|
|
0b09fb2b1e | ||
|
|
21c4c59587 | ||
|
|
1e9f89b638 | ||
|
|
f5389a4225 | ||
|
|
8c9e5f1974 | ||
|
|
e83bbfacf1 | ||
|
|
d5e4f11be7 | ||
|
|
51a997294e | ||
|
|
7f687cae77 | ||
|
|
b197ae79c5 | ||
|
|
0345623e97 | ||
|
|
37efd5c5f9 | ||
|
|
5fd9c1eaff | ||
|
|
bf6fae7df9 | ||
|
|
f4c26cd3ed | ||
|
|
f360af0889 | ||
|
|
c8f2edd94e | ||
|
|
07533eb590 | ||
|
|
6c43bdfa85 | ||
|
|
16189ae167 | ||
|
|
fc6f2e33e2 | ||
|
|
f752653814 | ||
|
|
54a9495715 | ||
|
|
4bc365cbb5 | ||
|
|
f29d7875cf | ||
|
|
ceb80723a9 | ||
|
|
a4fb06073c | ||
|
|
6f6b58785e | ||
|
|
a55546c9df | ||
|
|
6cc92c0e2b | ||
|
|
47ca937905 | ||
|
|
4b64b81d21 | ||
|
|
c551408ec2 | ||
|
|
5d0e806bdb | ||
|
|
dac6b4f2c5 | ||
|
|
c38a32e2e1 | ||
|
|
99a89f8bd4 | ||
|
|
6ea673b68a | ||
|
|
ef2541a1ef | ||
|
|
8e596bd85f | ||
|
|
dfc5fd86a7 | ||
|
|
b7aae374bf | ||
|
|
32648b7cc7 | ||
|
|
b9b93f3cdb | ||
|
|
96c3ada6f2 | ||
|
|
4ddedc72cd | ||
|
|
f29a4e6e14 | ||
|
|
57c621e654 | ||
|
|
4a34da368e | ||
|
|
912f7f5c64 | ||
|
|
e1f4c441f4 | ||
|
|
390874e7c3 | ||
|
|
0ae17566f2 | ||
|
|
d4a1278018 | ||
|
|
6d2600c09d | ||
|
|
c6faaff410 | ||
|
|
8e7ca70352 | ||
|
|
890c06117a | ||
|
|
6a8c2469c5 | ||
|
|
3a3579ed68 | ||
|
|
344c9265a6 | ||
|
|
7c2d8f7251 | ||
|
|
1b8962d7c2 | ||
|
|
c5c2d197dc | ||
|
|
bc4e1a989c | ||
|
|
807b93fb05 | ||
|
|
138e30df38 | ||
|
|
f32295429f | ||
|
|
2d8dc8b457 | ||
|
|
d3e1be8b6e | ||
|
|
cd7bb1e37d | ||
|
|
5f02641859 | ||
|
|
9c1bc64af4 | ||
|
|
52afec565b | ||
|
|
37990b5e90 | ||
|
|
80ec1f1d10 | ||
|
|
a2de6c886e | ||
|
|
808bcf39cd | ||
|
|
c1f6cde926 | ||
|
|
d23ec56f0d | ||
|
|
0c4a0dcf7d | ||
|
|
398326f19c | ||
|
|
d4cf1d0d6f | ||
|
|
6bcefd0d59 | ||
|
|
715d1736e9 | ||
|
|
5f50055750 | ||
|
|
c21616d1ee | ||
|
|
0816d4a2fd | ||
|
|
c3c11e4c76 | ||
|
|
110495ed9f | ||
|
|
739e2d1107 | ||
|
|
3d414960c2 | ||
|
|
c5083e7f32 | ||
|
|
593132e434 | ||
|
|
4ac5364004 | ||
|
|
7dee2c158f | ||
|
|
be4fe881e3 | ||
|
|
3a77f9c28a | ||
|
|
0186bccdce | ||
|
|
2af9e879a7 | ||
|
|
bc93a745ab | ||
|
|
acabcf085d | ||
|
|
c3c1216633 | ||
|
|
4de0f83aca | ||
|
|
dcf28ff248 | ||
|
|
9a4e0e4c85 | ||
|
|
7982f52830 | ||
|
|
106f641ff3 | ||
|
|
e474303991 | ||
|
|
ec04c4bf9a | ||
|
|
43931caccb | ||
|
|
640af6b20f | ||
|
|
382533da96 | ||
|
|
eaaf125d13 | ||
|
|
72b9577d3c | ||
|
|
08efbf2254 | ||
|
|
1de8615caf | ||
|
|
bf614354cc | ||
|
|
2fee779161 | ||
|
|
e3c20982a8 | ||
|
|
695f25600b | ||
|
|
a12cc84df4 | ||
|
|
7bfa93de05 | ||
|
|
3b7e9b0779 | ||
|
|
a1aa9b0d75 | ||
|
|
7465199fff | ||
|
|
aaa7076b52 | ||
|
|
06421554d3 | ||
|
|
39ac8cf996 | ||
|
|
026ae3af7a | ||
|
|
9f3d894c10 | ||
|
|
b2790f610c | ||
|
|
5faf043f6c | ||
|
|
c889edf172 | ||
|
|
f00c84ccad | ||
|
|
ebe9b087ad | ||
|
|
1ebbd9d7bc | ||
|
|
d456be1943 | ||
|
|
9b845f4415 | ||
|
|
ca0fa1e4e1 | ||
|
|
15c32c66f0 | ||
|
|
edb3c27aa4 | ||
|
|
67f1e3a889 | ||
|
|
87ee525b01 | ||
|
|
74b6f237d1 | ||
|
|
30711940c4 | ||
|
|
a16f3d704e | ||
|
|
deeea620f6 | ||
|
|
df1605a333 | ||
|
|
d8b9a0f5ab | ||
|
|
c967b39f18 | ||
|
|
9c0007173b | ||
|
|
16d793db38 | ||
|
|
de17f14da4 | ||
|
|
197bab7931 | ||
|
|
a5fbeef6f8 | ||
|
|
d9f8bacc76 | ||
|
|
25e3556050 | ||
|
|
52c6c0a0cf | ||
|
|
0bf4864d84 | ||
|
|
4d33f57325 | ||
|
|
ce42b7c1da | ||
|
|
995def4927 | ||
|
|
76e7806251 | ||
|
|
9f81c82100 | ||
|
|
df62776308 | ||
|
|
5c9a06c03d | ||
|
|
3b820add3b | ||
|
|
0572e41b65 | ||
|
|
0080739830 | ||
|
|
e46f2487fb | ||
|
|
8bcdc2896c | ||
|
|
2f4dbe3ca7 | ||
|
|
d9f224b122 | ||
|
|
6bf27b6c4e | ||
|
|
99c9248a17 | ||
|
|
6cc669e4e2 | ||
|
|
d139b97a28 | ||
|
|
e9e271ec30 | ||
|
|
363418bee2 | ||
|
|
7f558a1a3b | ||
|
|
38f3cdf7cf | ||
|
|
0a02161943 | ||
|
|
b2a5f7f97e | ||
|
|
18b61154cd | ||
|
|
b126943143 | ||
|
|
2cc60d6167 | ||
|
|
e7f2fc9ab0 | ||
|
|
ca039e5e25 | ||
|
|
e8e7f7a9fb | ||
|
|
2d476cab79 | ||
|
|
080d4b6f09 | ||
|
|
2118aefcdd | ||
|
|
5355671022 | ||
|
|
e6f1245ffc | ||
|
|
5bc1eafd3e | ||
|
|
6cb03f8e04 | ||
|
|
4cabb5842c | ||
|
|
2013ded3cb | ||
|
|
2e2c365d57 | ||
|
|
b2e45b8151 | ||
|
|
c7f4108eff | ||
|
|
6c5c184e6d | ||
|
|
fdcd818fba | ||
|
|
b8b58c81f2 | ||
|
|
baec6f9e33 | ||
|
|
393a1809ca | ||
|
|
45a94f58bd | ||
|
|
5b06b5457a | ||
|
|
f5e97f0f6b | ||
|
|
219adaa456 | ||
|
|
2746898e9a | ||
|
|
0309d598a1 | ||
|
|
e9a51bd84f | ||
|
|
42925490bd | ||
|
|
4856f85de2 | ||
|
|
ad543e37f5 | ||
|
|
9ee0ddf24f | ||
|
|
d46523e6ad | ||
|
|
42d51098ae | ||
|
|
931505a0e4 | ||
|
|
918d0f2f8a | ||
|
|
f16042d52a | ||
|
|
c9d4854114 | ||
|
|
11226544f7 | ||
|
|
0d41a7b82f | ||
|
|
60e2857d82 | ||
|
|
8ed6fe5edf | ||
|
|
daa66c0646 | ||
|
|
fb4e148985 | ||
|
|
710414730d | ||
|
|
0bd9a4d033 | ||
|
|
6efaf12d00 | ||
|
|
88a3bf8aab | ||
|
|
46eefd16ee | ||
|
|
328ab5a611 | ||
|
|
83373292f0 | ||
|
|
a7619fdfdb | ||
|
|
e2c7ed2d0c | ||
|
|
c525cfcced | ||
|
|
f3538dd7fe | ||
|
|
470c63d436 | ||
|
|
ebbc9acc90 | ||
|
|
4f9e59b87d | ||
|
|
ed2c0ad4ee | ||
|
|
a9f1ad414e | ||
|
|
d60ae4a1df | ||
|
|
0f8d5c6e57 | ||
|
|
84f8230a47 | ||
|
|
a6155387da | ||
|
|
95ef466b9b | ||
|
|
613b35eedf | ||
|
|
4c9ec363a3 | ||
|
|
7a969654f6 | ||
|
|
e01ca8919e | ||
|
|
e3e1c4d214 | ||
|
|
00413a3263 | ||
|
|
62e1da2ea3 | ||
|
|
b2bdd65338 | ||
|
|
56c5eaf317 | ||
|
|
835ba5efd6 | ||
|
|
1d68d7f2e9 | ||
|
|
4305d7e82d | ||
|
|
18df76b654 | ||
|
|
d4ec630b2f | ||
|
|
3709cac938 | ||
|
|
0ac8b1c5fa | ||
|
|
01dd7e607c | ||
|
|
f091b85b03 | ||
|
|
6ca2f509e3 | ||
|
|
a8832c74d0 | ||
|
|
e6b4de6442 | ||
|
|
09f9100ce7 | ||
|
|
0291895498 | ||
|
|
b831fd857f | ||
|
|
f06234fda8 | ||
|
|
d1deabe5ac | ||
|
|
8fbeb23bbf | ||
|
|
cd00ea2462 | ||
|
|
2c78c1e1fb | ||
|
|
e277a91842 | ||
|
|
8d352fe52e | ||
|
|
05bcfa7a2a | ||
|
|
6798f591bd | ||
|
|
e75f72476b | ||
|
|
2ccb8a7d88 | ||
|
|
440f24f35f | ||
|
|
508407b350 | ||
|
|
b414d2af19 | ||
|
|
135620ab64 | ||
|
|
9cf4d05c9e | ||
|
|
329e0ddb02 | ||
|
|
46e732c28b | ||
|
|
6353eb526d | ||
|
|
2707269118 | ||
|
|
bb9d306399 | ||
|
|
596047aaef | ||
|
|
75e432a49a | ||
|
|
37f9f7773c | ||
|
|
dfeca5806f | ||
|
|
a0518e28bb | ||
|
|
9c9a5ac435 | ||
|
|
495c1c9dd0 | ||
|
|
3c2552e671 | ||
|
|
3e7e61dcb7 | ||
|
|
aabcbf1261 | ||
|
|
7fc020098c | ||
|
|
46b8380490 | ||
|
|
43b19e7668 | ||
|
|
2953f48d9b | ||
|
|
da19aa4eb1 | ||
|
|
c6ae30593c | ||
|
|
9cae4ce7e7 | ||
|
|
2b96f694f7 | ||
|
|
d8db536d36 | ||
|
|
777851a7ec | ||
|
|
b9e62aad8a | ||
|
|
c5e1a3eae3 | ||
|
|
0a38fedeec | ||
|
|
f0a33cddbd | ||
|
|
2722d16303 | ||
|
|
c3d16a39f5 | ||
|
|
cee1bdfb5a | ||
|
|
e66a24dc5b | ||
|
|
84e6845aa6 | ||
|
|
6e8e234e61 | ||
|
|
7df106bc25 | ||
|
|
5f9811d085 | ||
|
|
f210d93ea6 | ||
|
|
839e0a4aaf | ||
|
|
37b648a3e0 | ||
|
|
d4b472d2e5 | ||
|
|
61a9c78e1d | ||
|
|
c5d8113302 | ||
|
|
9454c71a58 | ||
|
|
f76327e076 | ||
|
|
c551acf4d1 | ||
|
|
adad89dc0e | ||
|
|
54aba261d2 | ||
|
|
b4457b871f | ||
|
|
35cbd2e56a | ||
|
|
e490c503fd | ||
|
|
03fd89abea | ||
|
|
3277f3acfb | ||
|
|
ae723a69f6 | ||
|
|
823dcd8843 | ||
|
|
474253719f | ||
|
|
0cc3644e55 | ||
|
|
14b74962d6 | ||
|
|
b12b7f785e | ||
|
|
11d28c661b | ||
|
|
4b886d07f7 | ||
|
|
c3c74257fa | ||
|
|
013bd12592 | ||
|
|
5075f27ea0 | ||
|
|
c2f85ffc51 | ||
|
|
b1a9bc966b | ||
|
|
1ed1349e7c | ||
|
|
42415eadd9 | ||
|
|
eeaddbb385 | ||
|
|
f5259828b6 | ||
|
|
14310e66fe | ||
|
|
ffa855d76e | ||
|
|
cec53759dd | ||
|
|
fdfede8b96 | ||
|
|
e661c72272 | ||
|
|
f5c5c9d7a3 | ||
|
|
ef4ff8cfd0 | ||
|
|
a73988d38d | ||
|
|
d9821d09c7 | ||
|
|
4e62826e01 | ||
|
|
3f386ecd34 | ||
|
|
1d0c51f057 | ||
|
|
ef8f820d4a | ||
|
|
bdaecfebb8 | ||
|
|
20d648aaad | ||
|
|
dc47f9ea45 | ||
|
|
0f00ad19cb | ||
|
|
bf7f2a5d88 | ||
|
|
49073cf527 | ||
|
|
446e36807f | ||
|
|
7012594926 | ||
|
|
fbbc4271a3 | ||
|
|
0e0c325194 | ||
|
|
abd8c8f666 | ||
|
|
5474c3c3a5 | ||
|
|
1a3df16e27 | ||
|
|
d7be4353ad | ||
|
|
337801717e | ||
|
|
c9ecbf9fab | ||
|
|
247918339e | ||
|
|
50aacea749 | ||
|
|
57299da899 | ||
|
|
785bf36b9b | ||
|
|
8fd7982087 | ||
|
|
ad0bab69a1 | ||
|
|
6b0248d68c | ||
|
|
54a4515b09 | ||
|
|
ee1b429441 | ||
|
|
a35b6b0c4b | ||
|
|
49d5f4f236 | ||
|
|
67dd3549a7 | ||
|
|
54c517b2d9 | ||
|
|
0121bdc475 | ||
|
|
5b86e3d418 | ||
|
|
3080bca85a | ||
|
|
41b5bc662e | ||
|
|
9ba92bd728 | ||
|
|
18c97222c4 | ||
|
|
03f894bab0 | ||
|
|
7f4baba41c | ||
|
|
00b4717c6e | ||
|
|
84e7b744a6 | ||
|
|
29b221671f | ||
|
|
7599079d61 | ||
|
|
60062432b8 | ||
|
|
50fcf64058 | ||
|
|
9eeb2f1930 | ||
|
|
7fe191bc10 | ||
|
|
ea28343166 | ||
|
|
67070762d0 | ||
|
|
0d1280a5b2 | ||
|
|
22c1a16dce | ||
|
|
39f4cbfc98 | ||
|
|
bc87bc8588 | ||
|
|
4f56442249 | ||
|
|
e1f53b7f39 | ||
|
|
2e7aee3573 | ||
|
|
01b9abc5ef | ||
|
|
d47b4974ce | ||
|
|
52b23384e0 | ||
|
|
9ba0c3cfd3 | ||
|
|
c02cdcb5ce | ||
|
|
3dff64364f | ||
|
|
1dd8729d13 | ||
|
|
115525d000 | ||
|
|
3b422e31a2 | ||
|
|
5ade045654 | ||
|
|
244c3b597f | ||
|
|
41d8ce7fff | ||
|
|
b16a2e41e8 | ||
|
|
e4693ebc83 | ||
|
|
6bf81ebe59 | ||
|
|
f4587ea434 | ||
|
|
8db1153519 | ||
|
|
36740e0100 | ||
|
|
edb074f438 | ||
|
|
f846879399 | ||
|
|
e5809ee052 | ||
|
|
1a37f445a2 | ||
|
|
653b8703bc | ||
|
|
90fd6fbc65 | ||
|
|
11d1f3653a | ||
|
|
b1b5653393 | ||
|
|
6544996a33 | ||
|
|
3c1b8dcdcc | ||
|
|
3273ba6333 | ||
|
|
95eac7b4e5 | ||
|
|
9098996b87 | ||
|
|
00148467ef | ||
|
|
e4e5f62d44 | ||
|
|
16bde0c61d | ||
|
|
1344bec7bb | ||
|
|
f4558472df | ||
|
|
3e209f6d20 | ||
|
|
41520f1022 | ||
|
|
ca91b368c1 | ||
|
|
45e3af5cdc | ||
|
|
ad195b289a | ||
|
|
f11ab0da3e | ||
|
|
0393fd8a72 | ||
|
|
357f27658e | ||
|
|
a671625637 | ||
|
|
9495e2b8a9 | ||
|
|
7c5b5d12ed | ||
|
|
b0065bfe9a | ||
|
|
e447b46d36 | ||
|
|
283052c15a | ||
|
|
d17e68c43f | ||
|
|
cd84d007cd | ||
|
|
469929d4f6 | ||
|
|
9c7aa4d423 | ||
|
|
2f65cf7124 | ||
|
|
6e332a5d32 | ||
|
|
00f1d6c3d8 | ||
|
|
f45e619559 | ||
|
|
5cc63c1b34 | ||
|
|
5f4b422ab1 | ||
|
|
7ecd51dc80 | ||
|
|
6a3ac7f7b0 | ||
|
|
8f22785cf0 | ||
|
|
5c67ab2a7a | ||
|
|
d33066cdd7 | ||
|
|
810617997b | ||
|
|
a661f14d2c | ||
|
|
dc1738ce57 | ||
|
|
abf37dbdde | ||
|
|
5e37d43881 | ||
|
|
22a5fad902 | ||
|
|
75c3d3ecf8 | ||
|
|
2548fcad25 | ||
|
|
f6939a1cf0 | ||
|
|
c745582ef5 | ||
|
|
f7bb4c95ed | ||
|
|
99079dd955 | ||
|
|
d42646e91f | ||
|
|
67b4732c26 | ||
|
|
5f8ece7017 | ||
|
|
f9e2b1d8b9 | ||
|
|
ddf63e0863 | ||
|
|
231a41a22f | ||
|
|
6f73e42d05 | ||
|
|
3a2d16a3bc | ||
|
|
48c22e2aa7 | ||
|
|
d1c372f5ee | ||
|
|
70b7b42f5d | ||
|
|
a179e8c695 | ||
|
|
784ad934a4 | ||
|
|
118d8574c8 | ||
|
|
437a8d32f2 | ||
|
|
106b4a37d4 | ||
|
|
e6a5951a47 | ||
|
|
efd1526423 | ||
|
|
49300d8ee0 | ||
|
|
a3853c2c3d | ||
|
|
95e89f786a | ||
|
|
182f52603c | ||
|
|
ea21281f38 | ||
|
|
797cdbc72f | ||
|
|
b8e27cc02b | ||
|
|
6e2522b657 | ||
|
|
87087a4629 | ||
|
|
f4e174870e | ||
|
|
d206b06c70 | ||
|
|
06f336a581 | ||
|
|
8ceb671cc8 | ||
|
|
354ec08b9b | ||
|
|
b05fcdbfbd | ||
|
|
8eed27820c | ||
|
|
ee18160c4e | ||
|
|
9ad5ca2e5a | ||
|
|
dee2d5ee06 | ||
|
|
3a1b790588 | ||
|
|
a065cff8c1 | ||
|
|
db713c8264 | ||
|
|
a1db2b8d35 | ||
|
|
c09bcfdc97 | ||
|
|
cd77dd0e62 | ||
|
|
79d8e7f61d | ||
|
|
b67937f247 | ||
|
|
fa04146cfb | ||
|
|
4a399172b6 | ||
|
|
d6654e84a7 | ||
|
|
6daa8ccc0d | ||
|
|
be3c63d55e | ||
|
|
03662b3dfe | ||
|
|
bdbb5f6d27 | ||
|
|
7dd924797b | ||
|
|
ed361a856f | ||
|
|
6753c51ab8 | ||
|
|
692590b30a | ||
|
|
848ac24490 | ||
|
|
6961bfeaa1 | ||
|
|
5a285602e2 | ||
|
|
426a5be235 | ||
|
|
ff04b47942 | ||
|
|
c847b81629 | ||
|
|
367ce4626c | ||
|
|
846096d435 | ||
|
|
476220c18b | ||
|
|
973f48dde7 | ||
|
|
9e82e49446 | ||
|
|
ce18660127 | ||
|
|
8f3d8d77ab | ||
|
|
5bd93b97ad | ||
|
|
e46bfe67b6 | ||
|
|
d7c3e8c2bc | ||
|
|
d8b06f94ee | ||
|
|
d4329600d1 | ||
|
|
c244fbf945 | ||
|
|
f5107f3e83 | ||
|
|
569c2dce55 | ||
|
|
987579b7b7 | ||
|
|
2fb38af3e0 | ||
|
|
7887c365d1 | ||
|
|
e7ca02c4d8 | ||
|
|
be0e037809 | ||
|
|
6eb4483069 | ||
|
|
b8b2c58cda | ||
|
|
700cea78db | ||
|
|
b9922d8ed5 | ||
|
|
88cbe24201 | ||
|
|
7956d7ceaf | ||
|
|
0e80287625 | ||
|
|
ab70dae0a8 | ||
|
|
de778e6235 | ||
|
|
fc723d7b15 | ||
|
|
7dd2c60b12 | ||
|
|
63129dd3dc | ||
|
|
5c9b3ee05a | ||
|
|
5f12dd99a3 | ||
|
|
b0b6f6ca37 | ||
|
|
ca4fa88598 | ||
|
|
7f08c0d404 | ||
|
|
11d5e071ec | ||
|
|
12fb9ab831 | ||
|
|
47de1e15a4 | ||
|
|
494d727108 | ||
|
|
a2df282086 | ||
|
|
0470f96887 | ||
|
|
c499255098 | ||
|
|
2770143f50 | ||
|
|
64e0a9cbd9 | ||
|
|
bac776f8b4 | ||
|
|
84bfbd92a1 | ||
|
|
57efceeb02 | ||
|
|
2c0988ab4c | ||
|
|
ac7728097f | ||
|
|
642504f5f9 | ||
|
|
6192c11038 | ||
|
|
e874f705a9 | ||
|
|
a16485f8aa | ||
|
|
5d7f21f130 | ||
|
|
9f0dc9c1af | ||
|
|
543000151f | ||
|
|
413f5762c4 | ||
|
|
95970e539e | ||
|
|
a32e6e108c | ||
|
|
cad1df748e | ||
|
|
3c80f0fb3e | ||
|
|
f60e03b4ef | ||
|
|
a50e9a995e | ||
|
|
f34a87fe38 | ||
|
|
1a478c7147 | ||
|
|
69d8822303 | ||
|
|
47dd57faa7 | ||
|
|
2aecb49f50 | ||
|
|
ed59342d28 | ||
|
|
703380d62d | ||
|
|
bc53b6b343 | ||
|
|
332e35039d | ||
|
|
254620676f | ||
|
|
78f16bc04b | ||
|
|
2b5d21da5b | ||
|
|
2d6a7d2186 | ||
|
|
db7c74a042 | ||
|
|
35817c0d85 | ||
|
|
f2c4452e8d | ||
|
|
8600721de0 | ||
|
|
04793138b5 | ||
|
|
f978b702b1 | ||
|
|
f82f4945b9 | ||
|
|
c634ef9610 | ||
|
|
56a4ab5234 | ||
|
|
7f2cce1021 | ||
|
|
a97c4d10af | ||
|
|
ba3e564e34 | ||
|
|
39dd760c60 | ||
|
|
0a27618cd4 | ||
|
|
e18c8ec224 | ||
|
|
a858255ea2 | ||
|
|
c74acf6c25 | ||
|
|
dcdc19238b | ||
|
|
b4b057196d | ||
|
|
06e4772864 | ||
|
|
c28a85ab34 | ||
|
|
9fdbe98330 | ||
|
|
f055cf398d | ||
|
|
5481a235ed | ||
|
|
fc5b43a0b0 | ||
|
|
58b958860e | ||
|
|
e615f17573 | ||
|
|
21217a1fad | ||
|
|
97976e4daf | ||
|
|
01627e0367 | ||
|
|
13131706aa | ||
|
|
c1f7963c2a | ||
|
|
f21c44751e | ||
|
|
0003d7a2d0 | ||
|
|
d0309b4e1e | ||
|
|
0869be11f8 | ||
|
|
3597e09600 | ||
|
|
8912090c4d | ||
|
|
1da30b545a | ||
|
|
2f3c0bc596 | ||
|
|
1d485d8bbc | ||
|
|
2fe254821c | ||
|
|
f70fc7ea28 | ||
|
|
e7f1a8f55d | ||
|
|
d3a5b352b2 | ||
|
|
aec99d2b6f | ||
|
|
6ed9645465 | ||
|
|
c96e58af01 | ||
|
|
260e8261d5 | ||
|
|
e91a79dab7 | ||
|
|
bb0efd777f | ||
|
|
f754741d58 | ||
|
|
8a7c71694d | ||
|
|
aa31e814b2 | ||
|
|
11389d101a | ||
|
|
b535534611 | ||
|
|
1d7e89e069 | ||
|
|
de34ce606f | ||
|
|
c4812af436 | ||
|
|
11faea9dbc | ||
|
|
ac3ac3382b | ||
|
|
8b36e2d9b7 | ||
|
|
ae9361bb34 | ||
|
|
4a2710c779 | ||
|
|
1f2a5d99b1 | ||
|
|
29bbd79830 | ||
|
|
3738c3fc38 | ||
|
|
165bd7b219 | ||
|
|
e15e50c5ee | ||
|
|
f468529084 | ||
|
|
385161b12a | ||
|
|
8c7890eb52 | ||
|
|
e2262617aa | ||
|
|
12b2e5d67c | ||
|
|
ee42b18226 | ||
|
|
d89d1668dc | ||
|
|
9a48bbaa36 | ||
|
|
04cf29f7cd | ||
|
|
bb564d5eb6 | ||
|
|
f03021edd1 | ||
|
|
c7ebc66e64 | ||
|
|
a6f8e209ac | ||
|
|
6f1938d501 | ||
|
|
bb1ef8ea5e | ||
|
|
b22e442b10 | ||
|
|
43bf1b8f7c | ||
|
|
ba8c6154a0 | ||
|
|
548f26882f | ||
|
|
63abd4e71c | ||
|
|
c2ada3175e | ||
|
|
8153efc6ed | ||
|
|
40aa6fbb64 | ||
|
|
34122b4bf3 | ||
|
|
d9fa0629f6 | ||
|
|
25a6fdcdb1 | ||
|
|
7aa8d8d628 | ||
|
|
8e6945c496 | ||
|
|
e1392cec0e | ||
|
|
13def13f01 | ||
|
|
ea653a52e3 | ||
|
|
6054c1a12b | ||
|
|
b43d915e71 | ||
|
|
4f8f7980f0 | ||
|
|
a6d7e98db3 | ||
|
|
ad43eba25c | ||
|
|
a97abf10ab | ||
|
|
86168ab1e2 | ||
|
|
2f83c5dab5 | ||
|
|
63a37e4947 | ||
|
|
a1a33141d7 | ||
|
|
82fe584f51 | ||
|
|
b90bd2c528 | ||
|
|
43448f147c | ||
|
|
1b39e7836d | ||
|
|
034e8683c8 | ||
|
|
2942bae034 | ||
|
|
c623886625 | ||
|
|
f65d5654d3 | ||
|
|
198f4a92f5 | ||
|
|
57e589f2e1 | ||
|
|
e30ee9c846 | ||
|
|
b68698a086 | ||
|
|
0d7cb9b39f | ||
|
|
c81ee31c3b | ||
|
|
a172bf0f55 | ||
|
|
4f39329ca9 | ||
|
|
4152c5d292 | ||
|
|
52f2137397 | ||
|
|
6619aba582 | ||
|
|
1aacf8d15a | ||
|
|
93b59609a8 | ||
|
|
e7c7b5058d | ||
|
|
986254f56f | ||
|
|
32ceb47937 | ||
|
|
354006a699 | ||
|
|
17812c33cc | ||
|
|
2673558a52 | ||
|
|
a1b829997e | ||
|
|
bcf6b185d7 | ||
|
|
8e870c809c | ||
|
|
5eea411a3c | ||
|
|
8e135c1015 | ||
|
|
cdf1ebe861 | ||
|
|
99a131a91d | ||
|
|
929ac1f09f | ||
|
|
f3d0642994 | ||
|
|
9f1c11ac34 | ||
|
|
c48e835d0c | ||
|
|
af62143327 | ||
|
|
b60623df4d | ||
|
|
a3ce0f3e28 | ||
|
|
c10f869836 | ||
|
|
c1dbba1a31 | ||
|
|
8d99bf66bd | ||
|
|
2ff45313de | ||
|
|
52ec847cbd | ||
|
|
933ac4be43 | ||
|
|
8c698366b8 | ||
|
|
21bb281c75 | ||
|
|
831357ee88 | ||
|
|
f30a0c1864 | ||
|
|
76f8ebb1f2 | ||
|
|
a13d5eeccb | ||
|
|
875dd91bc2 | ||
|
|
546dafa0b0 | ||
|
|
a88b4bfecd | ||
|
|
8593235571 | ||
|
|
98b4693525 | ||
|
|
94c05e9e2d | ||
|
|
172a2af982 | ||
|
|
1efa2bda30 | ||
|
|
6ced56e11d | ||
|
|
1408dd5245 | ||
|
|
3b6609f13a | ||
|
|
2c6aa8e0d0 | ||
|
|
fc26e6321b | ||
|
|
ed2889cecf | ||
|
|
33c7d9cba5 | ||
|
|
7d5940101b | ||
|
|
4760fd7f52 | ||
|
|
3f292e3ce3 | ||
|
|
941fc5f51c | ||
|
|
8d59ad2713 | ||
|
|
2010a525d3 | ||
|
|
ff6db3e08e | ||
|
|
914e8c6c7a | ||
|
|
bf801f4f7f | ||
|
|
f9f08f7f5c | ||
|
|
b940d9f3a1 | ||
|
|
3372d8f102 | ||
|
|
55e4c7e4cb | ||
|
|
57af462ecf | ||
|
|
8ea56477d9 | ||
|
|
f2093a3f76 | ||
|
|
03428f3380 | ||
|
|
5d39e1357e | ||
|
|
99dbd109ce | ||
|
|
a7735677ae | ||
|
|
ae7ac460b9 | ||
|
|
ead1c144b2 | ||
|
|
207421cb7b | ||
|
|
f4efb37b03 | ||
|
|
df075e6628 | ||
|
|
faf4641625 | ||
|
|
e8268969ea | ||
|
|
bfd26c98e3 | ||
|
|
18ff08243b | ||
|
|
b9a895f825 | ||
|
|
dabd2af828 | ||
|
|
954f76d107 | ||
|
|
fb20b96024 | ||
|
|
f322a8b159 | ||
|
|
60c47e96a8 | ||
|
|
8df58db415 | ||
|
|
878dd7a0c9 | ||
|
|
567d5181ca | ||
|
|
3413ca9617 | ||
|
|
78b6df769b | ||
|
|
9a0053a501 | ||
|
|
963d10f1ac | ||
|
|
3337af64ca |
512 changed files with 44245 additions and 11483 deletions
|
|
@ -410,13 +410,15 @@ build_on_fedora_html_docs:
|
||||||
-Dsndfile=enabled
|
-Dsndfile=enabled
|
||||||
-Dsession-managers=[]
|
-Dsession-managers=[]
|
||||||
before_script:
|
before_script:
|
||||||
- git fetch origin 1.0 1.2 1.4 master
|
- git fetch origin 1.0 1.2 1.4 1.6 master
|
||||||
- git branch -f 1.0 origin/1.0
|
- git branch -f 1.0 origin/1.0
|
||||||
- git clone -b 1.0 . branch-1.0
|
- git clone -b 1.0 . branch-1.0
|
||||||
- git branch -f 1.2 origin/1.2
|
- git branch -f 1.2 origin/1.2
|
||||||
- git clone -b 1.2 . branch-1.2
|
- git clone -b 1.2 . branch-1.2
|
||||||
- git branch -f 1.4 origin/1.4
|
- git branch -f 1.4 origin/1.4
|
||||||
- git clone -b 1.4 . branch-1.4
|
- git clone -b 1.4 . branch-1.4
|
||||||
|
- git branch -f 1.6 origin/1.6
|
||||||
|
- git clone -b 1.6 . branch-1.6
|
||||||
- git branch -f master origin/master
|
- git branch -f master origin/master
|
||||||
- git clone -b master . branch-master
|
- git clone -b master . branch-master
|
||||||
- !reference [.build, before_script]
|
- !reference [.build, before_script]
|
||||||
|
|
@ -433,6 +435,10 @@ build_on_fedora_html_docs:
|
||||||
- meson setup builddir $MESON_OPTIONS
|
- meson setup builddir $MESON_OPTIONS
|
||||||
- meson compile -C builddir doc/pipewire-docs
|
- meson compile -C builddir doc/pipewire-docs
|
||||||
- cd ..
|
- cd ..
|
||||||
|
- cd branch-1.6
|
||||||
|
- meson setup builddir $MESON_OPTIONS
|
||||||
|
- meson compile -C builddir doc/pipewire-docs
|
||||||
|
- cd ..
|
||||||
- cd branch-master
|
- cd branch-master
|
||||||
- meson setup builddir $MESON_OPTIONS
|
- meson setup builddir $MESON_OPTIONS
|
||||||
- meson compile -C builddir doc/pipewire-docs
|
- meson compile -C builddir doc/pipewire-docs
|
||||||
|
|
@ -658,7 +664,7 @@ doccheck:
|
||||||
- cat pipewire_module_pages
|
- cat pipewire_module_pages
|
||||||
- |
|
- |
|
||||||
for page in $(cat pipewire_module_pages); do
|
for page in $(cat pipewire_module_pages); do
|
||||||
git grep -q -e "\\\subpage $page" || (echo "\\page $page is missing \\subpage entry in doc/pipewire-modules.dox" && false)
|
git grep -q -e "\\\subpage $page" || (echo "\\page $page is missing \\subpage entry in doc/dox/modules.dox" && false)
|
||||||
done
|
done
|
||||||
|
|
||||||
check_missing_headers:
|
check_missing_headers:
|
||||||
|
|
@ -682,12 +688,13 @@ pages:
|
||||||
- job: build_on_fedora_html_docs
|
- job: build_on_fedora_html_docs
|
||||||
artifacts: true
|
artifacts: true
|
||||||
script:
|
script:
|
||||||
- mkdir public public/1.0 public/1.2 public/1.4 public/devel
|
- mkdir public public/1.0 public/1.2 public/1.4 public/1.6 public/devel
|
||||||
- cp -R branch-1.0/builddir/doc/html/* public/1.0/
|
- cp -R branch-1.0/builddir/doc/html/* public/1.0/
|
||||||
- cp -R branch-1.2/builddir/doc/html/* public/1.2/
|
- cp -R branch-1.2/builddir/doc/html/* public/1.2/
|
||||||
- cp -R branch-1.4/builddir/doc/html/* public/1.4/
|
- cp -R branch-1.4/builddir/doc/html/* public/1.4/
|
||||||
|
- cp -R branch-1.6/builddir/doc/html/* public/1.6/
|
||||||
- cp -R branch-master/builddir/doc/html/* public/devel/
|
- cp -R branch-master/builddir/doc/html/* public/devel/
|
||||||
- (cd public && ln -s 1.4/* .)
|
- (cd public && ln -s 1.6/* .)
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
|
|
|
||||||
206
NEWS
206
NEWS
|
|
@ -1,3 +1,206 @@
|
||||||
|
# PipeWire 1.6.0 (2026-02-19)
|
||||||
|
|
||||||
|
This is the 1.6 release that is API and ABI compatible with previous
|
||||||
|
1.4.x releases.
|
||||||
|
|
||||||
|
This release contains some of the bigger changes that happened since
|
||||||
|
the 1.4 release last year, including:
|
||||||
|
|
||||||
|
* An LDAC decoder was added for bluetooth.
|
||||||
|
* SpanDSP for bluetooth packet loss concealment.
|
||||||
|
* Safe parsing and building of PODs in shared memory.
|
||||||
|
* Added support for metadata features. This is used to signal that
|
||||||
|
the sync_timeline metadata supports the RELEASE operation.
|
||||||
|
* Node commands and events can contain extra user data.
|
||||||
|
* Support for more compressed format helper functions to create
|
||||||
|
and parse formats.
|
||||||
|
* Support for compile time max channels. The max channels was
|
||||||
|
increased to 128.
|
||||||
|
* Support for audio channel layouts was added. This makes it possible
|
||||||
|
to set "audio.layout" = "5.1" instead of the more verbose
|
||||||
|
audio.position = [ FL, FR, FC, LFE, SL, SR ]
|
||||||
|
* Support for Capability Params was added. This can be used to
|
||||||
|
negotiate capabilities on a link before format and buffer
|
||||||
|
negotiation takes place.
|
||||||
|
* More HDR colortypes are added.
|
||||||
|
* Loops now have locking with priority inversion. Most code was adapted
|
||||||
|
to use the faster locks instead of epoll/eventfd to update shared state.
|
||||||
|
* Channel position are parsed from EDID data.
|
||||||
|
* Channel maps are now set on ALSA.
|
||||||
|
* The resampler now supports configurable window functions such
|
||||||
|
as blackman and kaiser windows. The phases are now also calculated
|
||||||
|
with fixed point math, which makes it more accurate.
|
||||||
|
* Many bluetooth updates and improvements.
|
||||||
|
* The filter-graph has an ffmpeg and ONNX plugin. The ffmpeg plugin
|
||||||
|
can run an audio AVFilterGraph. The ONNX plugin can run some models
|
||||||
|
such as the silero VAD.
|
||||||
|
* Many AVB updates. Work is ongoing to merge the Milan protocol.
|
||||||
|
* Support for v0 clients was removed.
|
||||||
|
* The jack-tunnel module can now autoconnect ports.
|
||||||
|
* ROC support multitrack layouts now.
|
||||||
|
* Many RTP updates.
|
||||||
|
* rlimits can now be set in the config file.
|
||||||
|
* Thread reset on fork can now be configured. JACK clients expect this
|
||||||
|
to be disabled.
|
||||||
|
* node.exclusive is now enforced.
|
||||||
|
* node.reliable enables reliable transport.
|
||||||
|
* pw-cat supports sysex and midiclip as well as some more uncompressed
|
||||||
|
formats. Options were added to set the container and codec formats
|
||||||
|
as well as list the supported containers, codecs, layouts and channel
|
||||||
|
names.
|
||||||
|
* Documentation updates.
|
||||||
|
|
||||||
|
|
||||||
|
## Highlights (since the previous 1.5.85 prerelease)
|
||||||
|
- Fix a 64 channel limit in the channel mixer.
|
||||||
|
- Fix an fd leak in pulse-server in some error cases.
|
||||||
|
- Some small fixes and improvements.
|
||||||
|
|
||||||
|
|
||||||
|
## PipeWire
|
||||||
|
- Fix Capability leaks.
|
||||||
|
- Return an error in pw-stream get-time when not STREAMING.
|
||||||
|
- Set the current time in the driver position before starting.
|
||||||
|
Some followers might look at it.
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
- Improve default channel handling in module-filter-chain.
|
||||||
|
- Support source and sink only module-filter-chain.
|
||||||
|
- Tweak the filter-chain spatializer example gains.
|
||||||
|
- Handle new snapcast service type. (#5104)
|
||||||
|
- Implement socket activation without depending on libsystemd.
|
||||||
|
- Support ipv4 link-local addresses in RAOP and snapcast. (#4830)
|
||||||
|
- Forward ROC-toolkit logs to pipewire.
|
||||||
|
|
||||||
|
## SPA
|
||||||
|
- Improve default channel handling in filter-graph. (#5084)
|
||||||
|
- Clamp control values to min/max. (#5088)
|
||||||
|
- Support mode JBL gaming headsets.
|
||||||
|
- Handle some SOFA errors and add gain option.
|
||||||
|
- Really handle more than 64 channels in the channelmixer. (#5118)
|
||||||
|
- Allow removal in ALSA-udev of ignored cards.
|
||||||
|
|
||||||
|
# pulse-server
|
||||||
|
- Fix mono mixdown query.
|
||||||
|
- Expose headset autoswitch message.
|
||||||
|
- Handle EPROTO errors by disconnecting.
|
||||||
|
- Handle timeouts in play-sample streams. (#5099)
|
||||||
|
|
||||||
|
## GStreamer
|
||||||
|
- Fix crop metadata.
|
||||||
|
- Fix a race in the buffer release function.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
- Improve format support and detection in pw-cat.
|
||||||
|
- Add some more options to pw-cat to list supported containers
|
||||||
|
and formats. (#5117)
|
||||||
|
|
||||||
|
Older versions:
|
||||||
|
|
||||||
|
# PipeWire 1.5.85 (2026-01-19)
|
||||||
|
|
||||||
|
This is the fifth and hopefully last 1.6 release candidate that
|
||||||
|
is API and ABI compatible with previous 1.4.x, 1.2.x and 1.0.x
|
||||||
|
releases.
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
- Fix errors in older clients that blindly mmap buffer data.
|
||||||
|
- ALSA channel mapping should work in more cases.
|
||||||
|
- Fix an overflow in the resampler with some sample rates.
|
||||||
|
- Device ID negotiation for DMABUF was added.
|
||||||
|
- The channelmixer can now also downmix most REAR and TOP
|
||||||
|
channel positions.
|
||||||
|
- Various small fixes and improvements.
|
||||||
|
|
||||||
|
|
||||||
|
## PipeWire
|
||||||
|
- Avoid doing flushing invoke in pw-stream. (#5010)
|
||||||
|
- Fix stream time delay calculations in some cases. (#4957)
|
||||||
|
- Avoid suspending a node when the ports are busy.
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
- Mode AVB module updates.
|
||||||
|
- Remove MAPPABLE flag from memptr data in client-node. This avoids
|
||||||
|
errors in older clients that blindly map buffers. (#5003)
|
||||||
|
- Don't leak the filter-chain module in module-parametric-equalizer.
|
||||||
|
(#5045)
|
||||||
|
- make it possible to run pulse tunnel sink and source with the same
|
||||||
|
name. (#5079)
|
||||||
|
|
||||||
|
## SPA
|
||||||
|
- The delay filter in filter-graph now has feedback and feedforward
|
||||||
|
options to make it possible to implement comb and allpass filters.
|
||||||
|
- The resampler can be compiled with a custom default quality.
|
||||||
|
- Firewire latency is scaled correctly now. (#4977)
|
||||||
|
- The mixer will only passthrough dynamic data.
|
||||||
|
- Fix filter-graph state in audioconvert after flush.
|
||||||
|
- Set the channel map in ALSA nodes to tell ALSA our channel layout
|
||||||
|
and avoid wrong channels.
|
||||||
|
- Fix AVX2 function, make sure they don't run on AVX-only CPUs.
|
||||||
|
(#5072)
|
||||||
|
- Fix an overflow and crash when too many phases are used in the
|
||||||
|
resampler. (#5073)
|
||||||
|
- Add some more channel downmix positions, mostly REAR and TOP
|
||||||
|
channels.
|
||||||
|
|
||||||
|
## pulse-server
|
||||||
|
- Add a message to enable mono mixdown.
|
||||||
|
|
||||||
|
## Tools
|
||||||
|
- Support filenames in raw mode in pw-cat. (#5012)
|
||||||
|
- Enable clipping in spa-resample.
|
||||||
|
|
||||||
|
## examples
|
||||||
|
- Update device ID negotiation examples.
|
||||||
|
|
||||||
|
## Docs
|
||||||
|
- Document the resampler properties better.
|
||||||
|
|
||||||
|
# PipeWire 1.5.84 (2025-11-27)
|
||||||
|
|
||||||
|
This is the fourth 1.6 release candidate that is API and ABI
|
||||||
|
compatible with previous 1.4.x, 1.2.x and 1.0.x releases.
|
||||||
|
|
||||||
|
Changes since the last pre-release:
|
||||||
|
|
||||||
|
## Highlights
|
||||||
|
- Capabilities wer added to improve negotiation over links.
|
||||||
|
- The audio resampler now has a configurable window function to better
|
||||||
|
tune the resampler quality. A kaiser and blackman window was added
|
||||||
|
and the default parameters were tuned.
|
||||||
|
- Various small fixes and improvements.
|
||||||
|
|
||||||
|
## PipeWire
|
||||||
|
- Capabilities and PeerCapabilities were added to exchange key/value
|
||||||
|
pairs between consumer and producer right after a link is made. This
|
||||||
|
can be used to detect how the negotiation of formats and buffers
|
||||||
|
should be done.
|
||||||
|
|
||||||
|
## Modules
|
||||||
|
- Avoid segfaults in RTP source. (#4970)
|
||||||
|
- The AVB module has seen some improvements.
|
||||||
|
|
||||||
|
## Pulse-server
|
||||||
|
- @NONE@ can now be used to clear the default sink/source.
|
||||||
|
|
||||||
|
## SPA
|
||||||
|
- Support longer convolver filenames and also support inline
|
||||||
|
IRs.
|
||||||
|
- The audio resampler window function is now selectable and
|
||||||
|
configurable. A kaiser window and blackman window was added
|
||||||
|
and the default qualities were tweaked to improve quality.
|
||||||
|
- The filter-graph convolver latency is now set by default to
|
||||||
|
something more sensible. (0 by default and N/2 for hilbert).
|
||||||
|
(#4980)
|
||||||
|
|
||||||
|
## Bluetooth
|
||||||
|
- Better xrun and error handling for iso streams.
|
||||||
|
- The +CNUM reply was fixed.
|
||||||
|
- The CIEC call status was fixed. (#1744)
|
||||||
|
- Add BAP context metadata to improve compatibility.
|
||||||
|
- Improve compatiblity with Creative Zen Hybrid Pro by releasing
|
||||||
|
transports simultaneously.
|
||||||
|
|
||||||
# PipeWire 1.5.83 (2025-11-06)
|
# PipeWire 1.5.83 (2025-11-06)
|
||||||
|
|
||||||
This is the third 1.6 release candidate that is API and ABI
|
This is the third 1.6 release candidate that is API and ABI
|
||||||
|
|
@ -8,9 +211,6 @@ Changes since the last pre-release:
|
||||||
## Highlights
|
## Highlights
|
||||||
- Include the NEWS and updated version number.
|
- Include the NEWS and updated version number.
|
||||||
|
|
||||||
|
|
||||||
Older versions:
|
|
||||||
|
|
||||||
# PipeWire 1.5.82 (2025-11-06)
|
# PipeWire 1.5.82 (2025-11-06)
|
||||||
|
|
||||||
This is the second 1.6 release candidate that is API and ABI
|
This is the second 1.6 release candidate that is API and ABI
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@
|
||||||
<tab type="usergroup" title="PipeWire Versions">
|
<tab type="usergroup" title="PipeWire Versions">
|
||||||
<tab type="user" url="https://docs.pipewire.org/1.2/" title="1.2.x"/>
|
<tab type="user" url="https://docs.pipewire.org/1.2/" title="1.2.x"/>
|
||||||
<tab type="user" url="https://docs.pipewire.org/1.4/" title="1.4.x"/>
|
<tab type="user" url="https://docs.pipewire.org/1.4/" title="1.4.x"/>
|
||||||
|
<tab type="user" url="https://docs.pipewire.org/1.6/" title="1.6.x"/>
|
||||||
<tab type="user" url="https://docs.pipewire.org/devel/" title="Development"/>
|
<tab type="user" url="https://docs.pipewire.org/devel/" title="Development"/>
|
||||||
</tab>
|
</tab>
|
||||||
</navindex>
|
</navindex>
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,14 @@ stream.properties = {
|
||||||
#node.autoconnect = true
|
#node.autoconnect = true
|
||||||
#resample.disable = false
|
#resample.disable = false
|
||||||
#resample.quality = 4
|
#resample.quality = 4
|
||||||
|
#resample.window = exp # blackman kaiser
|
||||||
|
#resample.cutoff = 0.0
|
||||||
|
#resample.n-taps = 0
|
||||||
|
#resample.param.exp.A = 0.0
|
||||||
|
#resample.param.blackman.alpha = 0.0
|
||||||
|
#resample.param.kaiser.alpha = 0.0
|
||||||
|
#resample.param.kaiser.stopband-attenuation = 0.0
|
||||||
|
#resample.param.kaiser.transition-bandwidth = 0.0
|
||||||
#monitor.channel-volumes = false
|
#monitor.channel-volumes = false
|
||||||
#channelmix.disable = false
|
#channelmix.disable = false
|
||||||
#channelmix.min-volume = 0.0
|
#channelmix.min-volume = 0.0
|
||||||
|
|
@ -72,6 +80,9 @@ stream.properties = {
|
||||||
#channelmix.fc-cutoff = 12000.0
|
#channelmix.fc-cutoff = 12000.0
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
||||||
|
|
|
||||||
|
|
@ -450,11 +450,25 @@ Whether the node target may be changed using metadata.
|
||||||
|
|
||||||
@PAR@ node-prop node.passive = false
|
@PAR@ node-prop node.passive = false
|
||||||
\parblock
|
\parblock
|
||||||
This is a passive node and so it should not keep sinks/sources busy. This property makes the session manager create passive links to the sink/sources. If the node is not otherwise linked (via a non-passive link), the node and the sink it is linked to are idle (and eventually suspended).
|
This can be used to configure the port.passive property for all ports of this node.
|
||||||
|
|
||||||
|
Possible values are:
|
||||||
|
|
||||||
|
* "out": output ports are passive, They will not make the peers active and active peers will
|
||||||
|
not make this node active.
|
||||||
|
* "in": input ports are passive, They will not make the peers active and active peers will
|
||||||
|
not make this node active.
|
||||||
|
* "true": A combination in "in" and "out", both input and output ports are passive.
|
||||||
|
* "out-follow": output ports will not make the peer active but when the peer is activated via
|
||||||
|
some other way, this node will also become active.
|
||||||
|
* "in-follow": input ports will not make the peer active but when the peer is activated via
|
||||||
|
some other way, this node will also become active.
|
||||||
|
* "follow": A combination of "in-follow" and "out-follow".
|
||||||
|
|
||||||
This is used for filter nodes that sit in front of sinks/sources and need to suspend together with the sink/source.
|
This is used for filter nodes that sit in front of sinks/sources and need to suspend together with the sink/source.
|
||||||
\endparblock
|
\endparblock
|
||||||
|
|
||||||
|
|
||||||
@PAR@ node-prop node.link-group = ID
|
@PAR@ node-prop node.link-group = ID
|
||||||
Add the node to a certain link group. Nodes from the same link group are not automatically linked to each other by the session manager. And example is a coupled stream where you don't want the output to link to the input streams, making a useless loop.
|
Add the node to a certain link group. Nodes from the same link group are not automatically linked to each other by the session manager. And example is a coupled stream where you don't want the output to link to the input streams, making a useless loop.
|
||||||
|
|
||||||
|
|
@ -547,17 +561,139 @@ Below is an explanation of the options that can be tuned in the sample converter
|
||||||
\parblock
|
\parblock
|
||||||
The quality of the resampler. from 0 to 14, the default is 4.
|
The quality of the resampler. from 0 to 14, the default is 4.
|
||||||
|
|
||||||
|
The quality of a resampler depends on multiple factors:
|
||||||
|
|
||||||
|
1. Anti-Aliasing, how well are unwanted frequencies filtered out. Poor anti-aliasing
|
||||||
|
will make the original inaudible frequencies audible as distortion and noise.
|
||||||
|
2. Cutoff frequency. At what frequency the transition band will start. This is the
|
||||||
|
frequency where the signal will start to fade out. A too low cutoff might remove too
|
||||||
|
much of the high frequencies and make the sound dull. A too high cutoff might cause
|
||||||
|
aliasing. The cutoff frequency is usually expressed as a ratio of the Nyquist
|
||||||
|
frequency, 1.0 being the Nyquist frequency (frequency/2).
|
||||||
|
3. Transition band length. How quickly the unwanted frequencies are filtered out. A
|
||||||
|
shorter transition band requires longer filters with more CPU and latency but
|
||||||
|
causes less aliasing. The transition band length is expressed as a ratio of the
|
||||||
|
Nyquist frequency.
|
||||||
|
4. Stopband attenuation. How well the unwanted frequencies are filtered out. This is
|
||||||
|
usually measured in dB. 96dB is below audible on CD quality audio, 150dB is below
|
||||||
|
the precision of floating point values.
|
||||||
|
5. CPU usage. Better anti-aliasing needs longer filters and is therefore more CPU
|
||||||
|
intensive.
|
||||||
|
6. Latency. Longer filters have a higher Latency. In real-time application the latency
|
||||||
|
should be kept as low as possible. The required latency is usually
|
||||||
|
(filter-length/2)/source-sample-rate, so a resample filter with length of 128 on a
|
||||||
|
48Khz signal has 1.3ms ((128/2)/48000) of latency.
|
||||||
|
7. Ringing. A too short transition band length might cause ringing because of how the
|
||||||
|
sinc filters work. This can sound like flutter on sharp attacks in the audio signal.
|
||||||
|
|
||||||
Increasing the quality will result in better cutoff and less aliasing at the expense of
|
Increasing the quality will result in better cutoff and less aliasing at the expense of
|
||||||
(much) more CPU consumption. The default quality of 4 has been selected as a good compromise
|
(much) more CPU consumption, latency and more ringing. The default quality of 4 has
|
||||||
between quality and performance with no artifacts that are well below the audible range.
|
been selected as a good compromise between quality and performance with no artifact
|
||||||
|
s that are well below the audible range.
|
||||||
|
|
||||||
|
The default resampler quality for the exp window results in a cutoff of 0.87 and a
|
||||||
|
filter size of about 48 taps. It has a Stopband attenuation of about 150 dB.
|
||||||
|
|
||||||
See [Infinite Wave](https://src.infinitewave.ca/) for a comparison of the performance.
|
See [Infinite Wave](https://src.infinitewave.ca/) for a comparison of the performance.
|
||||||
|
|
||||||
|
You can tune the resampler in a variaty of ways:
|
||||||
|
|
||||||
|
* Tune the cutoff frequency. Increase the cutoff to preserve more high frequencies at the
|
||||||
|
expense of more aliasing.
|
||||||
|
* Tune the transition band. Reduce the transition band to better filter out the frequencies
|
||||||
|
around the cutoff frequency and get less aliasing at the expense of more ringing, CPU and
|
||||||
|
Latency. This can be done by increasing the number of taps.
|
||||||
|
* Tune the stopband attenuation. Increase the attenuation to reduce aliasing at the expense
|
||||||
|
of a wider transition band. This can only be done on the kaiser window, the exp and
|
||||||
|
blackman window have 150dB and 96dB attenuation respecively.
|
||||||
\endparblock
|
\endparblock
|
||||||
|
|
||||||
@PAR@ node-prop resample.disable = false
|
@PAR@ node-prop resample.disable = false
|
||||||
Disable the resampler entirely. The node will only be able to negotiate with the graph
|
Disable the resampler entirely. The node will only be able to negotiate with the graph
|
||||||
when the samplerates are compatible.
|
when the samplerates are compatible.
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.window = exp
|
||||||
|
\parblock
|
||||||
|
The resampler window function to use. By default an exponential window function is used
|
||||||
|
that gives a good balance between complexitiy and quality.
|
||||||
|
|
||||||
|
You can also specify a blackman or kaiser window, both with different tradeoffs. The
|
||||||
|
kaiser window has some extra tunable parameters for the specific use cases.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.cutoff = 0.0
|
||||||
|
\parblock
|
||||||
|
The resampler cutoff frequency. This is a value between 0.0 and 1.0. A value of 0.0 will
|
||||||
|
use a predefined value based on the resampler quality.
|
||||||
|
|
||||||
|
A higher cutoff value will preserve more high frequency content but depending on the
|
||||||
|
size of the transition band will cause more aliasing.
|
||||||
|
|
||||||
|
The default quality 4 setting for all windows is 0.87.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.n-taps = 0
|
||||||
|
\parblock
|
||||||
|
The resampler number of taps. A value of 0 will use a predefined value based on
|
||||||
|
the resampler quality or other window function parameters.
|
||||||
|
|
||||||
|
A higher number of taps will use more CPU, Latency and cause more ringing but will
|
||||||
|
reduce aliasing.
|
||||||
|
|
||||||
|
The default quality setting for the exp window is 48.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.param.exp.A = 0.0
|
||||||
|
\parblock
|
||||||
|
The A parameter for the exponential window function. A value of 0.0 will use a predefined
|
||||||
|
value based on the quality when the exp window is in use.
|
||||||
|
|
||||||
|
The default setting for the exp window is 16.97789.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.param.blackman.alpha = 0.0
|
||||||
|
\parblock
|
||||||
|
The alpha value of the blackman function. A value of 0.0 will use a predefined
|
||||||
|
value based on the quality when the blackman window is in use.
|
||||||
|
|
||||||
|
The default quality setting for the blackman window is 0.16.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.param.kaiser.stopband-attenuation = 0.0
|
||||||
|
\parblock
|
||||||
|
The kaiser window stopband attenuation parameter in dB. A default value of 0.0 will use a
|
||||||
|
predefined value based on the quality.
|
||||||
|
|
||||||
|
A higher value will filter out more of the unwanted frequencies and reduce aliasing at the
|
||||||
|
expense of a larger transition band. A value of 96dB is below the dynamic range of CD quality
|
||||||
|
audio. 150dB is the limit of the precision of the resampler.
|
||||||
|
|
||||||
|
The default quality setting for the kaiser window is 130.000000.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.param.kaiser.transition-bandwidth = 0.0
|
||||||
|
\parblock
|
||||||
|
The kaiser window transition bandwidth parameter. A default value of 0.0 will use a
|
||||||
|
predefined value based on the quality.
|
||||||
|
|
||||||
|
A smaller transition band will cause a steeper cutoff with less unwanted frequencies
|
||||||
|
in the final signal at the expense of more a larger filter and more CPU usage and
|
||||||
|
latency. A smaller transition band can also cause more ringing.
|
||||||
|
|
||||||
|
The default quality setting for the kaiser window is 0.177032
|
||||||
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop resample.param.kaiser.alpha = 0.0
|
||||||
|
\parblock
|
||||||
|
The kaiser window alpha parameter. A default value of 0.0 will calculate an alpha value
|
||||||
|
based on the stopband-attenuation and transition-bandwidth parameters.
|
||||||
|
|
||||||
|
This value is usually calculated from the other parameters but can be set explicitly
|
||||||
|
with this property.
|
||||||
|
|
||||||
|
The default quality setting for the kaiser window is 4.254931.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
## Channel Mixer Parameters
|
## Channel Mixer Parameters
|
||||||
|
|
||||||
Source, sinks, capture and playback streams can apply channel mixing on the incoming signal.
|
Source, sinks, capture and playback streams can apply channel mixing on the incoming signal.
|
||||||
|
|
@ -647,6 +783,15 @@ more to the center speaker and leaves the ambient sound in the stereo channels.
|
||||||
This is only active when up-mix is enabled and a Front Center channel is mixed.
|
This is only active when up-mix is enabled and a Front Center channel is mixed.
|
||||||
\endparblock
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ node-prop channelmix.center-level = 0.707106781
|
||||||
|
The level of the center channel when up/downmixing.
|
||||||
|
|
||||||
|
@PAR@ node-prop channelmix.surround-level = 0.707106781
|
||||||
|
The level of the surround channels when up/downmixing.
|
||||||
|
|
||||||
|
@PAR@ node-prop channelmix.lfe-level = 0.5
|
||||||
|
The level of the LFE channel when up/downmixing.
|
||||||
|
|
||||||
@PAR@ node-prop channelmix.hilbert-taps = 0
|
@PAR@ node-prop channelmix.hilbert-taps = 0
|
||||||
\parblock
|
\parblock
|
||||||
This option will apply a 90 degree phase shift to the rear channels to improve specialization.
|
This option will apply a 90 degree phase shift to the rear channels to improve specialization.
|
||||||
|
|
@ -1018,6 +1163,15 @@ HFP/HSP backend (default: native). Available values: any, none, hsphfpd, ofono,
|
||||||
|
|
||||||
@PAR@ monitor-prop bluez5.hfphsp-backend-native-modem # string
|
@PAR@ monitor-prop bluez5.hfphsp-backend-native-modem # string
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.hfphsp-backend-native-pts # boolean
|
||||||
|
Enable specific workarounds for Bluetooth qualification.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.disable-dummy-call # boolean
|
||||||
|
By default a call status event is sent on audio stream connection/disconnection to
|
||||||
|
workaround some headset timeout disconnection when the HFP HF is used by another
|
||||||
|
application than telephony one, e.g. a conference application/website.
|
||||||
|
This prevent to send this event.
|
||||||
|
|
||||||
@PAR@ monitor-prop bluez5.dummy-avrcp player # boolean
|
@PAR@ monitor-prop bluez5.dummy-avrcp player # boolean
|
||||||
Register dummy AVRCP player. Some devices have wrongly functioning
|
Register dummy AVRCP player. Some devices have wrongly functioning
|
||||||
volume or playback controls if this is not enabled. Default: false
|
volume or playback controls if this is not enabled. Default: false
|
||||||
|
|
@ -1040,6 +1194,15 @@ in a platform-specific way. See `tests/examples/bt-pinephone.lua` in WirePlumber
|
||||||
Do not enable this setting if you don't know what all this means, as it won't work.
|
Do not enable this setting if you don't know what all this means, as it won't work.
|
||||||
\endparblock
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.hw-offload-datapath # integer
|
||||||
|
\parblock
|
||||||
|
HFP/HSP hardware offload data path ID (default: 0).
|
||||||
|
|
||||||
|
This feature configures the SCO hardware‑offload data path for HFP/HSP using the Bluetooth
|
||||||
|
SIG–specified procedure. It is intended for advanced setups and vendor integrations. Do not
|
||||||
|
edit this unless required; incorrect values can disable SCO offload.
|
||||||
|
\endparblock
|
||||||
|
|
||||||
@PAR@ monitor-prop bluez5.a2dp.opus.pro.channels = 3 # integer
|
@PAR@ monitor-prop bluez5.a2dp.opus.pro.channels = 3 # integer
|
||||||
PipeWire Opus Pro audio profile channel count.
|
PipeWire Opus Pro audio profile channel count.
|
||||||
|
|
||||||
|
|
@ -1071,6 +1234,7 @@ PipeWire Opus Pro audio profile duplex max bitrate.
|
||||||
PipeWire Opus Pro audio profile duplex frame duration (1/10 ms).
|
PipeWire Opus Pro audio profile duplex frame duration (1/10 ms).
|
||||||
|
|
||||||
@PAR@ monitor-prop bluez5.bcast_source.config = [] # JSON
|
@PAR@ monitor-prop bluez5.bcast_source.config = [] # JSON
|
||||||
|
For a per-adapter configuration of multiple BIGs use an "adapter" entry in the BIG with the BD address.
|
||||||
\parblock
|
\parblock
|
||||||
Example:
|
Example:
|
||||||
```
|
```
|
||||||
|
|
@ -1127,6 +1291,18 @@ Available sink contexts PACS bitmask of the the server.
|
||||||
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.supported-contexts # integer
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.supported-contexts # integer
|
||||||
Supported sink contexts PACS bitmask of the the server.
|
Supported sink contexts PACS bitmask of the the server.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.delay-min # integer
|
||||||
|
Minimum presentation delay supported, in microseconds.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.delay-max # integer
|
||||||
|
Maximum presentation delay supported, in microseconds.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.preferred-delay-min # integer
|
||||||
|
Minimum preferred presentation delay supported, in microseconds.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.sink.preferred-delay-max # integer
|
||||||
|
Maximum preferred presentation delay supported, in microseconds.
|
||||||
|
|
||||||
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.locations # JSON or integer
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.locations # JSON or integer
|
||||||
Source audio locations of the server, as channel positions or PACS bitmask.
|
Source audio locations of the server, as channel positions or PACS bitmask.
|
||||||
Example: `FL,FR`
|
Example: `FL,FR`
|
||||||
|
|
@ -1137,6 +1313,30 @@ Available source contexts PACS bitmask of the the server.
|
||||||
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.supported-contexts # integer
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.supported-contexts # integer
|
||||||
Supported source contexts PACS bitmask of the the server.
|
Supported source contexts PACS bitmask of the the server.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.delay-min # integer
|
||||||
|
Minimum presentation delay supported, in microseconds.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.delay-max # integer
|
||||||
|
Maximum presentation delay supported, in microseconds.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.preferred-delay-min # integer
|
||||||
|
Minimum preferred presentation delay supported, in microseconds.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-capabilities.source.preferred-delay-max # integer
|
||||||
|
Maximum preferred presentation delay supported, in microseconds.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-tmap-features = null # array of string
|
||||||
|
Override advertised TMAP service features. See TMAP specification for their meaning.
|
||||||
|
Possible values: "cg", "ct", "ums", "umr", "bms", "bmr".
|
||||||
|
Default: none.
|
||||||
|
|
||||||
|
@PAR@ monitor-prop bluez5.bap-server-gmap-features = null # array of string
|
||||||
|
Override advertised GMAP service features. See GMAP specification for their meaning.
|
||||||
|
Possible values: "ugg", "ugt", "bgs", "bgr", "ugg-multiplex", "ugg-96kbps-source", "ugg-multisink",
|
||||||
|
"ugt-source", "ugt-80kbps-source", "ugt-sink", "ugt-64kbps-sink", "ugt-multiplex", "ugt-multisink",
|
||||||
|
"ugt-multisource", "bgs-96kbps", "bgr-multisink", "bgr-multiplex".
|
||||||
|
Default: none.
|
||||||
|
|
||||||
## Device properties
|
## Device properties
|
||||||
|
|
||||||
@PAR@ device-prop bluez5.auto-connect # boolean
|
@PAR@ device-prop bluez5.auto-connect # boolean
|
||||||
|
|
@ -1196,6 +1396,12 @@ BAP QoS framing that needs to be applied for vendor defined preset
|
||||||
This property is experimental.
|
This property is experimental.
|
||||||
Default: as per QoS preset.
|
Default: as per QoS preset.
|
||||||
|
|
||||||
|
@PAR@ device-prop bluez5.bap.force-target-latency = "balanced" # string
|
||||||
|
BAP QoS target latency profile forced for QoS configuration selection.
|
||||||
|
If not set or set to "balanced", both low-latency and high-reliability QoS configuration table are used.
|
||||||
|
This property is experimental.
|
||||||
|
Available: low-latency, high-reliability, balanced
|
||||||
|
|
||||||
## Node properties
|
## Node properties
|
||||||
|
|
||||||
@PAR@ node-prop bluez5.media-source-role # string
|
@PAR@ node-prop bluez5.media-source-role # string
|
||||||
|
|
@ -1217,6 +1423,10 @@ Latency adjustment to apply on the node. Larger values add a
|
||||||
constant latency, but reduces timing jitter caused by Bluetooth
|
constant latency, but reduces timing jitter caused by Bluetooth
|
||||||
transport.
|
transport.
|
||||||
|
|
||||||
|
@PAR@ node-prop bluez5.debug.iso-mono = false # boolean
|
||||||
|
Debugging option for forcing ISO sinks send identical packets out for
|
||||||
|
all streams.
|
||||||
|
|
||||||
# PORT PROPERTIES @IDX@ props
|
# PORT PROPERTIES @IDX@ props
|
||||||
|
|
||||||
Port properties are usually not directly configurable via PipeWire
|
Port properties are usually not directly configurable via PipeWire
|
||||||
|
|
@ -1233,6 +1443,11 @@ them. Below are some port properties may interesting for users:
|
||||||
\copydoc PW_KEY_PORT_ALIAS
|
\copydoc PW_KEY_PORT_ALIAS
|
||||||
\endparblock
|
\endparblock
|
||||||
|
|
||||||
|
@PAR@ port-prop port.passive # string
|
||||||
|
\parblock
|
||||||
|
\copydoc PW_KEY_PORT_PASSIVE
|
||||||
|
\endparblock
|
||||||
|
|
||||||
\see pw_keys in the API documentation for a full list.
|
\see pw_keys in the API documentation for a full list.
|
||||||
|
|
||||||
# LINK PROPERTIES @IDX@ props
|
# LINK PROPERTIES @IDX@ props
|
||||||
|
|
|
||||||
|
|
@ -93,6 +93,9 @@ stream.properties = {
|
||||||
#channelmix.fc-cutoff = 12000.0
|
#channelmix.fc-cutoff = 12000.0
|
||||||
#channelmix.rear-delay = 12.0
|
#channelmix.rear-delay = 12.0
|
||||||
#channelmix.stereo-widen = 0.0
|
#channelmix.stereo-widen = 0.0
|
||||||
|
#channelmix.center-level = 0.707106781
|
||||||
|
#channelmix.surround-level = 0.707106781
|
||||||
|
#channelmix.lfe-level = 0.5
|
||||||
#channelmix.hilbert-taps = 0
|
#channelmix.hilbert-taps = 0
|
||||||
#dither.noise = 0
|
#dither.noise = 0
|
||||||
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
#dither.method = none # rectangular, triangular, triangular-hf, wannamaker3, shaped5
|
||||||
|
|
|
||||||
|
|
@ -6,31 +6,55 @@ The PipeWire server configuration file
|
||||||
|
|
||||||
# SYNOPSIS
|
# SYNOPSIS
|
||||||
|
|
||||||
|
*$PIPEWIRE_CONFIG_DIR/pipewire/pipewire.conf*
|
||||||
|
|
||||||
*$XDG_CONFIG_HOME/pipewire/pipewire.conf*
|
*$XDG_CONFIG_HOME/pipewire/pipewire.conf*
|
||||||
|
|
||||||
*$(PIPEWIRE_CONFIG_DIR)/pipewire.conf*
|
*$(PIPEWIRE_CONFIG_DIR)/pipewire.conf*
|
||||||
|
|
||||||
*$(PIPEWIRE_CONFDATADIR)/pipewire.conf*
|
*$(PIPEWIRE_CONFDATADIR)/pipewire.conf*
|
||||||
|
|
||||||
|
*$PIPEWIRE_CONFIG_DIR/pipewire/pipewire.conf.d/*
|
||||||
|
|
||||||
*$(PIPEWIRE_CONFDATADIR)/pipewire.conf.d/*
|
*$(PIPEWIRE_CONFDATADIR)/pipewire.conf.d/*
|
||||||
|
|
||||||
*$(PIPEWIRE_CONFIG_DIR)/pipewire.conf.d/*
|
*$(PIPEWIRE_CONFIG_DIR)/pipewire.conf.d/*
|
||||||
|
|
||||||
*$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/*
|
*$XDG_CONFIG_HOME/pipewire/pipewire.conf.d/*
|
||||||
|
|
||||||
|
|
||||||
# DESCRIPTION
|
# DESCRIPTION
|
||||||
|
|
||||||
PipeWire is a service that facilitates sharing of multimedia content
|
PipeWire is a service that facilitates sharing of multimedia content
|
||||||
between devices and applications.
|
between devices and applications.
|
||||||
|
|
||||||
On startup, the daemon reads a main configuration file to configure
|
On startup, the daemon reads a main configuration file to configure
|
||||||
itself. It executes a series of commands listed in the config file.
|
itself. After that it will apply a set of drop-in config overrides.
|
||||||
|
|
||||||
The config file is looked up in the order listed in the
|
By default the pipewire daemon will read `pipewire.conf` and looks
|
||||||
[SYNOPSIS](#synopsis). The environment variables `PIPEWIRE_CONFIG_DIR`,
|
for drop-in config files in the `pipewire.conf.d` subdirectory.
|
||||||
`PIPEWIRE_CONFIG_PREFIX` and `PIPEWIRE_CONFIG_NAME` can be used to
|
The environment variable `PIPEWIRE_CONFIG_NAME` can be used to specify
|
||||||
specify an alternative config directory, subdirectory and file
|
an alternative config file name and the drop-in config file directory
|
||||||
respectively.
|
name (by appending `.d` to the config name).
|
||||||
|
|
||||||
|
The config file and the drop-in config directories are looked up in
|
||||||
|
the order listed in the [SYNOPSIS](#synopsis).
|
||||||
|
|
||||||
|
If the environment variable `PIPEWIRE_CONFIG_DIR` is set, it is the
|
||||||
|
only place where the main config file and the drop-in config files
|
||||||
|
are looked up.
|
||||||
|
|
||||||
|
If the environment variable `PIPEWIRE_CONFIG_PREFIX` contains an
|
||||||
|
absolute path, it will be searched first for the main config file and
|
||||||
|
the drop-in config files.
|
||||||
|
If `PIPEWIRE_CONFIG_PREFIX` does not contain an absolute path, it is
|
||||||
|
used as a subdirectory to locate the main config file and the drop-in
|
||||||
|
config files.
|
||||||
|
|
||||||
|
When the environment variable `PIPEWIRE_NO_CONFIG` is set to `true`,
|
||||||
|
only the data config directory $(PIPEWIRE_CONFDATADIR) is searched.
|
||||||
|
This is useful when you want to run with the default configuration
|
||||||
|
without any system or user overrides.
|
||||||
|
|
||||||
Other PipeWire configuration files generally follow the same lookup
|
Other PipeWire configuration files generally follow the same lookup
|
||||||
logic, replacing `pipewire.conf` with the name of the particular
|
logic, replacing `pipewire.conf` with the name of the particular
|
||||||
|
|
@ -38,11 +62,19 @@ config file.
|
||||||
|
|
||||||
# DROP-IN CONFIGURATION FILES @IDX@ pipewire.conf
|
# DROP-IN CONFIGURATION FILES @IDX@ pipewire.conf
|
||||||
|
|
||||||
|
The config file drop-in overrides are looked up in the order
|
||||||
|
of the `pipewire.conf.d` directories listed in the[SYNOPSIS](#synopsis).
|
||||||
|
|
||||||
All `*.conf` files in the `pipewire.conf.d/` directories are loaded
|
All `*.conf` files in the `pipewire.conf.d/` directories are loaded
|
||||||
and merged into the configuration. Dictionary sections are merged,
|
in alphabetical order and merged into the main configuration.
|
||||||
overriding properties if they already existed, and array sections are
|
Dictionary sections are merged, overriding properties if they already
|
||||||
appended to. The drop-in files have same format as the main
|
existed, and array sections are appended to. The drop-in files have
|
||||||
configuration file, but only contain the settings to be modified.
|
same format as the main configuration file, but only contain the
|
||||||
|
settings to be modified.
|
||||||
|
|
||||||
|
If a config overrides with the same name exists in multiple `conf.d`
|
||||||
|
directories, the one from the last directory in the above search order
|
||||||
|
is used.
|
||||||
|
|
||||||
As the `pipewire.conf` configuration file contains various parts
|
As the `pipewire.conf` configuration file contains various parts
|
||||||
that must be present for correct functioning, using drop-in files
|
that must be present for correct functioning, using drop-in files
|
||||||
|
|
@ -256,6 +288,12 @@ Default video rate denominator
|
||||||
@PAR@ pipewire.conf library.name.system = support/libspa-support
|
@PAR@ pipewire.conf library.name.system = support/libspa-support
|
||||||
The name of the shared library to use for the system functions for the main thread.
|
The name of the shared library to use for the system functions for the main thread.
|
||||||
|
|
||||||
|
@PAR@ pipewire.conf library.use-fallback = true
|
||||||
|
When a plugin feature is not listed in context.spa-libs, a predefined fallback
|
||||||
|
plugin location is used by default. If this option is set to false, only plugin
|
||||||
|
features explicitly listed in context.spa-libs will be loadable. This can be used
|
||||||
|
to lock down what plugins that can be loaded.
|
||||||
|
|
||||||
@PAR@ pipewire.conf link.max-buffers = 64
|
@PAR@ pipewire.conf link.max-buffers = 64
|
||||||
The maximum number of buffers to negotiate between nodes. Note that version < 3 clients
|
The maximum number of buffers to negotiate between nodes. Note that version < 3 clients
|
||||||
can only support 16 buffers. More buffers is almost always worse than less, latency
|
can only support 16 buffers. More buffers is almost always worse than less, latency
|
||||||
|
|
@ -326,6 +364,8 @@ factory-name and the plugin where the factory can be found.
|
||||||
Factory names can contain a wildcard to group several related factories into one
|
Factory names can contain a wildcard to group several related factories into one
|
||||||
plugin. The plugin is loaded from the first matching factory-name.
|
plugin. The plugin is loaded from the first matching factory-name.
|
||||||
|
|
||||||
|
A special `blocked` value for the plugin disables the factory-name.
|
||||||
|
|
||||||
## Example
|
## Example
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
@ -342,6 +382,7 @@ context.spa-libs = {
|
||||||
api.jack.* = jack/libspa-jack
|
api.jack.* = jack/libspa-jack
|
||||||
support.* = support/libspa-support
|
support.* = support/libspa-support
|
||||||
video.convert.* = videoconvert/libspa-videoconvert
|
video.convert.* = videoconvert/libspa-videoconvert
|
||||||
|
#filter.graph = blocked
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -301,5 +301,118 @@ they complete processing the buffer. This can be done in the hardware as part of
|
||||||
the render pipeline or explicitly with drmSyncobjTimelineSignal() on the release
|
the render pipeline or explicitly with drmSyncobjTimelineSignal() on the release
|
||||||
handle and the release_point of the metadata.
|
handle and the release_point of the metadata.
|
||||||
|
|
||||||
|
# Device ID negotation
|
||||||
|
|
||||||
|
The DRM device used for accessing or allocating DMA-BUFs by default undefined. To
|
||||||
|
negotiate what DRM device should be used, and to advertise what DRM device is associated
|
||||||
|
with what combination of format and list of modifiers, device ID negotiation can be
|
||||||
|
performed.
|
||||||
|
|
||||||
|
## Capability discovery
|
||||||
|
|
||||||
|
Device ID negotiation needs explicit support by both end points of a stream, thus, the
|
||||||
|
first step of negotiation is discovering whether other peer has support for it. This is
|
||||||
|
done by advertising a \ref SPA_PARAM_Capability with the key \ref
|
||||||
|
PW_CAPABILITY_DEVICE_ID_NEGOTIATION and value `1` which corresponds to the
|
||||||
|
current negotiation API version.
|
||||||
|
|
||||||
|
```
|
||||||
|
spa_param_dict_build_dict(&b, SPA_PARAM_Capability,
|
||||||
|
&SPA_DICT_ITEMS(
|
||||||
|
SPA_DICT_ITEM(PW_CAPABILITY_DEVICE_ID_NEGOTIATION, "1")));
|
||||||
|
```
|
||||||
|
|
||||||
|
To do this, when connecting to the stream, the \ref PW_STREAM_FLAG_INACTIVE flag must be
|
||||||
|
passed, and a bare minimum video format parameter must be sent. A bare minimum video
|
||||||
|
format parameter must contain a \ref SPA_FORMAT_mediaType with \ref SPA_MEDIA_TYPE_video;
|
||||||
|
\ref SPA_FORMAT_mediaSubtype with \ref SPA_MEDIA_SUBTYPE_raw, \ref SPA_FORMAT_VIDEO_format
|
||||||
|
with something appropriate, and a \ref SPA_FORMAT_VIDEO_size with a rectangle or range of
|
||||||
|
rectangles. For example
|
||||||
|
|
||||||
|
```
|
||||||
|
spa_pod_builder_push_object(&b, &f, SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_mediaType,
|
||||||
|
SPA_POD_Id (SPA_MEDIA_TYPE_video),
|
||||||
|
0);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_mediaSubtype,
|
||||||
|
SPA_POD_Id (SPA_MEDIA_SUBTYPE_raw),
|
||||||
|
0);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_VIDEO_format,
|
||||||
|
SPA_POD_Id(SPA_VIDEO_FORMAT_RGBA),
|
||||||
|
0);
|
||||||
|
spa_pod_builder_add(&b, SPA_FORMAT_VIDEO_size,
|
||||||
|
SPA_POD_CHOICE_RANGE_Rectangle(
|
||||||
|
&SPA_RECTANGLE(320, 240),
|
||||||
|
&SPA_RECTANGLE(1,1),
|
||||||
|
&SPA_RECTANGLE(8192, 8192)),
|
||||||
|
0);
|
||||||
|
params[n_params++] = spa_pod_builder_pop(&b, &f);
|
||||||
|
```
|
||||||
|
|
||||||
|
After having received the first \ref SPA_PARAM_PeerCapability param, if it contained the
|
||||||
|
\ref PW_CAPABILITY_DEVICE_ID_NEGOTIATION set to a supported API version number, the full
|
||||||
|
set of formats can be sent using \ref pw_stream_update_params following by activating the
|
||||||
|
stream usina supported API version numberstream_set_active(stream, true)`.
|
||||||
|
|
||||||
|
Note that the first \ref SPA_PARAM_Format received may be the result of the initial format
|
||||||
|
negotian with bare minimum parameters, and will be superseded by the result of the format
|
||||||
|
negotiation of the later provided format parameters.
|
||||||
|
|
||||||
|
## Device subset capability
|
||||||
|
|
||||||
|
A producer can advertise what devices it's capable of performing device ID negotiation
|
||||||
|
with. This can be used to reduce the amount of devices that are queried for format
|
||||||
|
metadata, which can be a time consuming task, if devices needs to be woken up.
|
||||||
|
|
||||||
|
To achieve this, the consumer adds another \ref SPA_PARAM_PeerCapability item with the key
|
||||||
|
\ref PW_CAPABILITY_DEVICE_IDS set to a JSON object describing what device IDs are supported.
|
||||||
|
|
||||||
|
This JSON object as of version 1 contains a single key "available-devices" that contain
|
||||||
|
a list of hexadecimal encoded `dev_t` device IDs.
|
||||||
|
|
||||||
|
```
|
||||||
|
char *device_ids = "{\"available-devices\": [\"6464000000000000\",\"c8c8000000000000\"]}";
|
||||||
|
&SPA_DICT_ITEMS(
|
||||||
|
SPA_DICT_ITEM(PW_CAPABILITY_DEVICE_ID_NEGOTIATION, "1"),
|
||||||
|
SPA_DICT_ITEM(PW_CAPABILITY_DEVICE_IDS, device_ids)));
|
||||||
|
```
|
||||||
|
|
||||||
|
## Device ID aware formats
|
||||||
|
|
||||||
|
When both the source and the sink advertises support for device ID negotation, format
|
||||||
|
entries must have a device ID set.
|
||||||
|
|
||||||
|
A device ID is represented as a byte array containing a `dev_t` (see `man 3type dev_t`)
|
||||||
|
device identifier.
|
||||||
|
|
||||||
|
Each format with an associated DRM device (i.e. including all but not only formats with
|
||||||
|
modifiers) must have a \ref SPA_FORMAT_VIDEO_deviceId entry with the \ref
|
||||||
|
SPA_POD_PROP_FLAG_MANDATORY set. E.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
dev_t device_id;
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
spa_pod_builder_prop(&b, SPA_FORMAT_VIDEO_deviceId,
|
||||||
|
SPA_POD_PROP_FLAG_MANDATORY);
|
||||||
|
spa_pod_builder_bytes(&b, &device_id, sizeof device_id);
|
||||||
|
```
|
||||||
|
|
||||||
|
## Negotiated device ID
|
||||||
|
|
||||||
|
Once a format is finally negotiated, the resulting device ID is exposed as a \ref
|
||||||
|
SPA_FORMAT_VIDEO_deviceId and may be retrieved by e.g.
|
||||||
|
|
||||||
|
```
|
||||||
|
device_prop = spa_pod_find_prop(format, NULL, SPA_FORMAT_VIDEO_deviceId);
|
||||||
|
spa_pod_parse_object(format,
|
||||||
|
SPA_TYPE_OBJECT_Format, NULL,
|
||||||
|
SPA_FORMAT_VIDEO_deviceId,
|
||||||
|
SPA_POD_OPT_Bytes(&bytes, &size));
|
||||||
|
```
|
||||||
|
|
||||||
|
This device should be used for accessing the associated DMA-BUFs, by e.g. creating a
|
||||||
|
`EGLDisplay` using `EGL_PLATFORM_DEVICE_EXT`.
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -32,8 +32,11 @@ updated as follows:
|
||||||
|
|
||||||
- \ref spa_io_clock::nsec : Must be set to the time (according to the monotonic
|
- \ref spa_io_clock::nsec : Must be set to the time (according to the monotonic
|
||||||
system clock) when the cycle that the driver is about to trigger started. To
|
system clock) when the cycle that the driver is about to trigger started. To
|
||||||
minimize jitter, it is usually a good idea to increment this by a fixed amount
|
minimize jitter, it is usually a good idea to increment this by a computed
|
||||||
|
amount (instead of sampling a timestamp from the monotonic system clock)
|
||||||
except for when the driver starts and when discontinuities occur in its clock.
|
except for when the driver starts and when discontinuities occur in its clock.
|
||||||
|
The computed amount can be fixed, or varying over time, for example due to
|
||||||
|
adjustments made by a DLL (more on that below).
|
||||||
- \ref spa_io_clock::rate : Set to a value that can translate samples to nanoseconds.
|
- \ref spa_io_clock::rate : Set to a value that can translate samples to nanoseconds.
|
||||||
- \ref spa_io_clock::position : Current cycle position, in samples. This is the
|
- \ref spa_io_clock::position : Current cycle position, in samples. This is the
|
||||||
ideal position of the graph cycle (this is explained in greater detail further below).
|
ideal position of the graph cycle (this is explained in greater detail further below).
|
||||||
|
|
@ -52,7 +55,7 @@ updated as follows:
|
||||||
some cases, this may actually be in the past relative to nsec, for example, when
|
some cases, this may actually be in the past relative to nsec, for example, when
|
||||||
some internal driver clock experienced a discontinuity. Consider setting the
|
some internal driver clock experienced a discontinuity. Consider setting the
|
||||||
\ref SPA_IO_CLOCK_FLAG_DISCONT flag in such a case. Just like with nsec, to
|
\ref SPA_IO_CLOCK_FLAG_DISCONT flag in such a case. Just like with nsec, to
|
||||||
minimize jitter, it is usually a good idea to increment this by a fixed amount
|
minimize jitter, it is usually a good idea to increment this by a computed amount
|
||||||
except for when the driver starts and when discontinuities occur in its clock.
|
except for when the driver starts and when discontinuities occur in its clock.
|
||||||
|
|
||||||
The driver node signals the start of the graph cycle by calling \ref spa_node_call_ready
|
The driver node signals the start of the graph cycle by calling \ref spa_node_call_ready
|
||||||
|
|
@ -60,6 +63,11 @@ with the \ref SPA_STATUS_HAVE_DATA and \ref SPA_STATUS_NEED_DATA flags passed
|
||||||
to that function call. That call must happen inside the thread that runs the
|
to that function call. That call must happen inside the thread that runs the
|
||||||
data loop assigned to the driver node.
|
data loop assigned to the driver node.
|
||||||
|
|
||||||
|
Drivers must make sure that the next cycle is started at the time indicated by
|
||||||
|
the \ref spa_io_clock::next_nsec timestamp. They do not have to use the monotonic
|
||||||
|
clock itself for scheduling the next cycle. If for example the internal clock
|
||||||
|
can directly be used with \c timerfd , the next cycle can be triggered that way.
|
||||||
|
|
||||||
As mentioned above, the \ref spa_io_clock::position field is the _ideal_ position
|
As mentioned above, the \ref spa_io_clock::position field is the _ideal_ position
|
||||||
of the graph cycle, in samples. This contrasts with \ref spa_io_clock::nsec, which
|
of the graph cycle, in samples. This contrasts with \ref spa_io_clock::nsec, which
|
||||||
is the moment in monotonic clock time when the cycle _actually_ happens. This is an
|
is the moment in monotonic clock time when the cycle _actually_ happens. This is an
|
||||||
|
|
@ -103,11 +111,12 @@ expected position (in samples) and the actual position (derived from the current
|
||||||
of the driver's internal clock), passes the delta between these two quantities into the
|
of the driver's internal clock), passes the delta between these two quantities into the
|
||||||
DLL, and the DLL computes a correction factor (2.0 in the above example) which is used
|
DLL, and the DLL computes a correction factor (2.0 in the above example) which is used
|
||||||
for scaling durations between \c timerfd timeouts. This forms a control loop, since the
|
for scaling durations between \c timerfd timeouts. This forms a control loop, since the
|
||||||
correction factor causes the durations between the timeouts to be adjusted such that the
|
correction factor causes the \ref spa_io_clock::next_nsec increments (that is, the
|
||||||
difference between the expected position and the actual position reaches zero. Keep in
|
durations between the timerfd timeouts) to be adjusted such that, over time, the difference
|
||||||
mind the notes above about \ref spa_io_clock::position being the ideal position of the
|
between the expected position and the actual position reaches zero. Keep in mind the
|
||||||
graph cycle, meaning that even in this case, the duration it is incremented by is
|
notes above about \ref spa_io_clock::position being the ideal position of the graph
|
||||||
_not_ scaled by the correction factor; the duration in samples remains unchanged.
|
cycle, meaning that even in this case, the duration it is incremented by is _not_
|
||||||
|
scaled by the correction factor; the duration in samples remains unchanged.
|
||||||
|
|
||||||
(Other popular control loop mechanisms that are suitable alternatives to the DLL are
|
(Other popular control loop mechanisms that are suitable alternatives to the DLL are
|
||||||
PID controllers and Kalman filters.)
|
PID controllers and Kalman filters.)
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
- \subpage page_objects_design
|
- \subpage page_objects_design
|
||||||
- \subpage page_library
|
- \subpage page_library
|
||||||
- \subpage page_dma_buf
|
- \subpage page_dma_buf
|
||||||
|
- \subpage page_running
|
||||||
- \subpage page_scheduling
|
- \subpage page_scheduling
|
||||||
- \subpage page_driver
|
- \subpage page_driver
|
||||||
- \subpage page_latency
|
- \subpage page_latency
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ down and upstream.
|
||||||
# Async nodes
|
# Async nodes
|
||||||
|
|
||||||
When a node has the node.async property set to true, it will be considered an async
|
When a node has the node.async property set to true, it will be considered an async
|
||||||
node and will be scheduled differently, see scheduling.dox.
|
node and will be scheduled differently, see \ref page_scheduling .
|
||||||
|
|
||||||
A link between a port of an async node and another port (async or not) is called an
|
A link between a port of an async node and another port (async or not) is called an
|
||||||
async link and will have the link.async=true property.
|
async link and will have the link.async=true property.
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,13 @@ As of 1.4, SPA_CONTROL_UMP (Universal Midi Packet) is the prefered format
|
||||||
for the MIDI 1.0 and 2.0 messages in the \ref spa_pod_sequence. Conversion
|
for the MIDI 1.0 and 2.0 messages in the \ref spa_pod_sequence. Conversion
|
||||||
to SPA_CONTROL_Midi is performed for legacy applications.
|
to SPA_CONTROL_Midi is performed for legacy applications.
|
||||||
|
|
||||||
|
As of 1.7 the prefered format is Midi1 again because most devices and
|
||||||
|
applications are still Midi1 and conversions between Midi1 and UMP are not
|
||||||
|
completely transparent in ALSA and PipeWire. UMP in the ALSA sequencer
|
||||||
|
and consumers must be enabled explicitly. UMP in producers is supported
|
||||||
|
still and will be converted to Midi1 by all consumers that did not explicitly
|
||||||
|
enable UMP support.
|
||||||
|
|
||||||
## The PipeWire Daemon
|
## The PipeWire Daemon
|
||||||
|
|
||||||
Nothing special is implemented for MIDI. Negotiation of formats
|
Nothing special is implemented for MIDI. Negotiation of formats
|
||||||
|
|
@ -104,13 +111,14 @@ filtering out the \ref SPA_CONTROL_Midi, \ref SPA_CONTROL_OSC and
|
||||||
\ref SPA_CONTROL_UMP types. On output ports, the JACK event stream is
|
\ref SPA_CONTROL_UMP types. On output ports, the JACK event stream is
|
||||||
converted to control messages in a similar way.
|
converted to control messages in a similar way.
|
||||||
|
|
||||||
Normally, all MIDI and UMP messages are converted to MIDI1 jack events unless
|
Normally, all MIDI and UMP input messages are converted to MIDI1 jack
|
||||||
the JACK port was created with an explcit "32 bit raw UMP" format or with
|
events unless the JACK port was created with an explcit "32 bit raw UMP"
|
||||||
the JackPortIsMIDI2 flag, in which case the raw UMP is passed to the JACK
|
format or with the JackPortIsMIDI2 flag, in which case the messages are
|
||||||
application directly. For output ports,
|
converted to UMP or passed on directly.
|
||||||
the JACK events are assumed to be MIDI1 and converted to UMP unless the port
|
|
||||||
has the "32 bit raw UMP" format or the JackPortIsMIDI2 flag, in which case
|
For output ports, the JACK events are assumed to be
|
||||||
the UMP messages are simply passed on.
|
MIDI1 unless the port has the "32 bit raw UMP" format or the JackPortIsMIDI2
|
||||||
|
flag, in which case the control messages are assumed to be UMP.
|
||||||
|
|
||||||
There is a 1 to 1 mapping between the JACK events and control
|
There is a 1 to 1 mapping between the JACK events and control
|
||||||
messages so there is no information loss or need for complicated
|
messages so there is no information loss or need for complicated
|
||||||
|
|
|
||||||
|
|
@ -1130,6 +1130,8 @@ follows:
|
||||||
|<----------------------------------------|
|
|<----------------------------------------|
|
||||||
| ClientNode::PortSetMixInfo | mixer inputs for each linked port
|
| ClientNode::PortSetMixInfo | mixer inputs for each linked port
|
||||||
|<----------------------------------------|
|
|<----------------------------------------|
|
||||||
|
| ClientNode::PortSetParam | PeerCapability of the ports
|
||||||
|
|<----------------------------------------|
|
||||||
| ClientNode::PortSetParam | Latency of the ports
|
| ClientNode::PortSetParam | Latency of the ports
|
||||||
|<----------------------------------------|
|
|<----------------------------------------|
|
||||||
| ClientNode::SetActivation | activation of port peers
|
| ClientNode::SetActivation | activation of port peers
|
||||||
|
|
|
||||||
393
doc/dox/internals/running.dox
Normal file
393
doc/dox/internals/running.dox
Normal file
|
|
@ -0,0 +1,393 @@
|
||||||
|
/** \page page_running Node running
|
||||||
|
|
||||||
|
This document tries to explain how the Nodes in a PipeWire graph become
|
||||||
|
runnable so that they can be scheduled later.
|
||||||
|
|
||||||
|
It also describes how nodes are grouped together and scheduled together.
|
||||||
|
|
||||||
|
# Runnable Nodes
|
||||||
|
|
||||||
|
A runnable node is a node that will participate in the dataflow in the
|
||||||
|
PipeWire graph.
|
||||||
|
|
||||||
|
Not all nodes should participate by default. For example, filters or device
|
||||||
|
nodes that are not linked to any runnable nodes should not do useless
|
||||||
|
processing.
|
||||||
|
|
||||||
|
Nodes form one or more groups depending on properties and how they are
|
||||||
|
linked. For each group, one driver is selected to run the group. Inside the
|
||||||
|
group, all runnable nodes are scheduled by the group driver. If there are no
|
||||||
|
runnable nodes in a group, the driver is not started.
|
||||||
|
|
||||||
|
PipeWire provides mechanisms to precisely describe how and when nodes should
|
||||||
|
be scheduled and grouped using:
|
||||||
|
|
||||||
|
- port properties to control how port links control runnable state
|
||||||
|
- node properties to control processing
|
||||||
|
- grouping of nodes and internal links between nodes
|
||||||
|
|
||||||
|
# Port passive modes
|
||||||
|
|
||||||
|
A Port has 4 passive modes, this depends on the value of the `port.passive` property:
|
||||||
|
|
||||||
|
- `false`, the port will make the peer active and an active peer will make this port
|
||||||
|
active.
|
||||||
|
- `true`, the port will not make the peer active and an active peer will not make this
|
||||||
|
port active.
|
||||||
|
- `follow`, the port will not make the peer active but an active peer will make this
|
||||||
|
port active.
|
||||||
|
- `follow-suspend`, the port will only make another follow-suspend peer active but any
|
||||||
|
active peer will make this port active.
|
||||||
|
|
||||||
|
The combination of these 4 modes on the output and input ports of a link results in a
|
||||||
|
wide range of use cases.
|
||||||
|
|
||||||
|
# Node passive modes
|
||||||
|
|
||||||
|
A Node can have 10 passive modes, `node.passive` can be set to a comma separated list
|
||||||
|
of the following values:
|
||||||
|
|
||||||
|
- `false`, both input and output ports have `port.passive = false`
|
||||||
|
- `in`, input ports have `port.passive = true`
|
||||||
|
- `out`, output ports have `port.passive = true`
|
||||||
|
- `true`, both input and output ports have `port.passive = true`. This is the same
|
||||||
|
as `in,out`.
|
||||||
|
- `in-follow`, input ports have `port.passive = follow`
|
||||||
|
- `out-follow`, output ports have `port.passive = follow`
|
||||||
|
- `follow`, input and output ports have `port.passive = follow`. This is the same
|
||||||
|
as `in-follow,out-follow`.
|
||||||
|
- `in-follow-suspend`, input ports have `port.passive = follow-suspend`
|
||||||
|
- `out-follow-suspend`, output ports have `port.passive = follow-suspend`
|
||||||
|
- `follow-suspend`, input and output ports have `port.passive = follow-suspend`.
|
||||||
|
This is the same as `in-follow-suspend,out-follow-suspend`.
|
||||||
|
|
||||||
|
Nodes by default have the `false` mode but nodes with the `media.class` property
|
||||||
|
containing `Sink`, `Source` or `Duplex` receive the `follow-suspend` mode by default.
|
||||||
|
|
||||||
|
Unless explicitly configured, ports inherit the mode from their parent node.
|
||||||
|
|
||||||
|
# Updating the node runnable state
|
||||||
|
|
||||||
|
We iterate all nodes A in the graph and look at its peers B.
|
||||||
|
|
||||||
|
Based on the port passive modes of the port links we can decide if the nodes are
|
||||||
|
runnable or not. A link will always make both nodes runnable or none.
|
||||||
|
|
||||||
|
The following table decides the runnability of the 2 nodes based on the port.passive
|
||||||
|
mode of the link between the 2 ports:
|
||||||
|
|
||||||
|
```
|
||||||
|
B-false B-true B-follow B-follow-suspend
|
||||||
|
|
||||||
|
A-false X X X X
|
||||||
|
A-true
|
||||||
|
A-follow
|
||||||
|
A-follow-suspend X
|
||||||
|
Table 1
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
When a node is made runnable, the port passive mode will then decide if the peer ports
|
||||||
|
should become active as well with the following table.
|
||||||
|
|
||||||
|
```
|
||||||
|
B-false B-true B-follow B-follow-suspend
|
||||||
|
|
||||||
|
A-false X X X
|
||||||
|
A-true X X X
|
||||||
|
A-follow X X X
|
||||||
|
A-follow-suspend X X X
|
||||||
|
Table 2
|
||||||
|
```
|
||||||
|
|
||||||
|
So when A is runnable, all peers are activated except those with `port.passive=true`.
|
||||||
|
|
||||||
|
When A is runnable, all the nodes that share the same group or link-group will also
|
||||||
|
be made runnable.
|
||||||
|
|
||||||
|
# Use cases
|
||||||
|
|
||||||
|
Let's check some cases that we want to solve with these node and port properties.
|
||||||
|
|
||||||
|
## Device nodes
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +--------+
|
||||||
|
| ALSA | | ALSA |
|
||||||
|
| Source | | Sink |
|
||||||
|
| FL FL |
|
||||||
|
| FR FR |
|
||||||
|
+--------+ +--------+
|
||||||
|
```
|
||||||
|
|
||||||
|
Unlinked device nodes are supposed to stay suspended when nothing is linked to
|
||||||
|
them.
|
||||||
|
|
||||||
|
```
|
||||||
|
+----------+ +--------+
|
||||||
|
| playback | | ALSA |
|
||||||
|
| | | Sink |
|
||||||
|
| FL ------ FL |
|
||||||
|
| FR ------ FR |
|
||||||
|
+----------+ +--------+
|
||||||
|
```
|
||||||
|
|
||||||
|
An (active) player node linked to a device node should make both nodes runnable.
|
||||||
|
|
||||||
|
Device nodes have the `port.passive = follow-suspend` property by default. The
|
||||||
|
playback node has the `port.passive = false` by default.
|
||||||
|
|
||||||
|
If we look at the playback node as A and the sink as B, both nodes will be made
|
||||||
|
runnable according to Table 1.
|
||||||
|
|
||||||
|
The two runnable nodes form a group and will be scheduled together. One of the
|
||||||
|
nodes of a group with the `node.driver = true` property is selected as the
|
||||||
|
driver. In the above case, that will be the ALSA Sink.
|
||||||
|
|
||||||
|
Likewise, a capture node linked to an ALSA Source should make both nodes runnable.
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +---------+
|
||||||
|
| ALSA | | capture |
|
||||||
|
| Source | | |
|
||||||
|
| FL ------ FL |
|
||||||
|
| FR ------ FR |
|
||||||
|
+--------+ +---------+
|
||||||
|
```
|
||||||
|
|
||||||
|
The ALSA Source is now the driver.
|
||||||
|
|
||||||
|
Also, linking 2 device nodes together should make them runnable:
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +--------+
|
||||||
|
| ALSA | | ALSA |
|
||||||
|
| Source | | Sink |
|
||||||
|
| FL ----------------------- FL |
|
||||||
|
| FR ----------------------- FR |
|
||||||
|
+--------+ +--------+
|
||||||
|
```
|
||||||
|
|
||||||
|
This is the case because in Table 1, the two `port.passive = follow-suspend` ports
|
||||||
|
from the Source and Sink activate each other.
|
||||||
|
|
||||||
|
## Filter nodes
|
||||||
|
|
||||||
|
When there is a filter in front of the ALSA Sink, it should not make the filter and
|
||||||
|
sink runnable.
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +--------+
|
||||||
|
| filter | | ALSA |
|
||||||
|
| | | Sink |
|
||||||
|
FL FL ------ FL |
|
||||||
|
FR FR ------ FR |
|
||||||
|
+--------+ +--------+
|
||||||
|
```
|
||||||
|
|
||||||
|
The links between the filter and ALSA Sink are `port.passive = true` and don't make
|
||||||
|
the nodes runnable.
|
||||||
|
|
||||||
|
The filter needs to be made runnable via some other means to also make the ALSA
|
||||||
|
Sink runnable, for example by linking a playback node:
|
||||||
|
|
||||||
|
```
|
||||||
|
+----------+ +--------+ +--------+
|
||||||
|
| playback | | filter | | ALSA |
|
||||||
|
| | | | | Sink |
|
||||||
|
| FL ------ FL FL ------ FL |
|
||||||
|
| FR ------ FR FR ------ FR |
|
||||||
|
+----------+ +--------+ +--------+
|
||||||
|
```
|
||||||
|
|
||||||
|
The input port of the filter is `port.passive = follow-suspend' and so it can be
|
||||||
|
activated by the playback node.
|
||||||
|
|
||||||
|
Likewise, if the ALSA Sink is runnable, it should not automatically make the
|
||||||
|
filter runnable. For example:
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +--------+
|
||||||
|
| filter | | ALSA |
|
||||||
|
| | | Sink |
|
||||||
|
FL FL ---+-- FL |
|
||||||
|
FR FR ---|+- FR |
|
||||||
|
+--------+ || +--------+
|
||||||
|
||
|
||||||
|
+----------+ ||
|
||||||
|
| playback | ||
|
||||||
|
| | ||
|
||||||
|
| FL ---+|
|
||||||
|
| FR ----+
|
||||||
|
+----------+
|
||||||
|
```
|
||||||
|
|
||||||
|
Here the playback node makes the ALSA Sink runnable but the filter
|
||||||
|
stays not-runnable because the output port is `port.passive = true`.
|
||||||
|
|
||||||
|
## Device node monitor
|
||||||
|
|
||||||
|
Consider the case where we have an ALSA Sink and a monitor stream
|
||||||
|
connected to the sink monitor ports.
|
||||||
|
|
||||||
|
```
|
||||||
|
+-------+ +--------++
|
||||||
|
| ALSA | | monitor |
|
||||||
|
| Sink | | |
|
||||||
|
FL FL ------ FL |
|
||||||
|
FR FR ------ FR |
|
||||||
|
+-------+ +---------+
|
||||||
|
```
|
||||||
|
|
||||||
|
We would like to keep the monitor stream and the ALSA sink suspended
|
||||||
|
unless something else activates the ALSA Sink:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
+----------+ +-------+ +---------+
|
||||||
|
| playback | | ALSA | | monitor |
|
||||||
|
| | | Sink | | |
|
||||||
|
| FL ------ FL FL ------ FL |
|
||||||
|
| FR ------ FR FR ------ FR |
|
||||||
|
+----------+ +-------+ +---------+
|
||||||
|
```
|
||||||
|
|
||||||
|
We can do this by making the monitor stream input ports `port.passive = follow`
|
||||||
|
and leave the ALSA Sink monitor output ports as `port.passive = follow-suspend`.
|
||||||
|
|
||||||
|
According to Table 1, both nodes will not activate each other but when ALSA Sink
|
||||||
|
becomes runnable because of playback, according to Table 2, the monitor will
|
||||||
|
become runnable as well.
|
||||||
|
|
||||||
|
Note how we need the distinction between `follow` and `follow-suspend` for this
|
||||||
|
use case.
|
||||||
|
|
||||||
|
## Node groups
|
||||||
|
|
||||||
|
Normally when an application makes a capture and playback node, both nodes will
|
||||||
|
be scheduled in different groups, consider:
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +---------+
|
||||||
|
| ALSA | | capture |
|
||||||
|
| Source | | |
|
||||||
|
| FL ------ FL |
|
||||||
|
| FR ------ FR |
|
||||||
|
+--------+ +---------+
|
||||||
|
|
||||||
|
+----------+ +--------+
|
||||||
|
| playback | | ALSA |
|
||||||
|
| | | Sink |
|
||||||
|
| FL ------ FL |
|
||||||
|
| FR ------ FR |
|
||||||
|
+----------+ +--------+
|
||||||
|
```
|
||||||
|
|
||||||
|
Here we see 2 groups with the ALSA Source and ALSA Sink respectively as the
|
||||||
|
drivers. Depending on the clocks of the nodes, the capture and playback will not
|
||||||
|
be in sync. They will each run in their own time domain depending on the rate of
|
||||||
|
the drivers.
|
||||||
|
|
||||||
|
When we place a node.group property with the same value on the capture and playback
|
||||||
|
nodes, they will be grouped together and this whole graph becomes one single group.
|
||||||
|
|
||||||
|
Because there are 2 potential drivers in the group, the one with the highest
|
||||||
|
`priority.driver` property is selected as the driver in the group. The other nodes
|
||||||
|
in the group (including the other driver) become followers in the group.
|
||||||
|
|
||||||
|
When a node becomes runnable, all other nodes with the same node.group property
|
||||||
|
become runnable as well.
|
||||||
|
|
||||||
|
## Node link groups
|
||||||
|
|
||||||
|
When we have a filter that is constructed from two nodes, an input and an output
|
||||||
|
node, we could use the `node.group` property to make sure they are both scheduled
|
||||||
|
and made runnable together.
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +-------+ +--------+ +-------+
|
||||||
|
| ALSA | | input | | output | | ALSA |
|
||||||
|
| Source | | | | | | Sink |
|
||||||
|
| FL ------ FL -- processing-- FL ------ FL |
|
||||||
|
| FR ------ FR | | FR ------ FR |
|
||||||
|
+--------+ +-------+ +--------+ +-------+
|
||||||
|
```
|
||||||
|
|
||||||
|
This would work fine but it does not describe that there is an implicit internal
|
||||||
|
link between the input and output node. This information is important for the
|
||||||
|
session manager to avoid linking the output node to the input node and make a
|
||||||
|
loop.
|
||||||
|
|
||||||
|
The `node.link-group` property can be used to both group the nodes together and
|
||||||
|
descibe that they are internally linked together.
|
||||||
|
|
||||||
|
When a node becomes runnable, all other nodes with the same node.link-group property
|
||||||
|
become runnable as well.
|
||||||
|
|
||||||
|
For the 2 node filters, like loopback and filter-chain, the same `port.passive`
|
||||||
|
property rules apply as for the filter nodes. Note that for the virtual devices,
|
||||||
|
the Source/Sink nodes will be `follow-suspend` by default and the other node should
|
||||||
|
be set to `node.passive = true` to make the ports passive.
|
||||||
|
|
||||||
|
## Want driver
|
||||||
|
|
||||||
|
When there is no driver node in the group, nothing should be scheduled. This can
|
||||||
|
happen when a playback node is linked to a capture node:
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+ +---------+
|
||||||
|
| player | | capture |
|
||||||
|
| | | |
|
||||||
|
| FL ----------- FL |
|
||||||
|
| FR ----------- FR |
|
||||||
|
+--------+ +---------+
|
||||||
|
```
|
||||||
|
|
||||||
|
None of these nodes is a driver so there is no driver in the group and nothing
|
||||||
|
will be scheduled.
|
||||||
|
|
||||||
|
When one of the nodes has `node.want-driver = true` they are grouped and
|
||||||
|
scheduled with a random driver node. This is often the driver node with the
|
||||||
|
highest priority (usually the Dummy-Driver) or otherwise a driver that is already
|
||||||
|
scheduling some other nodes.
|
||||||
|
|
||||||
|
## Always process nodes
|
||||||
|
|
||||||
|
A simple node, unlinked to anything should normally not run.
|
||||||
|
|
||||||
|
```
|
||||||
|
+--------+
|
||||||
|
| player |
|
||||||
|
| |
|
||||||
|
| FL
|
||||||
|
| FR
|
||||||
|
+--------+
|
||||||
|
```
|
||||||
|
|
||||||
|
When the `node.always-process = true` property is set, the node will however be
|
||||||
|
made runnable even if unlinked. This is done by adding the node to a random driver.
|
||||||
|
|
||||||
|
`node.always-process = true` implies the `node.want-driver = true` property.
|
||||||
|
|
||||||
|
## Sync groups
|
||||||
|
|
||||||
|
In some cases, you only want to group nodes together depending on some condition.
|
||||||
|
|
||||||
|
For example, when the JACK transport is activated, all nodes in the graph should share
|
||||||
|
the same driver node, regardless of the grouping or linking of the nodes.
|
||||||
|
|
||||||
|
This is done by setting the same node.sync-group property on all nodes (by default all
|
||||||
|
nodes have `node.sync-group = group.sync.0`). When a node sets `node.sync = true` all
|
||||||
|
the other nodes with the same `node.sync-group` property are grouped together.
|
||||||
|
|
||||||
|
This can be used to implement the JACK transport. When the transport is started, the
|
||||||
|
`node.sync=true` property is set and all nodes join one group with a shared driver
|
||||||
|
and timing information.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -23,6 +23,9 @@ node is scheduled to run.
|
||||||
This document describes the processing that happens in the data processing
|
This document describes the processing that happens in the data processing
|
||||||
thread after the main thread has configured it.
|
thread after the main thread has configured it.
|
||||||
|
|
||||||
|
Before scheduling of the node happens, the scheduler will collect a list of
|
||||||
|
nodes that are runnable, see \ref page_running
|
||||||
|
|
||||||
# Nodes
|
# Nodes
|
||||||
|
|
||||||
Nodes are objects with 0 or more input and output ports.
|
Nodes are objects with 0 or more input and output ports.
|
||||||
|
|
|
||||||
|
|
@ -54,11 +54,11 @@ in the graph. Output Tag objects on output ports are propagated to linked input
|
||||||
ports and input Tag objects on input ports are propagated to linked output ports.
|
ports and input Tag objects on input ports are propagated to linked output ports.
|
||||||
|
|
||||||
If a port has links with multiple other ports, the Tag objects are merged by
|
If a port has links with multiple other ports, the Tag objects are merged by
|
||||||
appending the dictionaties to the Tag param. Intermediate nodes or sinks are allowed
|
appending the dictionaries to the Tag param. Intermediate nodes or sinks are allowed
|
||||||
to take the multiple dictionaries in a Tag and combine them into one dictionary if
|
to take the multiple dictionaries in a Tag and combine them into one dictionary if
|
||||||
they would like to do so.
|
they would like to do so.
|
||||||
|
|
||||||
This way, Output Tag always describes the aggragated total upstream metadata of
|
This way, Output Tag always describes the aggregated total upstream metadata of the
|
||||||
signal up to the port and Input tag describes the aggregated downstream metadata
|
signal up to the port and Input tag describes the aggregated downstream metadata
|
||||||
of the signal from the port.
|
of the signal from the port.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,6 +81,7 @@ List of known modules:
|
||||||
- \subpage page_module_raop_discover
|
- \subpage page_module_raop_discover
|
||||||
- \subpage page_module_roc_sink
|
- \subpage page_module_roc_sink
|
||||||
- \subpage page_module_roc_source
|
- \subpage page_module_roc_source
|
||||||
|
- \subpage page_module_scheduler_v1
|
||||||
- \subpage page_module_rtp_sap
|
- \subpage page_module_rtp_sap
|
||||||
- \subpage page_module_rtp_sink
|
- \subpage page_module_rtp_sink
|
||||||
- \subpage page_module_rtp_source
|
- \subpage page_module_rtp_source
|
||||||
|
|
@ -90,6 +91,8 @@ List of known modules:
|
||||||
- \subpage page_module_spa_node_factory
|
- \subpage page_module_spa_node_factory
|
||||||
- \subpage page_module_spa_device
|
- \subpage page_module_spa_device
|
||||||
- \subpage page_module_spa_device_factory
|
- \subpage page_module_spa_device_factory
|
||||||
|
- \subpage page_module_sendspin_recv
|
||||||
|
- \subpage page_module_sendspin_send
|
||||||
- \subpage page_module_session_manager
|
- \subpage page_module_session_manager
|
||||||
- \subpage page_module_snapcast_discover
|
- \subpage page_module_snapcast_discover
|
||||||
- \subpage page_module_vban_recv
|
- \subpage page_module_vban_recv
|
||||||
|
|
|
||||||
|
|
@ -77,7 +77,7 @@ Certain properties are, by convention, expected for specific object types.
|
||||||
|
|
||||||
Each object type has a list of methods that it needs to implement.
|
Each object type has a list of methods that it needs to implement.
|
||||||
|
|
||||||
The session manager is responsible for defining the list of permissions each client has. Each permission entry is an object ID and four flags. The four flags are:
|
The session manager is responsible for defining the list of permissions each client has. Each permission entry is an object ID and five flags. The five flags are:
|
||||||
|
|
||||||
- Read: the object can be seen and events can be received;
|
- Read: the object can be seen and events can be received;
|
||||||
- Write: the object can be modified, usually through methods (which requires the execute flag)
|
- Write: the object can be modified, usually through methods (which requires the execute flag)
|
||||||
|
|
@ -109,7 +109,7 @@ Modules in PipeWire can only be loaded in their own process. A client, for examp
|
||||||
|
|
||||||
Nodes are the core data processing entities in PipeWire.
|
Nodes are the core data processing entities in PipeWire.
|
||||||
They may produce data (capture devices, signal generators, ...), consume data (playback devices, network endpoints, ...) or both (filters).
|
They may produce data (capture devices, signal generators, ...), consume data (playback devices, network endpoints, ...) or both (filters).
|
||||||
Notes have a method `process`, which eats up data from input ports and provides data for each output port.
|
Nodes have a method `process`, which eats up data from input ports and provides data for each output port.
|
||||||
|
|
||||||
#### Ports
|
#### Ports
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ Manual pages:
|
||||||
|
|
||||||
- \subpage page_man_pipewire_1
|
- \subpage page_man_pipewire_1
|
||||||
- \subpage page_man_pipewire-pulse_1
|
- \subpage page_man_pipewire-pulse_1
|
||||||
|
- \subpage page_man_pw-audioconvert_1
|
||||||
- \subpage page_man_pw-cat_1
|
- \subpage page_man_pw-cat_1
|
||||||
- \subpage page_man_pw-cli_1
|
- \subpage page_man_pw-cli_1
|
||||||
- \subpage page_man_pw-config_1
|
- \subpage page_man_pw-config_1
|
||||||
|
|
|
||||||
62
doc/dox/programs/pw-audioconvert.1.md
Normal file
62
doc/dox/programs/pw-audioconvert.1.md
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
\page page_man_pw-audioconvert_1 pw-audioconvert
|
||||||
|
|
||||||
|
The PipeWire audioconvert utility
|
||||||
|
|
||||||
|
# SYNOPSIS
|
||||||
|
|
||||||
|
**pw-audioconvert** \[*OPTIONS*\] *INFILE* *OUTFILE*
|
||||||
|
|
||||||
|
# DESCRIPTION
|
||||||
|
|
||||||
|
Use the PipeWire audioconvert to convert input file to output file,
|
||||||
|
following the given options.
|
||||||
|
|
||||||
|
This is useful only for doing audio conversion but also apply effects
|
||||||
|
on the audio using a filter-graph.
|
||||||
|
|
||||||
|
It understands all audio file formats supported by `libsndfile` for input
|
||||||
|
and output. The filename extension is used to guess the output file
|
||||||
|
container and format with the WAV file format as the default.
|
||||||
|
|
||||||
|
# OPTIONS
|
||||||
|
|
||||||
|
\par -r RATE | \--rate=RATE
|
||||||
|
Output sample rate. Default the same as the input sample rate.
|
||||||
|
|
||||||
|
\par -f FORMAT | \--format=FORMAT
|
||||||
|
Output sample format (s8 | s16 | s32 | f32 | f64). Default the same
|
||||||
|
as the input format.
|
||||||
|
|
||||||
|
\par -b BLOCKSIZE | \--blocksize=BLOCKSIZE
|
||||||
|
Number of samples per iteration (default 4096)
|
||||||
|
|
||||||
|
\par -P PROPERTIES | \--properties=PROPERTIES
|
||||||
|
Set extra stream properties as a JSON object. One can also use @filename to
|
||||||
|
read the JSON object with properties from filename.
|
||||||
|
|
||||||
|
\par -c CHANNELS | \--channels=CHANNELS
|
||||||
|
The number of output channels, default the same as the input.
|
||||||
|
|
||||||
|
\par \--channel-map=VALUE
|
||||||
|
The channelmap. Possible values include are either a predefined channel layout
|
||||||
|
such as **Mono**, **Stereo**, **2.1**, **Quad**, **2.2**, **5.1**,
|
||||||
|
or comma separated array of channel names such as **FL,FR**.
|
||||||
|
|
||||||
|
\par -h
|
||||||
|
Show help.
|
||||||
|
|
||||||
|
\par -v
|
||||||
|
Verbose operation.
|
||||||
|
|
||||||
|
# EXAMPLES
|
||||||
|
|
||||||
|
**pw-audioconvert** -r 48000 -f s32 in.wav out.wav
|
||||||
|
|
||||||
|
# AUTHORS
|
||||||
|
|
||||||
|
The PipeWire Developers <$(PACKAGE_BUGREPORT)>;
|
||||||
|
PipeWire is available from <$(PACKAGE_URL)>
|
||||||
|
|
||||||
|
# SEE ALSO
|
||||||
|
|
||||||
|
\ref page_man_pipewire_1 "pipewire(1)"
|
||||||
|
|
@ -24,9 +24,9 @@ Play and record media with PipeWire
|
||||||
|
|
||||||
**pw-cat** is a simple tool for playing back or capturing raw or encoded
|
**pw-cat** is a simple tool for playing back or capturing raw or encoded
|
||||||
media files on a PipeWire server. It understands all audio file formats
|
media files on a PipeWire server. It understands all audio file formats
|
||||||
supported by `libsndfile` for PCM capture and playback. When capturing
|
supported by `libsndfile` for PCM capture and playback. When no container
|
||||||
PCM, the filename extension is used to guess the file format with the
|
is specified for capturing PCM, the filename extension is used to guess
|
||||||
WAV file format as the default.
|
the file format with the WAV file format as the default.
|
||||||
|
|
||||||
It understands standard MIDI files and MIDI 2.0 clip files for playback
|
It understands standard MIDI files and MIDI 2.0 clip files for playback
|
||||||
and recording. This tool will not render MIDI files, it will simply make
|
and recording. This tool will not render MIDI files, it will simply make
|
||||||
|
|
@ -37,8 +37,15 @@ DSD playback is supported with the DSF file format. This tool will only
|
||||||
work with native DSD capable hardware and will produce an error when no
|
work with native DSD capable hardware and will produce an error when no
|
||||||
such hardware was found.
|
such hardware was found.
|
||||||
|
|
||||||
When the *FILE* is - input and output will be raw data from STDIN and
|
When the *FILE* is - input will be from STDIN. If no format is specified,
|
||||||
STDOUT respectively.
|
libsndfile will attempt to parse and stream the format from STDIN. For
|
||||||
|
some formats, this is not possible and libsndfile will give an error.
|
||||||
|
Raw, MIDI and DSD formats are all streamable from STDIN.
|
||||||
|
|
||||||
|
When the *FILE* is - output will be to STDOUT. If no format is specified,
|
||||||
|
libsndfile is instructed to output the .au format, which is streamble and
|
||||||
|
preserves the format, rate and channels.
|
||||||
|
Raw and DSD formats are all streamable to STDOUT.
|
||||||
|
|
||||||
# OPTIONS
|
# OPTIONS
|
||||||
|
|
||||||
|
|
@ -87,6 +94,11 @@ DSD mode. *FILE* is a DSF file. If the tool is called under the name
|
||||||
render the DSD audio. You need a DSD capable device to play DSD content
|
render the DSD audio. You need a DSD capable device to play DSD content
|
||||||
or this program will exit with an error.
|
or this program will exit with an error.
|
||||||
|
|
||||||
|
\par -s | \--sysex
|
||||||
|
SysEx mode. *FILE* is a File that contains a raw SysEx MIDI message.
|
||||||
|
If the tool is called under the name **pw-sysex** this is the default.
|
||||||
|
The File is read and sent as a MIDI control message into the graph.
|
||||||
|
|
||||||
\par \--media-type=VALUE
|
\par \--media-type=VALUE
|
||||||
Set the media type property (default Audio/Midi depending on mode). The
|
Set the media type property (default Audio/Midi depending on mode). The
|
||||||
media type is used by the session manager to select a suitable target to
|
media type is used by the session manager to select a suitable target to
|
||||||
|
|
@ -112,6 +124,9 @@ Set a node target (default auto). The value can be:
|
||||||
- <b>\<id\></b>: The object.serial or the node.name of a target node
|
- <b>\<id\></b>: The object.serial or the node.name of a target node
|
||||||
\endparblock
|
\endparblock
|
||||||
|
|
||||||
|
\par -C | \--monitor
|
||||||
|
In recording mode, record from monitor ports.
|
||||||
|
|
||||||
\par \--latency=VALUE\[*units*\]
|
\par \--latency=VALUE\[*units*\]
|
||||||
\parblock
|
\parblock
|
||||||
Set the node latency (default 100ms)
|
Set the node latency (default 100ms)
|
||||||
|
|
@ -138,6 +153,17 @@ does not match the samplerate of the server, the data will be resampled.
|
||||||
Higher quality uses more CPU. Values between 0 and 15 are allowed, the
|
Higher quality uses more CPU. Values between 0 and 15 are allowed, the
|
||||||
default quality is 4.
|
default quality is 4.
|
||||||
|
|
||||||
|
\par -a | \--raw
|
||||||
|
Raw samples will be read or written. The \--rate, \--format, \--channels
|
||||||
|
and \--channelmap can be used to specify the raw format.
|
||||||
|
|
||||||
|
\par -M | \--force-midi
|
||||||
|
Force midi format, one of "midi" or "ump", (default ump).
|
||||||
|
When reading or writing midi, for one of midi or UMP.
|
||||||
|
|
||||||
|
\par -n | \--sample-count=COUNT
|
||||||
|
Stop after COUNT samples.
|
||||||
|
|
||||||
\par \--rate=VALUE
|
\par \--rate=VALUE
|
||||||
The sample rate, default 48000.
|
The sample rate, default 48000.
|
||||||
|
|
||||||
|
|
@ -145,19 +171,38 @@ The sample rate, default 48000.
|
||||||
The number of channels, default 2.
|
The number of channels, default 2.
|
||||||
|
|
||||||
\par \--channel-map=VALUE
|
\par \--channel-map=VALUE
|
||||||
The channelmap. Possible values include: **mono**, **stereo**,
|
The channelmap. Possible values include are either a channel layout
|
||||||
|
such as **mono**, **stereo**,
|
||||||
**surround-21**, **quad**, **surround-22**, **surround-40**,
|
**surround-21**, **quad**, **surround-22**, **surround-40**,
|
||||||
**surround-31**, **surround-41**, **surround-50**, **surround-51**,
|
or comma separated array of channel names such as **FL,FR**.
|
||||||
**surround-51r**, **surround-70**, **surround-71** or a comma separated
|
See \--list-layouts and \--list-channel-names to get a complete
|
||||||
list of channel names: **FL**, **FR**, **FC**, **LFE**, **SL**, **SR**,
|
list of possible values.
|
||||||
**FLC**, **FRC**, **RC**, **RL**, **RR**, **TC**, **TFL**, **TFC**,
|
|
||||||
**TFR**, **TRL**, **TRC**, **TRR**, **RLC**, **RRC**, **FLW**, **FRW**,
|
\par \--list-layouts
|
||||||
**LFE2**, **FLH**, **FCH**, **FRH**, **TFLC**, **TFRC**, **TSL**,
|
List all known channel layouts. One of these can be used as the
|
||||||
**TSR**, **LLFR**, **RLFE**, **BC**, **BLC**, **BRC**
|
\--channel-map value.
|
||||||
|
|
||||||
|
\par \--list-channel-names
|
||||||
|
List all known channel names. An array of these can be used as the
|
||||||
|
\--channel-map value.
|
||||||
|
|
||||||
\par \--format=VALUE
|
\par \--format=VALUE
|
||||||
The sample format to use. One of: **u8**, **s8**, **s16** (default),
|
The sample format to use. Some possible values include: **u8**, **s8**,
|
||||||
**s24**, **s32**, **f32**, **f64**.
|
**s16** (default), **s24**, **s32**, **f32**, **f64**. See
|
||||||
|
\--list-formats to get a complete list of values.
|
||||||
|
|
||||||
|
\par \--list-formats
|
||||||
|
List all known format values.
|
||||||
|
|
||||||
|
\par \--container=VALUE
|
||||||
|
Specify the container to use when saving. This is usually guessed from
|
||||||
|
the filename extension but can be specified explicitly. When using
|
||||||
|
STDOUT and no container is specified, the AU container will be used.
|
||||||
|
Then using a filename and the container was not specified and it could
|
||||||
|
not be derived from the filename, the WAV container is used.
|
||||||
|
|
||||||
|
\par \--list-containers
|
||||||
|
List all known container values.
|
||||||
|
|
||||||
\par \--volume=VALUE
|
\par \--volume=VALUE
|
||||||
The stream volume, default 1.000. Depending on the locale you have
|
The stream volume, default 1.000. Depending on the locale you have
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ Target device to play to
|
||||||
Wanted properties of capture node (in JSON)
|
Wanted properties of capture node (in JSON)
|
||||||
|
|
||||||
\par -o | \--playback-props=PROPS
|
\par -o | \--playback-props=PROPS
|
||||||
Wanted properties of capture node (in JSON)
|
Wanted properties of playback node (in JSON)
|
||||||
|
|
||||||
# AUTHORS
|
# AUTHORS
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ node and device statistics.
|
||||||
|
|
||||||
A hierarchical view is shown of Driver nodes and follower nodes. The
|
A hierarchical view is shown of Driver nodes and follower nodes. The
|
||||||
Driver nodes are actively using a timer to schedule dataflow in the
|
Driver nodes are actively using a timer to schedule dataflow in the
|
||||||
followers. The followers of a driver node as shown below their driver
|
followers. The followers of a driver node are shown below their driver
|
||||||
with a + sign (or = for async nodes) in a tree-like representation.
|
with a + sign (or = for async nodes) in a tree-like representation.
|
||||||
|
|
||||||
The columns presented are as follows:
|
The columns presented are as follows:
|
||||||
|
|
@ -188,6 +188,11 @@ Quit
|
||||||
Clear the ERR counters. This does *not* clear the counters globally,
|
Clear the ERR counters. This does *not* clear the counters globally,
|
||||||
it will only reset the counters in this instance of *pw-top*.
|
it will only reset the counters in this instance of *pw-top*.
|
||||||
|
|
||||||
|
\par [f|F]
|
||||||
|
Cycle through filter presets. If any nodes are filtered from view,
|
||||||
|
the current preset will be indicated in the header bar. Only nodes
|
||||||
|
with the indicated state or higher, will be printed.
|
||||||
|
|
||||||
# OPTIONS
|
# OPTIONS
|
||||||
|
|
||||||
\par -h | \--help
|
\par -h | \--help
|
||||||
|
|
@ -199,6 +204,9 @@ Run in non-interactive batch mode, similar to top\'s batch mode.
|
||||||
\par -n | \--iterations=NUMBER
|
\par -n | \--iterations=NUMBER
|
||||||
Exit after NUMBER of batch iterations. Only used in batch mode.
|
Exit after NUMBER of batch iterations. Only used in batch mode.
|
||||||
|
|
||||||
|
\par -f | \--filter=NUMBER
|
||||||
|
Start with filter preset NUMBER selected.
|
||||||
|
|
||||||
\par -r | \--remote=NAME
|
\par -r | \--remote=NAME
|
||||||
The name the *remote* instance to monitor. If left unspecified, a
|
The name the *remote* instance to monitor. If left unspecified, a
|
||||||
connection is made to the default PipeWire instance.
|
connection is made to the default PipeWire instance.
|
||||||
|
|
|
||||||
23
doc/examples/meson.build
Normal file
23
doc/examples/meson.build
Normal file
|
|
@ -0,0 +1,23 @@
|
||||||
|
tutorials = [
|
||||||
|
'tutorial1',
|
||||||
|
'tutorial2',
|
||||||
|
'tutorial3',
|
||||||
|
'tutorial4',
|
||||||
|
'tutorial5',
|
||||||
|
'tutorial6',
|
||||||
|
'tutorial7',
|
||||||
|
]
|
||||||
|
|
||||||
|
if not get_option('examples').allowed()
|
||||||
|
subdir_done()
|
||||||
|
endif
|
||||||
|
|
||||||
|
foreach c : tutorials
|
||||||
|
executable(
|
||||||
|
c,
|
||||||
|
sources: c + '.c',
|
||||||
|
dependencies: [ pipewire_dep, mathlib ],
|
||||||
|
install: installed_tests_enabled,
|
||||||
|
install_dir: installed_tests_execdir / 'examples',
|
||||||
|
)
|
||||||
|
endforeach
|
||||||
|
|
@ -56,7 +56,7 @@ static void on_process(void *userdata)
|
||||||
* Another common method to convert a double to
|
* Another common method to convert a double to
|
||||||
* 16 bits is to multiple by 32768.0 and then clamp to
|
* 16 bits is to multiple by 32768.0 and then clamp to
|
||||||
* [-32768 32767] to get the full 16 bits range. */
|
* [-32768 32767] to get the full 16 bits range. */
|
||||||
val = sin(data->accumulator) * DEFAULT_VOLUME * 32767.0;
|
val = (int16_t) (sin(data->accumulator) * DEFAULT_VOLUME * 32767.0);
|
||||||
for (c = 0; c < DEFAULT_CHANNELS; c++)
|
for (c = 0; c < DEFAULT_CHANNELS; c++)
|
||||||
*dst++ = val;
|
*dst++ = val;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,6 +67,7 @@ extra_docs = [
|
||||||
'dox/internals/session-manager.dox',
|
'dox/internals/session-manager.dox',
|
||||||
'dox/internals/objects.dox',
|
'dox/internals/objects.dox',
|
||||||
'dox/internals/audio.dox',
|
'dox/internals/audio.dox',
|
||||||
|
'dox/internals/running.dox',
|
||||||
'dox/internals/scheduling.dox',
|
'dox/internals/scheduling.dox',
|
||||||
'dox/internals/driver.dox',
|
'dox/internals/driver.dox',
|
||||||
'dox/internals/protocol.dox',
|
'dox/internals/protocol.dox',
|
||||||
|
|
@ -99,6 +100,7 @@ manpage_docs = [
|
||||||
'dox/config/libpipewire-modules.7.md',
|
'dox/config/libpipewire-modules.7.md',
|
||||||
'dox/programs/pipewire-pulse.1.md',
|
'dox/programs/pipewire-pulse.1.md',
|
||||||
'dox/programs/pipewire.1.md',
|
'dox/programs/pipewire.1.md',
|
||||||
|
'dox/programs/pw-audioconvert.1.md',
|
||||||
'dox/programs/pw-cat.1.md',
|
'dox/programs/pw-cat.1.md',
|
||||||
'dox/programs/pw-cli.1.md',
|
'dox/programs/pw-cli.1.md',
|
||||||
'dox/programs/pw-config.1.md',
|
'dox/programs/pw-config.1.md',
|
||||||
|
|
@ -167,18 +169,14 @@ cssfiles = [
|
||||||
]
|
]
|
||||||
|
|
||||||
# Example files (in order from simple to esoteric)
|
# Example files (in order from simple to esoteric)
|
||||||
example_files = [
|
example_files = []
|
||||||
'tutorial1.c',
|
|
||||||
'tutorial2.c',
|
|
||||||
'tutorial3.c',
|
|
||||||
'tutorial4.c',
|
|
||||||
'tutorial5.c',
|
|
||||||
'tutorial6.c',
|
|
||||||
'tutorial7.c',
|
|
||||||
]
|
|
||||||
example_dep_files = []
|
example_dep_files = []
|
||||||
foreach h : example_files
|
|
||||||
example_dep_files += ['examples/' + h]
|
subdir('examples')
|
||||||
|
|
||||||
|
foreach h : tutorials
|
||||||
|
example_files += [h + '.c']
|
||||||
|
example_dep_files += ['examples/' + h + '.c']
|
||||||
endforeach
|
endforeach
|
||||||
foreach h : examples
|
foreach h : examples
|
||||||
example_files += [h + '.c']
|
example_files += [h + '.c']
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
project('pipewire', ['c' ],
|
project('pipewire', ['c' ],
|
||||||
version : '1.5.83',
|
version : '1.7.0',
|
||||||
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
|
license : [ 'MIT', 'LGPL-2.1-or-later', 'GPL-2.0-only' ],
|
||||||
meson_version : '>= 0.61.1',
|
meson_version : '>= 0.61.1',
|
||||||
default_options : [ 'warning_level=3',
|
default_options : [ 'warning_level=3',
|
||||||
|
|
@ -82,6 +82,7 @@ common_flags = [
|
||||||
'-fvisibility=hidden',
|
'-fvisibility=hidden',
|
||||||
'-fno-strict-aliasing',
|
'-fno-strict-aliasing',
|
||||||
'-fno-strict-overflow',
|
'-fno-strict-overflow',
|
||||||
|
'-DSPA_AUDIO_MAX_CHANNELS=128u',
|
||||||
'-Werror=suggest-attribute=format',
|
'-Werror=suggest-attribute=format',
|
||||||
'-Wsign-compare',
|
'-Wsign-compare',
|
||||||
'-Wpointer-arith',
|
'-Wpointer-arith',
|
||||||
|
|
@ -115,7 +116,7 @@ cc_flags = common_flags + [
|
||||||
'-Werror=old-style-definition',
|
'-Werror=old-style-definition',
|
||||||
'-Werror=missing-parameter-type',
|
'-Werror=missing-parameter-type',
|
||||||
'-Werror=strict-prototypes',
|
'-Werror=strict-prototypes',
|
||||||
'-DSPA_AUDIO_MAX_CHANNELS=128u',
|
'-Werror=discarded-qualifiers',
|
||||||
]
|
]
|
||||||
add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c')
|
add_project_arguments(cc.get_supported_arguments(cc_flags), language: 'c')
|
||||||
add_project_arguments(cc_native.get_supported_arguments(cc_flags),
|
add_project_arguments(cc_native.get_supported_arguments(cc_flags),
|
||||||
|
|
@ -367,7 +368,7 @@ cdata.set('HAVE_OPUS', opus_dep.found())
|
||||||
summary({'readline (for pw-cli)': readline_dep.found()}, bool_yn: true, section: 'Misc dependencies')
|
summary({'readline (for pw-cli)': readline_dep.found()}, bool_yn: true, section: 'Misc dependencies')
|
||||||
cdata.set('HAVE_READLINE', readline_dep.found())
|
cdata.set('HAVE_READLINE', readline_dep.found())
|
||||||
ncurses_dep = dependency('ncursesw', required : false)
|
ncurses_dep = dependency('ncursesw', required : false)
|
||||||
sndfile_dep = dependency('sndfile', version : '>= 1.0.20', required : get_option('sndfile'))
|
sndfile_dep = dependency('sndfile', version : '>= 1.1.0', required : get_option('sndfile'))
|
||||||
summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain')
|
summary({'sndfile': sndfile_dep.found()}, bool_yn: true, section: 'pw-cat/pw-play/pw-dump/filter-chain')
|
||||||
cdata.set('HAVE_SNDFILE', sndfile_dep.found())
|
cdata.set('HAVE_SNDFILE', sndfile_dep.found())
|
||||||
pulseaudio_dep = dependency('libpulse', required : get_option('libpulse'))
|
pulseaudio_dep = dependency('libpulse', required : get_option('libpulse'))
|
||||||
|
|
@ -411,7 +412,7 @@ gst_deps_def = {
|
||||||
'gio-unix-2.0': {},
|
'gio-unix-2.0': {},
|
||||||
'gstreamer-1.0': {'version': '>= 1.10.0'},
|
'gstreamer-1.0': {'version': '>= 1.10.0'},
|
||||||
'gstreamer-base-1.0': {},
|
'gstreamer-base-1.0': {},
|
||||||
'gstreamer-video-1.0': {},
|
'gstreamer-video-1.0': {'version': '>= 1.22.0'},
|
||||||
'gstreamer-audio-1.0': {},
|
'gstreamer-audio-1.0': {},
|
||||||
'gstreamer-allocators-1.0': {},
|
'gstreamer-allocators-1.0': {},
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -294,6 +294,10 @@ option('legacy-rtkit',
|
||||||
description: 'Build legacy rtkit module',
|
description: 'Build legacy rtkit module',
|
||||||
type: 'boolean',
|
type: 'boolean',
|
||||||
value: true)
|
value: true)
|
||||||
|
option('avb-virtual',
|
||||||
|
description: 'Enable AVB Virtual code for testing',
|
||||||
|
type: 'feature',
|
||||||
|
value: 'disabled')
|
||||||
option('avb',
|
option('avb',
|
||||||
description: 'Enable AVB code',
|
description: 'Enable AVB code',
|
||||||
type: 'feature',
|
type: 'feature',
|
||||||
|
|
|
||||||
|
|
@ -1248,6 +1248,7 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pipewire)
|
||||||
int err;
|
int err;
|
||||||
const char *str;
|
const char *str;
|
||||||
snd_ctl_pipewire_t *ctl;
|
snd_ctl_pipewire_t *ctl;
|
||||||
|
struct pw_properties *props2;
|
||||||
struct pw_loop *loop;
|
struct pw_loop *loop;
|
||||||
|
|
||||||
pw_init(NULL, NULL);
|
pw_init(NULL, NULL);
|
||||||
|
|
@ -1392,20 +1393,20 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pipewire)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
pw_thread_loop_lock(ctl->mainloop);
|
pw_thread_loop_lock(ctl->mainloop);
|
||||||
ctl->core = pw_context_connect(ctl->context, pw_properties_copy(ctl->props), 0);
|
if ((props2 = pw_properties_copy(ctl->props)) == NULL)
|
||||||
if (ctl->core == NULL) {
|
goto error_unlock_errno;
|
||||||
err = -errno;
|
|
||||||
goto error_unlock;
|
ctl->core = pw_context_connect(ctl->context, props2, 0);
|
||||||
}
|
if (ctl->core == NULL)
|
||||||
|
goto error_unlock_errno;
|
||||||
|
|
||||||
pw_core_add_listener(ctl->core,
|
pw_core_add_listener(ctl->core,
|
||||||
&ctl->core_listener,
|
&ctl->core_listener,
|
||||||
&core_events, ctl);
|
&core_events, ctl);
|
||||||
|
|
||||||
ctl->registry = pw_core_get_registry(ctl->core, PW_VERSION_REGISTRY, 0);
|
ctl->registry = pw_core_get_registry(ctl->core, PW_VERSION_REGISTRY, 0);
|
||||||
if (ctl->registry == NULL) {
|
if (ctl->registry == NULL)
|
||||||
err = -errno;
|
goto error_unlock_errno;
|
||||||
goto error_unlock;
|
|
||||||
}
|
|
||||||
|
|
||||||
pw_registry_add_listener(ctl->registry,
|
pw_registry_add_listener(ctl->registry,
|
||||||
&ctl->registry_listener,
|
&ctl->registry_listener,
|
||||||
|
|
@ -1437,6 +1438,8 @@ SND_CTL_PLUGIN_DEFINE_FUNC(pipewire)
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_unlock_errno:
|
||||||
|
err = -errno;
|
||||||
error_unlock:
|
error_unlock:
|
||||||
pw_thread_loop_unlock(ctl->mainloop);
|
pw_thread_loop_unlock(ctl->mainloop);
|
||||||
error:
|
error:
|
||||||
|
|
|
||||||
|
|
@ -951,6 +951,8 @@ static snd_pcm_chmap_t * snd_pcm_pipewire_get_chmap(snd_pcm_ioplug_t * io)
|
||||||
|
|
||||||
map = calloc(1, sizeof(snd_pcm_chmap_t) +
|
map = calloc(1, sizeof(snd_pcm_chmap_t) +
|
||||||
channels * sizeof(unsigned int));
|
channels * sizeof(unsigned int));
|
||||||
|
if (map == NULL)
|
||||||
|
return NULL;
|
||||||
map->channels = channels;
|
map->channels = channels;
|
||||||
for (i = 0; i < channels; i++)
|
for (i = 0; i < channels; i++)
|
||||||
map->pos[i] = channel_to_chmap(position[i]);
|
map->pos[i] = channel_to_chmap(position[i]);
|
||||||
|
|
@ -958,33 +960,39 @@ static snd_pcm_chmap_t * snd_pcm_pipewire_get_chmap(snd_pcm_ioplug_t * io)
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void make_map(snd_pcm_chmap_query_t **maps, int index, int channels, ...)
|
static void make_map(snd_pcm_chmap_query_t **maps, int *index, int channels, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
int i;
|
int i, idx = *index;
|
||||||
|
|
||||||
maps[index] = malloc(sizeof(snd_pcm_chmap_query_t) + (channels * sizeof(unsigned int)));
|
maps[idx] = malloc(sizeof(snd_pcm_chmap_query_t) + (channels * sizeof(unsigned int)));
|
||||||
maps[index]->type = SND_CHMAP_TYPE_FIXED;
|
if (maps[idx] == NULL)
|
||||||
maps[index]->map.channels = channels;
|
return;
|
||||||
|
maps[idx]->type = SND_CHMAP_TYPE_FIXED;
|
||||||
|
maps[idx]->map.channels = channels;
|
||||||
va_start(args, channels);
|
va_start(args, channels);
|
||||||
for (i = 0; i < channels; i++)
|
for (i = 0; i < channels; i++)
|
||||||
maps[index]->map.pos[i] = va_arg(args, int);
|
maps[idx]->map.pos[i] = va_arg(args, int);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
(*index)++;
|
||||||
}
|
}
|
||||||
|
|
||||||
static snd_pcm_chmap_query_t **snd_pcm_pipewire_query_chmaps(snd_pcm_ioplug_t *io)
|
static snd_pcm_chmap_query_t **snd_pcm_pipewire_query_chmaps(snd_pcm_ioplug_t *io)
|
||||||
{
|
{
|
||||||
snd_pcm_chmap_query_t **maps;
|
snd_pcm_chmap_query_t **maps;
|
||||||
|
int idx = 0;
|
||||||
|
|
||||||
maps = calloc(7, sizeof(*maps));
|
maps = calloc(7, sizeof(*maps));
|
||||||
make_map(maps, 0, 1, SND_CHMAP_MONO);
|
if (maps == NULL)
|
||||||
make_map(maps, 1, 2, SND_CHMAP_FL, SND_CHMAP_FR);
|
return NULL;
|
||||||
make_map(maps, 2, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR);
|
make_map(maps, &idx, 1, SND_CHMAP_MONO);
|
||||||
make_map(maps, 3, 5, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR,
|
make_map(maps, &idx, 2, SND_CHMAP_FL, SND_CHMAP_FR);
|
||||||
|
make_map(maps, &idx, 4, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR);
|
||||||
|
make_map(maps, &idx, 5, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR,
|
||||||
SND_CHMAP_FC);
|
SND_CHMAP_FC);
|
||||||
make_map(maps, 4, 6, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR,
|
make_map(maps, &idx, 6, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR,
|
||||||
SND_CHMAP_FC, SND_CHMAP_LFE);
|
SND_CHMAP_FC, SND_CHMAP_LFE);
|
||||||
make_map(maps, 5, 8, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR,
|
make_map(maps, &idx, 8, SND_CHMAP_FL, SND_CHMAP_FR, SND_CHMAP_RL, SND_CHMAP_RR,
|
||||||
SND_CHMAP_FC, SND_CHMAP_LFE, SND_CHMAP_SL, SND_CHMAP_SR);
|
SND_CHMAP_FC, SND_CHMAP_LFE, SND_CHMAP_SL, SND_CHMAP_SR);
|
||||||
|
|
||||||
return maps;
|
return maps;
|
||||||
|
|
@ -1244,7 +1252,7 @@ static ssize_t log_write(void *cookie, const char *buf, size_t size)
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cookie_io_functions_t io_funcs = {
|
static const cookie_io_functions_t io_funcs = {
|
||||||
.write = log_write,
|
.write = log_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1261,6 +1269,7 @@ static int snd_pcm_pipewire_open(snd_pcm_t **pcmp,
|
||||||
struct pw_properties *props, snd_pcm_stream_t stream, int mode)
|
struct pw_properties *props, snd_pcm_stream_t stream, int mode)
|
||||||
{
|
{
|
||||||
snd_pcm_pipewire_t *pw;
|
snd_pcm_pipewire_t *pw;
|
||||||
|
struct pw_properties *props2;
|
||||||
int err;
|
int err;
|
||||||
const char *str, *node_name = NULL;
|
const char *str, *node_name = NULL;
|
||||||
struct pw_loop *loop;
|
struct pw_loop *loop;
|
||||||
|
|
@ -1276,8 +1285,7 @@ static int snd_pcm_pipewire_open(snd_pcm_t **pcmp,
|
||||||
pw->log_file = fopencookie(pw, "w", io_funcs);
|
pw->log_file = fopencookie(pw, "w", io_funcs);
|
||||||
if (pw->log_file == NULL) {
|
if (pw->log_file == NULL) {
|
||||||
pw_log_error("can't create log file: %m");
|
pw_log_error("can't create log file: %m");
|
||||||
err = -errno;
|
goto error_errno;
|
||||||
goto error;
|
|
||||||
}
|
}
|
||||||
if ((err = snd_output_stdio_attach(&pw->output, pw->log_file, 0)) < 0) {
|
if ((err = snd_output_stdio_attach(&pw->output, pw->log_file, 0)) < 0) {
|
||||||
pw_log_error("can't attach log file: %s", snd_strerror(err));
|
pw_log_error("can't attach log file: %s", snd_strerror(err));
|
||||||
|
|
@ -1285,20 +1293,17 @@ static int snd_pcm_pipewire_open(snd_pcm_t **pcmp,
|
||||||
}
|
}
|
||||||
|
|
||||||
pw->main_loop = pw_thread_loop_new("alsa-pipewire", NULL);
|
pw->main_loop = pw_thread_loop_new("alsa-pipewire", NULL);
|
||||||
if (pw->main_loop == NULL) {
|
if (pw->main_loop == NULL)
|
||||||
err = -errno;
|
goto error_errno;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
loop = pw_thread_loop_get_loop(pw->main_loop);
|
loop = pw_thread_loop_get_loop(pw->main_loop);
|
||||||
pw->system = loop->system;
|
pw->system = loop->system;
|
||||||
if ((pw->context = pw_context_new(loop,
|
if ((pw->context = pw_context_new(loop,
|
||||||
pw_properties_new(
|
pw_properties_new(
|
||||||
PW_KEY_CLIENT_API, "alsa",
|
PW_KEY_CLIENT_API, "alsa",
|
||||||
NULL),
|
NULL),
|
||||||
0)) == NULL) {
|
0)) == NULL)
|
||||||
err = -errno;
|
goto error_errno;
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
|
|
||||||
pw_context_conf_update_props(pw->context, "alsa.properties", pw->props);
|
pw_context_conf_update_props(pw->context, "alsa.properties", pw->props);
|
||||||
|
|
||||||
|
|
@ -1348,12 +1353,14 @@ static int snd_pcm_pipewire_open(snd_pcm_t **pcmp,
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
pw_thread_loop_lock(pw->main_loop);
|
pw_thread_loop_lock(pw->main_loop);
|
||||||
pw->core = pw_context_connect(pw->context, pw_properties_copy(pw->props), 0);
|
props2 = pw_properties_copy(pw->props);
|
||||||
if (pw->core == NULL) {
|
if (props2 == NULL)
|
||||||
err = -errno;
|
goto error_unlock_errno;
|
||||||
pw_thread_loop_unlock(pw->main_loop);
|
|
||||||
goto error;
|
pw->core = pw_context_connect(pw->context, props2, 0);
|
||||||
}
|
if (pw->core == NULL)
|
||||||
|
goto error_unlock_errno;
|
||||||
|
|
||||||
pw_core_add_listener(pw->core, &pw->core_listener, &core_events, pw);
|
pw_core_add_listener(pw->core, &pw->core_listener, &core_events, pw);
|
||||||
pw_thread_loop_unlock(pw->main_loop);
|
pw_thread_loop_unlock(pw->main_loop);
|
||||||
|
|
||||||
|
|
@ -1391,6 +1398,12 @@ static int snd_pcm_pipewire_open(snd_pcm_t **pcmp,
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
error_unlock_errno:
|
||||||
|
err = -errno;
|
||||||
|
pw_thread_loop_unlock(pw->main_loop);
|
||||||
|
goto error;
|
||||||
|
error_errno:
|
||||||
|
err = -errno;
|
||||||
error:
|
error:
|
||||||
pw_log_debug("%p: failed to open %s :%s", pw, node_name, spa_strerror(err));
|
pw_log_debug("%p: failed to open %s :%s", pw, node_name, spa_strerror(err));
|
||||||
snd_pcm_pipewire_free(pw);
|
snd_pcm_pipewire_free(pw);
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ pipewire_jackserver = shared_library('jackserver',
|
||||||
pipewire_jackserver_sources,
|
pipewire_jackserver_sources,
|
||||||
soversion : soversion,
|
soversion : soversion,
|
||||||
version : libjackversion,
|
version : libjackversion,
|
||||||
c_args : pipewire_jack_c_args,
|
c_args : pipewire_jack_c_args + '-DLIBJACKSERVER',
|
||||||
include_directories : [configinc, jack_inc],
|
include_directories : [configinc, jack_inc],
|
||||||
dependencies : [pipewire_dep, mathlib],
|
dependencies : [pipewire_dep, mathlib],
|
||||||
install : true,
|
install : true,
|
||||||
|
|
|
||||||
|
|
@ -26,13 +26,6 @@ static jack_description_t *find_description(jack_uuid_t subject)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_property(jack_property_t *prop, const char *key, const char *value, const char *type)
|
|
||||||
{
|
|
||||||
prop->key = strdup(key);
|
|
||||||
prop->data = strdup(value);
|
|
||||||
prop->type = strdup(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void clear_property(jack_property_t *prop)
|
static void clear_property(jack_property_t *prop)
|
||||||
{
|
{
|
||||||
free((char*)prop->key);
|
free((char*)prop->key);
|
||||||
|
|
@ -40,16 +33,41 @@ static void clear_property(jack_property_t *prop)
|
||||||
free((char*)prop->type);
|
free((char*)prop->type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int set_property(jack_property_t *prop, const char *key, const char *value, const char *type)
|
||||||
|
{
|
||||||
|
prop->key = strdup(key);
|
||||||
|
prop->data = strdup(value);
|
||||||
|
prop->type = strdup(type);
|
||||||
|
if (prop->key == NULL || prop->data == NULL || prop->type == NULL) {
|
||||||
|
int err = errno;
|
||||||
|
clear_property(prop);
|
||||||
|
spa_zero(*prop);
|
||||||
|
return -err;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static jack_property_t *copy_properties(jack_property_t *src, uint32_t cnt)
|
static jack_property_t *copy_properties(jack_property_t *src, uint32_t cnt)
|
||||||
{
|
{
|
||||||
jack_property_t *dst;
|
jack_property_t *dst;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
dst = malloc(sizeof(jack_property_t) * cnt);
|
|
||||||
if (dst != NULL) {
|
dst = pw_reallocarray(NULL, cnt, sizeof(jack_property_t));
|
||||||
for (i = 0; i < cnt; i++)
|
if (dst == NULL)
|
||||||
set_property(&dst[i], src[i].key, src[i].data, src[i].type);
|
return NULL;
|
||||||
|
|
||||||
|
for (i = 0; i < cnt; i++) {
|
||||||
|
if (set_property(&dst[i], src[i].key, src[i].data, src[i].type) < 0)
|
||||||
|
goto cleanup;
|
||||||
}
|
}
|
||||||
return dst;
|
return dst;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
while (i > 0)
|
||||||
|
clear_property(&dst[--i]);
|
||||||
|
free(dst);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int copy_description(jack_description_t *dst, jack_description_t *src)
|
static int copy_description(jack_description_t *dst, jack_description_t *src)
|
||||||
|
|
@ -106,8 +124,10 @@ static jack_property_t *add_property(jack_description_t *desc, const char *key,
|
||||||
desc->property_size = ns;
|
desc->property_size = ns;
|
||||||
desc->properties = np;
|
desc->properties = np;
|
||||||
}
|
}
|
||||||
prop = &desc->properties[desc->property_cnt++];
|
prop = &desc->properties[desc->property_cnt];
|
||||||
set_property(prop, key, value, type);
|
if (set_property(prop, key, value, type) < 0)
|
||||||
|
return NULL;
|
||||||
|
desc->property_cnt++;
|
||||||
return prop;
|
return prop;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -127,13 +147,19 @@ static int change_property(jack_property_t *prop, const char *value, const char
|
||||||
{
|
{
|
||||||
int changed = 0;
|
int changed = 0;
|
||||||
if (!spa_streq(prop->data, value)) {
|
if (!spa_streq(prop->data, value)) {
|
||||||
|
char *v = strdup(value);
|
||||||
|
if (v == NULL)
|
||||||
|
return -errno;
|
||||||
free((char*)prop->data);
|
free((char*)prop->data);
|
||||||
prop->data = strdup(value);
|
prop->data = v;
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
if (!spa_streq(prop->type, type)) {
|
if (!spa_streq(prop->type, type)) {
|
||||||
|
char *t = strdup(type);
|
||||||
|
if (t == NULL)
|
||||||
|
return -errno;
|
||||||
free((char*)prop->type);
|
free((char*)prop->type);
|
||||||
prop->type = strdup(type);
|
prop->type = t;
|
||||||
changed++;
|
changed++;
|
||||||
}
|
}
|
||||||
return changed;
|
return changed;
|
||||||
|
|
@ -245,26 +271,38 @@ int jack_get_property(jack_uuid_t subject,
|
||||||
{
|
{
|
||||||
jack_description_t *desc;
|
jack_description_t *desc;
|
||||||
jack_property_t *prop;
|
jack_property_t *prop;
|
||||||
int res = -1;
|
char *v, *t;
|
||||||
|
|
||||||
pthread_mutex_lock(&globals.lock);
|
pthread_mutex_lock(&globals.lock);
|
||||||
desc = find_description(subject);
|
desc = find_description(subject);
|
||||||
if (desc == NULL)
|
if (desc == NULL)
|
||||||
goto done;
|
goto error;
|
||||||
|
|
||||||
prop = find_property(desc, key);
|
prop = find_property(desc, key);
|
||||||
if (prop == NULL)
|
if (prop == NULL)
|
||||||
goto done;
|
goto error;
|
||||||
|
|
||||||
*value = strdup(prop->data);
|
v = strdup(prop->data);
|
||||||
*type = strdup(prop->type);
|
t = strdup(prop->type);
|
||||||
res = 0;
|
if (v == NULL || t == NULL)
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&globals.lock);
|
||||||
|
|
||||||
|
*value = v;
|
||||||
|
*type = t;
|
||||||
|
|
||||||
pw_log_debug("subject:%"PRIu64" key:'%s' value:'%s' type:'%s'",
|
pw_log_debug("subject:%"PRIu64" key:'%s' value:'%s' type:'%s'",
|
||||||
subject, key, *value, *type);
|
subject, key, v, t);
|
||||||
done:
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
free(v);
|
||||||
|
free(t);
|
||||||
|
error:
|
||||||
pthread_mutex_unlock(&globals.lock);
|
pthread_mutex_unlock(&globals.lock);
|
||||||
return res;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
|
|
@ -312,12 +350,26 @@ int jack_get_all_properties (jack_description_t** result)
|
||||||
len = pw_array_get_len(descriptions, jack_description_t);
|
len = pw_array_get_len(descriptions, jack_description_t);
|
||||||
src = descriptions->data;
|
src = descriptions->data;
|
||||||
dst = malloc(descriptions->size);
|
dst = malloc(descriptions->size);
|
||||||
for (i = 0; i < len; i++)
|
if (dst == NULL)
|
||||||
copy_description(&dst[i], &src[i]);
|
goto error;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if (copy_description(&dst[i], &src[i]) < 0)
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
*result = dst;
|
*result = dst;
|
||||||
pthread_mutex_unlock(&globals.lock);
|
pthread_mutex_unlock(&globals.lock);
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
while (i > 0)
|
||||||
|
jack_free_description(&dst[--i], false);
|
||||||
|
free(dst);
|
||||||
|
error:
|
||||||
|
*result = NULL;
|
||||||
|
pthread_mutex_unlock(&globals.lock);
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
|
|
|
||||||
|
|
@ -73,7 +73,6 @@ PW_LOG_TOPIC_STATIC(jack_log_topic, "jack");
|
||||||
|
|
||||||
#define TYPE_ID_IS_EVENT(t) ((t) >= TYPE_ID_MIDI && (t) <= TYPE_ID_UMP)
|
#define TYPE_ID_IS_EVENT(t) ((t) >= TYPE_ID_MIDI && (t) <= TYPE_ID_UMP)
|
||||||
#define TYPE_ID_CAN_OSC(t) ((t) == TYPE_ID_MIDI || (t) == TYPE_ID_OSC)
|
#define TYPE_ID_CAN_OSC(t) ((t) == TYPE_ID_MIDI || (t) == TYPE_ID_OSC)
|
||||||
#define TYPE_ID_IS_HIDDEN(t) ((t) >= TYPE_ID_OTHER)
|
|
||||||
#define TYPE_ID_IS_COMPATIBLE(a,b)(((a) == (b)) || (TYPE_ID_IS_EVENT(a) && TYPE_ID_IS_EVENT(b)))
|
#define TYPE_ID_IS_COMPATIBLE(a,b)(((a) == (b)) || (TYPE_ID_IS_EVENT(a) && TYPE_ID_IS_EVENT(b)))
|
||||||
|
|
||||||
#define SELF_CONNECT_ALLOW 0
|
#define SELF_CONNECT_ALLOW 0
|
||||||
|
|
@ -86,7 +85,7 @@ PW_LOG_TOPIC_STATIC(jack_log_topic, "jack");
|
||||||
#define OTHER_CONNECT_FAIL -1
|
#define OTHER_CONNECT_FAIL -1
|
||||||
#define OTHER_CONNECT_IGNORE 0
|
#define OTHER_CONNECT_IGNORE 0
|
||||||
|
|
||||||
#define NOTIFY_BUFFER_SIZE (1u<<13)
|
#define NOTIFY_BUFFER_SIZE (1u<<16)
|
||||||
#define NOTIFY_BUFFER_MASK (NOTIFY_BUFFER_SIZE-1)
|
#define NOTIFY_BUFFER_MASK (NOTIFY_BUFFER_SIZE-1)
|
||||||
|
|
||||||
struct notify {
|
struct notify {
|
||||||
|
|
@ -104,8 +103,8 @@ struct notify {
|
||||||
#define NOTIFY_TYPE_TOTAL_LATENCY ((9<<4)|NOTIFY_ACTIVE_FLAG)
|
#define NOTIFY_TYPE_TOTAL_LATENCY ((9<<4)|NOTIFY_ACTIVE_FLAG)
|
||||||
#define NOTIFY_TYPE_PORT_RENAME ((10<<4)|NOTIFY_ACTIVE_FLAG)
|
#define NOTIFY_TYPE_PORT_RENAME ((10<<4)|NOTIFY_ACTIVE_FLAG)
|
||||||
int type;
|
int type;
|
||||||
struct object *object;
|
|
||||||
int arg1;
|
int arg1;
|
||||||
|
struct object *object;
|
||||||
const char *msg;
|
const char *msg;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -492,6 +491,8 @@ struct client {
|
||||||
jack_position_t jack_position;
|
jack_position_t jack_position;
|
||||||
jack_transport_state_t jack_state;
|
jack_transport_state_t jack_state;
|
||||||
struct frame_times jack_times;
|
struct frame_times jack_times;
|
||||||
|
|
||||||
|
struct object dummy_port;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define return_val_if_fail(expr, val) \
|
#define return_val_if_fail(expr, val) \
|
||||||
|
|
@ -1446,8 +1447,9 @@ static size_t convert_from_event(void *midi, void *buffer, size_t size, uint32_t
|
||||||
|
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
|
event_type = SPA_CONTROL_Midi;
|
||||||
|
break;
|
||||||
case TYPE_ID_OSC:
|
case TYPE_ID_OSC:
|
||||||
/* we handle MIDI as OSC, check below */
|
|
||||||
event_type = SPA_CONTROL_OSC;
|
event_type = SPA_CONTROL_OSC;
|
||||||
break;
|
break;
|
||||||
case TYPE_ID_UMP:
|
case TYPE_ID_UMP:
|
||||||
|
|
@ -1464,27 +1466,15 @@ static size_t convert_from_event(void *midi, void *buffer, size_t size, uint32_t
|
||||||
for (i = 0; i < count; i++) {
|
for (i = 0; i < count; i++) {
|
||||||
jack_midi_event_t ev;
|
jack_midi_event_t ev;
|
||||||
jack_midi_event_get(&ev, midi, i);
|
jack_midi_event_get(&ev, midi, i);
|
||||||
|
uint32_t ev_type;
|
||||||
|
|
||||||
if (type != TYPE_ID_MIDI || is_osc(&ev)) {
|
if (type == TYPE_ID_MIDI && is_osc(&ev))
|
||||||
/* no midi port or it's OSC */
|
ev_type = SPA_CONTROL_OSC;
|
||||||
spa_pod_builder_control(&b, ev.time, event_type);
|
else
|
||||||
|
ev_type = event_type;
|
||||||
|
|
||||||
|
spa_pod_builder_control(&b, ev.time, ev_type);
|
||||||
spa_pod_builder_bytes(&b, ev.buffer, ev.size);
|
spa_pod_builder_bytes(&b, ev.buffer, ev.size);
|
||||||
} else {
|
|
||||||
/* midi port and it's not OSC, convert to UMP */
|
|
||||||
uint8_t *data = ev.buffer;
|
|
||||||
size_t size = ev.size;
|
|
||||||
uint64_t state = 0;
|
|
||||||
|
|
||||||
while (size > 0) {
|
|
||||||
uint32_t ump[4];
|
|
||||||
int ump_size = spa_ump_from_midi(&data, &size,
|
|
||||||
ump, sizeof(ump), 0, &state);
|
|
||||||
if (ump_size <= 0)
|
|
||||||
break;
|
|
||||||
spa_pod_builder_control(&b, ev.time, SPA_CONTROL_UMP);
|
|
||||||
spa_pod_builder_bytes(&b, ump, ump_size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
spa_pod_builder_pop(&b, &f);
|
spa_pod_builder_pop(&b, &f);
|
||||||
return b.state.offset;
|
return b.state.offset;
|
||||||
|
|
@ -1579,6 +1569,8 @@ static inline int midi_event_append(void *port_buffer, const jack_midi_data_t *d
|
||||||
size_t old_size;
|
size_t old_size;
|
||||||
uint8_t *old, *buf;
|
uint8_t *old, *buf;
|
||||||
|
|
||||||
|
if (mb->event_count == 0)
|
||||||
|
return -ENOBUFS;
|
||||||
ev = &events[--mb->event_count];
|
ev = &events[--mb->event_count];
|
||||||
mb->write_pos -= ev->size;
|
mb->write_pos -= ev->size;
|
||||||
old_size = ev->size;
|
old_size = ev->size;
|
||||||
|
|
@ -1776,7 +1768,7 @@ static inline void process_empty(struct port *p, uint32_t frames)
|
||||||
case TYPE_ID_AUDIO:
|
case TYPE_ID_AUDIO:
|
||||||
ptr = get_buffer_output(p, frames, sizeof(float), NULL);
|
ptr = get_buffer_output(p, frames, sizeof(float), NULL);
|
||||||
if (SPA_LIKELY(ptr != NULL))
|
if (SPA_LIKELY(ptr != NULL))
|
||||||
memcpy(ptr, src, frames * sizeof(float));
|
spa_memcpy(ptr, src, frames * sizeof(float));
|
||||||
break;
|
break;
|
||||||
case TYPE_ID_MIDI:
|
case TYPE_ID_MIDI:
|
||||||
case TYPE_ID_OSC:
|
case TYPE_ID_OSC:
|
||||||
|
|
@ -1790,7 +1782,7 @@ static inline void process_empty(struct port *p, uint32_t frames)
|
||||||
* to do this concurrently */
|
* to do this concurrently */
|
||||||
b->datas[0].chunk->size = convert_from_event(src, midi_scratch,
|
b->datas[0].chunk->size = convert_from_event(src, midi_scratch,
|
||||||
MIDI_SCRATCH_FRAMES * sizeof(float), type);
|
MIDI_SCRATCH_FRAMES * sizeof(float), type);
|
||||||
memcpy(ptr, midi_scratch, b->datas[0].chunk->size);
|
spa_memcpy(ptr, midi_scratch, b->datas[0].chunk->size);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2208,7 +2200,7 @@ on_rtsocket_condition(void *data, int fd, uint32_t mask)
|
||||||
}
|
}
|
||||||
} else if (SPA_LIKELY(mask & SPA_IO_IN)) {
|
} else if (SPA_LIKELY(mask & SPA_IO_IN)) {
|
||||||
uint32_t buffer_frames;
|
uint32_t buffer_frames;
|
||||||
int status = 0;
|
int status = -EBUSY;
|
||||||
|
|
||||||
buffer_frames = cycle_run(c);
|
buffer_frames = cycle_run(c);
|
||||||
|
|
||||||
|
|
@ -3724,8 +3716,8 @@ static int update_port_name(struct object *o, const char *name)
|
||||||
if (spa_streq(port_name, o->port.name))
|
if (spa_streq(port_name, o->port.name))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
strcpy(o->port.old_name, o->port.name);
|
snprintf(o->port.old_name, sizeof(o->port.old_name), "%s", o->port.name);
|
||||||
strcpy(o->port.name, port_name);
|
snprintf(o->port.name, sizeof(o->port.name), "%s", port_name);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3798,7 +3790,8 @@ static void registry_event_global(void *data, uint32_t id,
|
||||||
if ((str = spa_dict_lookup(props, PW_KEY_SEC_PID)) != NULL) {
|
if ((str = spa_dict_lookup(props, PW_KEY_SEC_PID)) != NULL) {
|
||||||
pw_log_debug("%p: pid of \"%s\" is \"%s\"", c, app, str);
|
pw_log_debug("%p: pid of \"%s\" is \"%s\"", c, app, str);
|
||||||
} else {
|
} else {
|
||||||
pw_log_debug("%p: pid of \"%s\" is unknown", c, app);
|
pw_log_warn("%p: pid of \"%s\" is unknown", c, app);
|
||||||
|
str = "0";
|
||||||
}
|
}
|
||||||
|
|
||||||
o = alloc_object(c, INTERFACE_Client);
|
o = alloc_object(c, INTERFACE_Client);
|
||||||
|
|
@ -3903,8 +3896,9 @@ static void registry_event_global(void *data, uint32_t id,
|
||||||
const char *name;
|
const char *name;
|
||||||
|
|
||||||
if ((str = spa_dict_lookup(props, PW_KEY_FORMAT_DSP)) == NULL)
|
if ((str = spa_dict_lookup(props, PW_KEY_FORMAT_DSP)) == NULL)
|
||||||
str = "other";
|
goto exit;
|
||||||
if ((type_id = string_to_type(str)) == SPA_ID_INVALID)
|
if ((type_id = string_to_type(str)) == SPA_ID_INVALID ||
|
||||||
|
!type_is_dsp(type_id))
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
if ((str = spa_dict_lookup(props, PW_KEY_NODE_ID)) == NULL)
|
if ((str = spa_dict_lookup(props, PW_KEY_NODE_ID)) == NULL)
|
||||||
|
|
@ -4386,13 +4380,17 @@ jack_client_t * jack_client_open (const char *client_name,
|
||||||
if (client->core == NULL)
|
if (client->core == NULL)
|
||||||
goto server_failed;
|
goto server_failed;
|
||||||
|
|
||||||
client->pool = pw_core_get_mempool(client->core);
|
|
||||||
|
|
||||||
pw_core_add_listener(client->core,
|
pw_core_add_listener(client->core,
|
||||||
&client->core_listener,
|
&client->core_listener,
|
||||||
&core_events, client);
|
&core_events, client);
|
||||||
|
|
||||||
|
client->pool = pw_core_get_mempool(client->core);
|
||||||
|
|
||||||
client->registry = pw_core_get_registry(client->core,
|
client->registry = pw_core_get_registry(client->core,
|
||||||
PW_VERSION_REGISTRY, 0);
|
PW_VERSION_REGISTRY, 0);
|
||||||
|
if (client->registry == NULL)
|
||||||
|
goto init_failed;
|
||||||
|
|
||||||
pw_registry_add_listener(client->registry,
|
pw_registry_add_listener(client->registry,
|
||||||
&client->registry_listener,
|
&client->registry_listener,
|
||||||
®istry_events, client);
|
®istry_events, client);
|
||||||
|
|
@ -4468,6 +4466,11 @@ jack_client_t * jack_client_open (const char *client_name,
|
||||||
0, NULL, &client->info);
|
0, NULL, &client->info);
|
||||||
client->info.change_mask = 0;
|
client->info.change_mask = 0;
|
||||||
|
|
||||||
|
client->dummy_port.type = INTERFACE_Port;
|
||||||
|
snprintf(client->dummy_port.port.name, sizeof(client->dummy_port.port.name), "%s:dummy", client_name);
|
||||||
|
snprintf(client->dummy_port.port.alias1, sizeof(client->dummy_port.port.alias1), "%s:dummy", client_name);
|
||||||
|
snprintf(client->dummy_port.port.alias2, sizeof(client->dummy_port.port.alias2), "%s:dummy", client_name);
|
||||||
|
|
||||||
client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
|
client->show_monitor = pw_properties_get_bool(client->props, "jack.show-monitor", true);
|
||||||
client->show_midi = pw_properties_get_bool(client->props, "jack.show-midi", true);
|
client->show_midi = pw_properties_get_bool(client->props, "jack.show-midi", true);
|
||||||
client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", true);
|
client->merge_monitor = pw_properties_get_bool(client->props, "jack.merge-monitor", true);
|
||||||
|
|
@ -4868,7 +4871,7 @@ int jack_activate (jack_client_t *client)
|
||||||
freeze_callbacks(c);
|
freeze_callbacks(c);
|
||||||
|
|
||||||
/* reemit buffer_frames */
|
/* reemit buffer_frames */
|
||||||
c->buffer_frames = 0;
|
c->buffer_frames = (uint32_t)-1;
|
||||||
|
|
||||||
pw_data_loop_start(c->loop);
|
pw_data_loop_start(c->loop);
|
||||||
c->active = true;
|
c->active = true;
|
||||||
|
|
@ -4880,9 +4883,21 @@ int jack_activate (jack_client_t *client)
|
||||||
c->activation->pending_sync = true;
|
c->activation->pending_sync = true;
|
||||||
|
|
||||||
spa_list_for_each(o, &c->context.objects, link) {
|
spa_list_for_each(o, &c->context.objects, link) {
|
||||||
|
#if !defined(LIBJACKSERVER)
|
||||||
if (o->type != INTERFACE_Port || o->port.port == NULL ||
|
if (o->type != INTERFACE_Port || o->port.port == NULL ||
|
||||||
o->port.port->client != c || !o->port.port->valid)
|
o->port.port->client != c || !o->port.port->valid)
|
||||||
continue;
|
continue;
|
||||||
|
#else
|
||||||
|
/* emits all foreign active ports, skips own (already announced via jack_port_register) */
|
||||||
|
if (o->type != INTERFACE_Port || o->removed)
|
||||||
|
continue;
|
||||||
|
/* own ports are handled by jack_port_register */
|
||||||
|
if (o->port.port != NULL && o->port.port->client == c)
|
||||||
|
continue;
|
||||||
|
/* only announce ports whose node is active */
|
||||||
|
if (o->port.node != NULL && !node_is_active(c, o->port.node))
|
||||||
|
continue;
|
||||||
|
#endif
|
||||||
o->registered = 0;
|
o->registered = 0;
|
||||||
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, o, 1, NULL);
|
queue_notify(c, NOTIFY_TYPE_PORTREGISTRATION, o, 1, NULL);
|
||||||
}
|
}
|
||||||
|
|
@ -5318,7 +5333,7 @@ int jack_set_freewheel(jack_client_t* client, int onoff)
|
||||||
pw_thread_loop_lock(c->context.loop);
|
pw_thread_loop_lock(c->context.loop);
|
||||||
str = pw_properties_get(c->props, PW_KEY_NODE_GROUP);
|
str = pw_properties_get(c->props, PW_KEY_NODE_GROUP);
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
char *p = strstr(str, ",pipewire.freewheel");
|
const char *p = strstr(str, ",pipewire.freewheel");
|
||||||
if (p == NULL)
|
if (p == NULL)
|
||||||
p = strstr(str, "pipewire.freewheel");
|
p = strstr(str, "pipewire.freewheel");
|
||||||
if (p == NULL && onoff)
|
if (p == NULL && onoff)
|
||||||
|
|
@ -5437,7 +5452,7 @@ SPA_EXPORT
|
||||||
jack_nframes_t jack_get_buffer_size (jack_client_t *client)
|
jack_nframes_t jack_get_buffer_size (jack_client_t *client)
|
||||||
{
|
{
|
||||||
struct client *c = (struct client *) client;
|
struct client *c = (struct client *) client;
|
||||||
jack_nframes_t res = -1;
|
uint32_t res = -1;
|
||||||
|
|
||||||
return_val_if_fail(c != NULL, 0);
|
return_val_if_fail(c != NULL, 0);
|
||||||
|
|
||||||
|
|
@ -5454,7 +5469,7 @@ jack_nframes_t jack_get_buffer_size (jack_client_t *client)
|
||||||
}
|
}
|
||||||
c->buffer_frames = res;
|
c->buffer_frames = res;
|
||||||
pw_log_debug("buffer_frames: %u", res);
|
pw_log_debug("buffer_frames: %u", res);
|
||||||
return res;
|
return (jack_nframes_t)res;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
|
|
@ -5523,7 +5538,8 @@ jack_port_t * jack_port_register (jack_client_t *client,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((type_id = string_to_type(port_type)) == SPA_ID_INVALID) {
|
if ((type_id = string_to_type(port_type)) == SPA_ID_INVALID ||
|
||||||
|
!type_is_dsp(type_id)) {
|
||||||
pw_log_warn("unknown port type %s", port_type);
|
pw_log_warn("unknown port type %s", port_type);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -5551,7 +5567,7 @@ jack_port_t * jack_port_register (jack_client_t *client,
|
||||||
|
|
||||||
o = p->object;
|
o = p->object;
|
||||||
o->port.flags = flags;
|
o->port.flags = flags;
|
||||||
strcpy(o->port.name, name);
|
snprintf(o->port.name, sizeof(o->port.name), "%s", name);
|
||||||
o->port.type_id = type_id;
|
o->port.type_id = type_id;
|
||||||
|
|
||||||
init_buffer(p, c->max_frames);
|
init_buffer(p, c->max_frames);
|
||||||
|
|
@ -5842,11 +5858,11 @@ static void *get_buffer_input_midi(struct port *p, jack_nframes_t frames)
|
||||||
* the per port buffer. This makes it possible to call this function concurrently
|
* the per port buffer. This makes it possible to call this function concurrently
|
||||||
* but also have different pointers per port */
|
* but also have different pointers per port */
|
||||||
convert_to_event(mix_info, n_mix_info, mb, p->client->fix_midi_events, p->object->port.type_id);
|
convert_to_event(mix_info, n_mix_info, mb, p->client->fix_midi_events, p->object->port.type_id);
|
||||||
memcpy(ptr, mb, sizeof(struct midi_buffer) + (mb->event_count
|
spa_memcpy(ptr, mb, sizeof(struct midi_buffer) + (mb->event_count
|
||||||
* sizeof(struct midi_event)));
|
* sizeof(struct midi_event)));
|
||||||
if (mb->write_pos > 0) {
|
if (mb->write_pos > 0) {
|
||||||
size_t offs = mb->buffer_size - mb->write_pos;
|
size_t offs = mb->buffer_size - mb->write_pos;
|
||||||
memcpy(SPA_PTROFF(ptr, offs, void), SPA_PTROFF(mb, offs, void), mb->write_pos);
|
spa_memcpy(SPA_PTROFF(ptr, offs, void), SPA_PTROFF(mb, offs, void), mb->write_pos);
|
||||||
}
|
}
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
|
@ -5951,9 +5967,7 @@ static const char *port_name(struct object *o)
|
||||||
{
|
{
|
||||||
const char *name;
|
const char *name;
|
||||||
struct client *c = o->client;
|
struct client *c = o->client;
|
||||||
if (c == NULL)
|
if (c != NULL && c->default_as_system && is_port_default(c, o))
|
||||||
return NULL;
|
|
||||||
if (c->default_as_system && is_port_default(c, o))
|
|
||||||
name = o->port.system;
|
name = o->port.system;
|
||||||
else
|
else
|
||||||
name = o->port.name;
|
name = o->port.name;
|
||||||
|
|
@ -5977,7 +5991,8 @@ const char * jack_port_short_name (const jack_port_t *port)
|
||||||
return_val_if_fail(o != NULL, NULL);
|
return_val_if_fail(o != NULL, NULL);
|
||||||
if (o->type != INTERFACE_Port)
|
if (o->type != INTERFACE_Port)
|
||||||
return NULL;
|
return NULL;
|
||||||
return strchr(port_name(o), ':') + 1;
|
const char *p = strchr(port_name(o), ':');
|
||||||
|
return p ? p + 1 : port_name(o);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
|
|
@ -6007,7 +6022,16 @@ jack_port_type_id_t jack_port_type_id (const jack_port_t *port)
|
||||||
return_val_if_fail(o != NULL, 0);
|
return_val_if_fail(o != NULL, 0);
|
||||||
if (o->type != INTERFACE_Port)
|
if (o->type != INTERFACE_Port)
|
||||||
return TYPE_ID_OTHER;
|
return TYPE_ID_OTHER;
|
||||||
return o->port.type_id;
|
|
||||||
|
/* map internal type IDs to jack1/jack2 compatible public values */
|
||||||
|
switch (o->port.type_id) {
|
||||||
|
case TYPE_ID_AUDIO: return 0;
|
||||||
|
case TYPE_ID_MIDI:
|
||||||
|
case TYPE_ID_OSC:
|
||||||
|
case TYPE_ID_UMP: return 1; /* all MIDI variants map to 1 */
|
||||||
|
case TYPE_ID_VIDEO: return 3; /* video maps to 3 */
|
||||||
|
default: return o->port.type_id;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_EXPORT
|
SPA_EXPORT
|
||||||
|
|
@ -6498,10 +6522,10 @@ int jack_connect (jack_client_t *client,
|
||||||
if ((res = check_connect(c, src, dst)) != 1)
|
if ((res = check_connect(c, src, dst)) != 1)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
snprintf(val[0], sizeof(val[0]), "%d", src->port.node_id);
|
snprintf(val[0], sizeof(val[0]), "%u", src->port.node_id);
|
||||||
snprintf(val[1], sizeof(val[1]), "%d", src->id);
|
snprintf(val[1], sizeof(val[1]), "%u", src->id);
|
||||||
snprintf(val[2], sizeof(val[2]), "%d", dst->port.node_id);
|
snprintf(val[2], sizeof(val[2]), "%u", dst->port.node_id);
|
||||||
snprintf(val[3], sizeof(val[3]), "%d", dst->id);
|
snprintf(val[3], sizeof(val[3]), "%u", dst->id);
|
||||||
|
|
||||||
props = SPA_DICT_INIT(items, 0);
|
props = SPA_DICT_INIT(items, 0);
|
||||||
items[props.n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_LINK_OUTPUT_NODE, val[0]);
|
items[props.n_items++] = SPA_DICT_ITEM_INIT(PW_KEY_LINK_OUTPUT_NODE, val[0]);
|
||||||
|
|
@ -6564,8 +6588,6 @@ int jack_disconnect (jack_client_t *client,
|
||||||
src = find_port_by_name(c, source_port);
|
src = find_port_by_name(c, source_port);
|
||||||
dst = find_port_by_name(c, destination_port);
|
dst = find_port_by_name(c, destination_port);
|
||||||
|
|
||||||
pw_log_debug("%p: %d %d", client, src->id, dst->id);
|
|
||||||
|
|
||||||
if (src == NULL || dst == NULL ||
|
if (src == NULL || dst == NULL ||
|
||||||
!(src->port.flags & JackPortIsOutput) ||
|
!(src->port.flags & JackPortIsOutput) ||
|
||||||
!(dst->port.flags & JackPortIsInput)) {
|
!(dst->port.flags & JackPortIsInput)) {
|
||||||
|
|
@ -6920,8 +6942,6 @@ const char ** jack_get_ports (jack_client_t *client,
|
||||||
continue;
|
continue;
|
||||||
pw_log_debug("%p: check port type:%d flags:%08lx name:\"%s\"", c,
|
pw_log_debug("%p: check port type:%d flags:%08lx name:\"%s\"", c,
|
||||||
o->port.type_id, o->port.flags, o->port.name);
|
o->port.type_id, o->port.flags, o->port.name);
|
||||||
if (TYPE_ID_IS_HIDDEN(o->port.type_id))
|
|
||||||
continue;
|
|
||||||
if (!SPA_FLAG_IS_SET(o->port.flags, flags))
|
if (!SPA_FLAG_IS_SET(o->port.flags, flags))
|
||||||
continue;
|
continue;
|
||||||
if (str != NULL && o->port.node != NULL) {
|
if (str != NULL && o->port.node != NULL) {
|
||||||
|
|
@ -6999,13 +7019,11 @@ jack_port_t * jack_port_by_id (jack_client_t *client,
|
||||||
|
|
||||||
pthread_mutex_lock(&c->context.lock);
|
pthread_mutex_lock(&c->context.lock);
|
||||||
res = find_by_serial(c, port_id);
|
res = find_by_serial(c, port_id);
|
||||||
if (res && res->type != INTERFACE_Port)
|
|
||||||
res = NULL;
|
|
||||||
pw_log_debug("%p: port %d -> %p", c, port_id, res);
|
|
||||||
pthread_mutex_unlock(&c->context.lock);
|
pthread_mutex_unlock(&c->context.lock);
|
||||||
|
if (res == NULL || res->type != INTERFACE_Port)
|
||||||
|
res = &c->dummy_port;
|
||||||
|
|
||||||
if (res == NULL)
|
pw_log_debug("%p: port %d -> %p", c, port_id, res);
|
||||||
pw_log_info("%p: port %d not found", c, port_id);
|
|
||||||
|
|
||||||
return object_to_port(res);
|
return object_to_port(res);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -132,10 +132,10 @@ size_t jack_ringbuffer_read(jack_ringbuffer_t *rb, char *dest, size_t cnt)
|
||||||
n2 = 0;
|
n2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
|
spa_memcpy (dest, &(rb->buf[rb->read_ptr]), n1);
|
||||||
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
|
rb->read_ptr = (rb->read_ptr + n1) & rb->size_mask;
|
||||||
if (n2) {
|
if (n2) {
|
||||||
memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
|
spa_memcpy (dest + n1, &(rb->buf[rb->read_ptr]), n2);
|
||||||
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
|
rb->read_ptr = (rb->read_ptr + n2) & rb->size_mask;
|
||||||
}
|
}
|
||||||
return to_read;
|
return to_read;
|
||||||
|
|
@ -167,11 +167,11 @@ size_t jack_ringbuffer_peek(jack_ringbuffer_t *rb, char *dest, size_t cnt)
|
||||||
n2 = 0;
|
n2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
|
spa_memcpy (dest, &(rb->buf[tmp_read_ptr]), n1);
|
||||||
tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
|
tmp_read_ptr = (tmp_read_ptr + n1) & rb->size_mask;
|
||||||
|
|
||||||
if (n2)
|
if (n2)
|
||||||
memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
|
spa_memcpy (dest + n1, &(rb->buf[tmp_read_ptr]), n2);
|
||||||
|
|
||||||
return to_read;
|
return to_read;
|
||||||
}
|
}
|
||||||
|
|
@ -249,10 +249,10 @@ size_t jack_ringbuffer_write(jack_ringbuffer_t *rb, const char *src,
|
||||||
n2 = 0;
|
n2 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy (&(rb->buf[rb->write_ptr]), src, n1);
|
spa_memcpy (&(rb->buf[rb->write_ptr]), src, n1);
|
||||||
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
|
rb->write_ptr = (rb->write_ptr + n1) & rb->size_mask;
|
||||||
if (n2) {
|
if (n2) {
|
||||||
memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
|
spa_memcpy (&(rb->buf[rb->write_ptr]), src + n1, n2);
|
||||||
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
|
rb->write_ptr = (rb->write_ptr + n2) & rb->size_mask;
|
||||||
}
|
}
|
||||||
return to_write;
|
return to_write;
|
||||||
|
|
|
||||||
|
|
@ -2570,7 +2570,10 @@ static void *v4l2_mmap(void *addr, size_t length, int prot,
|
||||||
buf = &file->buffers[id];
|
buf = &file->buffers[id];
|
||||||
data = &buf->buf->buffer->datas[0];
|
data = &buf->buf->buffer->datas[0];
|
||||||
|
|
||||||
pw_map_range_init(&range, data->mapoffset, data->maxsize, 1024);
|
if (pw_map_range_init(&range, data->mapoffset, data->maxsize, 1024) < 0) {
|
||||||
|
res = MAP_FAILED;
|
||||||
|
goto error_unlock;
|
||||||
|
}
|
||||||
|
|
||||||
if (!SPA_FLAG_IS_SET(data->flags, SPA_DATA_FLAG_READABLE))
|
if (!SPA_FLAG_IS_SET(data->flags, SPA_DATA_FLAG_READABLE))
|
||||||
prot &= ~PROT_READ;
|
prot &= ~PROT_READ;
|
||||||
|
|
|
||||||
10
po/LINGUAS
10
po/LINGUAS
|
|
@ -7,9 +7,10 @@ bn_IN
|
||||||
ca
|
ca
|
||||||
cs
|
cs
|
||||||
da
|
da
|
||||||
de_CH
|
|
||||||
de
|
de
|
||||||
|
de_CH
|
||||||
el
|
el
|
||||||
|
eo
|
||||||
es
|
es
|
||||||
fi
|
fi
|
||||||
fr
|
fr
|
||||||
|
|
@ -36,14 +37,15 @@ oc
|
||||||
or
|
or
|
||||||
pa
|
pa
|
||||||
pl
|
pl
|
||||||
pt_BR
|
|
||||||
pt
|
pt
|
||||||
|
pt_BR
|
||||||
ro
|
ro
|
||||||
ru
|
ru
|
||||||
|
si
|
||||||
sk
|
sk
|
||||||
sl
|
sl
|
||||||
sr@latin
|
|
||||||
sr
|
sr
|
||||||
|
sr@latin
|
||||||
sv
|
sv
|
||||||
ta
|
ta
|
||||||
te
|
te
|
||||||
|
|
@ -51,5 +53,3 @@ tr
|
||||||
uk
|
uk
|
||||||
zh_CN
|
zh_CN
|
||||||
zh_TW
|
zh_TW
|
||||||
eo
|
|
||||||
si
|
|
||||||
|
|
|
||||||
573
po/kk.po
573
po/kk.po
|
|
@ -1,15 +1,14 @@
|
||||||
# Kazakh translation of pipewire.
|
# Kazakh translation of pipewire.
|
||||||
# Copyright (C) 2020 The pipewire authors.
|
# Copyright (C) 2020 The pipewire authors.
|
||||||
# This file is distributed under the same license as the pipewire package.
|
# This file is distributed under the same license as the pipewire package.
|
||||||
# Baurzhan Muftakhidinov <baurthefirst@gmail.com>, 2020.
|
# Baurzhan Muftakhidinov <baurthefirst@gmail.com>, 2020-2026.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: \n"
|
"Project-Id-Version: \n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
|
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues\n"
|
||||||
"issues/new\n"
|
"POT-Creation-Date: 2026-03-09 12:19+0000\n"
|
||||||
"POT-Creation-Date: 2021-04-18 16:54+0800\n"
|
"PO-Revision-Date: 2026-03-17 00:04+0500\n"
|
||||||
"PO-Revision-Date: 2020-06-30 08:04+0500\n"
|
|
||||||
"Last-Translator: Baurzhan Muftakhidinov <baurthefirst@gmail.com>\n"
|
"Last-Translator: Baurzhan Muftakhidinov <baurthefirst@gmail.com>\n"
|
||||||
"Language-Team: \n"
|
"Language-Team: \n"
|
||||||
"Language: kk\n"
|
"Language: kk\n"
|
||||||
|
|
@ -17,96 +16,199 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||||
"X-Generator: Poedit 2.3.1\n"
|
"X-Generator: Poedit 3.9\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.c:43
|
#: src/daemon/pipewire.c:29
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options]\n"
|
"%s [options]\n"
|
||||||
" -h, --help Show this help\n"
|
" -h, --help Show this help\n"
|
||||||
|
" -v, --verbose Increase verbosity by one level\n"
|
||||||
" --version Show version\n"
|
" --version Show version\n"
|
||||||
" -c, --config Load config (Default %s)\n"
|
" -c, --config Load config (Default %s)\n"
|
||||||
|
" -P --properties Set context properties\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%s [опциялар]\n"
|
||||||
|
" -h, --help Осы көмекті көрсету\n"
|
||||||
|
" -v, --verbose Ақпараттылығын бір деңгейге арттыру\n"
|
||||||
|
" --version Нұсқасын көрсету\n"
|
||||||
|
" -c, --config Конфигурацияны жүктеу (Бастапқы %s)\n"
|
||||||
|
" -P --properties Контекст қасиеттерін орнату\n"
|
||||||
|
|
||||||
|
#: src/daemon/pipewire.desktop.in:3
|
||||||
|
msgid "PipeWire Media System"
|
||||||
|
msgstr "PipeWire медиа жүйесі"
|
||||||
|
|
||||||
#: src/daemon/pipewire.desktop.in:4
|
#: src/daemon/pipewire.desktop.in:4
|
||||||
msgid "PipeWire Media System"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: src/daemon/pipewire.desktop.in:5
|
|
||||||
msgid "Start the PipeWire Media System"
|
msgid "Start the PipeWire Media System"
|
||||||
msgstr ""
|
msgstr "PipeWire медиа жүйесін іске қосу"
|
||||||
|
|
||||||
#: src/examples/media-session/alsa-monitor.c:526
|
#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:159
|
||||||
#: spa/plugins/alsa/acp/compat.c:187
|
#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:159
|
||||||
msgid "Built-in Audio"
|
#, c-format
|
||||||
msgstr "Құрамындағы аудио"
|
msgid "Tunnel to %s%s%s"
|
||||||
|
msgstr "%s%s%s бағытына туннель"
|
||||||
|
|
||||||
#: src/examples/media-session/alsa-monitor.c:530
|
#: src/modules/module-fallback-sink.c:40
|
||||||
#: spa/plugins/alsa/acp/compat.c:192
|
msgid "Dummy Output"
|
||||||
msgid "Modem"
|
msgstr "Жалған шығыс"
|
||||||
msgstr "Модем"
|
|
||||||
|
|
||||||
#: src/examples/media-session/alsa-monitor.c:539
|
#: src/modules/module-pulse-tunnel.c:761
|
||||||
|
#, c-format
|
||||||
|
msgid "Tunnel for %s@%s"
|
||||||
|
msgstr "%s@%s үшін туннель"
|
||||||
|
|
||||||
|
#: src/modules/module-zeroconf-discover.c:290
|
||||||
msgid "Unknown device"
|
msgid "Unknown device"
|
||||||
msgstr ""
|
msgstr "Белгісіз құрылғы"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:991
|
#: src/modules/module-zeroconf-discover.c:302
|
||||||
|
#, c-format
|
||||||
|
msgid "%s on %s@%s"
|
||||||
|
msgstr "%s, %s@%s ішінде"
|
||||||
|
|
||||||
|
#: src/modules/module-zeroconf-discover.c:306
|
||||||
|
#, c-format
|
||||||
|
msgid "%s on %s"
|
||||||
|
msgstr "%s, %s ішінде"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:269
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported formats:\n"
|
||||||
|
msgstr "Қолдау көрсетілетін пішімдер:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:754
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layouts:\n"
|
||||||
|
msgstr "Қолдау көрсетілетін арна жаймалары:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:764
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layout aliases:\n"
|
||||||
|
msgstr "Қолдау көрсетілетін арна жаймаларының алиастары:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:766
|
||||||
|
#, c-format
|
||||||
|
msgid " %s -> %s\n"
|
||||||
|
msgstr " %s -> %s\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:771
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel names:\n"
|
||||||
|
msgstr "Қолдау көрсетілетін арна атаулары:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:1182
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] <file>\n"
|
"%s [options] [<file>|-]\n"
|
||||||
" -h, --help Show this help\n"
|
" -h, --help Show this help\n"
|
||||||
" --version Show version\n"
|
" --version Show version\n"
|
||||||
" -v, --verbose Enable verbose operations\n"
|
" -v, --verbose Enable verbose operations\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%s [опциялар] [<файл>|-]\n"
|
||||||
|
" -h, --help Осы көмекті көрсету\n"
|
||||||
|
" --version Нұсқасын көрсету\n"
|
||||||
|
" -v, --verbose Толық ақпаратты іске қосу\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:998
|
#: src/tools/pw-cat.c:1189
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" -R, --remote Remote daemon name\n"
|
" -R, --remote Remote daemon name\n"
|
||||||
" --media-type Set media type (default %s)\n"
|
" --media-type Set media type (default %s)\n"
|
||||||
" --media-category Set media category (default %s)\n"
|
" --media-category Set media category (default %s)\n"
|
||||||
" --media-role Set media role (default %s)\n"
|
" --media-role Set media role (default %s)\n"
|
||||||
" --target Set node target (default %s)\n"
|
" --target Set node target serial or name (default %s)\n"
|
||||||
" 0 means don't link\n"
|
" 0 means don't link\n"
|
||||||
" --latency Set node latency (default %s)\n"
|
" --latency Set node latency (default %s)\n"
|
||||||
" Xunit (unit = s, ms, us, ns)\n"
|
" Xunit (unit = s, ms, us, ns)\n"
|
||||||
" or direct samples (256)\n"
|
" or direct samples (256)\n"
|
||||||
" the rate is the one of the source "
|
" the rate is the one of the source file\n"
|
||||||
"file\n"
|
" -P --properties Set node properties\n"
|
||||||
" --list-targets List available targets for --target\n"
|
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
" -R, --remote Қашықтағы қызмет атауы\n"
|
||||||
|
" --media-type Медиа түрін орнату (бастапқы %s)\n"
|
||||||
|
" --media-category Медиа категориясын орнату (бастапқы %s)\n"
|
||||||
|
" --media-role Медиа рөлін орнату (бастапқы %s)\n"
|
||||||
|
" --target Түйін мақсатының сериялық нөмірін немесе атын орнату (бастапқы "
|
||||||
|
"%s)\n"
|
||||||
|
" 0 байланыстырмауды білдіреді\n"
|
||||||
|
" --latency Түйін кідірісін орнату (бастапқы %s)\n"
|
||||||
|
" Xюнит (юнит = с, мс, мкс, нс)\n"
|
||||||
|
" немесе тікелей үлгілер (256)\n"
|
||||||
|
" жиілік бастапқы файлдың жиілігі болып табылады\n"
|
||||||
|
" -P --properties Түйін қасиеттерін орнату\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1016
|
#: src/tools/pw-cat.c:1207
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" --rate Sample rate (req. for rec) (default "
|
" --rate Sample rate (default %u)\n"
|
||||||
"%u)\n"
|
" --channels Number of channels (default %u)\n"
|
||||||
" --channels Number of channels (req. for rec) "
|
|
||||||
"(default %u)\n"
|
|
||||||
" --channel-map Channel map\n"
|
" --channel-map Channel map\n"
|
||||||
" one of: \"stereo\", "
|
" a channel layout: \"Stereo\", \"5.1\",... or\n"
|
||||||
"\"surround-51\",... or\n"
|
" comma separated list of channel names: eg. \"FL,FR\"\n"
|
||||||
" comma separated list of channel "
|
" --list-layouts List supported channel layouts\n"
|
||||||
"names: eg. \"FL,FR\"\n"
|
" --list-channel-names List supported channel maps\n"
|
||||||
" --format Sample format %s (req. for rec) "
|
" --format Sample format (default %s)\n"
|
||||||
"(default %s)\n"
|
" --list-formats List supported sample formats\n"
|
||||||
|
" --container Container format\n"
|
||||||
|
" --list-containers List supported containers and extensions\n"
|
||||||
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
||||||
" -q --quality Resampler quality (0 - 15) (default "
|
" -q --quality Resampler quality (0 - 15) (default %d)\n"
|
||||||
"%d)\n"
|
" -a, --raw RAW mode\n"
|
||||||
|
" -M, --force-midi Force midi format, one of \"midi\" or \"ump\", (default ump)\n"
|
||||||
|
" -n, --sample-count COUNT Stop after COUNT samples\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
" --rate Дискреттеу жиілігі (бастапқы %u)\n"
|
||||||
|
" --channels Арналар саны (бастапқы %u)\n"
|
||||||
|
" --channel-map Арналар картасы\n"
|
||||||
|
" арна жаймасы: «Stereo», «5.1»,... немесе\n"
|
||||||
|
" үтірмен ажыратылған арна атауларының тізімі: мысалы, "
|
||||||
|
"«FL,FR»\n"
|
||||||
|
" --list-layouts Қолдау көрсетілетін арна жаймаларын тізімдеу\n"
|
||||||
|
" --list-channel-names Қолдау көрсетілетін арналар картасын тізімдеу\n"
|
||||||
|
" --format Дискреттеу пішімі (бастапқы %s)\n"
|
||||||
|
" --list-formats Қолдау көрсетілетін дискреттеу пішімдерін тізімдеу\n"
|
||||||
|
" --container Контейнер пішімі\n"
|
||||||
|
" --list-containers Қолдау көрсетілетін контейнерлер мен кеңейтулерді тізімдеу\n"
|
||||||
|
" --volume Ағын дыбыс деңгейі 0-1.0 (бастапқы %.3f)\n"
|
||||||
|
" -q --quality Қайта дискреттеу сапасы (0 - 15) (бастапқы %d)\n"
|
||||||
|
" -a, --raw RAW режимі\n"
|
||||||
|
" -M, --force-midi Midi пішімін мәжбүрлеу, «midi» немесе «ump» біреуі, (бастапқы "
|
||||||
|
"ump)\n"
|
||||||
|
" -n, --sample-count COUNT COUNT үлгісінен кейін тоқтату\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1033
|
#: src/tools/pw-cat.c:1232
|
||||||
msgid ""
|
msgid ""
|
||||||
" -p, --playback Playback mode\n"
|
" -p, --playback Playback mode\n"
|
||||||
" -r, --record Recording mode\n"
|
" -r, --record Recording mode\n"
|
||||||
" -m, --midi Midi mode\n"
|
" -m, --midi Midi mode\n"
|
||||||
|
" -d, --dsd DSD mode\n"
|
||||||
|
" -o, --encoded Encoded mode\n"
|
||||||
|
" -s, --sysex SysEx mode\n"
|
||||||
|
" -c, --midi-clip MIDI clip mode\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
" -p, --playback Ойнату режимі\n"
|
||||||
|
" -r, --record Жазу режимі\n"
|
||||||
|
" -m, --midi Midi режимі\n"
|
||||||
|
" -d, --dsd DSD режимі\n"
|
||||||
|
" -o, --encoded Шифрленген режим\n"
|
||||||
|
" -s, --sysex SysEx режимі\n"
|
||||||
|
" -c, --midi-clip MIDI clip режимі\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cli.c:2932
|
#: src/tools/pw-cat.c:1837
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported containers and extensions:\n"
|
||||||
|
msgstr "Қолдау көрсетілетін контейнерлер мен кеңейтулер:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cli.c:2386
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] [command]\n"
|
"%s [options] [command]\n"
|
||||||
|
|
@ -114,465 +216,506 @@ msgid ""
|
||||||
" --version Show version\n"
|
" --version Show version\n"
|
||||||
" -d, --daemon Start as daemon (Default false)\n"
|
" -d, --daemon Start as daemon (Default false)\n"
|
||||||
" -r, --remote Remote daemon name\n"
|
" -r, --remote Remote daemon name\n"
|
||||||
|
" -m, --monitor Monitor activity\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%s [опциялар] [команда]\n"
|
||||||
|
" -h, --help Осы көмекті көрсету\n"
|
||||||
|
" --version Нұсқасын көрсету\n"
|
||||||
|
" -d, --daemon Қызмет ретінде іске қосу (Бастапқы false)\n"
|
||||||
|
" -r, --remote Қашықтағы қызмет атауы\n"
|
||||||
|
" -m, --monitor Белсенділікті бақылау\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:290
|
#: spa/plugins/alsa/acp/acp.c:361
|
||||||
msgid "Pro Audio"
|
msgid "Pro Audio"
|
||||||
msgstr ""
|
msgstr "Кәсіби аудио"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:411 spa/plugins/alsa/acp/alsa-mixer.c:4704
|
#: spa/plugins/alsa/acp/acp.c:535 spa/plugins/alsa/acp/alsa-mixer.c:4699
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1000
|
#: spa/plugins/bluez5/bluez5-device.c:2021
|
||||||
msgid "Off"
|
msgid "Off"
|
||||||
msgstr "Сөнд."
|
msgstr "Сөнд."
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/channelmap.h:466
|
#: spa/plugins/alsa/acp/acp.c:618
|
||||||
msgid "(invalid)"
|
#, c-format
|
||||||
msgstr "(жарамсыз)"
|
msgid "%s [ALSA UCM error]"
|
||||||
|
msgstr "%s [ALSA UCM қатесі]"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2709
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2721
|
||||||
msgid "Input"
|
msgid "Input"
|
||||||
msgstr "Кіріс"
|
msgstr "Кіріс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2710
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2722
|
||||||
msgid "Docking Station Input"
|
msgid "Docking Station Input"
|
||||||
msgstr "Док-станция кірісі"
|
msgstr "Док-станция кірісі"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2711
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2723
|
||||||
msgid "Docking Station Microphone"
|
msgid "Docking Station Microphone"
|
||||||
msgstr "Док-станция микрофоны"
|
msgstr "Док-станция микрофоны"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2712
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2724
|
||||||
msgid "Docking Station Line In"
|
msgid "Docking Station Line In"
|
||||||
msgstr "Док-станцияның сызықтық кірісі"
|
msgstr "Док-станцияның сызықтық кірісі"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2713
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2725 spa/plugins/alsa/acp/alsa-mixer.c:2816
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2804
|
|
||||||
msgid "Line In"
|
msgid "Line In"
|
||||||
msgstr "Сызықтық кіріс"
|
msgstr "Сызықтық кіріс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2714
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2726 spa/plugins/alsa/acp/alsa-mixer.c:2810
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2798
|
#: spa/plugins/bluez5/bluez5-device.c:2422
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1145
|
|
||||||
msgid "Microphone"
|
msgid "Microphone"
|
||||||
msgstr "Микрофон"
|
msgstr "Микрофон"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2715
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2727 spa/plugins/alsa/acp/alsa-mixer.c:2811
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2799
|
|
||||||
msgid "Front Microphone"
|
msgid "Front Microphone"
|
||||||
msgstr "Алдыңғы микрофон"
|
msgstr "Алдыңғы микрофон"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2716
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2728 spa/plugins/alsa/acp/alsa-mixer.c:2812
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2800
|
|
||||||
msgid "Rear Microphone"
|
msgid "Rear Microphone"
|
||||||
msgstr "Артқы микрофон"
|
msgstr "Артқы микрофон"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2717
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2729
|
||||||
msgid "External Microphone"
|
msgid "External Microphone"
|
||||||
msgstr "Сыртқы микрофон"
|
msgstr "Сыртқы микрофон"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2718
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2730 spa/plugins/alsa/acp/alsa-mixer.c:2814
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2802
|
|
||||||
msgid "Internal Microphone"
|
msgid "Internal Microphone"
|
||||||
msgstr "Ішкі микрофон"
|
msgstr "Ішкі микрофон"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2719
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2731 spa/plugins/alsa/acp/alsa-mixer.c:2817
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2805
|
|
||||||
msgid "Radio"
|
msgid "Radio"
|
||||||
msgstr "Радио"
|
msgstr "Радио"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2720
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2732 spa/plugins/alsa/acp/alsa-mixer.c:2818
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2806
|
|
||||||
msgid "Video"
|
msgid "Video"
|
||||||
msgstr "Видео"
|
msgstr "Видео"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2721
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2733
|
||||||
msgid "Automatic Gain Control"
|
msgid "Automatic Gain Control"
|
||||||
msgstr "Күшейтуді автореттеу"
|
msgstr "Күшейтуді автореттеу"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2722
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2734
|
||||||
msgid "No Automatic Gain Control"
|
msgid "No Automatic Gain Control"
|
||||||
msgstr "Күшейтуді автореттеу жоқ"
|
msgstr "Күшейтуді автореттеу жоқ"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2723
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2735
|
||||||
msgid "Boost"
|
msgid "Boost"
|
||||||
msgstr "Күшейту"
|
msgstr "Күшейту"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2724
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2736
|
||||||
msgid "No Boost"
|
msgid "No Boost"
|
||||||
msgstr "Күшейту жоқ"
|
msgstr "Күшейту жоқ"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2725
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2737
|
||||||
msgid "Amplifier"
|
msgid "Amplifier"
|
||||||
msgstr "Күшейткіш"
|
msgstr "Күшейткіш"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2738
|
||||||
msgid "No Amplifier"
|
msgid "No Amplifier"
|
||||||
msgstr "Күшейткіш жоқ"
|
msgstr "Күшейткіш жоқ"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2727
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2739
|
||||||
msgid "Bass Boost"
|
msgid "Bass Boost"
|
||||||
msgstr "Бас күшейту"
|
msgstr "Бас күшейту"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2728
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
|
||||||
msgid "No Bass Boost"
|
msgid "No Bass Boost"
|
||||||
msgstr "Бас күшейту жоқ"
|
msgstr "Бас күшейту жоқ"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2729
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2741 spa/plugins/bluez5/bluez5-device.c:2428
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1150
|
|
||||||
msgid "Speaker"
|
msgid "Speaker"
|
||||||
msgstr "Динамик"
|
msgstr "Динамик"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2730
|
#. Don't call it "headset", the HF one has the mic
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2808
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2742 spa/plugins/alsa/acp/alsa-mixer.c:2820
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2434 spa/plugins/bluez5/bluez5-device.c:2501
|
||||||
msgid "Headphones"
|
msgid "Headphones"
|
||||||
msgstr "Құлаққаптар"
|
msgstr "Құлаққаптар"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2797
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2809
|
||||||
msgid "Analog Input"
|
msgid "Analog Input"
|
||||||
msgstr "Аналогтық кіріс"
|
msgstr "Аналогтық кіріс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2801
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2813
|
||||||
msgid "Dock Microphone"
|
msgid "Dock Microphone"
|
||||||
msgstr "Док-станция микрофоны"
|
msgstr "Док-станция микрофоны"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2803
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2815
|
||||||
msgid "Headset Microphone"
|
msgid "Headset Microphone"
|
||||||
msgstr "Гарнитура микрофоны"
|
msgstr "Гарнитура микрофоны"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2807
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2819
|
||||||
msgid "Analog Output"
|
msgid "Analog Output"
|
||||||
msgstr "Аналогтық шығыс"
|
msgstr "Аналогтық шығыс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2809
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2821
|
||||||
#, fuzzy
|
|
||||||
msgid "Headphones 2"
|
msgid "Headphones 2"
|
||||||
msgstr "Құлаққаптар"
|
msgstr "Құлаққап 2"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2822
|
||||||
msgid "Headphones Mono Output"
|
msgid "Headphones Mono Output"
|
||||||
msgstr "Құлаққаптардың моно шығысы"
|
msgstr "Құлаққаптардың моно шығысы"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2811
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2823
|
||||||
msgid "Line Out"
|
msgid "Line Out"
|
||||||
msgstr "Сызықтық шығыс"
|
msgstr "Сызықтық шығыс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2812
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2824
|
||||||
msgid "Analog Mono Output"
|
msgid "Analog Mono Output"
|
||||||
msgstr "Аналогтық моно шығысы"
|
msgstr "Аналогтық моно шығысы"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2813
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2825
|
||||||
msgid "Speakers"
|
msgid "Speakers"
|
||||||
msgstr "Динамиктер"
|
msgstr "Динамиктер"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2814
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2826
|
||||||
msgid "HDMI / DisplayPort"
|
msgid "HDMI / DisplayPort"
|
||||||
msgstr "HDMI / DisplayPort"
|
msgstr "HDMI / DisplayPort"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2815
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2827
|
||||||
msgid "Digital Output (S/PDIF)"
|
msgid "Digital Output (S/PDIF)"
|
||||||
msgstr "Цифрлық шығыс (S/PDIF)"
|
msgstr "Цифрлық шығыс (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2816
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2828
|
||||||
msgid "Digital Input (S/PDIF)"
|
msgid "Digital Input (S/PDIF)"
|
||||||
msgstr "Цифрлық кіріс (S/PDIF)"
|
msgstr "Цифрлық кіріс (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2817
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2829
|
||||||
msgid "Multichannel Input"
|
msgid "Multichannel Input"
|
||||||
msgstr "Көпарналы кіріс"
|
msgstr "Көпарналы кіріс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2818
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2830
|
||||||
msgid "Multichannel Output"
|
msgid "Multichannel Output"
|
||||||
msgstr "Көпарналы шығыс"
|
msgstr "Көпарналы шығыс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2819
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2831
|
||||||
msgid "Game Output"
|
msgid "Game Output"
|
||||||
msgstr "Ойын шығысы"
|
msgstr "Ойын шығысы"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2832 spa/plugins/alsa/acp/alsa-mixer.c:2833
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2821
|
|
||||||
msgid "Chat Output"
|
msgid "Chat Output"
|
||||||
msgstr "Чат шығысы"
|
msgstr "Чат шығысы"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2822
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2834
|
||||||
#, fuzzy
|
|
||||||
msgid "Chat Input"
|
msgid "Chat Input"
|
||||||
msgstr "Чат шығысы"
|
msgstr "Чат кірісі"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2823
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2835
|
||||||
#, fuzzy
|
|
||||||
msgid "Virtual Surround 7.1"
|
msgid "Virtual Surround 7.1"
|
||||||
msgstr "Виртуалды көлемді аудиоқабылдағыш"
|
msgstr "Виртуалды көлемді дыбыс 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4527
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4522
|
||||||
msgid "Analog Mono"
|
msgid "Analog Mono"
|
||||||
msgstr "Аналогтық моно"
|
msgstr "Аналогтық моно"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4528
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4523
|
||||||
#, fuzzy
|
|
||||||
msgid "Analog Mono (Left)"
|
msgid "Analog Mono (Left)"
|
||||||
msgstr "Аналогтық моно"
|
msgstr "Аналогты моно (Сол жақ)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4529
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4524
|
||||||
#, fuzzy
|
|
||||||
msgid "Analog Mono (Right)"
|
msgid "Analog Mono (Right)"
|
||||||
msgstr "Аналогтық моно"
|
msgstr "Аналогты моно (Оң жақ)"
|
||||||
|
|
||||||
#. Note: Not translated to "Analog Stereo Input", because the source
|
#. Note: Not translated to "Analog Stereo Input", because the source
|
||||||
#. * name gets "Input" appended to it automatically, so adding "Input"
|
#. * name gets "Input" appended to it automatically, so adding "Input"
|
||||||
#. * here would lead to the source name to become "Analog Stereo Input
|
#. * here would lead to the source name to become "Analog Stereo Input
|
||||||
#. * Input". The same logic applies to analog-stereo-output,
|
#. * Input". The same logic applies to analog-stereo-output,
|
||||||
#. * multichannel-input and multichannel-output.
|
#. * multichannel-input and multichannel-output.
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4530
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4525 spa/plugins/alsa/acp/alsa-mixer.c:4533
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4538
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4534
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4539
|
|
||||||
msgid "Analog Stereo"
|
msgid "Analog Stereo"
|
||||||
msgstr "Аналогтық стерео"
|
msgstr "Аналогтық стерео"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4531
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4526
|
||||||
msgid "Mono"
|
msgid "Mono"
|
||||||
msgstr "Моно"
|
msgstr "Моно"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4532
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4527
|
||||||
msgid "Stereo"
|
msgid "Stereo"
|
||||||
msgstr "Стерео"
|
msgstr "Стерео"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4540
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4535 spa/plugins/alsa/acp/alsa-mixer.c:4693
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4698
|
#: spa/plugins/bluez5/bluez5-device.c:2410
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1135
|
|
||||||
msgid "Headset"
|
msgid "Headset"
|
||||||
msgstr "Гарнитура"
|
msgstr "Гарнитура"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4541
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4536 spa/plugins/alsa/acp/alsa-mixer.c:4694
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4699
|
|
||||||
#, fuzzy
|
|
||||||
msgid "Speakerphone"
|
msgid "Speakerphone"
|
||||||
msgstr "Динамик"
|
msgstr "Динамик"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4542
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4537 spa/plugins/alsa/acp/alsa-mixer.c:4538
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4543
|
|
||||||
msgid "Multichannel"
|
msgid "Multichannel"
|
||||||
msgstr "Көпарналы"
|
msgstr "Көпарналы"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4544
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4539
|
||||||
msgid "Analog Surround 2.1"
|
msgid "Analog Surround 2.1"
|
||||||
msgstr "Аналогтық көлемді 2.1"
|
msgstr "Аналогтық көлемді 2.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4545
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4540
|
||||||
msgid "Analog Surround 3.0"
|
msgid "Analog Surround 3.0"
|
||||||
msgstr "Аналогтық көлемді 3.0"
|
msgstr "Аналогтық көлемді 3.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4546
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4541
|
||||||
msgid "Analog Surround 3.1"
|
msgid "Analog Surround 3.1"
|
||||||
msgstr "Аналогтық көлемді 3.1"
|
msgstr "Аналогтық көлемді 3.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4547
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4542
|
||||||
msgid "Analog Surround 4.0"
|
msgid "Analog Surround 4.0"
|
||||||
msgstr "Аналогтық көлемді 4.0"
|
msgstr "Аналогтық көлемді 4.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4548
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4543
|
||||||
msgid "Analog Surround 4.1"
|
msgid "Analog Surround 4.1"
|
||||||
msgstr "Аналогтық көлемді 4.1"
|
msgstr "Аналогтық көлемді 4.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4549
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4544
|
||||||
msgid "Analog Surround 5.0"
|
msgid "Analog Surround 5.0"
|
||||||
msgstr "Аналогтық көлемді 5.0"
|
msgstr "Аналогтық көлемді 5.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4550
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4545
|
||||||
msgid "Analog Surround 5.1"
|
msgid "Analog Surround 5.1"
|
||||||
msgstr "Аналогтық көлемді 5.1"
|
msgstr "Аналогтық көлемді 5.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4551
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4546
|
||||||
msgid "Analog Surround 6.0"
|
msgid "Analog Surround 6.0"
|
||||||
msgstr "Аналогтық көлемді 6.0"
|
msgstr "Аналогтық көлемді 6.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4552
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4547
|
||||||
msgid "Analog Surround 6.1"
|
msgid "Analog Surround 6.1"
|
||||||
msgstr "Аналогтық көлемді 6.1"
|
msgstr "Аналогтық көлемді 6.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4553
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4548
|
||||||
msgid "Analog Surround 7.0"
|
msgid "Analog Surround 7.0"
|
||||||
msgstr "Аналогтық көлемді 7.0"
|
msgstr "Аналогтық көлемді 7.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4554
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4549
|
||||||
msgid "Analog Surround 7.1"
|
msgid "Analog Surround 7.1"
|
||||||
msgstr "Аналогтық көлемді 7.1"
|
msgstr "Аналогтық көлемді 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4555
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4550
|
||||||
msgid "Digital Stereo (IEC958)"
|
msgid "Digital Stereo (IEC958)"
|
||||||
msgstr "Цифрлық стерео (IEC958)"
|
msgstr "Цифрлық стерео (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4556
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4551
|
||||||
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
||||||
msgstr "Цифрлық көлемді 4.0 (IEC958/AC3)"
|
msgstr "Цифрлық көлемді 4.0 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4557
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4552
|
||||||
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
||||||
msgstr "Цифрлық көлемді 5.1 (IEC958/AC3)"
|
msgstr "Цифрлық көлемді 5.1 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4558
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4553
|
||||||
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
||||||
msgstr "Цифрлық көлемді 5.1 (IEC958/DTS)"
|
msgstr "Цифрлық көлемді 5.1 (IEC958/DTS)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4559
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4554
|
||||||
msgid "Digital Stereo (HDMI)"
|
msgid "Digital Stereo (HDMI)"
|
||||||
msgstr "Цифрлық стерео (HDMI)"
|
msgstr "Цифрлық стерео (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4560
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4555
|
||||||
msgid "Digital Surround 5.1 (HDMI)"
|
msgid "Digital Surround 5.1 (HDMI)"
|
||||||
msgstr "Цифрлық көлемді 5.1 (HDMI)"
|
msgstr "Цифрлық көлемді 5.1 (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4561
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4556
|
||||||
msgid "Chat"
|
msgid "Chat"
|
||||||
msgstr ""
|
msgstr "Чат"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4562
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4557
|
||||||
msgid "Game"
|
msgid "Game"
|
||||||
msgstr ""
|
msgstr "Ойын"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4696
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4691
|
||||||
msgid "Analog Mono Duplex"
|
msgid "Analog Mono Duplex"
|
||||||
msgstr "Аналогтық моно дуплекс"
|
msgstr "Аналогтық моно дуплекс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4697
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4692
|
||||||
msgid "Analog Stereo Duplex"
|
msgid "Analog Stereo Duplex"
|
||||||
msgstr "Аналогтық стерео дуплекс"
|
msgstr "Аналогтық стерео дуплекс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4700
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4695
|
||||||
msgid "Digital Stereo Duplex (IEC958)"
|
msgid "Digital Stereo Duplex (IEC958)"
|
||||||
msgstr "Цифрлық стерео дуплекс (IEC958)"
|
msgstr "Цифрлық стерео дуплекс (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4701
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4696
|
||||||
msgid "Multichannel Duplex"
|
msgid "Multichannel Duplex"
|
||||||
msgstr "Көпарналы дуплекс"
|
msgstr "Көпарналы дуплекс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4702
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4697
|
||||||
msgid "Stereo Duplex"
|
msgid "Stereo Duplex"
|
||||||
msgstr "Стерео дуплекс"
|
msgstr "Стерео дуплекс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4703
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4698
|
||||||
msgid "Mono Chat + 7.1 Surround"
|
msgid "Mono Chat + 7.1 Surround"
|
||||||
msgstr ""
|
msgstr "Моно чат + 7.1 көлемді дыбыс"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4806
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4799
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Output"
|
msgid "%s Output"
|
||||||
msgstr "%s шығысы"
|
msgstr "%s шығысы"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4813
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4807
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Input"
|
msgid "%s Input"
|
||||||
msgstr "%s кірісі"
|
msgstr "%s кірісі"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1175 spa/plugins/alsa/acp/alsa-util.c:1269
|
#: spa/plugins/alsa/acp/alsa-util.c:1233 spa/plugins/alsa/acp/alsa-util.c:1327
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
|
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
|
||||||
"ms).\n"
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
|
||||||
"to the ALSA developers."
|
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu "
|
"snd_pcm_avail() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
|
||||||
"ms).\n"
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
|
||||||
"to the ALSA developers."
|
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
|
"snd_pcm_avail() өте үлкен мән қайтарды: %lu байт (%lu мс).\n"
|
||||||
|
"Бұл ALSA драйверіндегі («%s») қате болуы әбден мүмкін. Бұл мәселе туралы ALSA әзірлеушілеріне хабарлаңыз."
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
"snd_pcm_avail() өте үлкен мән қайтарды: %lu байт (%lu мс).\n"
|
||||||
|
"Бұл ALSA драйверіндегі («%s») қате болуы әбден мүмкін. Бұл мәселе туралы ALSA әзірлеушілеріне хабарлаңыз."
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1241
|
#: spa/plugins/alsa/acp/alsa-util.c:1299
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
|
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s%lu ms).\n"
|
||||||
"%lu ms).\n"
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
|
||||||
"to the ALSA developers."
|
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
|
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s%lu ms).\n"
|
||||||
"%lu ms).\n"
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
|
||||||
"to the ALSA developers."
|
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
|
"snd_pcm_delay() өте үлкен мән қайтарды: %li байт (%s%lu мс).\n"
|
||||||
|
"Бұл ALSA драйверіндегі («%s») қате болуы әбден мүмкін. Бұл мәселе туралы ALSA әзірлеушілеріне хабарлаңыз."
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
"snd_pcm_delay() өте үлкен мән қайтарды: %li байт (%s%lu мс).\n"
|
||||||
|
"Бұл ALSA драйверіндегі («%s») қате болуы әбден мүмкін. Бұл мәселе туралы ALSA әзірлеушілеріне хабарлаңыз."
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1288
|
#: spa/plugins/alsa/acp/alsa-util.c:1346
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
|
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail %lu.\n"
|
||||||
"%lu.\n"
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
|
||||||
"to the ALSA developers."
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"snd_pcm_avail_delay() оғаш мәндер қайтарды: кідіріс %lu мәні қолжетімді %lu мәнінен аз.\n"
|
||||||
|
"Бұл ALSA драйверіндегі («%s») қате болуы әбден мүмкін. Бұл мәселе туралы ALSA әзірлеушілеріне хабарлаңыз."
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1331
|
#: spa/plugins/alsa/acp/alsa-util.c:1389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
|
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte (%lu ms).\n"
|
||||||
"(%lu ms).\n"
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
|
||||||
"to the ALSA developers."
|
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes "
|
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu bytes (%lu ms).\n"
|
||||||
"(%lu ms).\n"
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue to the ALSA developers."
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
|
||||||
"to the ALSA developers."
|
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
|
"snd_pcm_mmap_begin() өте үлкен мән қайтарды: %lu байт (%lu мс).\n"
|
||||||
|
"Бұл ALSA драйверіндегі («%s») қате болуы әбден мүмкін. Бұл мәселе туралы ALSA әзірлеушілеріне хабарлаңыз."
|
||||||
msgstr[1] ""
|
msgstr[1] ""
|
||||||
|
"snd_pcm_mmap_begin() өте үлкен мән қайтарды: %lu байт (%lu мс).\n"
|
||||||
|
"Бұл ALSA драйверіндегі («%s») қате болуы әбден мүмкін. Бұл мәселе туралы ALSA әзірлеушілеріне хабарлаңыз."
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1010
|
#: spa/plugins/alsa/acp/channelmap.h:460
|
||||||
|
msgid "(invalid)"
|
||||||
|
msgstr "(жарамсыз)"
|
||||||
|
|
||||||
|
#: spa/plugins/alsa/acp/compat.c:194
|
||||||
|
msgid "Built-in Audio"
|
||||||
|
msgstr "Құрамындағы аудио"
|
||||||
|
|
||||||
|
#: spa/plugins/alsa/acp/compat.c:199
|
||||||
|
msgid "Modem"
|
||||||
|
msgstr "Модем"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2032
|
||||||
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
||||||
msgstr ""
|
msgstr "Аудио шлюзі (A2DP бастапқы көзі және HSP/HFP AG)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1033
|
#: spa/plugins/bluez5/bluez5-device.c:2061
|
||||||
|
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
||||||
|
msgstr "Есту аппараттарына арналған аудио ағыны (ASHA қабылдағышы)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2104
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
||||||
msgstr ""
|
msgstr "Жоғары сапалы ойнату (A2DP қабылдағышы, кодек %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1035
|
#: spa/plugins/bluez5/bluez5-device.c:2107
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
||||||
msgstr ""
|
msgstr "Жоғары сапалы дуплекс (A2DP бастапқы көзі/қабылдағышы, кодек %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1041
|
#: spa/plugins/bluez5/bluez5-device.c:2115
|
||||||
msgid "High Fidelity Playback (A2DP Sink)"
|
msgid "High Fidelity Playback (A2DP Sink)"
|
||||||
msgstr ""
|
msgstr "Жоғары сапалы ойнату (A2DP қабылдағышы)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1043
|
#: spa/plugins/bluez5/bluez5-device.c:2117
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
||||||
msgstr ""
|
msgstr "Жоғары сапалы дуплекс (A2DP бастапқы көзі/қабылдағышы)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1070
|
#: spa/plugins/bluez5/bluez5-device.c:2194
|
||||||
|
#, c-format
|
||||||
|
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
||||||
|
msgstr "Жоғары сапалы ойнату (BAP қабылдағышы, кодек %s)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2199
|
||||||
|
#, c-format
|
||||||
|
msgid "High Fidelity Input (BAP Source, codec %s)"
|
||||||
|
msgstr "Жоғары сапалы кіріс (BAP бастапқы көзі, кодек %s)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2203
|
||||||
|
#, c-format
|
||||||
|
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
||||||
|
msgstr "Жоғары сапалы дуплекс (BAP бастапқы көзі/қабылдағышы, кодек %s)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2212
|
||||||
|
msgid "High Fidelity Playback (BAP Sink)"
|
||||||
|
msgstr "Жоғары сапалы ойнату (BAP қабылдағышы)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2216
|
||||||
|
msgid "High Fidelity Input (BAP Source)"
|
||||||
|
msgstr "Жоғары сапалы кіріс (BAP бастапқы көзі)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2219
|
||||||
|
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
||||||
|
msgstr "Жоғары сапалы дуплекс (BAP бастапқы көзі/қабылдағышы)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2259
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
||||||
msgstr ""
|
msgstr "Гарнитура (HSP/HFP, кодек %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1074
|
#: spa/plugins/bluez5/bluez5-device.c:2411 spa/plugins/bluez5/bluez5-device.c:2416
|
||||||
msgid "Headset Head Unit (HSP/HFP)"
|
#: spa/plugins/bluez5/bluez5-device.c:2423 spa/plugins/bluez5/bluez5-device.c:2429
|
||||||
msgstr ""
|
#: spa/plugins/bluez5/bluez5-device.c:2435 spa/plugins/bluez5/bluez5-device.c:2441
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2447 spa/plugins/bluez5/bluez5-device.c:2453
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1140
|
#: spa/plugins/bluez5/bluez5-device.c:2459
|
||||||
msgid "Handsfree"
|
msgid "Handsfree"
|
||||||
msgstr "Хендс-фри"
|
msgstr "Хендс-фри"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1155
|
#: spa/plugins/bluez5/bluez5-device.c:2417
|
||||||
msgid "Headphone"
|
msgid "Handsfree (HFP)"
|
||||||
msgstr "Құлаққап"
|
msgstr "Гарнитура (HFP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1160
|
#: spa/plugins/bluez5/bluez5-device.c:2440
|
||||||
msgid "Portable"
|
msgid "Portable"
|
||||||
msgstr "Портативті динамик"
|
msgstr "Портативті динамик"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1165
|
#: spa/plugins/bluez5/bluez5-device.c:2446
|
||||||
msgid "Car"
|
msgid "Car"
|
||||||
msgstr "Автомобильдік динамик"
|
msgstr "Автомобильдік динамик"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1170
|
#: spa/plugins/bluez5/bluez5-device.c:2452
|
||||||
msgid "HiFi"
|
msgid "HiFi"
|
||||||
msgstr "HiFi"
|
msgstr "HiFi"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1175
|
#: spa/plugins/bluez5/bluez5-device.c:2458
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "Телефон"
|
msgstr "Телефон"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1181
|
#: spa/plugins/bluez5/bluez5-device.c:2465
|
||||||
msgid "Bluetooth"
|
msgid "Bluetooth"
|
||||||
msgstr "Bluetooth"
|
msgstr "Bluetooth"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2466
|
||||||
|
msgid "Bluetooth Handsfree"
|
||||||
|
msgstr "Bluetooth гарнитурасы"
|
||||||
|
|
||||||
|
#~ msgid "Headphone"
|
||||||
|
#~ msgstr "Құлаққап"
|
||||||
|
|
|
||||||
371
po/sl.po
371
po/sl.po
|
|
@ -2,23 +2,21 @@
|
||||||
# Copyright (C) 2024 PipeWire's COPYRIGHT HOLDER
|
# Copyright (C) 2024 PipeWire's COPYRIGHT HOLDER
|
||||||
# This file is distributed under the same license as the PipeWire package.
|
# This file is distributed under the same license as the PipeWire package.
|
||||||
#
|
#
|
||||||
# Martin <miles@filmsi.net>, 2024, 2025.
|
# Martin <miles@filmsi.net>, 2024, 2025, 2026.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PipeWire master\n"
|
"Project-Id-Version: PipeWire master\n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
|
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/issues\n"
|
||||||
"issues\n"
|
"POT-Creation-Date: 2026-02-09 12:55+0000\n"
|
||||||
"POT-Creation-Date: 2025-09-11 03:34+0000\n"
|
"PO-Revision-Date: 2026-02-15 16:18+0100\n"
|
||||||
"PO-Revision-Date: 2025-09-11 11:47+0200\n"
|
|
||||||
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
|
"Last-Translator: Martin Srebotnjak <miles@filmsi.net>\n"
|
||||||
"Language-Team: Slovenian <gnome-si@googlegroups.com>\n"
|
"Language-Team: Slovenian <gnome-si@googlegroups.com>\n"
|
||||||
"Language: sl\n"
|
"Language: sl\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && "
|
"Plural-Forms: nplurals=4; plural=(n%100==1 ? 0 : n%100==2 ? 1 : n%100>=3 && n%100<=4 ? 2 : 3);\n"
|
||||||
"n%100<=4 ? 2 : 3);\n"
|
|
||||||
"X-Generator: Poedit 2.2.1\n"
|
"X-Generator: Poedit 2.2.1\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.c:29
|
#: src/daemon/pipewire.c:29
|
||||||
|
|
@ -35,8 +33,7 @@ msgstr ""
|
||||||
" -h, --help Pokaži to pomoč\n"
|
" -h, --help Pokaži to pomoč\n"
|
||||||
" -v, --verbose Povečaj opisnost za eno raven\n"
|
" -v, --verbose Povečaj opisnost za eno raven\n"
|
||||||
" --version Pokaži različico\n"
|
" --version Pokaži različico\n"
|
||||||
" -c, --config Naloži prilagoditev config (privzeto "
|
" -c, --config Naloži prilagoditev config (privzeto %s)\n"
|
||||||
"%s)\n"
|
|
||||||
" -P --properties Določi lastnosti konteksta\n"
|
" -P --properties Določi lastnosti konteksta\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.desktop.in:3
|
#: src/daemon/pipewire.desktop.in:3
|
||||||
|
|
@ -57,26 +54,51 @@ msgstr "Prehod do %s%s%s"
|
||||||
msgid "Dummy Output"
|
msgid "Dummy Output"
|
||||||
msgstr "Lažni izhod"
|
msgstr "Lažni izhod"
|
||||||
|
|
||||||
#: src/modules/module-pulse-tunnel.c:760
|
#: src/modules/module-pulse-tunnel.c:761
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Tunnel for %s@%s"
|
msgid "Tunnel for %s@%s"
|
||||||
msgstr "Prehod za %s@%s"
|
msgstr "Prehod za %s@%s"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:320
|
#: src/modules/module-zeroconf-discover.c:326
|
||||||
msgid "Unknown device"
|
msgid "Unknown device"
|
||||||
msgstr "Neznana naprava"
|
msgstr "Neznana naprava"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:332
|
#: src/modules/module-zeroconf-discover.c:338
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s on %s@%s"
|
msgid "%s on %s@%s"
|
||||||
msgstr "%s na %s@%s"
|
msgstr "%s na %s@%s"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:336
|
#: src/modules/module-zeroconf-discover.c:342
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s on %s"
|
msgid "%s on %s"
|
||||||
msgstr "%s na %s"
|
msgstr "%s na %s"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1084
|
#: src/tools/pw-cat.c:264
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported formats:\n"
|
||||||
|
msgstr "Podprti zapisi:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:749
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layouts:\n"
|
||||||
|
msgstr "Podprte postavitve kanalov:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:759
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layout aliases:\n"
|
||||||
|
msgstr "Podprti vzdevki postavitev kanalov:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:761
|
||||||
|
#, c-format
|
||||||
|
msgid " %s -> %s\n"
|
||||||
|
msgstr " %s -> %s\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:766
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel names:\n"
|
||||||
|
msgstr "Podprta imena kanalov:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:1177
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] [<file>|-]\n"
|
"%s [options] [<file>|-]\n"
|
||||||
|
|
@ -92,7 +114,7 @@ msgstr ""
|
||||||
"\n"
|
"\n"
|
||||||
"</file>\n"
|
"</file>\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1091
|
#: src/tools/pw-cat.c:1184
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" -R, --remote Remote daemon name\n"
|
" -R, --remote Remote daemon name\n"
|
||||||
|
|
@ -129,20 +151,23 @@ msgstr ""
|
||||||
" -P --properties Nastavi lastnosti vozlišča\n"
|
" -P --properties Nastavi lastnosti vozlišča\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1109
|
#: src/tools/pw-cat.c:1202
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" --rate Sample rate (req. for rec) (default "
|
" --rate Sample rate (default %u)\n"
|
||||||
"%u)\n"
|
" --channels Number of channels (default %u)\n"
|
||||||
" --channels Number of channels (req. for rec) "
|
|
||||||
"(default %u)\n"
|
|
||||||
" --channel-map Channel map\n"
|
" --channel-map Channel map\n"
|
||||||
" one of: \"stereo\", "
|
" a channel layout: \"Stereo\", "
|
||||||
"\"surround-51\",... or\n"
|
"\"5.1\",... or\n"
|
||||||
" comma separated list of channel "
|
" comma separated list of channel "
|
||||||
"names: eg. \"FL,FR\"\n"
|
"names: eg. \"FL,FR\"\n"
|
||||||
" --format Sample format %s (req. for rec) "
|
" --list-layouts List supported channel layouts\n"
|
||||||
"(default %s)\n"
|
" --list-channel-names List supported channel maps\n"
|
||||||
|
" --format Sample format (default %s)\n"
|
||||||
|
" --list-formats List supported sample formats\n"
|
||||||
|
" --container Container format\n"
|
||||||
|
" --list-containers List supported containers and "
|
||||||
|
"extensions\n"
|
||||||
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
||||||
" -q --quality Resampler quality (0 - 15) (default "
|
" -q --quality Resampler quality (0 - 15) (default "
|
||||||
"%d)\n"
|
"%d)\n"
|
||||||
|
|
@ -157,22 +182,27 @@ msgstr ""
|
||||||
" --channels Število kanalov (zaht. za snemanje) "
|
" --channels Število kanalov (zaht. za snemanje) "
|
||||||
"(privzeto %u)\n"
|
"(privzeto %u)\n"
|
||||||
" --channel-map Preslikava kanalov\n"
|
" --channel-map Preslikava kanalov\n"
|
||||||
" Ena izmed: \"stereo\", "
|
" Ena izmed: \"Stereo\", "
|
||||||
"\"surround-51\",... ali\n"
|
"\"5.1\",... ali\n"
|
||||||
" seznam imen kanalov, ločen z "
|
" seznam imen kanalov, ločen z "
|
||||||
"vejico: npr. \"FL,FR\"\n"
|
"vejico: npr. \"FL,FR\"\n"
|
||||||
" --format Vzorčne oblike zapisa %s (zahtevano "
|
" —list-layouts Izpiše podprte postavitve kanalov\n"
|
||||||
"za rec) (privzeto %s)\n"
|
" —list-channel-names Izpiše podprte preslikave kanalov\n"
|
||||||
|
" --format Oblika zapisa vzorcev (privzeto %s)\n"
|
||||||
|
" —list-formats Izpiše podprte zapise vzorcev\n"
|
||||||
|
" —container Oblika vsebnika\n"
|
||||||
|
" —list-containers Seznam podprtih vsebnikov in "
|
||||||
|
"razširitev\n"
|
||||||
" --volume Glasnost toka 0-1.0 (privzeto %.3f)\n"
|
" --volume Glasnost toka 0-1.0 (privzeto %.3f)\n"
|
||||||
" -q --quality Kakovost prevzorčenja (0 - 15) "
|
" -q --quality Kakovost prevzorčenja (0 - 15) "
|
||||||
"(privzeto %d)\n"
|
"(privzeto %d)\n"
|
||||||
" -a, --raw neobdelan način (RAW)\n"
|
" -a, --raw neobdelan način (RAW)\n"
|
||||||
" -M, --force-midi Vsili zapis midi, eden izmed "
|
" -M, --force-midi Vsili zapis midi, eden izmed \"midi"
|
||||||
"\"midi\" ali \"ump\" (privzeto ump)\n"
|
"\" ali \"ump\" (privzeto ump)\n"
|
||||||
" -n, --sample-count ŠTEVEC Ustavi po ŠTEVEC vzorcih\n"
|
" -n, --sample-count ŠTEVEC Ustavi po ŠTEVEC vzorcih\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1129
|
#: src/tools/pw-cat.c:1227
|
||||||
msgid ""
|
msgid ""
|
||||||
" -p, --playback Playback mode\n"
|
" -p, --playback Playback mode\n"
|
||||||
" -r, --record Recording mode\n"
|
" -r, --record Recording mode\n"
|
||||||
|
|
@ -192,6 +222,11 @@ msgstr ""
|
||||||
" -c, --midi-clip Način posnetka MIDI\n"
|
" -c, --midi-clip Način posnetka MIDI\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:1827
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported containers and extensions:\n"
|
||||||
|
msgstr "Podprti vsebniki in razširitve:\n"
|
||||||
|
|
||||||
#: src/tools/pw-cli.c:2386
|
#: src/tools/pw-cli.c:2386
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
|
|
@ -212,203 +247,203 @@ msgstr ""
|
||||||
" -m, --monitor Spremljaj dejavnosti\n"
|
" -m, --monitor Spremljaj dejavnosti\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:351
|
#: spa/plugins/alsa/acp/acp.c:361
|
||||||
msgid "Pro Audio"
|
msgid "Pro Audio"
|
||||||
msgstr "Profesionalni zvok"
|
msgstr "Profesionalni zvok"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:527 spa/plugins/alsa/acp/alsa-mixer.c:4635
|
#: spa/plugins/alsa/acp/acp.c:537 spa/plugins/alsa/acp/alsa-mixer.c:4699
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1974
|
#: spa/plugins/bluez5/bluez5-device.c:2021
|
||||||
msgid "Off"
|
msgid "Off"
|
||||||
msgstr "Izklopljeno"
|
msgstr "Izklopljeno"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:610
|
#: spa/plugins/alsa/acp/acp.c:620
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s [ALSA UCM error]"
|
msgid "%s [ALSA UCM error]"
|
||||||
msgstr "%s [napaka ALSA UCM]"
|
msgstr "%s [napaka ALSA UCM]"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2721
|
||||||
msgid "Input"
|
msgid "Input"
|
||||||
msgstr "Vhod"
|
msgstr "Vhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2653
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2722
|
||||||
msgid "Docking Station Input"
|
msgid "Docking Station Input"
|
||||||
msgstr "Vhod priklopne postaje"
|
msgstr "Vhod priklopne postaje"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2654
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2723
|
||||||
msgid "Docking Station Microphone"
|
msgid "Docking Station Microphone"
|
||||||
msgstr "Mikrofon priklopne postaje"
|
msgstr "Mikrofon priklopne postaje"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2655
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2724
|
||||||
msgid "Docking Station Line In"
|
msgid "Docking Station Line In"
|
||||||
msgstr "Linijski vhod priklopne postaje"
|
msgstr "Linijski vhod priklopne postaje"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2656
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2725
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2747
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2816
|
||||||
msgid "Line In"
|
msgid "Line In"
|
||||||
msgstr "Linijski vhod"
|
msgstr "Linijski vhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2372
|
#: spa/plugins/bluez5/bluez5-device.c:2422
|
||||||
msgid "Microphone"
|
msgid "Microphone"
|
||||||
msgstr "Mikrofon"
|
msgstr "Mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2658
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2727
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2811
|
||||||
msgid "Front Microphone"
|
msgid "Front Microphone"
|
||||||
msgstr "Sprednji mikrofon"
|
msgstr "Sprednji mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2659
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2728
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2743
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2812
|
||||||
msgid "Rear Microphone"
|
msgid "Rear Microphone"
|
||||||
msgstr "Zadnji mikrofon"
|
msgstr "Zadnji mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2660
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2729
|
||||||
msgid "External Microphone"
|
msgid "External Microphone"
|
||||||
msgstr "Zunanji mikrofon"
|
msgstr "Zunanji mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2661
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2730
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2745
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2814
|
||||||
msgid "Internal Microphone"
|
msgid "Internal Microphone"
|
||||||
msgstr "Notranji mikrofon"
|
msgstr "Notranji mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2662
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2731
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2748
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2817
|
||||||
msgid "Radio"
|
msgid "Radio"
|
||||||
msgstr "Radio"
|
msgstr "Radio"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2663
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2732
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2749
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2818
|
||||||
msgid "Video"
|
msgid "Video"
|
||||||
msgstr "Video"
|
msgstr "Video"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2664
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2733
|
||||||
msgid "Automatic Gain Control"
|
msgid "Automatic Gain Control"
|
||||||
msgstr "Samodejni nadzor ojačanja"
|
msgstr "Samodejni nadzor ojačanja"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2665
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2734
|
||||||
msgid "No Automatic Gain Control"
|
msgid "No Automatic Gain Control"
|
||||||
msgstr "Brez samodejnega nadzora ojačanja"
|
msgstr "Brez samodejnega nadzora ojačanja"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2666
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2735
|
||||||
msgid "Boost"
|
msgid "Boost"
|
||||||
msgstr "Ojačitev"
|
msgstr "Ojačitev"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2667
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2736
|
||||||
msgid "No Boost"
|
msgid "No Boost"
|
||||||
msgstr "Brez ojačitve"
|
msgstr "Brez ojačitve"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2668
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2737
|
||||||
msgid "Amplifier"
|
msgid "Amplifier"
|
||||||
msgstr "Ojačevalnik"
|
msgstr "Ojačevalnik"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2669
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2738
|
||||||
msgid "No Amplifier"
|
msgid "No Amplifier"
|
||||||
msgstr "Brez ojačevalnika"
|
msgstr "Brez ojačevalnika"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2670
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2739
|
||||||
msgid "Bass Boost"
|
msgid "Bass Boost"
|
||||||
msgstr "Ojačitev nizkih tonov"
|
msgstr "Ojačitev nizkih tonov"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2671
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
|
||||||
msgid "No Bass Boost"
|
msgid "No Bass Boost"
|
||||||
msgstr "Brez ojačitve nizkih tonov"
|
msgstr "Brez ojačitve nizkih tonov"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2378
|
#: spa/plugins/bluez5/bluez5-device.c:2428
|
||||||
msgid "Speaker"
|
msgid "Speaker"
|
||||||
msgstr "Zvočnik"
|
msgstr "Zvočnik"
|
||||||
|
|
||||||
#. Don't call it "headset", the HF one has the mic
|
#. Don't call it "headset", the HF one has the mic
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2384
|
#: spa/plugins/bluez5/bluez5-device.c:2434
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2451
|
#: spa/plugins/bluez5/bluez5-device.c:2501
|
||||||
msgid "Headphones"
|
msgid "Headphones"
|
||||||
msgstr "Slušalke"
|
msgstr "Slušalke"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2809
|
||||||
msgid "Analog Input"
|
msgid "Analog Input"
|
||||||
msgstr "Analogni vhod"
|
msgstr "Analogni vhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2744
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2813
|
||||||
msgid "Dock Microphone"
|
msgid "Dock Microphone"
|
||||||
msgstr "Priklopni mikrofon"
|
msgstr "Priklopni mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2746
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2815
|
||||||
msgid "Headset Microphone"
|
msgid "Headset Microphone"
|
||||||
msgstr "Mikrofon s slušalkami"
|
msgstr "Mikrofon s slušalkami"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2750
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2819
|
||||||
msgid "Analog Output"
|
msgid "Analog Output"
|
||||||
msgstr "Analogni izhod"
|
msgstr "Analogni izhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2752
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2821
|
||||||
msgid "Headphones 2"
|
msgid "Headphones 2"
|
||||||
msgstr "Slušalke 2"
|
msgstr "Slušalke 2"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2753
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2822
|
||||||
msgid "Headphones Mono Output"
|
msgid "Headphones Mono Output"
|
||||||
msgstr "Mono izhod slušalk"
|
msgstr "Mono izhod slušalk"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2754
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2823
|
||||||
msgid "Line Out"
|
msgid "Line Out"
|
||||||
msgstr "Linijsk izhod"
|
msgstr "Linijski izhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2755
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2824
|
||||||
msgid "Analog Mono Output"
|
msgid "Analog Mono Output"
|
||||||
msgstr "Analogni mono izhod"
|
msgstr "Analogni mono izhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2756
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2825
|
||||||
msgid "Speakers"
|
msgid "Speakers"
|
||||||
msgstr "Govorniki"
|
msgstr "Zvočniki"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2757
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2826
|
||||||
msgid "HDMI / DisplayPort"
|
msgid "HDMI / DisplayPort"
|
||||||
msgstr "HDMI / DisplayPort"
|
msgstr "HDMI / DisplayPort"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2758
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2827
|
||||||
msgid "Digital Output (S/PDIF)"
|
msgid "Digital Output (S/PDIF)"
|
||||||
msgstr "Digitalni izhod (S/PDIF)"
|
msgstr "Digitalni izhod (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2759
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2828
|
||||||
msgid "Digital Input (S/PDIF)"
|
msgid "Digital Input (S/PDIF)"
|
||||||
msgstr "Digitalni vhod (S/PDIF)"
|
msgstr "Digitalni vhod (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2760
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2829
|
||||||
msgid "Multichannel Input"
|
msgid "Multichannel Input"
|
||||||
msgstr "Večkanalni vhod"
|
msgstr "Večkanalni vhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2761
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2830
|
||||||
msgid "Multichannel Output"
|
msgid "Multichannel Output"
|
||||||
msgstr "Večkanalni izhod"
|
msgstr "Večkanalni izhod"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2762
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2831
|
||||||
msgid "Game Output"
|
msgid "Game Output"
|
||||||
msgstr "Vhod igre"
|
msgstr "Vhod igre"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2763
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2832
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2764
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2833
|
||||||
msgid "Chat Output"
|
msgid "Chat Output"
|
||||||
msgstr "Izhod klepeta"
|
msgstr "Izhod klepeta"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2765
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2834
|
||||||
msgid "Chat Input"
|
msgid "Chat Input"
|
||||||
msgstr "Vhod klepeta"
|
msgstr "Vhod klepeta"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2766
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2835
|
||||||
msgid "Virtual Surround 7.1"
|
msgid "Virtual Surround 7.1"
|
||||||
msgstr "Navidezni prostorski zvok 7.1"
|
msgstr "Navidezni prostorski zvok 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4522
|
||||||
msgid "Analog Mono"
|
msgid "Analog Mono"
|
||||||
msgstr "Analogni mono"
|
msgstr "Analogni mono"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4523
|
||||||
msgid "Analog Mono (Left)"
|
msgid "Analog Mono (Left)"
|
||||||
msgstr "Analogni mono (levo)"
|
msgstr "Analogni mono (levo)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4524
|
||||||
msgid "Analog Mono (Right)"
|
msgid "Analog Mono (Right)"
|
||||||
msgstr "Analogni mono (desno)"
|
msgstr "Analogni mono (desno)"
|
||||||
|
|
||||||
|
|
@ -417,142 +452,142 @@ msgstr "Analogni mono (desno)"
|
||||||
#. * here would lead to the source name to become "Analog Stereo Input
|
#. * here would lead to the source name to become "Analog Stereo Input
|
||||||
#. * Input". The same logic applies to analog-stereo-output,
|
#. * Input". The same logic applies to analog-stereo-output,
|
||||||
#. * multichannel-input and multichannel-output.
|
#. * multichannel-input and multichannel-output.
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4525
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4533
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4534
|
||||||
msgid "Analog Stereo"
|
msgid "Analog Stereo"
|
||||||
msgstr "Analogni stereo"
|
msgstr "Analogni stereo"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4462
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4526
|
||||||
msgid "Mono"
|
msgid "Mono"
|
||||||
msgstr "Mono"
|
msgstr "Mono"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4463
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4527
|
||||||
msgid "Stereo"
|
msgid "Stereo"
|
||||||
msgstr "Stereo"
|
msgstr "Stereo"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4535
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4693
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2360
|
#: spa/plugins/bluez5/bluez5-device.c:2410
|
||||||
msgid "Headset"
|
msgid "Headset"
|
||||||
msgstr "Slušalka"
|
msgstr "Slušalka"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4536
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4694
|
||||||
msgid "Speakerphone"
|
msgid "Speakerphone"
|
||||||
msgstr "Zvočnik telefona"
|
msgstr "Zvočnik telefona"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4537
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4538
|
||||||
msgid "Multichannel"
|
msgid "Multichannel"
|
||||||
msgstr "Večkanalno"
|
msgstr "Večkanalno"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4539
|
||||||
msgid "Analog Surround 2.1"
|
msgid "Analog Surround 2.1"
|
||||||
msgstr "Analogni prostorski zvok 2.1"
|
msgstr "Analogni prostorski zvok 2.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4540
|
||||||
msgid "Analog Surround 3.0"
|
msgid "Analog Surround 3.0"
|
||||||
msgstr "Analogni prostorski zvok 3.0"
|
msgstr "Analogni prostorski zvok 3.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4541
|
||||||
msgid "Analog Surround 3.1"
|
msgid "Analog Surround 3.1"
|
||||||
msgstr "Analogni prostorski zvok 3.1"
|
msgstr "Analogni prostorski zvok 3.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4542
|
||||||
msgid "Analog Surround 4.0"
|
msgid "Analog Surround 4.0"
|
||||||
msgstr "Analogni prostorski zvok 4.0"
|
msgstr "Analogni prostorski zvok 4.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4543
|
||||||
msgid "Analog Surround 4.1"
|
msgid "Analog Surround 4.1"
|
||||||
msgstr "Analogni prostorski zvok 4.1"
|
msgstr "Analogni prostorski zvok 4.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4544
|
||||||
msgid "Analog Surround 5.0"
|
msgid "Analog Surround 5.0"
|
||||||
msgstr "Analogni prostorski zvok 5.0"
|
msgstr "Analogni prostorski zvok 5.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4545
|
||||||
msgid "Analog Surround 5.1"
|
msgid "Analog Surround 5.1"
|
||||||
msgstr "Analogni prostorski zvok 5.1"
|
msgstr "Analogni prostorski zvok 5.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4546
|
||||||
msgid "Analog Surround 6.0"
|
msgid "Analog Surround 6.0"
|
||||||
msgstr "Analogni prostorski zvok 6.0"
|
msgstr "Analogni prostorski zvok 6.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4547
|
||||||
msgid "Analog Surround 6.1"
|
msgid "Analog Surround 6.1"
|
||||||
msgstr "Analogni prostorski zvok 6.1"
|
msgstr "Analogni prostorski zvok 6.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4548
|
||||||
msgid "Analog Surround 7.0"
|
msgid "Analog Surround 7.0"
|
||||||
msgstr "Analogni prostorski zvok 7.0"
|
msgstr "Analogni prostorski zvok 7.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4549
|
||||||
msgid "Analog Surround 7.1"
|
msgid "Analog Surround 7.1"
|
||||||
msgstr "Analogni prostorski zvok 7.1"
|
msgstr "Analogni prostorski zvok 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4550
|
||||||
msgid "Digital Stereo (IEC958)"
|
msgid "Digital Stereo (IEC958)"
|
||||||
msgstr "Digitalni stereo (IEC958)"
|
msgstr "Digitalni stereo (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4551
|
||||||
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
||||||
msgstr "Digitalni prostorski zvok 4.0 (IEC958/AC3)"
|
msgstr "Digitalni prostorski zvok 4.0 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4552
|
||||||
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
||||||
msgstr "Digitalni prostorski zvok 5.1 (IEC958/AC3)"
|
msgstr "Digitalni prostorski zvok 5.1 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4553
|
||||||
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
||||||
msgstr "Digitalni prostorski zvok 5.1 (IEC958/DTS)"
|
msgstr "Digitalni prostorski zvok 5.1 (IEC958/DTS)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4554
|
||||||
msgid "Digital Stereo (HDMI)"
|
msgid "Digital Stereo (HDMI)"
|
||||||
msgstr "Digitalni stereo (HDMI)"
|
msgstr "Digitalni stereo (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4555
|
||||||
msgid "Digital Surround 5.1 (HDMI)"
|
msgid "Digital Surround 5.1 (HDMI)"
|
||||||
msgstr "Digitalni prostorski zvok 5.1 (HDMI)"
|
msgstr "Digitalni prostorski zvok 5.1 (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4492
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4556
|
||||||
msgid "Chat"
|
msgid "Chat"
|
||||||
msgstr "Klepet"
|
msgstr "Klepet"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4493
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4557
|
||||||
msgid "Game"
|
msgid "Game"
|
||||||
msgstr "Igra"
|
msgstr "Igra"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4691
|
||||||
msgid "Analog Mono Duplex"
|
msgid "Analog Mono Duplex"
|
||||||
msgstr "Analogni mono dupleks"
|
msgstr "Analogni mono dupleks"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4692
|
||||||
msgid "Analog Stereo Duplex"
|
msgid "Analog Stereo Duplex"
|
||||||
msgstr "Analogni stereo dupleks"
|
msgstr "Analogni stereo dupleks"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4695
|
||||||
msgid "Digital Stereo Duplex (IEC958)"
|
msgid "Digital Stereo Duplex (IEC958)"
|
||||||
msgstr "Digitalni stereo dupleks (IEC958)"
|
msgstr "Digitalni stereo dupleks (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4696
|
||||||
msgid "Multichannel Duplex"
|
msgid "Multichannel Duplex"
|
||||||
msgstr "Večkanalni dupleks"
|
msgstr "Večkanalni dupleks"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4633
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4697
|
||||||
msgid "Stereo Duplex"
|
msgid "Stereo Duplex"
|
||||||
msgstr "Stereo dupleks"
|
msgstr "Stereo dupleks"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4634
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4698
|
||||||
msgid "Mono Chat + 7.1 Surround"
|
msgid "Mono Chat + 7.1 Surround"
|
||||||
msgstr "Mono klepet + prostorski zvok 7.1"
|
msgstr "Mono klepet + prostorski zvok 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4735
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4799
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Output"
|
msgid "%s Output"
|
||||||
msgstr "Izhod %s"
|
msgstr "Izhod %s"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4743
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4807
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Input"
|
msgid "%s Input"
|
||||||
msgstr "Vhod %s"
|
msgstr "Vhod %s"
|
||||||
|
|
@ -592,13 +627,13 @@ msgstr[3] ""
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1299
|
#: spa/plugins/alsa/acp/alsa-util.c:1299
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
|
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
|
||||||
"(%s%lu ms).\n"
|
"%lu ms).\n"
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
||||||
"to the ALSA developers."
|
"to the ALSA developers."
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
|
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
|
||||||
"(%s%lu ms).\n"
|
"%lu ms).\n"
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
||||||
"to the ALSA developers."
|
"to the ALSA developers."
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
|
|
@ -668,7 +703,7 @@ msgstr[3] ""
|
||||||
"Najverjetneje je to napaka v gonilniku ALSA »%s«. O tej težavi obvestite "
|
"Najverjetneje je to napaka v gonilniku ALSA »%s«. O tej težavi obvestite "
|
||||||
"razvijalce ALSA."
|
"razvijalce ALSA."
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/channelmap.h:457
|
#: spa/plugins/alsa/acp/channelmap.h:460
|
||||||
msgid "(invalid)"
|
msgid "(invalid)"
|
||||||
msgstr "(neveljavno)"
|
msgstr "(neveljavno)"
|
||||||
|
|
||||||
|
|
@ -680,100 +715,100 @@ msgstr "Vgrajen zvok"
|
||||||
msgid "Modem"
|
msgid "Modem"
|
||||||
msgstr "Modem"
|
msgstr "Modem"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1985
|
#: spa/plugins/bluez5/bluez5-device.c:2032
|
||||||
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
||||||
msgstr "Zvožni prehod (vir A2DP in HSP/HFP AG)"
|
msgstr "Zvožni prehod (vir A2DP in HSP/HFP AG)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2014
|
#: spa/plugins/bluez5/bluez5-device.c:2061
|
||||||
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
||||||
msgstr "Pretakanje zvoka za slušne aparate (ponor ASHA)"
|
msgstr "Pretakanje zvoka za slušne aparate (ponor ASHA)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2057
|
#: spa/plugins/bluez5/bluez5-device.c:2104
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
||||||
msgstr "Predvajanje visoke ločljivosti (ponor A2DP, kodek %s)"
|
msgstr "Predvajanje visoke ločljivosti (ponor A2DP, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2060
|
#: spa/plugins/bluez5/bluez5-device.c:2107
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
||||||
msgstr "Dupleks visoke ločljivosti (vir/ponor A2DP, kodek %s)"
|
msgstr "Dupleks visoke ločljivosti (vir/ponor A2DP, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2068
|
#: spa/plugins/bluez5/bluez5-device.c:2115
|
||||||
msgid "High Fidelity Playback (A2DP Sink)"
|
msgid "High Fidelity Playback (A2DP Sink)"
|
||||||
msgstr "Predvajanje visoke ločljivosti (ponor A2DP)"
|
msgstr "Predvajanje visoke ločljivosti (ponor A2DP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2070
|
#: spa/plugins/bluez5/bluez5-device.c:2117
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
||||||
msgstr "Dupleks visoke ločljivosti (vir/ponor A2DP)"
|
msgstr "Dupleks visoke ločljivosti (vir/ponor A2DP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2144
|
#: spa/plugins/bluez5/bluez5-device.c:2194
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
||||||
msgstr "Predvajanje visoke ločljivosti (ponor BAP, kodek %s)"
|
msgstr "Predvajanje visoke ločljivosti (ponor BAP, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2149
|
#: spa/plugins/bluez5/bluez5-device.c:2199
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Input (BAP Source, codec %s)"
|
msgid "High Fidelity Input (BAP Source, codec %s)"
|
||||||
msgstr "Vhod visoke ločljivosti (vir BAP, kodek %s)"
|
msgstr "Vhod visoke ločljivosti (vir BAP, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2153
|
#: spa/plugins/bluez5/bluez5-device.c:2203
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
||||||
msgstr "Dupleks visoke ločljivosti (vir/ponor BAP, kodek %s)"
|
msgstr "Dupleks visoke ločljivosti (vir/ponor BAP, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2162
|
#: spa/plugins/bluez5/bluez5-device.c:2212
|
||||||
msgid "High Fidelity Playback (BAP Sink)"
|
msgid "High Fidelity Playback (BAP Sink)"
|
||||||
msgstr "Predvajanje visoke ločljivosti (ponor BAP)"
|
msgstr "Predvajanje visoke ločljivosti (ponor BAP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2166
|
#: spa/plugins/bluez5/bluez5-device.c:2216
|
||||||
msgid "High Fidelity Input (BAP Source)"
|
msgid "High Fidelity Input (BAP Source)"
|
||||||
msgstr "Vhod visoke ločljivosti (vir BAP)"
|
msgstr "Vhod visoke ločljivosti (vir BAP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2169
|
#: spa/plugins/bluez5/bluez5-device.c:2219
|
||||||
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
||||||
msgstr "Dupleks visoke ločljivosti (vir/ponor BAP)"
|
msgstr "Dupleks visoke ločljivosti (vir/ponor BAP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2209
|
#: spa/plugins/bluez5/bluez5-device.c:2259
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
||||||
msgstr "Naglavna enota slušalk (HSP/HFP, kodek %s)"
|
msgstr "Naglavna enota slušalk (HSP/HFP, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2361
|
#: spa/plugins/bluez5/bluez5-device.c:2411
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2366
|
#: spa/plugins/bluez5/bluez5-device.c:2416
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2373
|
#: spa/plugins/bluez5/bluez5-device.c:2423
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2379
|
#: spa/plugins/bluez5/bluez5-device.c:2429
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2385
|
#: spa/plugins/bluez5/bluez5-device.c:2435
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2391
|
#: spa/plugins/bluez5/bluez5-device.c:2441
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2397
|
#: spa/plugins/bluez5/bluez5-device.c:2447
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2403
|
#: spa/plugins/bluez5/bluez5-device.c:2453
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2409
|
#: spa/plugins/bluez5/bluez5-device.c:2459
|
||||||
msgid "Handsfree"
|
msgid "Handsfree"
|
||||||
msgstr "Prostoročno telefoniranje"
|
msgstr "Prostoročno telefoniranje"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2367
|
#: spa/plugins/bluez5/bluez5-device.c:2417
|
||||||
msgid "Handsfree (HFP)"
|
msgid "Handsfree (HFP)"
|
||||||
msgstr "Prostoročno telefoniranje (HFP)"
|
msgstr "Prostoročno telefoniranje (HFP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2390
|
#: spa/plugins/bluez5/bluez5-device.c:2440
|
||||||
msgid "Portable"
|
msgid "Portable"
|
||||||
msgstr "Prenosna naprava"
|
msgstr "Prenosna naprava"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2396
|
#: spa/plugins/bluez5/bluez5-device.c:2446
|
||||||
msgid "Car"
|
msgid "Car"
|
||||||
msgstr "Avtomobil"
|
msgstr "Avtomobil"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2402
|
#: spa/plugins/bluez5/bluez5-device.c:2452
|
||||||
msgid "HiFi"
|
msgid "HiFi"
|
||||||
msgstr "HiFi"
|
msgstr "HiFi"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2408
|
#: spa/plugins/bluez5/bluez5-device.c:2458
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "Telefon"
|
msgstr "Telefon"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2415
|
#: spa/plugins/bluez5/bluez5-device.c:2465
|
||||||
msgid "Bluetooth"
|
msgid "Bluetooth"
|
||||||
msgstr "Bluetooth"
|
msgstr "Bluetooth"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2416
|
#: spa/plugins/bluez5/bluez5-device.c:2466
|
||||||
msgid "Bluetooth (HFP)"
|
msgid "Bluetooth Handsfree"
|
||||||
msgstr "Bluetooth (HFP)"
|
msgstr "Bluetooth - prostoročno"
|
||||||
|
|
|
||||||
695
po/sr@latin.po
695
po/sr@latin.po
File diff suppressed because it is too large
Load diff
382
po/sv.po
382
po/sv.po
|
|
@ -1,9 +1,9 @@
|
||||||
# Swedish translation for pipewire.
|
# Swedish translation for pipewire.
|
||||||
# Copyright © 2008-2025 Free Software Foundation, Inc.
|
# Copyright © 2008-2026 Free Software Foundation, Inc.
|
||||||
# This file is distributed under the same license as the pipewire package.
|
# This file is distributed under the same license as the pipewire package.
|
||||||
# Daniel Nylander <po@danielnylander.se>, 2008, 2012.
|
# Daniel Nylander <po@danielnylander.se>, 2008, 2012.
|
||||||
# Josef Andersson <josef.andersson@fripost.org>, 2014, 2017.
|
# Josef Andersson <josef.andersson@fripost.org>, 2014, 2017.
|
||||||
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021, 2022, 2023, 2024, 2025.
|
# Anders Jonsson <anders.jonsson@norsjovallen.se>, 2021, 2022, 2023, 2024, 2025, 2026.
|
||||||
#
|
#
|
||||||
# Termer:
|
# Termer:
|
||||||
# input/output: ingång/utgång (det handlar om ljud)
|
# input/output: ingång/utgång (det handlar om ljud)
|
||||||
|
|
@ -19,8 +19,8 @@ msgstr ""
|
||||||
"Project-Id-Version: pipewire\n"
|
"Project-Id-Version: pipewire\n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
|
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
|
||||||
"issues\n"
|
"issues\n"
|
||||||
"POT-Creation-Date: 2025-04-16 15:31+0000\n"
|
"POT-Creation-Date: 2026-02-09 12:55+0000\n"
|
||||||
"PO-Revision-Date: 2025-04-22 10:43+0200\n"
|
"PO-Revision-Date: 2026-02-22 21:48+0100\n"
|
||||||
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
|
"Last-Translator: Anders Jonsson <anders.jonsson@norsjovallen.se>\n"
|
||||||
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
"Language-Team: Swedish <tp-sv@listor.tp-sv.se>\n"
|
||||||
"Language: sv\n"
|
"Language: sv\n"
|
||||||
|
|
@ -28,7 +28,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
"Plural-Forms: nplurals=2; plural=n != 1;\n"
|
||||||
"X-Generator: Poedit 3.5\n"
|
"X-Generator: Poedit 3.8\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.c:29
|
#: src/daemon/pipewire.c:29
|
||||||
#, c-format
|
#, c-format
|
||||||
|
|
@ -47,11 +47,11 @@ msgstr ""
|
||||||
" -c, --config Läs in konfig (standard %s)\n"
|
" -c, --config Läs in konfig (standard %s)\n"
|
||||||
" -P --properties Ställ in kontextegenskaper\n"
|
" -P --properties Ställ in kontextegenskaper\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.desktop.in:4
|
#: src/daemon/pipewire.desktop.in:3
|
||||||
msgid "PipeWire Media System"
|
msgid "PipeWire Media System"
|
||||||
msgstr "PipeWire mediasystem"
|
msgstr "PipeWire mediasystem"
|
||||||
|
|
||||||
#: src/daemon/pipewire.desktop.in:5
|
#: src/daemon/pipewire.desktop.in:4
|
||||||
msgid "Start the PipeWire Media System"
|
msgid "Start the PipeWire Media System"
|
||||||
msgstr "Starta mediasystemet PipeWire"
|
msgstr "Starta mediasystemet PipeWire"
|
||||||
|
|
||||||
|
|
@ -65,26 +65,51 @@ msgstr "Tunnel till %s%s%s"
|
||||||
msgid "Dummy Output"
|
msgid "Dummy Output"
|
||||||
msgstr "Attrapputgång"
|
msgstr "Attrapputgång"
|
||||||
|
|
||||||
#: src/modules/module-pulse-tunnel.c:760
|
#: src/modules/module-pulse-tunnel.c:761
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Tunnel for %s@%s"
|
msgid "Tunnel for %s@%s"
|
||||||
msgstr "Tunnel för %s@%s"
|
msgstr "Tunnel för %s@%s"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:320
|
#: src/modules/module-zeroconf-discover.c:326
|
||||||
msgid "Unknown device"
|
msgid "Unknown device"
|
||||||
msgstr "Okänd enhet"
|
msgstr "Okänd enhet"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:332
|
#: src/modules/module-zeroconf-discover.c:338
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s on %s@%s"
|
msgid "%s on %s@%s"
|
||||||
msgstr "%s på %s@%s"
|
msgstr "%s på %s@%s"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:336
|
#: src/modules/module-zeroconf-discover.c:342
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s on %s"
|
msgid "%s on %s"
|
||||||
msgstr "%s på %s"
|
msgstr "%s på %s"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:973
|
#: src/tools/pw-cat.c:264
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported formats:\n"
|
||||||
|
msgstr "Format som stöds:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:749
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layouts:\n"
|
||||||
|
msgstr "Kanallayouter som stöds:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:759
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layout aliases:\n"
|
||||||
|
msgstr "Kanallayoutalias som stöds:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:761
|
||||||
|
#, c-format
|
||||||
|
msgid " %s -> %s\n"
|
||||||
|
msgstr " %s -> %s\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:766
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel names:\n"
|
||||||
|
msgstr "Kanalnamn som stöds:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:1177
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] [<file>|-]\n"
|
"%s [options] [<file>|-]\n"
|
||||||
|
|
@ -99,7 +124,7 @@ msgstr ""
|
||||||
" -v, --verbose Aktivera utförliga operationer\n"
|
" -v, --verbose Aktivera utförliga operationer\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:980
|
#: src/tools/pw-cat.c:1184
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" -R, --remote Remote daemon name\n"
|
" -R, --remote Remote daemon name\n"
|
||||||
|
|
@ -131,50 +156,64 @@ msgstr ""
|
||||||
" -P --properties Sätt nodegenskaper\n"
|
" -P --properties Sätt nodegenskaper\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:998
|
#: src/tools/pw-cat.c:1202
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" --rate Sample rate (req. for rec) (default "
|
" --rate Sample rate (default %u)\n"
|
||||||
"%u)\n"
|
" --channels Number of channels (default %u)\n"
|
||||||
" --channels Number of channels (req. for rec) "
|
|
||||||
"(default %u)\n"
|
|
||||||
" --channel-map Channel map\n"
|
" --channel-map Channel map\n"
|
||||||
" one of: \"stereo\", "
|
" a channel layout: \"Stereo\", "
|
||||||
"\"surround-51\",... or\n"
|
"\"5.1\",... or\n"
|
||||||
" comma separated list of channel "
|
" comma separated list of channel "
|
||||||
"names: eg. \"FL,FR\"\n"
|
"names: eg. \"FL,FR\"\n"
|
||||||
" --format Sample format %s (req. for rec) "
|
" --list-layouts List supported channel layouts\n"
|
||||||
"(default %s)\n"
|
" --list-channel-names List supported channel maps\n"
|
||||||
|
" --format Sample format (default %s)\n"
|
||||||
|
" --list-formats List supported sample formats\n"
|
||||||
|
" --container Container format\n"
|
||||||
|
" --list-containers List supported containers and "
|
||||||
|
"extensions\n"
|
||||||
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
||||||
" -q --quality Resampler quality (0 - 15) (default "
|
" -q --quality Resampler quality (0 - 15) (default "
|
||||||
"%d)\n"
|
"%d)\n"
|
||||||
" -a, --raw RAW mode\n"
|
" -a, --raw RAW mode\n"
|
||||||
|
" -M, --force-midi Force midi format, one of \"midi\" "
|
||||||
|
"or \"ump\", (default ump)\n"
|
||||||
|
" -n, --sample-count COUNT Stop after COUNT samples\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
" --rate Samplingsfrekvens (krävs för insp.) "
|
" --rate Samplingsfrekvens (standard %u)\n"
|
||||||
"(standard %u)\n"
|
" --channels Antal kanaler (standard %u)\n"
|
||||||
" --channels Antal kanaler (krävs för insp.) "
|
|
||||||
"(standard %u)\n"
|
|
||||||
" --channel-map Kanalmappning\n"
|
" --channel-map Kanalmappning\n"
|
||||||
" en av: \"stereo\", "
|
" en kanallayout: \"Stereo\", "
|
||||||
"\"surround-51\",... eller\n"
|
"\"5.1\",... eller\n"
|
||||||
" kommaseparerad lista av "
|
" kommaseparerad lista av "
|
||||||
"kanalnamn: t.ex. \"FL,FR\"\n"
|
"kanalnamn: t.ex. \"FL,FR\"\n"
|
||||||
" --format Samplingsformat %s (krävs för insp.) "
|
" --list-layouts Lista kanallayouter som stöds\n"
|
||||||
"(standard %s)\n"
|
" --list-channel-names Lista kanalmappningar som stöds\n"
|
||||||
|
" --format Samplingsformat (standard %s)\n"
|
||||||
|
" --list-formats Lista samplingsformat som stöds\n"
|
||||||
|
" --container Behållarformat\n"
|
||||||
|
" --list-containers Lista behållare och tillägg som "
|
||||||
|
"stöds\n"
|
||||||
" --volume Strömvolym 0-1.0 (standard %.3f)\n"
|
" --volume Strömvolym 0-1.0 (standard %.3f)\n"
|
||||||
" -q --quality Omsamplarkvalitet (0 - 15) (standard "
|
" -q --quality Omsamplarkvalitet (0 - 15) (standard "
|
||||||
"%d)\n"
|
"%d)\n"
|
||||||
" -a, --raw RAW-läge\n"
|
" -a, --raw RAW-läge\n"
|
||||||
|
" -M, --force-midi Tvinga midi-format, en av \"midi\" "
|
||||||
|
"eller \"ump\", (standard ump)\n"
|
||||||
|
" -n, --sample-count ANTAL Stoppa efter ANTAL samplar\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1016
|
#: src/tools/pw-cat.c:1227
|
||||||
msgid ""
|
msgid ""
|
||||||
" -p, --playback Playback mode\n"
|
" -p, --playback Playback mode\n"
|
||||||
" -r, --record Recording mode\n"
|
" -r, --record Recording mode\n"
|
||||||
" -m, --midi Midi mode\n"
|
" -m, --midi Midi mode\n"
|
||||||
" -d, --dsd DSD mode\n"
|
" -d, --dsd DSD mode\n"
|
||||||
" -o, --encoded Encoded mode\n"
|
" -o, --encoded Encoded mode\n"
|
||||||
|
" -s, --sysex SysEx mode\n"
|
||||||
|
" -c, --midi-clip MIDI clip mode\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
" -p, --playback Uppspelningsläge\n"
|
" -p, --playback Uppspelningsläge\n"
|
||||||
|
|
@ -182,9 +221,16 @@ msgstr ""
|
||||||
" -m, --midi Midiläge\n"
|
" -m, --midi Midiläge\n"
|
||||||
" -d, --dsd DSD-läge\n"
|
" -d, --dsd DSD-läge\n"
|
||||||
" -o, --encoded Kodat läge\n"
|
" -o, --encoded Kodat läge\n"
|
||||||
|
" -s, --sysex SysEx-läge\n"
|
||||||
|
" -c, --midi-clip MIDI-klippläge\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cli.c:2306
|
#: src/tools/pw-cat.c:1827
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported containers and extensions:\n"
|
||||||
|
msgstr "Behållare och tillägg som stöds:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cli.c:2386
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] [command]\n"
|
"%s [options] [command]\n"
|
||||||
|
|
@ -203,200 +249,203 @@ msgstr ""
|
||||||
" -m, --monitor Övervaka aktivitet\n"
|
" -m, --monitor Övervaka aktivitet\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:350
|
#: spa/plugins/alsa/acp/acp.c:361
|
||||||
msgid "Pro Audio"
|
msgid "Pro Audio"
|
||||||
msgstr "Professionellt ljud"
|
msgstr "Professionellt ljud"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:511 spa/plugins/alsa/acp/alsa-mixer.c:4635
|
#: spa/plugins/alsa/acp/acp.c:537 spa/plugins/alsa/acp/alsa-mixer.c:4699
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1802
|
#: spa/plugins/bluez5/bluez5-device.c:2021
|
||||||
msgid "Off"
|
msgid "Off"
|
||||||
msgstr "Av"
|
msgstr "Av"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:593
|
#: spa/plugins/alsa/acp/acp.c:620
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s [ALSA UCM error]"
|
msgid "%s [ALSA UCM error]"
|
||||||
msgstr "%s [ALSA UCM-fel]"
|
msgstr "%s [ALSA UCM-fel]"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2652
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2721
|
||||||
msgid "Input"
|
msgid "Input"
|
||||||
msgstr "Ingång"
|
msgstr "Ingång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2653
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2722
|
||||||
msgid "Docking Station Input"
|
msgid "Docking Station Input"
|
||||||
msgstr "Ingång för dockningsstation"
|
msgstr "Ingång för dockningsstation"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2654
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2723
|
||||||
msgid "Docking Station Microphone"
|
msgid "Docking Station Microphone"
|
||||||
msgstr "Mikrofon för dockningsstation"
|
msgstr "Mikrofon för dockningsstation"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2655
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2724
|
||||||
msgid "Docking Station Line In"
|
msgid "Docking Station Line In"
|
||||||
msgstr "Linje in för dockningsstation"
|
msgstr "Linje in för dockningsstation"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2656
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2725
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2747
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2816
|
||||||
msgid "Line In"
|
msgid "Line In"
|
||||||
msgstr "Linje in"
|
msgstr "Linje in"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2657
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2146
|
#: spa/plugins/bluez5/bluez5-device.c:2422
|
||||||
msgid "Microphone"
|
msgid "Microphone"
|
||||||
msgstr "Mikrofon"
|
msgstr "Mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2658
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2727
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2811
|
||||||
msgid "Front Microphone"
|
msgid "Front Microphone"
|
||||||
msgstr "Frontmikrofon"
|
msgstr "Frontmikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2659
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2728
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2743
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2812
|
||||||
msgid "Rear Microphone"
|
msgid "Rear Microphone"
|
||||||
msgstr "Bakre mikrofon"
|
msgstr "Bakre mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2660
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2729
|
||||||
msgid "External Microphone"
|
msgid "External Microphone"
|
||||||
msgstr "Extern mikrofon"
|
msgstr "Extern mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2661
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2730
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2745
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2814
|
||||||
msgid "Internal Microphone"
|
msgid "Internal Microphone"
|
||||||
msgstr "Intern mikrofon"
|
msgstr "Intern mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2662
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2731
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2748
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2817
|
||||||
msgid "Radio"
|
msgid "Radio"
|
||||||
msgstr "Radio"
|
msgstr "Radio"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2663
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2732
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2749
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2818
|
||||||
msgid "Video"
|
msgid "Video"
|
||||||
msgstr "Video"
|
msgstr "Video"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2664
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2733
|
||||||
msgid "Automatic Gain Control"
|
msgid "Automatic Gain Control"
|
||||||
msgstr "Automatisk förstärkningskontroll"
|
msgstr "Automatisk förstärkningskontroll"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2665
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2734
|
||||||
msgid "No Automatic Gain Control"
|
msgid "No Automatic Gain Control"
|
||||||
msgstr "Ingen automatisk förstärkningskontroll"
|
msgstr "Ingen automatisk förstärkningskontroll"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2666
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2735
|
||||||
msgid "Boost"
|
msgid "Boost"
|
||||||
msgstr "Ökning"
|
msgstr "Ökning"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2667
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2736
|
||||||
msgid "No Boost"
|
msgid "No Boost"
|
||||||
msgstr "Ingen ökning"
|
msgstr "Ingen ökning"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2668
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2737
|
||||||
msgid "Amplifier"
|
msgid "Amplifier"
|
||||||
msgstr "Förstärkare"
|
msgstr "Förstärkare"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2669
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2738
|
||||||
msgid "No Amplifier"
|
msgid "No Amplifier"
|
||||||
msgstr "Ingen förstärkare"
|
msgstr "Ingen förstärkare"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2670
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2739
|
||||||
msgid "Bass Boost"
|
msgid "Bass Boost"
|
||||||
msgstr "Basökning"
|
msgstr "Basökning"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2671
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
|
||||||
msgid "No Bass Boost"
|
msgid "No Bass Boost"
|
||||||
msgstr "Ingen basökning"
|
msgstr "Ingen basökning"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2672
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2152
|
#: spa/plugins/bluez5/bluez5-device.c:2428
|
||||||
msgid "Speaker"
|
msgid "Speaker"
|
||||||
msgstr "Högtalare"
|
msgstr "Högtalare"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2673
|
#. Don't call it "headset", the HF one has the mic
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2751
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
|
||||||
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2434
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2501
|
||||||
msgid "Headphones"
|
msgid "Headphones"
|
||||||
msgstr "Hörlurar"
|
msgstr "Hörlurar"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2809
|
||||||
msgid "Analog Input"
|
msgid "Analog Input"
|
||||||
msgstr "Analog ingång"
|
msgstr "Analog ingång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2744
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2813
|
||||||
msgid "Dock Microphone"
|
msgid "Dock Microphone"
|
||||||
msgstr "Dockmikrofon"
|
msgstr "Dockmikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2746
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2815
|
||||||
msgid "Headset Microphone"
|
msgid "Headset Microphone"
|
||||||
msgstr "Headset-mikrofon"
|
msgstr "Headset-mikrofon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2750
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2819
|
||||||
msgid "Analog Output"
|
msgid "Analog Output"
|
||||||
msgstr "Analog utgång"
|
msgstr "Analog utgång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2752
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2821
|
||||||
msgid "Headphones 2"
|
msgid "Headphones 2"
|
||||||
msgstr "Hörlurar 2"
|
msgstr "Hörlurar 2"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2753
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2822
|
||||||
msgid "Headphones Mono Output"
|
msgid "Headphones Mono Output"
|
||||||
msgstr "Monoutgång för hörlurar"
|
msgstr "Monoutgång för hörlurar"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2754
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2823
|
||||||
msgid "Line Out"
|
msgid "Line Out"
|
||||||
msgstr "Linje ut"
|
msgstr "Linje ut"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2755
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2824
|
||||||
msgid "Analog Mono Output"
|
msgid "Analog Mono Output"
|
||||||
msgstr "Analog monoutgång"
|
msgstr "Analog monoutgång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2756
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2825
|
||||||
msgid "Speakers"
|
msgid "Speakers"
|
||||||
msgstr "Högtalare"
|
msgstr "Högtalare"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2757
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2826
|
||||||
msgid "HDMI / DisplayPort"
|
msgid "HDMI / DisplayPort"
|
||||||
msgstr "HDMI / DisplayPort"
|
msgstr "HDMI / DisplayPort"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2758
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2827
|
||||||
msgid "Digital Output (S/PDIF)"
|
msgid "Digital Output (S/PDIF)"
|
||||||
msgstr "Digital utgång (S/PDIF)"
|
msgstr "Digital utgång (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2759
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2828
|
||||||
msgid "Digital Input (S/PDIF)"
|
msgid "Digital Input (S/PDIF)"
|
||||||
msgstr "Digital ingång (S/PDIF)"
|
msgstr "Digital ingång (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2760
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2829
|
||||||
msgid "Multichannel Input"
|
msgid "Multichannel Input"
|
||||||
msgstr "Multikanalingång"
|
msgstr "Multikanalingång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2761
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2830
|
||||||
msgid "Multichannel Output"
|
msgid "Multichannel Output"
|
||||||
msgstr "Multikanalutgång"
|
msgstr "Multikanalutgång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2762
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2831
|
||||||
msgid "Game Output"
|
msgid "Game Output"
|
||||||
msgstr "Spelutgång"
|
msgstr "Spelutgång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2763
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2832
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2764
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2833
|
||||||
msgid "Chat Output"
|
msgid "Chat Output"
|
||||||
msgstr "Chatt-utgång"
|
msgstr "Chatt-utgång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2765
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2834
|
||||||
msgid "Chat Input"
|
msgid "Chat Input"
|
||||||
msgstr "Chatt-ingång"
|
msgstr "Chatt-ingång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2766
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2835
|
||||||
msgid "Virtual Surround 7.1"
|
msgid "Virtual Surround 7.1"
|
||||||
msgstr "Virtual surround 7.1"
|
msgstr "Virtual surround 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4458
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4522
|
||||||
msgid "Analog Mono"
|
msgid "Analog Mono"
|
||||||
msgstr "Analog mono"
|
msgstr "Analog mono"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4459
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4523
|
||||||
msgid "Analog Mono (Left)"
|
msgid "Analog Mono (Left)"
|
||||||
msgstr "Analog mono (vänster)"
|
msgstr "Analog mono (vänster)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4460
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4524
|
||||||
msgid "Analog Mono (Right)"
|
msgid "Analog Mono (Right)"
|
||||||
msgstr "Analog mono (höger)"
|
msgstr "Analog mono (höger)"
|
||||||
|
|
||||||
|
|
@ -405,142 +454,142 @@ msgstr "Analog mono (höger)"
|
||||||
#. * here would lead to the source name to become "Analog Stereo Input
|
#. * here would lead to the source name to become "Analog Stereo Input
|
||||||
#. * Input". The same logic applies to analog-stereo-output,
|
#. * Input". The same logic applies to analog-stereo-output,
|
||||||
#. * multichannel-input and multichannel-output.
|
#. * multichannel-input and multichannel-output.
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4461
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4525
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4469
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4533
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4470
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4534
|
||||||
msgid "Analog Stereo"
|
msgid "Analog Stereo"
|
||||||
msgstr "Analog stereo"
|
msgstr "Analog stereo"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4462
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4526
|
||||||
msgid "Mono"
|
msgid "Mono"
|
||||||
msgstr "Mono"
|
msgstr "Mono"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4463
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4527
|
||||||
msgid "Stereo"
|
msgid "Stereo"
|
||||||
msgstr "Stereo"
|
msgstr "Stereo"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4471
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4535
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4629
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4693
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2134
|
#: spa/plugins/bluez5/bluez5-device.c:2410
|
||||||
msgid "Headset"
|
msgid "Headset"
|
||||||
msgstr "Headset"
|
msgstr "Headset"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4472
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4536
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4630
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4694
|
||||||
msgid "Speakerphone"
|
msgid "Speakerphone"
|
||||||
msgstr "Högtalartelefon"
|
msgstr "Högtalartelefon"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4473
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4537
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4474
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4538
|
||||||
msgid "Multichannel"
|
msgid "Multichannel"
|
||||||
msgstr "Multikanal"
|
msgstr "Multikanal"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4475
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4539
|
||||||
msgid "Analog Surround 2.1"
|
msgid "Analog Surround 2.1"
|
||||||
msgstr "Analog surround 2.1"
|
msgstr "Analog surround 2.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4476
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4540
|
||||||
msgid "Analog Surround 3.0"
|
msgid "Analog Surround 3.0"
|
||||||
msgstr "Analog surround 3.0"
|
msgstr "Analog surround 3.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4477
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4541
|
||||||
msgid "Analog Surround 3.1"
|
msgid "Analog Surround 3.1"
|
||||||
msgstr "Analog surround 3.1"
|
msgstr "Analog surround 3.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4478
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4542
|
||||||
msgid "Analog Surround 4.0"
|
msgid "Analog Surround 4.0"
|
||||||
msgstr "Analog surround 4.0"
|
msgstr "Analog surround 4.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4479
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4543
|
||||||
msgid "Analog Surround 4.1"
|
msgid "Analog Surround 4.1"
|
||||||
msgstr "Analog surround 4.1"
|
msgstr "Analog surround 4.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4480
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4544
|
||||||
msgid "Analog Surround 5.0"
|
msgid "Analog Surround 5.0"
|
||||||
msgstr "Analog surround 5.0"
|
msgstr "Analog surround 5.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4481
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4545
|
||||||
msgid "Analog Surround 5.1"
|
msgid "Analog Surround 5.1"
|
||||||
msgstr "Analog surround 5.1"
|
msgstr "Analog surround 5.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4482
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4546
|
||||||
msgid "Analog Surround 6.0"
|
msgid "Analog Surround 6.0"
|
||||||
msgstr "Analog surround 6.0"
|
msgstr "Analog surround 6.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4483
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4547
|
||||||
msgid "Analog Surround 6.1"
|
msgid "Analog Surround 6.1"
|
||||||
msgstr "Analog surround 6.1"
|
msgstr "Analog surround 6.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4484
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4548
|
||||||
msgid "Analog Surround 7.0"
|
msgid "Analog Surround 7.0"
|
||||||
msgstr "Analog surround 7.0"
|
msgstr "Analog surround 7.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4485
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4549
|
||||||
msgid "Analog Surround 7.1"
|
msgid "Analog Surround 7.1"
|
||||||
msgstr "Analog surround 7.1"
|
msgstr "Analog surround 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4486
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4550
|
||||||
msgid "Digital Stereo (IEC958)"
|
msgid "Digital Stereo (IEC958)"
|
||||||
msgstr "Digital stereo (IEC958)"
|
msgstr "Digital stereo (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4487
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4551
|
||||||
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
||||||
msgstr "Digital surround 4.0 (IEC958/AC3)"
|
msgstr "Digital surround 4.0 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4488
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4552
|
||||||
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
||||||
msgstr "Digital surround 5.1 (IEC958/AC3)"
|
msgstr "Digital surround 5.1 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4489
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4553
|
||||||
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
||||||
msgstr "Digital surround 5.1 (IEC958/DTS)"
|
msgstr "Digital surround 5.1 (IEC958/DTS)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4490
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4554
|
||||||
msgid "Digital Stereo (HDMI)"
|
msgid "Digital Stereo (HDMI)"
|
||||||
msgstr "Digital stereo (HDMI)"
|
msgstr "Digital stereo (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4491
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4555
|
||||||
msgid "Digital Surround 5.1 (HDMI)"
|
msgid "Digital Surround 5.1 (HDMI)"
|
||||||
msgstr "Digital surround 5.1 (HDMI)"
|
msgstr "Digital surround 5.1 (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4492
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4556
|
||||||
msgid "Chat"
|
msgid "Chat"
|
||||||
msgstr "Chatt"
|
msgstr "Chatt"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4493
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4557
|
||||||
msgid "Game"
|
msgid "Game"
|
||||||
msgstr "Spel"
|
msgstr "Spel"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4627
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4691
|
||||||
msgid "Analog Mono Duplex"
|
msgid "Analog Mono Duplex"
|
||||||
msgstr "Analog mono duplex"
|
msgstr "Analog mono duplex"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4628
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4692
|
||||||
msgid "Analog Stereo Duplex"
|
msgid "Analog Stereo Duplex"
|
||||||
msgstr "Analog stereo duplex"
|
msgstr "Analog stereo duplex"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4631
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4695
|
||||||
msgid "Digital Stereo Duplex (IEC958)"
|
msgid "Digital Stereo Duplex (IEC958)"
|
||||||
msgstr "Digital stereo duplex (IEC958)"
|
msgstr "Digital stereo duplex (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4632
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4696
|
||||||
msgid "Multichannel Duplex"
|
msgid "Multichannel Duplex"
|
||||||
msgstr "Multikanalduplex"
|
msgstr "Multikanalduplex"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4633
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4697
|
||||||
msgid "Stereo Duplex"
|
msgid "Stereo Duplex"
|
||||||
msgstr "Stereo duplex"
|
msgstr "Stereo duplex"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4634
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4698
|
||||||
msgid "Mono Chat + 7.1 Surround"
|
msgid "Mono Chat + 7.1 Surround"
|
||||||
msgstr "Mono Chatt + 7.1 Surround"
|
msgstr "Mono Chatt + 7.1 Surround"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4735
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4799
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Output"
|
msgid "%s Output"
|
||||||
msgstr "%s-utgång"
|
msgstr "%s-utgång"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4743
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4807
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Input"
|
msgid "%s Input"
|
||||||
msgstr "%s-ingång"
|
msgstr "%s-ingång"
|
||||||
|
|
@ -627,116 +676,115 @@ msgstr[1] ""
|
||||||
"Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
|
"Förmodligen är detta ett fel i ALSA-drivrutinen ”%s”. Vänligen rapportera "
|
||||||
"problemet till ALSA-utvecklarna."
|
"problemet till ALSA-utvecklarna."
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/channelmap.h:457
|
#: spa/plugins/alsa/acp/channelmap.h:460
|
||||||
msgid "(invalid)"
|
msgid "(invalid)"
|
||||||
msgstr "(ogiltig)"
|
msgstr "(ogiltig)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/compat.c:193
|
#: spa/plugins/alsa/acp/compat.c:194
|
||||||
msgid "Built-in Audio"
|
msgid "Built-in Audio"
|
||||||
msgstr "Inbyggt ljud"
|
msgstr "Inbyggt ljud"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/compat.c:198
|
#: spa/plugins/alsa/acp/compat.c:199
|
||||||
msgid "Modem"
|
msgid "Modem"
|
||||||
msgstr "Modem"
|
msgstr "Modem"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1813
|
#: spa/plugins/bluez5/bluez5-device.c:2032
|
||||||
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
||||||
msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)"
|
msgstr "Audio gateway (A2DP-källa & HSP/HFP AG)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1841
|
#: spa/plugins/bluez5/bluez5-device.c:2061
|
||||||
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
||||||
msgstr "Ljudströmning för hörhjälpmedel (ASHA-utgång)"
|
msgstr "Ljudströmning för hörhjälpmedel (ASHA-utgång)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1881
|
#: spa/plugins/bluez5/bluez5-device.c:2104
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
||||||
msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)"
|
msgstr "High fidelity-uppspelning (A2DP-utgång, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1884
|
#: spa/plugins/bluez5/bluez5-device.c:2107
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
||||||
msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)"
|
msgstr "High fidelity duplex (A2DP-källa/utgång, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1892
|
#: spa/plugins/bluez5/bluez5-device.c:2115
|
||||||
msgid "High Fidelity Playback (A2DP Sink)"
|
msgid "High Fidelity Playback (A2DP Sink)"
|
||||||
msgstr "High fidelity-uppspelning (A2DP-utgång)"
|
msgstr "High fidelity-uppspelning (A2DP-utgång)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1894
|
#: spa/plugins/bluez5/bluez5-device.c:2117
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
||||||
msgstr "High fidelity duplex (A2DP-källa/utgång)"
|
msgstr "High fidelity duplex (A2DP-källa/utgång)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1944
|
#: spa/plugins/bluez5/bluez5-device.c:2194
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
||||||
msgstr "High fidelity-uppspelning (BAP-utgång, kodek %s)"
|
msgstr "High fidelity-uppspelning (BAP-utgång, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1949
|
#: spa/plugins/bluez5/bluez5-device.c:2199
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Input (BAP Source, codec %s)"
|
msgid "High Fidelity Input (BAP Source, codec %s)"
|
||||||
msgstr "High fidelity-ingång (BAP-källa, kodek %s)"
|
msgstr "High fidelity-ingång (BAP-källa, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1953
|
#: spa/plugins/bluez5/bluez5-device.c:2203
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
||||||
msgstr "High fidelity duplex (BAP-källa/utgång, kodek %s)"
|
msgstr "High fidelity duplex (BAP-källa/utgång, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1962
|
#: spa/plugins/bluez5/bluez5-device.c:2212
|
||||||
msgid "High Fidelity Playback (BAP Sink)"
|
msgid "High Fidelity Playback (BAP Sink)"
|
||||||
msgstr "High fidelity-uppspelning (BAP-utgång)"
|
msgstr "High fidelity-uppspelning (BAP-utgång)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1966
|
#: spa/plugins/bluez5/bluez5-device.c:2216
|
||||||
msgid "High Fidelity Input (BAP Source)"
|
msgid "High Fidelity Input (BAP Source)"
|
||||||
msgstr "High fidelity-ingång (BAP-källa)"
|
msgstr "High fidelity-ingång (BAP-källa)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1969
|
#: spa/plugins/bluez5/bluez5-device.c:2219
|
||||||
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
||||||
msgstr "High fidelity duplex (BAP-källa/utgång)"
|
msgstr "High fidelity duplex (BAP-källa/utgång)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2015
|
#: spa/plugins/bluez5/bluez5-device.c:2259
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
||||||
msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)"
|
msgstr "Headset-huvudenhet (HSP/HFP, kodek %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2135
|
#: spa/plugins/bluez5/bluez5-device.c:2411
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2140
|
#: spa/plugins/bluez5/bluez5-device.c:2416
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2147
|
#: spa/plugins/bluez5/bluez5-device.c:2423
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2153
|
#: spa/plugins/bluez5/bluez5-device.c:2429
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2159
|
#: spa/plugins/bluez5/bluez5-device.c:2435
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2165
|
#: spa/plugins/bluez5/bluez5-device.c:2441
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2171
|
#: spa/plugins/bluez5/bluez5-device.c:2447
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2177
|
#: spa/plugins/bluez5/bluez5-device.c:2453
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2183
|
#: spa/plugins/bluez5/bluez5-device.c:2459
|
||||||
msgid "Handsfree"
|
msgid "Handsfree"
|
||||||
msgstr "Handsfree"
|
msgstr "Handsfree"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2141
|
#: spa/plugins/bluez5/bluez5-device.c:2417
|
||||||
msgid "Handsfree (HFP)"
|
msgid "Handsfree (HFP)"
|
||||||
msgstr "Handsfree (HFP)"
|
msgstr "Handsfree (HFP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2158
|
#: spa/plugins/bluez5/bluez5-device.c:2440
|
||||||
msgid "Headphone"
|
|
||||||
msgstr "Hörlurar"
|
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2164
|
|
||||||
msgid "Portable"
|
msgid "Portable"
|
||||||
msgstr "Bärbar"
|
msgstr "Bärbar"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2170
|
#: spa/plugins/bluez5/bluez5-device.c:2446
|
||||||
msgid "Car"
|
msgid "Car"
|
||||||
msgstr "Bil"
|
msgstr "Bil"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2176
|
#: spa/plugins/bluez5/bluez5-device.c:2452
|
||||||
msgid "HiFi"
|
msgid "HiFi"
|
||||||
msgstr "HiFi"
|
msgstr "HiFi"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2182
|
#: spa/plugins/bluez5/bluez5-device.c:2458
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "Telefon"
|
msgstr "Telefon"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2189
|
#: spa/plugins/bluez5/bluez5-device.c:2465
|
||||||
msgid "Bluetooth"
|
msgid "Bluetooth"
|
||||||
msgstr "Bluetooth"
|
msgstr "Bluetooth"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2190
|
#: spa/plugins/bluez5/bluez5-device.c:2466
|
||||||
msgid "Bluetooth (HFP)"
|
msgid "Bluetooth Handsfree"
|
||||||
msgstr "Bluetooth (HFP)"
|
msgstr "Bluetooth-handsfree"
|
||||||
|
|
||||||
|
#~ msgid "Headphone"
|
||||||
|
#~ msgstr "Hörlurar"
|
||||||
|
|
|
||||||
176
po/zh_CN.po
176
po/zh_CN.po
|
|
@ -6,15 +6,15 @@
|
||||||
# Cheng-Chia Tseng <pswo10680@gmail.com>, 2010, 2012.
|
# Cheng-Chia Tseng <pswo10680@gmail.com>, 2010, 2012.
|
||||||
# Frank Hill <hxf.prc@gmail.com>, 2015.
|
# Frank Hill <hxf.prc@gmail.com>, 2015.
|
||||||
# Mingye Wang (Arthur2e5) <arthur200126@gmail.com>, 2015.
|
# Mingye Wang (Arthur2e5) <arthur200126@gmail.com>, 2015.
|
||||||
# lumingzh <lumingzh@qq.com>, 2024-2025.
|
# lumingzh <lumingzh@qq.com>, 2024-2026.
|
||||||
#
|
#
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: pipewire.master-tx\n"
|
"Project-Id-Version: pipewire.master-tx\n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
|
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/-/"
|
||||||
"issues\n"
|
"issues\n"
|
||||||
"POT-Creation-Date: 2025-11-04 15:35+0000\n"
|
"POT-Creation-Date: 2026-04-08 13:01+0000\n"
|
||||||
"PO-Revision-Date: 2025-11-05 07:47+0800\n"
|
"PO-Revision-Date: 2026-04-09 08:06+0800\n"
|
||||||
"Last-Translator: lumingzh <lumingzh@qq.com>\n"
|
"Last-Translator: lumingzh <lumingzh@qq.com>\n"
|
||||||
"Language-Team: Chinese (China) <i18n-zh@googlegroups.com>\n"
|
"Language-Team: Chinese (China) <i18n-zh@googlegroups.com>\n"
|
||||||
"Language: zh_CN\n"
|
"Language: zh_CN\n"
|
||||||
|
|
@ -22,7 +22,7 @@ msgstr ""
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Launchpad-Export-Date: 2016-03-22 13:23+0000\n"
|
"X-Launchpad-Export-Date: 2016-03-22 13:23+0000\n"
|
||||||
"X-Generator: Gtranslator 49.0\n"
|
"X-Generator: Gtranslator 50.0\n"
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.c:29
|
#: src/daemon/pipewire.c:29
|
||||||
|
|
@ -65,21 +65,46 @@ msgstr "虚拟输出"
|
||||||
msgid "Tunnel for %s@%s"
|
msgid "Tunnel for %s@%s"
|
||||||
msgstr "用于 %s@%s 的隧道"
|
msgstr "用于 %s@%s 的隧道"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:320
|
#: src/modules/module-zeroconf-discover.c:290
|
||||||
msgid "Unknown device"
|
msgid "Unknown device"
|
||||||
msgstr "未知设备"
|
msgstr "未知设备"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:332
|
#: src/modules/module-zeroconf-discover.c:302
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s on %s@%s"
|
msgid "%s on %s@%s"
|
||||||
msgstr "%2$s@%3$s 上的 %1$s"
|
msgstr "%2$s@%3$s 上的 %1$s"
|
||||||
|
|
||||||
#: src/modules/module-zeroconf-discover.c:336
|
#: src/modules/module-zeroconf-discover.c:306
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s on %s"
|
msgid "%s on %s"
|
||||||
msgstr "%2$s 上的 %1$s"
|
msgstr "%2$s 上的 %1$s"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1096
|
#: src/tools/pw-cat.c:269
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported formats:\n"
|
||||||
|
msgstr "支持的格式:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:754
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layouts:\n"
|
||||||
|
msgstr "支持的声道布局:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:764
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layout aliases:\n"
|
||||||
|
msgstr "支持的声道布局别名:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:766
|
||||||
|
#, c-format
|
||||||
|
msgid " %s -> %s\n"
|
||||||
|
msgstr " %s -> %s\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:771
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel names:\n"
|
||||||
|
msgstr "支持的声道名称:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:1183
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] [<file>|-]\n"
|
"%s [options] [<file>|-]\n"
|
||||||
|
|
@ -94,7 +119,7 @@ msgstr ""
|
||||||
" -v, --verbose 输出详细操作\n"
|
" -v, --verbose 输出详细操作\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1103
|
#: src/tools/pw-cat.c:1190
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" -R, --remote Remote daemon name\n"
|
" -R, --remote Remote daemon name\n"
|
||||||
|
|
@ -104,6 +129,8 @@ msgid ""
|
||||||
" --target Set node target serial or name "
|
" --target Set node target serial or name "
|
||||||
"(default %s)\n"
|
"(default %s)\n"
|
||||||
" 0 means don't link\n"
|
" 0 means don't link\n"
|
||||||
|
" -C --monitor Capture monitor ports (in recording "
|
||||||
|
"mode)\n"
|
||||||
" --latency Set node latency (default %s)\n"
|
" --latency Set node latency (default %s)\n"
|
||||||
" Xunit (unit = s, ms, us, ns)\n"
|
" Xunit (unit = s, ms, us, ns)\n"
|
||||||
" or direct samples (256)\n"
|
" or direct samples (256)\n"
|
||||||
|
|
@ -118,6 +145,7 @@ msgstr ""
|
||||||
" --media-role 设置媒体角色 (默认 %s)\n"
|
" --media-role 设置媒体角色 (默认 %s)\n"
|
||||||
" --target 设置节点目标序列或名称 (默认 %s)\n"
|
" --target 设置节点目标序列或名称 (默认 %s)\n"
|
||||||
" 设为 0 则不链接节点\n"
|
" 设为 0 则不链接节点\n"
|
||||||
|
" -C --monitor 捕获监视器端口 (录制模式)\n"
|
||||||
" --latency 设置节点延迟 (默认 %s)\n"
|
" --latency 设置节点延迟 (默认 %s)\n"
|
||||||
" 时间 (单位可为 s, ms, us, ns)\n"
|
" 时间 (单位可为 s, ms, us, ns)\n"
|
||||||
" 或样本数 (如256)\n"
|
" 或样本数 (如256)\n"
|
||||||
|
|
@ -126,20 +154,23 @@ msgstr ""
|
||||||
" -P --properties 设置节点属性\n"
|
" -P --properties 设置节点属性\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1121
|
#: src/tools/pw-cat.c:1209
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" --rate Sample rate (req. for rec) (default "
|
" --rate Sample rate (default %u)\n"
|
||||||
"%u)\n"
|
" --channels Number of channels (default %u)\n"
|
||||||
" --channels Number of channels (req. for rec) "
|
|
||||||
"(default %u)\n"
|
|
||||||
" --channel-map Channel map\n"
|
" --channel-map Channel map\n"
|
||||||
" one of: \"stereo\", "
|
" a channel layout: \"Stereo\", "
|
||||||
"\"surround-51\",... or\n"
|
"\"5.1\",... or\n"
|
||||||
" comma separated list of channel "
|
" comma separated list of channel "
|
||||||
"names: eg. \"FL,FR\"\n"
|
"names: eg. \"FL,FR\"\n"
|
||||||
" --format Sample format %s (req. for rec) "
|
" --list-layouts List supported channel layouts\n"
|
||||||
"(default %s)\n"
|
" --list-channel-names List supported channel maps\n"
|
||||||
|
" --format Sample format (default %s)\n"
|
||||||
|
" --list-formats List supported sample formats\n"
|
||||||
|
" --container Container format\n"
|
||||||
|
" --list-containers List supported containers and "
|
||||||
|
"extensions\n"
|
||||||
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
||||||
" -q --quality Resampler quality (0 - 15) (default "
|
" -q --quality Resampler quality (0 - 15) (default "
|
||||||
"%d)\n"
|
"%d)\n"
|
||||||
|
|
@ -149,15 +180,19 @@ msgid ""
|
||||||
" -n, --sample-count COUNT Stop after COUNT samples\n"
|
" -n, --sample-count COUNT Stop after COUNT samples\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
" --rate 采样率 (录制模式需要) (默认 %u)\n"
|
" --rate 采样率 (默认 %u)\n"
|
||||||
" --channels 通道数 (录制模式需要) (默认 %u)\n"
|
" --channels 声道数 (默认 %u)\n"
|
||||||
" --channel-map 通道映射\n"
|
" --channel-map 声道映射\n"
|
||||||
" \"stereo\", \"surround-51\",... "
|
" 声道布局:\"stereo\", "
|
||||||
"中的其一或\n"
|
"\"5.1\",... 或\n"
|
||||||
" 以\",\"分隔的通道名列表: 如 "
|
" 以英文逗号分隔的声道名列表: 如 "
|
||||||
"\"FL,FR\"\n"
|
"\"FL,FR\"\n"
|
||||||
" --format 采样格式 %s (录制模式需要) (默认 "
|
" --list-layouts 列出支持的声道布局\n"
|
||||||
"%s)\n"
|
" --list-channel-names 列出支持的声道映射\n"
|
||||||
|
" --format 采样格式 (默认 %s)\n"
|
||||||
|
" --list-formats 列出支持的采样格式\n"
|
||||||
|
" --container 容器格式\n"
|
||||||
|
" --list-containers 列出支持的容器和扩展\n"
|
||||||
" --volume 媒体流音量 0-1.0 (默认 %.3f)\n"
|
" --volume 媒体流音量 0-1.0 (默认 %.3f)\n"
|
||||||
" -q --quality 重采样质量 (0 - 15) (默认 %d)\n"
|
" -q --quality 重采样质量 (0 - 15) (默认 %d)\n"
|
||||||
" -a, --raw 原生模式\n"
|
" -a, --raw 原生模式\n"
|
||||||
|
|
@ -166,7 +201,7 @@ msgstr ""
|
||||||
" -n, --sample-count COUNT 计数采样后停止\n"
|
" -n, --sample-count COUNT 计数采样后停止\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1141
|
#: src/tools/pw-cat.c:1234
|
||||||
msgid ""
|
msgid ""
|
||||||
" -p, --playback Playback mode\n"
|
" -p, --playback Playback mode\n"
|
||||||
" -r, --record Recording mode\n"
|
" -r, --record Recording mode\n"
|
||||||
|
|
@ -186,6 +221,11 @@ msgstr ""
|
||||||
" -c, --midi-clip MIDI 剪辑模式\n"
|
" -c, --midi-clip MIDI 剪辑模式\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:1839
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported containers and extensions:\n"
|
||||||
|
msgstr "支持的容器和扩展:\n"
|
||||||
|
|
||||||
#: src/tools/pw-cli.c:2386
|
#: src/tools/pw-cli.c:2386
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
|
|
@ -208,12 +248,12 @@ msgstr ""
|
||||||
msgid "Pro Audio"
|
msgid "Pro Audio"
|
||||||
msgstr "专业音频"
|
msgstr "专业音频"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:537 spa/plugins/alsa/acp/alsa-mixer.c:4699
|
#: spa/plugins/alsa/acp/acp.c:535 spa/plugins/alsa/acp/alsa-mixer.c:4699
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1976
|
#: spa/plugins/bluez5/bluez5-device.c:2163
|
||||||
msgid "Off"
|
msgid "Off"
|
||||||
msgstr "关"
|
msgstr "关"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:620
|
#: spa/plugins/alsa/acp/acp.c:618
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s [ALSA UCM error]"
|
msgid "%s [ALSA UCM error]"
|
||||||
msgstr "%s [ALSA UCM 错误]"
|
msgstr "%s [ALSA UCM 错误]"
|
||||||
|
|
@ -241,7 +281,7 @@ msgstr "输入插孔"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2374
|
#: spa/plugins/bluez5/bluez5-device.c:2596
|
||||||
msgid "Microphone"
|
msgid "Microphone"
|
||||||
msgstr "话筒"
|
msgstr "话筒"
|
||||||
|
|
||||||
|
|
@ -307,15 +347,15 @@ msgid "No Bass Boost"
|
||||||
msgstr "无重低音增强"
|
msgstr "无重低音增强"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2380
|
#: spa/plugins/bluez5/bluez5-device.c:2602
|
||||||
msgid "Speaker"
|
msgid "Speaker"
|
||||||
msgstr "扬声器"
|
msgstr "扬声器"
|
||||||
|
|
||||||
#. Don't call it "headset", the HF one has the mic
|
#. Don't call it "headset", the HF one has the mic
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2386
|
#: spa/plugins/bluez5/bluez5-device.c:2608
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2453
|
#: spa/plugins/bluez5/bluez5-device.c:2675
|
||||||
msgid "Headphones"
|
msgid "Headphones"
|
||||||
msgstr "模拟耳机"
|
msgstr "模拟耳机"
|
||||||
|
|
||||||
|
|
@ -425,7 +465,7 @@ msgstr "立体声"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4535
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4535
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4693
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4693
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2362
|
#: spa/plugins/bluez5/bluez5-device.c:2584
|
||||||
msgid "Headset"
|
msgid "Headset"
|
||||||
msgstr "耳机"
|
msgstr "耳机"
|
||||||
|
|
||||||
|
|
@ -620,101 +660,109 @@ msgstr "内置音频"
|
||||||
msgid "Modem"
|
msgid "Modem"
|
||||||
msgstr "调制解调器"
|
msgstr "调制解调器"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1987
|
#: spa/plugins/bluez5/bluez5-device.c:2174
|
||||||
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
||||||
msgstr "音频网关 (A2DP 信源 或 HSP/HFP 网关)"
|
msgstr "音频网关 (A2DP 信源 或 HSP/HFP 网关)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2016
|
#: spa/plugins/bluez5/bluez5-device.c:2203
|
||||||
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
||||||
msgstr "助听器音频流 (ASHA 信宿)"
|
msgstr "助听器音频流 (ASHA 信宿)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2059
|
#: spa/plugins/bluez5/bluez5-device.c:2246
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
||||||
msgstr "高保真回放 (A2DP 信宿, 编码 %s)"
|
msgstr "高保真回放 (A2DP 信宿, 编码 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2062
|
#: spa/plugins/bluez5/bluez5-device.c:2249
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
||||||
msgstr "高保真双工 (A2DP 信源/信宿, 编码 %s)"
|
msgstr "高保真双工 (A2DP 信源/信宿, 编码 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2070
|
#: spa/plugins/bluez5/bluez5-device.c:2257
|
||||||
msgid "High Fidelity Playback (A2DP Sink)"
|
msgid "High Fidelity Playback (A2DP Sink)"
|
||||||
msgstr "高保真回放 (A2DP 信宿)"
|
msgstr "高保真回放 (A2DP 信宿)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2072
|
#: spa/plugins/bluez5/bluez5-device.c:2259
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
||||||
msgstr "高保真双工 (A2DP 信源/信宿)"
|
msgstr "高保真双工 (A2DP 信源/信宿)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2146
|
#: spa/plugins/bluez5/bluez5-device.c:2281
|
||||||
|
msgid "Auto: Prefer Quality (A2DP)"
|
||||||
|
msgstr "自动:质量优先 (A2DP)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2286
|
||||||
|
msgid "Auto: Prefer Latency (A2DP)"
|
||||||
|
msgstr "自动:延迟优先 (A2DP)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2366
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
||||||
msgstr "高保真回放 (BAP 信宿, 编码 %s)"
|
msgstr "高保真回放 (BAP 信宿, 编码 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2151
|
#: spa/plugins/bluez5/bluez5-device.c:2371
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Input (BAP Source, codec %s)"
|
msgid "High Fidelity Input (BAP Source, codec %s)"
|
||||||
msgstr "高保真输入 (BAP 信源, 编码 %s)"
|
msgstr "高保真输入 (BAP 信源, 编码 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2155
|
#: spa/plugins/bluez5/bluez5-device.c:2375
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
||||||
msgstr "高保真双工 (BAP 信源/信宿, 编码 %s)"
|
msgstr "高保真双工 (BAP 信源/信宿, 编码 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2164
|
#: spa/plugins/bluez5/bluez5-device.c:2384
|
||||||
msgid "High Fidelity Playback (BAP Sink)"
|
msgid "High Fidelity Playback (BAP Sink)"
|
||||||
msgstr "高保真回放 (BAP 信宿)"
|
msgstr "高保真回放 (BAP 信宿)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2168
|
#: spa/plugins/bluez5/bluez5-device.c:2388
|
||||||
msgid "High Fidelity Input (BAP Source)"
|
msgid "High Fidelity Input (BAP Source)"
|
||||||
msgstr "高保真输入 (BAP 信源)"
|
msgstr "高保真输入 (BAP 信源)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2171
|
#: spa/plugins/bluez5/bluez5-device.c:2391
|
||||||
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
||||||
msgstr "高保真双工 (BAP 信源/信宿)"
|
msgstr "高保真双工 (BAP 信源/信宿)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2211
|
#: spa/plugins/bluez5/bluez5-device.c:2431
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
||||||
msgstr "头戴式耳机单元 (HSP/HFP, 编码 %s)"
|
msgstr "头戴式耳机单元 (HSP/HFP, 编码 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2363
|
#: spa/plugins/bluez5/bluez5-device.c:2585
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2368
|
#: spa/plugins/bluez5/bluez5-device.c:2590
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2375
|
#: spa/plugins/bluez5/bluez5-device.c:2597
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2381
|
#: spa/plugins/bluez5/bluez5-device.c:2603
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2387
|
#: spa/plugins/bluez5/bluez5-device.c:2609
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2393
|
#: spa/plugins/bluez5/bluez5-device.c:2615
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2399
|
#: spa/plugins/bluez5/bluez5-device.c:2621
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2405
|
#: spa/plugins/bluez5/bluez5-device.c:2627
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2411
|
#: spa/plugins/bluez5/bluez5-device.c:2633
|
||||||
msgid "Handsfree"
|
msgid "Handsfree"
|
||||||
msgstr "免提"
|
msgstr "免提"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2369
|
#: spa/plugins/bluez5/bluez5-device.c:2591
|
||||||
msgid "Handsfree (HFP)"
|
msgid "Handsfree (HFP)"
|
||||||
msgstr "免提(HFP)"
|
msgstr "免提(HFP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2392
|
#: spa/plugins/bluez5/bluez5-device.c:2614
|
||||||
msgid "Portable"
|
msgid "Portable"
|
||||||
msgstr "便携式"
|
msgstr "便携式"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2398
|
#: spa/plugins/bluez5/bluez5-device.c:2620
|
||||||
msgid "Car"
|
msgid "Car"
|
||||||
msgstr "车内"
|
msgstr "车内"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2404
|
#: spa/plugins/bluez5/bluez5-device.c:2626
|
||||||
msgid "HiFi"
|
msgid "HiFi"
|
||||||
msgstr "高保真"
|
msgstr "高保真"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2410
|
#: spa/plugins/bluez5/bluez5-device.c:2632
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "电话"
|
msgstr "电话"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2417
|
#: spa/plugins/bluez5/bluez5-device.c:2639
|
||||||
msgid "Bluetooth"
|
msgid "Bluetooth"
|
||||||
msgstr "蓝牙"
|
msgstr "蓝牙"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:2418
|
#: spa/plugins/bluez5/bluez5-device.c:2640
|
||||||
msgid "Bluetooth Handsfree"
|
msgid "Bluetooth Handsfree"
|
||||||
msgstr "蓝牙免提"
|
msgstr "蓝牙免提"
|
||||||
|
|
||||||
|
|
|
||||||
540
po/zh_TW.po
540
po/zh_TW.po
|
|
@ -4,110 +4,221 @@
|
||||||
#
|
#
|
||||||
# Cheng-Chia Tseng <pswo10680@gmail.com>, 2010, 2012.
|
# Cheng-Chia Tseng <pswo10680@gmail.com>, 2010, 2012.
|
||||||
# pan93412 <pan93412@gmail.com>, 2020.
|
# pan93412 <pan93412@gmail.com>, 2020.
|
||||||
|
# SPDX-FileCopyrightText: 2026 Kisaragi Hiu <mail@kisaragi-hiu.com>
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: PipeWire Volume Control\n"
|
"Project-Id-Version: PipeWire Volume Control\n"
|
||||||
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
|
"Report-Msgid-Bugs-To: https://gitlab.freedesktop.org/pipewire/pipewire/"
|
||||||
"issues/new\n"
|
"issues/new\n"
|
||||||
"POT-Creation-Date: 2021-04-18 16:54+0800\n"
|
"POT-Creation-Date: 2026-03-11 22:03+0900\n"
|
||||||
"PO-Revision-Date: 2020-01-11 13:49+0800\n"
|
"PO-Revision-Date: 2026-03-11 21:24+0900\n"
|
||||||
"Last-Translator: pan93412 <pan93412@gmail.com>\n"
|
"Last-Translator: Kisaragi Hiu <mail@kisaragi-hiu.com>\n"
|
||||||
"Language-Team: Chinese <zh-l10n@lists.linux.org.tw>\n"
|
"Language-Team: Chinese (Taiwan) <zh-l10n@lists.slat.org>\n"
|
||||||
"Language: zh_TW\n"
|
"Language: zh_TW\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"X-Generator: Lokalize 19.12.0\n"
|
"X-Generator: Lokalize 26.03.70\n"
|
||||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.c:43
|
#: src/daemon/pipewire.c:29
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options]\n"
|
"%s [options]\n"
|
||||||
" -h, --help Show this help\n"
|
" -h, --help Show this help\n"
|
||||||
|
" -v, --verbose Increase verbosity by one level\n"
|
||||||
" --version Show version\n"
|
" --version Show version\n"
|
||||||
" -c, --config Load config (Default %s)\n"
|
" -c, --config Load config (Default %s)\n"
|
||||||
|
" -P --properties Set context properties\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%s [選項]\n"
|
||||||
|
" -h, --help 顯示此說明\n"
|
||||||
|
" -v, --verbose 提高訊息詳細程度一階\n"
|
||||||
|
" --version 顯示版本\n"
|
||||||
|
" -c, --config 載入設定檔案(預設 %s)\n"
|
||||||
|
" -P --properties 設定前後文屬性\n"
|
||||||
|
|
||||||
#: src/daemon/pipewire.desktop.in:4
|
#: src/daemon/pipewire.desktop.in:4
|
||||||
msgid "PipeWire Media System"
|
msgid "PipeWire Media System"
|
||||||
msgstr ""
|
msgstr "PipeWire 媒體系統"
|
||||||
|
|
||||||
#: src/daemon/pipewire.desktop.in:5
|
#: src/daemon/pipewire.desktop.in:5
|
||||||
msgid "Start the PipeWire Media System"
|
msgid "Start the PipeWire Media System"
|
||||||
msgstr ""
|
msgstr "啟動 PipeWire 媒體系統"
|
||||||
|
|
||||||
#: src/examples/media-session/alsa-monitor.c:526
|
#: src/modules/module-protocol-pulse/modules/module-tunnel-sink.c:159
|
||||||
#: spa/plugins/alsa/acp/compat.c:187
|
#: src/modules/module-protocol-pulse/modules/module-tunnel-source.c:159
|
||||||
msgid "Built-in Audio"
|
#, c-format
|
||||||
msgstr "內部音效"
|
msgid "Tunnel to %s%s%s"
|
||||||
|
msgstr "穿隧到 %s%s%s"
|
||||||
|
|
||||||
#: src/examples/media-session/alsa-monitor.c:530
|
#: src/modules/module-fallback-sink.c:40
|
||||||
#: spa/plugins/alsa/acp/compat.c:192
|
msgid "Dummy Output"
|
||||||
msgid "Modem"
|
msgstr "虛擬輸出"
|
||||||
msgstr "數據機"
|
|
||||||
|
|
||||||
#: src/examples/media-session/alsa-monitor.c:539
|
#: src/modules/module-pulse-tunnel.c:761
|
||||||
|
#, c-format
|
||||||
|
msgid "Tunnel for %s@%s"
|
||||||
|
msgstr "%s@%s 的穿隧道"
|
||||||
|
|
||||||
|
#: src/modules/module-zeroconf-discover.c:290
|
||||||
msgid "Unknown device"
|
msgid "Unknown device"
|
||||||
msgstr ""
|
msgstr "未知裝置"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:991
|
#: src/modules/module-zeroconf-discover.c:302
|
||||||
|
#, c-format
|
||||||
|
msgid "%s on %s@%s"
|
||||||
|
msgstr "%s 於 %s@%s"
|
||||||
|
|
||||||
|
#: src/modules/module-zeroconf-discover.c:306
|
||||||
|
#, c-format
|
||||||
|
msgid "%s on %s"
|
||||||
|
msgstr "%s 於 %s"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:269
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported formats:\n"
|
||||||
|
msgstr "支援的格式:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:754
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layouts:\n"
|
||||||
|
msgstr "支援的頻道配置:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:764
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel layout aliases:\n"
|
||||||
|
msgstr "支援的頻道配置別名:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:766
|
||||||
|
#, c-format
|
||||||
|
msgid " %s -> %s\n"
|
||||||
|
msgstr " %s -> %s\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:771
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported channel names:\n"
|
||||||
|
msgstr "支援的頻道名稱:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cat.c:1182
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] <file>\n"
|
"%s [options] [<file>|-]\n"
|
||||||
" -h, --help Show this help\n"
|
" -h, --help Show this help\n"
|
||||||
" --version Show version\n"
|
" --version Show version\n"
|
||||||
" -v, --verbose Enable verbose operations\n"
|
" -v, --verbose Enable verbose operations\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%s [選項] [<檔案>|-]\n"
|
||||||
|
" -h, --help 顯示此說明\n"
|
||||||
|
" --version 顯示版本\n"
|
||||||
|
" -v, --verbose 操作進行時顯示詳細訊息\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:998
|
#: src/tools/pw-cat.c:1189
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" -R, --remote Remote daemon name\n"
|
" -R, --remote Remote daemon name\n"
|
||||||
" --media-type Set media type (default %s)\n"
|
" --media-type Set media type (default %s)\n"
|
||||||
" --media-category Set media category (default %s)\n"
|
" --media-category Set media category (default %s)\n"
|
||||||
" --media-role Set media role (default %s)\n"
|
" --media-role Set media role (default %s)\n"
|
||||||
" --target Set node target (default %s)\n"
|
" --target Set node target serial or name "
|
||||||
|
"(default %s)\n"
|
||||||
" 0 means don't link\n"
|
" 0 means don't link\n"
|
||||||
" --latency Set node latency (default %s)\n"
|
" --latency Set node latency (default %s)\n"
|
||||||
" Xunit (unit = s, ms, us, ns)\n"
|
" Xunit (unit = s, ms, us, ns)\n"
|
||||||
" or direct samples (256)\n"
|
" or direct samples (256)\n"
|
||||||
" the rate is the one of the source "
|
" the rate is the one of the source "
|
||||||
"file\n"
|
"file\n"
|
||||||
" --list-targets List available targets for --target\n"
|
" -P --properties Set node properties\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
" -R, --remote 遠端守護程式名稱\n"
|
||||||
|
" --media-type 設定媒體型態(預設 %s)\n"
|
||||||
|
" --media-category 設定媒體分類(預設 %s)\n"
|
||||||
|
" --media-role 設定媒體角色(預設 %s)\n"
|
||||||
|
" --target 設定節點目標序號或名稱(預設 %s)\n"
|
||||||
|
" 0 代表不要連結\n"
|
||||||
|
" --latency 設定節點延遲(預設 %s)\n"
|
||||||
|
" X單位(單位為 s, ms, us 或 ns)\n"
|
||||||
|
" 或直接指定樣本數 (256)\n"
|
||||||
|
" 取樣率取自來源檔案\n"
|
||||||
|
" -P --properties 設定節點屬性\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1016
|
#: src/tools/pw-cat.c:1207
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
" --rate Sample rate (req. for rec) (default "
|
" --rate Sample rate (default %u)\n"
|
||||||
"%u)\n"
|
" --channels Number of channels (default %u)\n"
|
||||||
" --channels Number of channels (req. for rec) "
|
|
||||||
"(default %u)\n"
|
|
||||||
" --channel-map Channel map\n"
|
" --channel-map Channel map\n"
|
||||||
" one of: \"stereo\", "
|
" a channel layout: \"Stereo\", "
|
||||||
"\"surround-51\",... or\n"
|
"\"5.1\",... or\n"
|
||||||
" comma separated list of channel "
|
" comma separated list of channel "
|
||||||
"names: eg. \"FL,FR\"\n"
|
"names: eg. \"FL,FR\"\n"
|
||||||
" --format Sample format %s (req. for rec) "
|
" --list-layouts List supported channel layouts\n"
|
||||||
"(default %s)\n"
|
" --list-channel-names List supported channel maps\n"
|
||||||
|
" --format Sample format (default %s)\n"
|
||||||
|
" --list-formats List supported sample formats\n"
|
||||||
|
" --container Container format\n"
|
||||||
|
" --list-containers List supported containers and "
|
||||||
|
"extensions\n"
|
||||||
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
" --volume Stream volume 0-1.0 (default %.3f)\n"
|
||||||
" -q --quality Resampler quality (0 - 15) (default "
|
" -q --quality Resampler quality (0 - 15) (default "
|
||||||
"%d)\n"
|
"%d)\n"
|
||||||
|
" -a, --raw RAW mode\n"
|
||||||
|
" -M, --force-midi Force midi format, one of \"midi\" "
|
||||||
|
"or \"ump\", (default ump)\n"
|
||||||
|
" -n, --sample-count COUNT Stop after COUNT samples\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
" --rate 取樣率(預設 %u)\n"
|
||||||
|
" --channels 頻道數量(預設 %u)\n"
|
||||||
|
" --channel-map 頻道映射\n"
|
||||||
|
" 可以是頻道配置名稱,像是 "
|
||||||
|
"\"Stereo\"、\"5.1\" 等等,或是\n"
|
||||||
|
" 以逗號分隔的頻道名稱清單,像是 "
|
||||||
|
"\"FL,FR\"\n"
|
||||||
|
" --list-layouts 列出支援的頻道配置\n"
|
||||||
|
" --list-channel-names 列出支援的頻道映射\n"
|
||||||
|
" --format 取樣格式(預設 %s)\n"
|
||||||
|
" --list-formats 列出支援的取樣格式\n"
|
||||||
|
" --container 容器格式\n"
|
||||||
|
" --list-containers 列出支援的容器與副檔名\n"
|
||||||
|
" --volume 串流音量 0-1.0(預設 %.3f)\n"
|
||||||
|
" -q --quality 重新取樣器品質 0-15(預設 %d)\n"
|
||||||
|
" -a, --raw 原始模式\n"
|
||||||
|
" -M, --force-midi 強制使用 midi 格式,可選擇 \"midi\" "
|
||||||
|
"或 \"ump\"(預設 ump)\n"
|
||||||
|
" -n, --sample-count 樣本數 在「樣本數」個樣本之後停止\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cat.c:1033
|
#: src/tools/pw-cat.c:1232
|
||||||
msgid ""
|
msgid ""
|
||||||
" -p, --playback Playback mode\n"
|
" -p, --playback Playback mode\n"
|
||||||
" -r, --record Recording mode\n"
|
" -r, --record Recording mode\n"
|
||||||
" -m, --midi Midi mode\n"
|
" -m, --midi Midi mode\n"
|
||||||
|
" -d, --dsd DSD mode\n"
|
||||||
|
" -o, --encoded Encoded mode\n"
|
||||||
|
" -s, --sysex SysEx mode\n"
|
||||||
|
" -c, --midi-clip MIDI clip mode\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
" -p, --playback 播放模式\n"
|
||||||
|
" -r, --record 錄製模式\n"
|
||||||
|
" -m, --midi Midi 模式\n"
|
||||||
|
" -d, --dsd DSD 模式\n"
|
||||||
|
" -o, --encoded 已編碼模式\n"
|
||||||
|
" -s, --sysex SysEx 模式\n"
|
||||||
|
" -c, --midi-clip MIDI 素材模式\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: src/tools/pw-cli.c:2932
|
#: src/tools/pw-cat.c:1837
|
||||||
|
#, c-format
|
||||||
|
msgid "Supported containers and extensions:\n"
|
||||||
|
msgstr "支援的容器與副檔名:\n"
|
||||||
|
|
||||||
|
#: src/tools/pw-cli.c:2386
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"%s [options] [command]\n"
|
"%s [options] [command]\n"
|
||||||
|
|
@ -115,357 +226,363 @@ msgid ""
|
||||||
" --version Show version\n"
|
" --version Show version\n"
|
||||||
" -d, --daemon Start as daemon (Default false)\n"
|
" -d, --daemon Start as daemon (Default false)\n"
|
||||||
" -r, --remote Remote daemon name\n"
|
" -r, --remote Remote daemon name\n"
|
||||||
|
" -m, --monitor Monitor activity\n"
|
||||||
"\n"
|
"\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
"%s [選項] [指令]\n"
|
||||||
|
" -h, --help 顯示此說明\n"
|
||||||
|
" --version 顯示版本\n"
|
||||||
|
" -d, --daemon 作為守護程式啟動(預設為否)\n"
|
||||||
|
" -r, --remote 遠端守護程式名稱\n"
|
||||||
|
" -m, --monitor 監控活動\n"
|
||||||
|
"\n"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:290
|
#: spa/plugins/alsa/acp/acp.c:361
|
||||||
msgid "Pro Audio"
|
msgid "Pro Audio"
|
||||||
msgstr ""
|
msgstr "Pro Audio"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/acp.c:411 spa/plugins/alsa/acp/alsa-mixer.c:4704
|
#: spa/plugins/alsa/acp/acp.c:535 spa/plugins/alsa/acp/alsa-mixer.c:4699
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1000
|
#: spa/plugins/bluez5/bluez5-device.c:2021
|
||||||
msgid "Off"
|
msgid "Off"
|
||||||
msgstr "關閉"
|
msgstr "關閉"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/channelmap.h:466
|
#: spa/plugins/alsa/acp/acp.c:618
|
||||||
msgid "(invalid)"
|
#, c-format
|
||||||
msgstr "(無效)"
|
msgid "%s [ALSA UCM error]"
|
||||||
|
msgstr "%s [ALSA UCM 錯誤]"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2709
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2721
|
||||||
msgid "Input"
|
msgid "Input"
|
||||||
msgstr "輸入"
|
msgstr "輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2710
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2722
|
||||||
msgid "Docking Station Input"
|
msgid "Docking Station Input"
|
||||||
msgstr "Docking Station 輸入"
|
msgstr "Docking Station 輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2711
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2723
|
||||||
msgid "Docking Station Microphone"
|
msgid "Docking Station Microphone"
|
||||||
msgstr "Docking Station 麥克風"
|
msgstr "Docking Station 麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2712
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2724
|
||||||
msgid "Docking Station Line In"
|
msgid "Docking Station Line In"
|
||||||
msgstr "Docking Station 線路輸入"
|
msgstr "Docking Station 線路輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2713
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2725
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2804
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2816
|
||||||
msgid "Line In"
|
msgid "Line In"
|
||||||
msgstr "線路輸入"
|
msgstr "線路輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2714
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2798
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1145
|
#: spa/plugins/bluez5/bluez5-device.c:2422
|
||||||
msgid "Microphone"
|
msgid "Microphone"
|
||||||
msgstr "麥克風"
|
msgstr "麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2715
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2727
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2799
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2811
|
||||||
msgid "Front Microphone"
|
msgid "Front Microphone"
|
||||||
msgstr "前方麥克風"
|
msgstr "前方麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2716
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2728
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2800
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2812
|
||||||
msgid "Rear Microphone"
|
msgid "Rear Microphone"
|
||||||
msgstr "後方麥克風"
|
msgstr "後方麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2717
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2729
|
||||||
msgid "External Microphone"
|
msgid "External Microphone"
|
||||||
msgstr "外接麥克風"
|
msgstr "外接麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2718
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2730
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2802
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2814
|
||||||
msgid "Internal Microphone"
|
msgid "Internal Microphone"
|
||||||
msgstr "內建麥克風"
|
msgstr "內建麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2719
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2731
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2805
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2817
|
||||||
msgid "Radio"
|
msgid "Radio"
|
||||||
msgstr "無線電"
|
msgstr "無線電"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2720
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2732
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2806
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2818
|
||||||
msgid "Video"
|
msgid "Video"
|
||||||
msgstr "視訊"
|
msgstr "視訊"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2721
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2733
|
||||||
msgid "Automatic Gain Control"
|
msgid "Automatic Gain Control"
|
||||||
msgstr "自動增益控制"
|
msgstr "自動增益控制"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2722
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2734
|
||||||
msgid "No Automatic Gain Control"
|
msgid "No Automatic Gain Control"
|
||||||
msgstr "無自動增益控制"
|
msgstr "無自動增益控制"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2723
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2735
|
||||||
msgid "Boost"
|
msgid "Boost"
|
||||||
msgstr "增強"
|
msgstr "增強"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2724
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2736
|
||||||
msgid "No Boost"
|
msgid "No Boost"
|
||||||
msgstr "無增強"
|
msgstr "無增強"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2725
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2737
|
||||||
msgid "Amplifier"
|
msgid "Amplifier"
|
||||||
msgstr "擴大器"
|
msgstr "擴大器"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2726
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2738
|
||||||
msgid "No Amplifier"
|
msgid "No Amplifier"
|
||||||
msgstr "無擴大器"
|
msgstr "無擴大器"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2727
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2739
|
||||||
msgid "Bass Boost"
|
msgid "Bass Boost"
|
||||||
msgstr "低音增強"
|
msgstr "低音增強"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2728
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2740
|
||||||
msgid "No Bass Boost"
|
msgid "No Bass Boost"
|
||||||
msgstr "無低音增強"
|
msgstr "無低音增強"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2729
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2741
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1150
|
#: spa/plugins/bluez5/bluez5-device.c:2428
|
||||||
msgid "Speaker"
|
msgid "Speaker"
|
||||||
msgstr "喇叭"
|
msgstr "喇叭"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2730
|
#. Don't call it "headset", the HF one has the mic
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2808
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2742
|
||||||
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2434
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2501
|
||||||
msgid "Headphones"
|
msgid "Headphones"
|
||||||
msgstr "頭戴式耳機"
|
msgstr "頭戴式耳機"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2797
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2809
|
||||||
msgid "Analog Input"
|
msgid "Analog Input"
|
||||||
msgstr "類比輸入"
|
msgstr "類比輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2801
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2813
|
||||||
msgid "Dock Microphone"
|
msgid "Dock Microphone"
|
||||||
msgstr "臺座麥克風"
|
msgstr "臺座麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2803
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2815
|
||||||
msgid "Headset Microphone"
|
msgid "Headset Microphone"
|
||||||
msgstr "耳麥麥克風"
|
msgstr "耳麥麥克風"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2807
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2819
|
||||||
msgid "Analog Output"
|
msgid "Analog Output"
|
||||||
msgstr "類比輸出"
|
msgstr "類比輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2809
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2821
|
||||||
#, fuzzy
|
|
||||||
msgid "Headphones 2"
|
msgid "Headphones 2"
|
||||||
msgstr "頭戴式耳機"
|
msgstr "頭戴式耳機 2"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2810
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2822
|
||||||
msgid "Headphones Mono Output"
|
msgid "Headphones Mono Output"
|
||||||
msgstr "頭戴式耳機單聲道輸出"
|
msgstr "頭戴式耳機單聲道輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2811
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2823
|
||||||
msgid "Line Out"
|
msgid "Line Out"
|
||||||
msgstr "線路輸出"
|
msgstr "線路輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2812
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2824
|
||||||
msgid "Analog Mono Output"
|
msgid "Analog Mono Output"
|
||||||
msgstr "類比單聲道輸出"
|
msgstr "類比單聲道輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2813
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2825
|
||||||
msgid "Speakers"
|
msgid "Speakers"
|
||||||
msgstr "喇叭"
|
msgstr "喇叭"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2814
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2826
|
||||||
msgid "HDMI / DisplayPort"
|
msgid "HDMI / DisplayPort"
|
||||||
msgstr "HDMI / DisplayPort"
|
msgstr "HDMI / DisplayPort"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2815
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2827
|
||||||
msgid "Digital Output (S/PDIF)"
|
msgid "Digital Output (S/PDIF)"
|
||||||
msgstr "數位輸出 (S/PDIF)"
|
msgstr "數位輸出 (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2816
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2828
|
||||||
msgid "Digital Input (S/PDIF)"
|
msgid "Digital Input (S/PDIF)"
|
||||||
msgstr "數位輸入 (S/PDIF)"
|
msgstr "數位輸入 (S/PDIF)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2817
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2829
|
||||||
msgid "Multichannel Input"
|
msgid "Multichannel Input"
|
||||||
msgstr "多聲道輸入"
|
msgstr "多聲道輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2818
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2830
|
||||||
msgid "Multichannel Output"
|
msgid "Multichannel Output"
|
||||||
msgstr "多聲道輸出"
|
msgstr "多聲道輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2819
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2831
|
||||||
msgid "Game Output"
|
msgid "Game Output"
|
||||||
msgstr "遊戲輸出"
|
msgstr "遊戲輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2820
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2832
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2821
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2833
|
||||||
msgid "Chat Output"
|
msgid "Chat Output"
|
||||||
msgstr "聊天輸出"
|
msgstr "聊天輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2822
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2834
|
||||||
#, fuzzy
|
|
||||||
msgid "Chat Input"
|
msgid "Chat Input"
|
||||||
msgstr "聊天輸出"
|
msgstr "聊天輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:2823
|
#: spa/plugins/alsa/acp/alsa-mixer.c:2835
|
||||||
#, fuzzy
|
|
||||||
msgid "Virtual Surround 7.1"
|
msgid "Virtual Surround 7.1"
|
||||||
msgstr "虛擬環繞聲 sink"
|
msgstr "虛擬環繞聲 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4527
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4522
|
||||||
msgid "Analog Mono"
|
msgid "Analog Mono"
|
||||||
msgstr "類比單聲道"
|
msgstr "類比單聲道"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4528
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4523
|
||||||
#, fuzzy
|
|
||||||
msgid "Analog Mono (Left)"
|
msgid "Analog Mono (Left)"
|
||||||
msgstr "類比單聲道"
|
msgstr "類比單聲道(左)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4529
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4524
|
||||||
#, fuzzy
|
|
||||||
msgid "Analog Mono (Right)"
|
msgid "Analog Mono (Right)"
|
||||||
msgstr "類比單聲道"
|
msgstr "類比單聲道(右)"
|
||||||
|
|
||||||
#. Note: Not translated to "Analog Stereo Input", because the source
|
#. Note: Not translated to "Analog Stereo Input", because the source
|
||||||
#. * name gets "Input" appended to it automatically, so adding "Input"
|
#. * name gets "Input" appended to it automatically, so adding "Input"
|
||||||
#. * here would lead to the source name to become "Analog Stereo Input
|
#. * here would lead to the source name to become "Analog Stereo Input
|
||||||
#. * Input". The same logic applies to analog-stereo-output,
|
#. * Input". The same logic applies to analog-stereo-output,
|
||||||
#. * multichannel-input and multichannel-output.
|
#. * multichannel-input and multichannel-output.
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4530
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4525
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4538
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4533
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4539
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4534
|
||||||
msgid "Analog Stereo"
|
msgid "Analog Stereo"
|
||||||
msgstr "類比立體聲"
|
msgstr "類比立體聲"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4531
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4526
|
||||||
msgid "Mono"
|
msgid "Mono"
|
||||||
msgstr "單聲道"
|
msgstr "單聲道"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4532
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4527
|
||||||
msgid "Stereo"
|
msgid "Stereo"
|
||||||
msgstr "立體聲"
|
msgstr "立體聲"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4540
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4535
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4698
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4693
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1135
|
#: spa/plugins/bluez5/bluez5-device.c:2410
|
||||||
msgid "Headset"
|
msgid "Headset"
|
||||||
msgstr "耳麥"
|
msgstr "耳麥"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4541
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4536
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4699
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4694
|
||||||
#, fuzzy
|
|
||||||
msgid "Speakerphone"
|
msgid "Speakerphone"
|
||||||
msgstr "喇叭"
|
msgstr "會議揚聲器"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4542
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4537
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4543
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4538
|
||||||
msgid "Multichannel"
|
msgid "Multichannel"
|
||||||
msgstr "多聲道"
|
msgstr "多聲道"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4544
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4539
|
||||||
msgid "Analog Surround 2.1"
|
msgid "Analog Surround 2.1"
|
||||||
msgstr "類比環繞聲 2.1"
|
msgstr "類比環繞聲 2.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4545
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4540
|
||||||
msgid "Analog Surround 3.0"
|
msgid "Analog Surround 3.0"
|
||||||
msgstr "類比環繞聲 3.0"
|
msgstr "類比環繞聲 3.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4546
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4541
|
||||||
msgid "Analog Surround 3.1"
|
msgid "Analog Surround 3.1"
|
||||||
msgstr "類比環繞聲 3.1"
|
msgstr "類比環繞聲 3.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4547
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4542
|
||||||
msgid "Analog Surround 4.0"
|
msgid "Analog Surround 4.0"
|
||||||
msgstr "類比環繞聲 4.0"
|
msgstr "類比環繞聲 4.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4548
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4543
|
||||||
msgid "Analog Surround 4.1"
|
msgid "Analog Surround 4.1"
|
||||||
msgstr "類比環繞聲 4.1"
|
msgstr "類比環繞聲 4.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4549
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4544
|
||||||
msgid "Analog Surround 5.0"
|
msgid "Analog Surround 5.0"
|
||||||
msgstr "類比環繞聲 5.0"
|
msgstr "類比環繞聲 5.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4550
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4545
|
||||||
msgid "Analog Surround 5.1"
|
msgid "Analog Surround 5.1"
|
||||||
msgstr "類比環繞聲 5.1"
|
msgstr "類比環繞聲 5.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4551
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4546
|
||||||
msgid "Analog Surround 6.0"
|
msgid "Analog Surround 6.0"
|
||||||
msgstr "類比環繞聲 6.0"
|
msgstr "類比環繞聲 6.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4552
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4547
|
||||||
msgid "Analog Surround 6.1"
|
msgid "Analog Surround 6.1"
|
||||||
msgstr "類比環繞聲 6.1"
|
msgstr "類比環繞聲 6.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4553
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4548
|
||||||
msgid "Analog Surround 7.0"
|
msgid "Analog Surround 7.0"
|
||||||
msgstr "類比環繞聲 7.0"
|
msgstr "類比環繞聲 7.0"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4554
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4549
|
||||||
msgid "Analog Surround 7.1"
|
msgid "Analog Surround 7.1"
|
||||||
msgstr "類比環繞聲 7.1"
|
msgstr "類比環繞聲 7.1"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4555
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4550
|
||||||
msgid "Digital Stereo (IEC958)"
|
msgid "Digital Stereo (IEC958)"
|
||||||
msgstr "數位立體聲 (IEC958)"
|
msgstr "數位立體聲 (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4556
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4551
|
||||||
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
msgid "Digital Surround 4.0 (IEC958/AC3)"
|
||||||
msgstr "數位環繞聲 4.0 (IEC958/AC3)"
|
msgstr "數位環繞聲 4.0 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4557
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4552
|
||||||
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
msgid "Digital Surround 5.1 (IEC958/AC3)"
|
||||||
msgstr "數位環繞聲 5.1 (IEC958/AC3)"
|
msgstr "數位環繞聲 5.1 (IEC958/AC3)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4558
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4553
|
||||||
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
msgid "Digital Surround 5.1 (IEC958/DTS)"
|
||||||
msgstr "數位環繞聲 5.1 (IEC958/DTS)"
|
msgstr "數位環繞聲 5.1 (IEC958/DTS)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4559
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4554
|
||||||
msgid "Digital Stereo (HDMI)"
|
msgid "Digital Stereo (HDMI)"
|
||||||
msgstr "數位立體聲 (HDMI)"
|
msgstr "數位立體聲 (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4560
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4555
|
||||||
msgid "Digital Surround 5.1 (HDMI)"
|
msgid "Digital Surround 5.1 (HDMI)"
|
||||||
msgstr "數位環繞聲 5.1 (HDMI)"
|
msgstr "數位環繞聲 5.1 (HDMI)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4561
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4556
|
||||||
msgid "Chat"
|
msgid "Chat"
|
||||||
msgstr ""
|
msgstr "聊天"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4562
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4557
|
||||||
msgid "Game"
|
msgid "Game"
|
||||||
msgstr ""
|
msgstr "遊戲"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4696
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4691
|
||||||
msgid "Analog Mono Duplex"
|
msgid "Analog Mono Duplex"
|
||||||
msgstr "類比單聲道雙工"
|
msgstr "類比單聲道雙工"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4697
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4692
|
||||||
msgid "Analog Stereo Duplex"
|
msgid "Analog Stereo Duplex"
|
||||||
msgstr "類比立體聲雙工"
|
msgstr "類比立體聲雙工"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4700
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4695
|
||||||
msgid "Digital Stereo Duplex (IEC958)"
|
msgid "Digital Stereo Duplex (IEC958)"
|
||||||
msgstr "數位立體聲雙工 (IEC958)"
|
msgstr "數位立體聲雙工 (IEC958)"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4701
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4696
|
||||||
msgid "Multichannel Duplex"
|
msgid "Multichannel Duplex"
|
||||||
msgstr "多聲道雙工"
|
msgstr "多聲道雙工"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4702
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4697
|
||||||
msgid "Stereo Duplex"
|
msgid "Stereo Duplex"
|
||||||
msgstr "立體聲雙工"
|
msgstr "立體聲雙工"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4703
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4698
|
||||||
msgid "Mono Chat + 7.1 Surround"
|
msgid "Mono Chat + 7.1 Surround"
|
||||||
msgstr ""
|
msgstr "單聲道聊天 + 7.1 立體聲"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4806
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4799
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Output"
|
msgid "%s Output"
|
||||||
msgstr "%s 輸出"
|
msgstr "%s 輸出"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-mixer.c:4813
|
#: spa/plugins/alsa/acp/alsa-mixer.c:4807
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "%s Input"
|
msgid "%s Input"
|
||||||
msgstr "%s 輸入"
|
msgstr "%s 輸入"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1175 spa/plugins/alsa/acp/alsa-util.c:1269
|
#: spa/plugins/alsa/acp/alsa-util.c:1233 spa/plugins/alsa/acp/alsa-util.c:1327
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
|
"snd_pcm_avail() returned a value that is exceptionally large: %lu byte (%lu "
|
||||||
|
|
@ -481,23 +598,23 @@ msgstr[0] ""
|
||||||
"snd_pcm_avail() 傳回超出預期的大值:%lu bytes (%lu ms)。\n"
|
"snd_pcm_avail() 傳回超出預期的大值:%lu bytes (%lu ms)。\n"
|
||||||
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1241
|
#: spa/plugins/alsa/acp/alsa-util.c:1299
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_delay() returned a value that is exceptionally large: %li byte (%s"
|
"snd_pcm_delay() returned a value that is exceptionally large: %li byte "
|
||||||
"%lu ms).\n"
|
"(%s%lu ms).\n"
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
||||||
"to the ALSA developers."
|
"to the ALSA developers."
|
||||||
msgid_plural ""
|
msgid_plural ""
|
||||||
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes (%s"
|
"snd_pcm_delay() returned a value that is exceptionally large: %li bytes "
|
||||||
"%lu ms).\n"
|
"(%s%lu ms).\n"
|
||||||
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
"Most likely this is a bug in the ALSA driver '%s'. Please report this issue "
|
||||||
"to the ALSA developers."
|
"to the ALSA developers."
|
||||||
msgstr[0] ""
|
msgstr[0] ""
|
||||||
"snd_pcm_delay() 傳回超出預期的大值:%li bytes (%s%lu ms)。\n"
|
"snd_pcm_delay() 傳回超出預期的大值:%li bytes (%s%lu ms)。\n"
|
||||||
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1288
|
#: spa/plugins/alsa/acp/alsa-util.c:1346
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
|
"snd_pcm_avail_delay() returned strange values: delay %lu is less than avail "
|
||||||
|
|
@ -508,7 +625,7 @@ msgstr ""
|
||||||
"snd_pcm_avail_delay() 傳回超出預期的大值:延遲 %lu 少於可用的 %lu。\n"
|
"snd_pcm_avail_delay() 傳回超出預期的大值:延遲 %lu 少於可用的 %lu。\n"
|
||||||
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
||||||
|
|
||||||
#: spa/plugins/alsa/acp/alsa-util.c:1331
|
#: spa/plugins/alsa/acp/alsa-util.c:1389
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid ""
|
msgid ""
|
||||||
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
|
"snd_pcm_mmap_begin() returned a value that is exceptionally large: %lu byte "
|
||||||
|
|
@ -524,62 +641,115 @@ msgstr[0] ""
|
||||||
"snd_pcm_mmap_begin() 傳回超出預期的大值:%lu bytes (%lu ms)。\n"
|
"snd_pcm_mmap_begin() 傳回超出預期的大值:%lu bytes (%lu ms)。\n"
|
||||||
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
"這很能是 ALSA 驅動程式「%s」的臭蟲。請回報這個問題給 ALSA 開發者。"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1010
|
#: spa/plugins/alsa/acp/channelmap.h:460
|
||||||
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
msgid "(invalid)"
|
||||||
msgstr ""
|
msgstr "(無效)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1033
|
#: spa/plugins/alsa/acp/compat.c:194
|
||||||
|
msgid "Built-in Audio"
|
||||||
|
msgstr "內部音效"
|
||||||
|
|
||||||
|
#: spa/plugins/alsa/acp/compat.c:199
|
||||||
|
msgid "Modem"
|
||||||
|
msgstr "數據機"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2032
|
||||||
|
msgid "Audio Gateway (A2DP Source & HSP/HFP AG)"
|
||||||
|
msgstr "音訊閘道 (A2DP Source & HSP/HFP AG)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2061
|
||||||
|
msgid "Audio Streaming for Hearing Aids (ASHA Sink)"
|
||||||
|
msgstr "助聽器的音訊串流 (ASHA Sink)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2104
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
msgid "High Fidelity Playback (A2DP Sink, codec %s)"
|
||||||
msgstr ""
|
msgstr "高傳真播放裝置 (A2DP Sink,編碼器 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1035
|
#: spa/plugins/bluez5/bluez5-device.c:2107
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink, codec %s)"
|
||||||
msgstr ""
|
msgstr "高傳真雙工裝置 (A2DP Source/Sink,編碼器 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1041
|
#: spa/plugins/bluez5/bluez5-device.c:2115
|
||||||
msgid "High Fidelity Playback (A2DP Sink)"
|
msgid "High Fidelity Playback (A2DP Sink)"
|
||||||
msgstr ""
|
msgstr "高傳真播放裝置 (A2DP Sink)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1043
|
#: spa/plugins/bluez5/bluez5-device.c:2117
|
||||||
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
msgid "High Fidelity Duplex (A2DP Source/Sink)"
|
||||||
msgstr ""
|
msgstr "高傳真雙工裝置 (A2DP Source/Sink)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1070
|
#: spa/plugins/bluez5/bluez5-device.c:2194
|
||||||
|
#, c-format
|
||||||
|
msgid "High Fidelity Playback (BAP Sink, codec %s)"
|
||||||
|
msgstr "高傳真播放裝置 (BAP Sink,編碼器 %s)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2199
|
||||||
|
#, c-format
|
||||||
|
msgid "High Fidelity Input (BAP Source, codec %s)"
|
||||||
|
msgstr "高傳真輸入裝置 (BAP Source,編碼器 %s)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2203
|
||||||
|
#, c-format
|
||||||
|
msgid "High Fidelity Duplex (BAP Source/Sink, codec %s)"
|
||||||
|
msgstr "高傳真雙工裝置 (BAP Source/Sink,編碼器 %s)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2212
|
||||||
|
msgid "High Fidelity Playback (BAP Sink)"
|
||||||
|
msgstr "高傳真播放裝置 (BAP Sink)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2216
|
||||||
|
msgid "High Fidelity Input (BAP Source)"
|
||||||
|
msgstr "高傳真輸入裝置 (BAP Source)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2219
|
||||||
|
msgid "High Fidelity Duplex (BAP Source/Sink)"
|
||||||
|
msgstr "高傳真雙工裝置 (BAP Source/Sink)"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2259
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
msgid "Headset Head Unit (HSP/HFP, codec %s)"
|
||||||
msgstr ""
|
msgstr "耳麥頭戴單元 (HSP/HFP,編碼器 %s)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1074
|
#: spa/plugins/bluez5/bluez5-device.c:2411
|
||||||
msgid "Headset Head Unit (HSP/HFP)"
|
#: spa/plugins/bluez5/bluez5-device.c:2416
|
||||||
msgstr ""
|
#: spa/plugins/bluez5/bluez5-device.c:2423
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2429
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1140
|
#: spa/plugins/bluez5/bluez5-device.c:2435
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2441
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2447
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2453
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2459
|
||||||
msgid "Handsfree"
|
msgid "Handsfree"
|
||||||
msgstr "免持裝置"
|
msgstr "免持裝置"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1155
|
#: spa/plugins/bluez5/bluez5-device.c:2417
|
||||||
msgid "Headphone"
|
msgid "Handsfree (HFP)"
|
||||||
msgstr "頭戴式耳機"
|
msgstr "免持裝置 (HFP)"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1160
|
#: spa/plugins/bluez5/bluez5-device.c:2440
|
||||||
msgid "Portable"
|
msgid "Portable"
|
||||||
msgstr "可攜裝置"
|
msgstr "可攜裝置"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1165
|
#: spa/plugins/bluez5/bluez5-device.c:2446
|
||||||
msgid "Car"
|
msgid "Car"
|
||||||
msgstr "汽車"
|
msgstr "汽車"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1170
|
#: spa/plugins/bluez5/bluez5-device.c:2452
|
||||||
msgid "HiFi"
|
msgid "HiFi"
|
||||||
msgstr "HiFi"
|
msgstr "HiFi"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1175
|
#: spa/plugins/bluez5/bluez5-device.c:2458
|
||||||
msgid "Phone"
|
msgid "Phone"
|
||||||
msgstr "手機"
|
msgstr "手機"
|
||||||
|
|
||||||
#: spa/plugins/bluez5/bluez5-device.c:1181
|
#: spa/plugins/bluez5/bluez5-device.c:2465
|
||||||
#, fuzzy
|
|
||||||
msgid "Bluetooth"
|
msgid "Bluetooth"
|
||||||
msgstr "藍牙輸入"
|
msgstr "藍牙"
|
||||||
|
|
||||||
|
#: spa/plugins/bluez5/bluez5-device.c:2466
|
||||||
|
msgid "Bluetooth Handsfree"
|
||||||
|
msgstr "藍牙免持裝置"
|
||||||
|
|
||||||
|
#~ msgid "Headphone"
|
||||||
|
#~ msgstr "頭戴式耳機"
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
|
||||||
#include <spa/debug/context.h>
|
#include <spa/debug/context.h>
|
||||||
|
#include <spa/utils/string.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
@ -30,13 +31,15 @@ SPA_API_DEBUG_MEM int spa_debugc_mem(struct spa_debug_context *ctx, int indent,
|
||||||
{
|
{
|
||||||
const uint8_t *t = (const uint8_t*)data;
|
const uint8_t *t = (const uint8_t*)data;
|
||||||
char buffer[512];
|
char buffer[512];
|
||||||
|
struct spa_strbuf b;
|
||||||
size_t i;
|
size_t i;
|
||||||
int pos = 0;
|
|
||||||
|
|
||||||
for (i = 0; i < size; i++) {
|
for (i = 0; i < size; i++) {
|
||||||
if (i % 16 == 0)
|
if (i % 16 == 0) {
|
||||||
pos = sprintf(buffer, "%p: ", &t[i]);
|
spa_strbuf_init(&b, buffer, sizeof(buffer));
|
||||||
pos += sprintf(buffer + pos, "%02x ", t[i]);
|
spa_strbuf_append(&b, "%p: ", &t[i]);
|
||||||
|
}
|
||||||
|
spa_strbuf_append(&b, "%02x ", t[i]);
|
||||||
if (i % 16 == 15 || i == size - 1) {
|
if (i % 16 == 15 || i == size - 1) {
|
||||||
spa_debugc(ctx, "%*s" "%s", indent, "", buffer);
|
spa_debugc(ctx, "%*s" "%s", indent, "", buffer);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,8 @@ spa_format_audio_dsd_parse(const struct spa_pod *format, struct spa_audio_info_d
|
||||||
{
|
{
|
||||||
struct spa_pod *position = NULL;
|
struct spa_pod *position = NULL;
|
||||||
int res;
|
int res;
|
||||||
|
uint32_t max_position = SPA_N_ELEMENTS(info->position);
|
||||||
|
|
||||||
info->flags = 0;
|
info->flags = 0;
|
||||||
res = spa_pod_parse_object(format,
|
res = spa_pod_parse_object(format,
|
||||||
SPA_TYPE_OBJECT_Format, NULL,
|
SPA_TYPE_OBJECT_Format, NULL,
|
||||||
|
|
@ -41,10 +43,13 @@ spa_format_audio_dsd_parse(const struct spa_pod *format, struct spa_audio_info_d
|
||||||
SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&info->rate),
|
SPA_FORMAT_AUDIO_rate, SPA_POD_OPT_Int(&info->rate),
|
||||||
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
|
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
|
||||||
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
|
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
|
||||||
|
if (info->channels > max_position)
|
||||||
|
return -EINVAL;
|
||||||
if (position == NULL ||
|
if (position == NULL ||
|
||||||
!spa_pod_copy_array(position, SPA_TYPE_Id, info->position, SPA_N_ELEMENTS(info->position)))
|
spa_pod_copy_array(position, SPA_TYPE_Id, info->position, max_position) != info->channels) {
|
||||||
SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
||||||
|
spa_memzero(info->position, max_position * sizeof(info->position[0]));
|
||||||
|
}
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -75,7 +75,7 @@ static const struct spa_type_audio_layout_info {
|
||||||
{ "7.1", { SPA_AUDIO_LAYOUT_7_1 } },
|
{ "7.1", { SPA_AUDIO_LAYOUT_7_1 } },
|
||||||
{ "7.1W", { SPA_AUDIO_LAYOUT_7_1W } },
|
{ "7.1W", { SPA_AUDIO_LAYOUT_7_1W } },
|
||||||
{ "7.1WR", { SPA_AUDIO_LAYOUT_7_1WR } },
|
{ "7.1WR", { SPA_AUDIO_LAYOUT_7_1WR } },
|
||||||
{ NULL, },
|
{ NULL, { 0, { SPA_AUDIO_CHANNEL_UNKNOWN } } },
|
||||||
};
|
};
|
||||||
|
|
||||||
SPA_API_AUDIO_LAYOUT_TYPES int
|
SPA_API_AUDIO_LAYOUT_TYPES int
|
||||||
|
|
@ -87,7 +87,7 @@ spa_audio_layout_info_parse_name(struct spa_audio_layout_info *layout, size_t si
|
||||||
uint32_t i, n_pos;
|
uint32_t i, n_pos;
|
||||||
if (spa_atou32(name+3, &n_pos, 10)) {
|
if (spa_atou32(name+3, &n_pos, 10)) {
|
||||||
if (n_pos > max_position)
|
if (n_pos > max_position)
|
||||||
return -ECHRNG;
|
return -EINVAL;
|
||||||
for (i = 0; i < 0x1000 && i < n_pos; i++)
|
for (i = 0; i < 0x1000 && i < n_pos; i++)
|
||||||
layout->position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
|
layout->position[i] = SPA_AUDIO_CHANNEL_AUX0 + i;
|
||||||
for (; i < n_pos; i++)
|
for (; i < n_pos; i++)
|
||||||
|
|
@ -99,7 +99,7 @@ spa_audio_layout_info_parse_name(struct spa_audio_layout_info *layout, size_t si
|
||||||
SPA_FOR_EACH_ELEMENT_VAR(spa_type_audio_layout_info, i) {
|
SPA_FOR_EACH_ELEMENT_VAR(spa_type_audio_layout_info, i) {
|
||||||
if (spa_streq(name, i->name)) {
|
if (spa_streq(name, i->name)) {
|
||||||
if (i->layout.n_channels > max_position)
|
if (i->layout.n_channels > max_position)
|
||||||
return -ECHRNG;
|
return -EINVAL;
|
||||||
*layout = i->layout;
|
*layout = i->layout;
|
||||||
return i->layout.n_channels;
|
return i->layout.n_channels;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -88,14 +88,14 @@ spa_audio_info_raw_ext_update(struct spa_audio_info_raw *info, size_t size,
|
||||||
} else if (spa_streq(key, SPA_KEY_AUDIO_CHANNELS)) {
|
} else if (spa_streq(key, SPA_KEY_AUDIO_CHANNELS)) {
|
||||||
if (spa_atou32(val, &v, 0) && (force || info->channels == 0)) {
|
if (spa_atou32(val, &v, 0) && (force || info->channels == 0)) {
|
||||||
if (v > max_position)
|
if (v > max_position)
|
||||||
return -ECHRNG;
|
return -EINVAL;
|
||||||
info->channels = v;
|
info->channels = v;
|
||||||
}
|
}
|
||||||
} else if (spa_streq(key, SPA_KEY_AUDIO_LAYOUT)) {
|
} else if (spa_streq(key, SPA_KEY_AUDIO_LAYOUT)) {
|
||||||
if (force || info->channels == 0) {
|
if (force || info->channels == 0) {
|
||||||
if (spa_audio_parse_layout(val, info->position, max_position, &v) > 0) {
|
if (spa_audio_parse_layout(val, info->position, max_position, &v) > 0) {
|
||||||
if (v > max_position)
|
if (v > max_position)
|
||||||
return -ECHRNG;
|
return -EINVAL;
|
||||||
info->channels = v;
|
info->channels = v;
|
||||||
SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
||||||
}
|
}
|
||||||
|
|
@ -105,7 +105,7 @@ spa_audio_info_raw_ext_update(struct spa_audio_info_raw *info, size_t size,
|
||||||
if (spa_audio_parse_position_n(val, strlen(val), info->position,
|
if (spa_audio_parse_position_n(val, strlen(val), info->position,
|
||||||
max_position, &v) > 0) {
|
max_position, &v) > 0) {
|
||||||
if (v > max_position)
|
if (v > max_position)
|
||||||
return -ECHRNG;
|
return -EINVAL;
|
||||||
info->channels = v;
|
info->channels = v;
|
||||||
SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
SPA_FLAG_CLEAR(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -46,10 +46,12 @@ spa_format_audio_raw_ext_parse(const struct spa_pod *format, struct spa_audio_in
|
||||||
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
|
SPA_FORMAT_AUDIO_channels, SPA_POD_OPT_Int(&info->channels),
|
||||||
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
|
SPA_FORMAT_AUDIO_position, SPA_POD_OPT_Pod(&position));
|
||||||
if (info->channels > max_position)
|
if (info->channels > max_position)
|
||||||
return -ECHRNG;
|
return -EINVAL;
|
||||||
if (position == NULL ||
|
if (position == NULL ||
|
||||||
spa_pod_copy_array(position, SPA_TYPE_Id, info->position, max_position) != info->channels)
|
spa_pod_copy_array(position, SPA_TYPE_Id, info->position, max_position) != info->channels) {
|
||||||
SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
SPA_FLAG_SET(info->flags, SPA_AUDIO_FLAG_UNPOSITIONED);
|
||||||
|
spa_memzero(info->position, max_position * sizeof(info->position[0]));
|
||||||
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -156,41 +156,42 @@ enum spa_audio_channel {
|
||||||
|
|
||||||
SPA_AUDIO_CHANNEL_MONO, /**< mono stream */
|
SPA_AUDIO_CHANNEL_MONO, /**< mono stream */
|
||||||
|
|
||||||
SPA_AUDIO_CHANNEL_FL, /**< front left */
|
/** Azimuth Elevation */
|
||||||
SPA_AUDIO_CHANNEL_FR, /**< front right */
|
SPA_AUDIO_CHANNEL_FL, /**< front left 30 0 */
|
||||||
SPA_AUDIO_CHANNEL_FC, /**< front center */
|
SPA_AUDIO_CHANNEL_FR, /**< front right -30 0 */
|
||||||
SPA_AUDIO_CHANNEL_LFE, /**< LFE */
|
SPA_AUDIO_CHANNEL_FC, /**< front center 0 0 */
|
||||||
SPA_AUDIO_CHANNEL_SL, /**< side left */
|
SPA_AUDIO_CHANNEL_LFE, /**< LFE 0 -30 */
|
||||||
SPA_AUDIO_CHANNEL_SR, /**< side right */
|
SPA_AUDIO_CHANNEL_SL, /**< side left 90 0 */
|
||||||
SPA_AUDIO_CHANNEL_FLC, /**< front left center */
|
SPA_AUDIO_CHANNEL_SR, /**< side right -90 0 */
|
||||||
SPA_AUDIO_CHANNEL_FRC, /**< front right center */
|
SPA_AUDIO_CHANNEL_FLC, /**< front left center 22.5 0 */
|
||||||
SPA_AUDIO_CHANNEL_RC, /**< rear center */
|
SPA_AUDIO_CHANNEL_FRC, /**< front right center -22.5 0 */
|
||||||
SPA_AUDIO_CHANNEL_RL, /**< rear left */
|
SPA_AUDIO_CHANNEL_RC, /**< rear center 180 0 */
|
||||||
SPA_AUDIO_CHANNEL_RR, /**< rear right */
|
SPA_AUDIO_CHANNEL_RL, /**< rear left 110 0 */
|
||||||
SPA_AUDIO_CHANNEL_TC, /**< top center */
|
SPA_AUDIO_CHANNEL_RR, /**< rear right -110 0 */
|
||||||
SPA_AUDIO_CHANNEL_TFL, /**< top front left */
|
SPA_AUDIO_CHANNEL_TC, /**< top center 0 90 */
|
||||||
SPA_AUDIO_CHANNEL_TFC, /**< top front center */
|
SPA_AUDIO_CHANNEL_TFL, /**< top front left 30 30 */
|
||||||
SPA_AUDIO_CHANNEL_TFR, /**< top front right */
|
SPA_AUDIO_CHANNEL_TFC, /**< top front center 0 30 */
|
||||||
SPA_AUDIO_CHANNEL_TRL, /**< top rear left */
|
SPA_AUDIO_CHANNEL_TFR, /**< top front right -30 30 */
|
||||||
SPA_AUDIO_CHANNEL_TRC, /**< top rear center */
|
SPA_AUDIO_CHANNEL_TRL, /**< top rear left 110 30 */
|
||||||
SPA_AUDIO_CHANNEL_TRR, /**< top rear right */
|
SPA_AUDIO_CHANNEL_TRC, /**< top rear center 180 30 */
|
||||||
SPA_AUDIO_CHANNEL_RLC, /**< rear left center */
|
SPA_AUDIO_CHANNEL_TRR, /**< top rear right -110 30 */
|
||||||
SPA_AUDIO_CHANNEL_RRC, /**< rear right center */
|
SPA_AUDIO_CHANNEL_RLC, /**< rear left center 135 0 */
|
||||||
SPA_AUDIO_CHANNEL_FLW, /**< front left wide */
|
SPA_AUDIO_CHANNEL_RRC, /**< rear right center -135 0 */
|
||||||
SPA_AUDIO_CHANNEL_FRW, /**< front right wide */
|
SPA_AUDIO_CHANNEL_FLW, /**< front left wide 60 0 */
|
||||||
SPA_AUDIO_CHANNEL_LFE2, /**< LFE 2 */
|
SPA_AUDIO_CHANNEL_FRW, /**< front right wide -60 0 */
|
||||||
SPA_AUDIO_CHANNEL_FLH, /**< front left high */
|
SPA_AUDIO_CHANNEL_LFE2, /**< LFE 2 0 -30 */
|
||||||
SPA_AUDIO_CHANNEL_FCH, /**< front center high */
|
SPA_AUDIO_CHANNEL_FLH, /**< front left high 22.5 30 */
|
||||||
SPA_AUDIO_CHANNEL_FRH, /**< front right high */
|
SPA_AUDIO_CHANNEL_FCH, /**< front center high 0 30 */
|
||||||
SPA_AUDIO_CHANNEL_TFLC, /**< top front left center */
|
SPA_AUDIO_CHANNEL_FRH, /**< front right high -22.5 30 */
|
||||||
SPA_AUDIO_CHANNEL_TFRC, /**< top front right center */
|
SPA_AUDIO_CHANNEL_TFLC, /**< top front left center 45 30 */
|
||||||
SPA_AUDIO_CHANNEL_TSL, /**< top side left */
|
SPA_AUDIO_CHANNEL_TFRC, /**< top front right center -45 30 */
|
||||||
SPA_AUDIO_CHANNEL_TSR, /**< top side right */
|
SPA_AUDIO_CHANNEL_TSL, /**< top side left 90 0 */
|
||||||
SPA_AUDIO_CHANNEL_LLFE, /**< left LFE */
|
SPA_AUDIO_CHANNEL_TSR, /**< top side right -90 0 */
|
||||||
SPA_AUDIO_CHANNEL_RLFE, /**< right LFE */
|
SPA_AUDIO_CHANNEL_LLFE, /**< left LFE 45 -30 */
|
||||||
SPA_AUDIO_CHANNEL_BC, /**< bottom center */
|
SPA_AUDIO_CHANNEL_RLFE, /**< right LFE -45 -30 */
|
||||||
SPA_AUDIO_CHANNEL_BLC, /**< bottom left center */
|
SPA_AUDIO_CHANNEL_BC, /**< bottom center 0 -30 */
|
||||||
SPA_AUDIO_CHANNEL_BRC, /**< bottom right center */
|
SPA_AUDIO_CHANNEL_BLC, /**< bottom left center 45 -30 */
|
||||||
|
SPA_AUDIO_CHANNEL_BRC, /**< bottom right center -45 -30 */
|
||||||
|
|
||||||
SPA_AUDIO_CHANNEL_START_Aux = 0x1000, /**< aux channels */
|
SPA_AUDIO_CHANNEL_START_Aux = 0x1000, /**< aux channels */
|
||||||
SPA_AUDIO_CHANNEL_AUX0 = SPA_AUDIO_CHANNEL_START_Aux,
|
SPA_AUDIO_CHANNEL_AUX0 = SPA_AUDIO_CHANNEL_START_Aux,
|
||||||
|
|
|
||||||
38
spa/include/spa/param/dict-types.h
Normal file
38
spa/include/spa/param/dict-types.h
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_PARAM_DICT_TYPES_H
|
||||||
|
#define SPA_PARAM_DICT_TYPES_H
|
||||||
|
|
||||||
|
#include <spa/utils/enum-types.h>
|
||||||
|
#include <spa/param/param-types.h>
|
||||||
|
#include <spa/param/dict.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup spa_param
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SPA_TYPE_INFO_PARAM_Dict SPA_TYPE_INFO_PARAM_BASE "Dict"
|
||||||
|
#define SPA_TYPE_INFO_PARAM_DICT_BASE SPA_TYPE_INFO_PARAM_Dict ":"
|
||||||
|
|
||||||
|
static const struct spa_type_info spa_type_param_dict[] = {
|
||||||
|
{ SPA_PARAM_DICT_START, SPA_TYPE_Id, SPA_TYPE_INFO_PARAM_DICT_BASE, spa_type_param, },
|
||||||
|
{ SPA_PARAM_DICT_info, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_DICT_BASE "info", NULL, },
|
||||||
|
{ 0, 0, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_PARAM_DICT_TYPES_H */
|
||||||
125
spa/include/spa/param/dict-utils.h
Normal file
125
spa/include/spa/param/dict-utils.h
Normal file
|
|
@ -0,0 +1,125 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_PARAM_DICT_UTILS_H
|
||||||
|
#define SPA_PARAM_DICT_UTILS_H
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
#include <spa/utils/dict.h>
|
||||||
|
#include <spa/pod/builder.h>
|
||||||
|
#include <spa/pod/iter.h>
|
||||||
|
#include <spa/pod/parser.h>
|
||||||
|
#include <spa/pod/compare.h>
|
||||||
|
#include <spa/param/dict.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup spa_param
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPA_API_DICT_UTILS
|
||||||
|
#ifdef SPA_API_IMPL
|
||||||
|
#define SPA_API_DICT_UTILS SPA_API_IMPL
|
||||||
|
#else
|
||||||
|
#define SPA_API_DICT_UTILS static inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPA_API_DICT_UTILS int
|
||||||
|
spa_param_dict_compare(const struct spa_pod *a, const struct spa_pod *b)
|
||||||
|
{
|
||||||
|
return spa_pod_memcmp(a, b);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_DICT_UTILS struct spa_pod *
|
||||||
|
spa_param_dict_build_dict(struct spa_pod_builder *builder, uint32_t id, struct spa_dict *dict)
|
||||||
|
{
|
||||||
|
struct spa_pod_frame f[2];
|
||||||
|
uint32_t i, n_items;
|
||||||
|
|
||||||
|
spa_pod_builder_push_object(builder, &f[0], SPA_TYPE_OBJECT_ParamDict, id);
|
||||||
|
|
||||||
|
n_items = dict ? dict->n_items : 0;
|
||||||
|
|
||||||
|
spa_pod_builder_prop(builder, SPA_PARAM_DICT_info, SPA_POD_PROP_FLAG_HINT_DICT);
|
||||||
|
spa_pod_builder_push_struct(builder, &f[1]);
|
||||||
|
spa_pod_builder_int(builder, n_items);
|
||||||
|
for (i = 0; i < n_items; i++) {
|
||||||
|
spa_pod_builder_string(builder, dict->items[i].key);
|
||||||
|
spa_pod_builder_string(builder, dict->items[i].value);
|
||||||
|
}
|
||||||
|
spa_pod_builder_pop(builder, &f[1]);
|
||||||
|
|
||||||
|
return (struct spa_pod*)spa_pod_builder_pop(builder, &f[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_DICT_UTILS struct spa_pod *
|
||||||
|
spa_param_dict_build_info(struct spa_pod_builder *builder, uint32_t id, struct spa_param_dict_info *info)
|
||||||
|
{
|
||||||
|
struct spa_pod_frame f;
|
||||||
|
spa_pod_builder_push_object(builder, &f, SPA_TYPE_OBJECT_ParamDict, id);
|
||||||
|
spa_pod_builder_add(builder, SPA_PARAM_DICT_info, SPA_POD_PROP_FLAG_HINT_DICT);
|
||||||
|
spa_pod_builder_primitive(builder, info->info);
|
||||||
|
return (struct spa_pod*)spa_pod_builder_pop(builder, &f);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_DICT_UTILS int
|
||||||
|
spa_param_dict_parse(const struct spa_pod *dict, struct spa_param_dict_info *info, size_t size)
|
||||||
|
{
|
||||||
|
memset(info, 0, size);
|
||||||
|
return spa_pod_parse_object(dict,
|
||||||
|
SPA_TYPE_OBJECT_ParamDict, NULL,
|
||||||
|
SPA_PARAM_DICT_info, SPA_POD_PodStruct(&info->info));
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_DICT_UTILS int
|
||||||
|
spa_param_dict_info_parse(const struct spa_param_dict_info *info, size_t size,
|
||||||
|
struct spa_dict *dict, struct spa_dict_item *items)
|
||||||
|
{
|
||||||
|
struct spa_pod_parser prs;
|
||||||
|
uint32_t n, n_items;
|
||||||
|
const char *key, *value;
|
||||||
|
struct spa_pod_frame f[1];
|
||||||
|
|
||||||
|
spa_pod_parser_pod(&prs, info->info);
|
||||||
|
if (spa_pod_parser_push_struct(&prs, &f[0]) < 0 ||
|
||||||
|
spa_pod_parser_get_int(&prs, (int32_t*)&n_items) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (items == NULL) {
|
||||||
|
dict->n_items = n_items;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
n_items = SPA_MIN(dict->n_items, n_items);
|
||||||
|
|
||||||
|
for (n = 0; n < n_items; n++) {
|
||||||
|
if (spa_pod_parser_get(&prs,
|
||||||
|
SPA_POD_String(&key),
|
||||||
|
SPA_POD_String(&value),
|
||||||
|
NULL) < 0)
|
||||||
|
break;
|
||||||
|
if (key == NULL || value == NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
items[n].key = key;
|
||||||
|
items[n].value = value;
|
||||||
|
}
|
||||||
|
dict->items = items;
|
||||||
|
spa_pod_parser_pop(&prs, &f[0]);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_PARAM_DICT_UTILS_H */
|
||||||
42
spa/include/spa/param/dict.h
Normal file
42
spa/include/spa/param/dict.h
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2025 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_PARAM_DICT_H
|
||||||
|
#define SPA_PARAM_DICT_H
|
||||||
|
|
||||||
|
#include <spa/param/param.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup spa_param
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** properties for SPA_TYPE_OBJECT_ParamDict */
|
||||||
|
enum spa_param_dict {
|
||||||
|
SPA_PARAM_DICT_START,
|
||||||
|
SPA_PARAM_DICT_info, /**< Struct(
|
||||||
|
* Int: n_items
|
||||||
|
* (String: key
|
||||||
|
* String: value)*
|
||||||
|
* ) */
|
||||||
|
};
|
||||||
|
|
||||||
|
/** helper structure for managing info objects */
|
||||||
|
struct spa_param_dict_info {
|
||||||
|
const struct spa_pod *info;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_PARAM_DICT_H */
|
||||||
|
|
@ -181,6 +181,8 @@ static const struct spa_type_info spa_type_format[] = {
|
||||||
{ SPA_FORMAT_VIDEO_H264_alignment, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE "alignment", NULL },
|
{ SPA_FORMAT_VIDEO_H264_alignment, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_VIDEO_H264_BASE "alignment", NULL },
|
||||||
|
|
||||||
{ SPA_FORMAT_CONTROL_types, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_CONTROL_BASE "types", spa_type_control },
|
{ SPA_FORMAT_CONTROL_types, SPA_TYPE_Id, SPA_TYPE_INFO_FORMAT_CONTROL_BASE "types", spa_type_control },
|
||||||
|
|
||||||
|
{ SPA_FORMAT_VIDEO_deviceId, SPA_TYPE_Bytes, SPA_TYPE_INFO_FORMAT_BASE "deviceId", NULL },
|
||||||
{ 0, 0, NULL, NULL },
|
{ 0, 0, NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -144,6 +144,7 @@ enum spa_format {
|
||||||
SPA_FORMAT_VIDEO_H264_alignment, /**< (Id enum spa_h264_alignment) */
|
SPA_FORMAT_VIDEO_H264_alignment, /**< (Id enum spa_h264_alignment) */
|
||||||
SPA_FORMAT_VIDEO_H265_streamFormat, /**< (Id enum spa_h265_stream_format) */
|
SPA_FORMAT_VIDEO_H265_streamFormat, /**< (Id enum spa_h265_stream_format) */
|
||||||
SPA_FORMAT_VIDEO_H265_alignment, /**< (Id enum spa_h265_alignment) */
|
SPA_FORMAT_VIDEO_H265_alignment, /**< (Id enum spa_h265_alignment) */
|
||||||
|
SPA_FORMAT_VIDEO_deviceId, /**< dev_t identifier (Bytes) */
|
||||||
|
|
||||||
/* Image Format keys */
|
/* Image Format keys */
|
||||||
SPA_FORMAT_START_Image = 0x30000,
|
SPA_FORMAT_START_Image = 0x30000,
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,9 @@ static const struct spa_type_info spa_type_param[] = {
|
||||||
{ SPA_PARAM_Latency, SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_INFO_PARAM_ID_BASE "Latency", NULL },
|
{ SPA_PARAM_Latency, SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_INFO_PARAM_ID_BASE "Latency", NULL },
|
||||||
{ SPA_PARAM_ProcessLatency, SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_INFO_PARAM_ID_BASE "ProcessLatency", NULL },
|
{ SPA_PARAM_ProcessLatency, SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_INFO_PARAM_ID_BASE "ProcessLatency", NULL },
|
||||||
{ SPA_PARAM_Tag, SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_INFO_PARAM_ID_BASE "Tag", NULL },
|
{ SPA_PARAM_Tag, SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_INFO_PARAM_ID_BASE "Tag", NULL },
|
||||||
{ SPA_PARAM_PeerFormats, SPA_TYPE_Struct, SPA_TYPE_INFO_PARAM_ID_BASE "PeerFormats", NULL },
|
{ SPA_PARAM_PeerEnumFormat, SPA_TYPE_OBJECT_PeerParam, SPA_TYPE_INFO_PARAM_ID_BASE "PeerEnumFormat", NULL },
|
||||||
|
{ SPA_PARAM_Capability, SPA_TYPE_OBJECT_ParamDict, SPA_TYPE_INFO_PARAM_ID_BASE "Capability", NULL },
|
||||||
|
{ SPA_PARAM_PeerCapability, SPA_TYPE_OBJECT_PeerParam, SPA_TYPE_INFO_PARAM_ID_BASE "PeerCapability", NULL },
|
||||||
{ 0, 0, NULL, NULL },
|
{ 0, 0, NULL, NULL },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,11 @@ enum spa_param_type {
|
||||||
SPA_PARAM_Latency, /**< latency reporting, a SPA_TYPE_OBJECT_ParamLatency */
|
SPA_PARAM_Latency, /**< latency reporting, a SPA_TYPE_OBJECT_ParamLatency */
|
||||||
SPA_PARAM_ProcessLatency, /**< processing latency, a SPA_TYPE_OBJECT_ParamProcessLatency */
|
SPA_PARAM_ProcessLatency, /**< processing latency, a SPA_TYPE_OBJECT_ParamProcessLatency */
|
||||||
SPA_PARAM_Tag, /**< tag reporting, a SPA_TYPE_OBJECT_ParamTag. Since 0.3.79 */
|
SPA_PARAM_Tag, /**< tag reporting, a SPA_TYPE_OBJECT_ParamTag. Since 0.3.79 */
|
||||||
SPA_PARAM_PeerFormats, /**< peer formats, a SPA_TYPE_Struct of SPA_TYPE_OBJECT_Format. Since 1.5.0 */
|
SPA_PARAM_PeerEnumFormat, /**< peer formats, a SPA_TYPE_OBJECT_PeerParam with
|
||||||
|
* SPA_TYPE_OBJECT_Format. Since 1.5.0 */
|
||||||
|
SPA_PARAM_Capability, /**< capability info, a SPA_TYPE_OBJECT_ParamDict, Since 1.5.84 */
|
||||||
|
SPA_PARAM_PeerCapability, /**< peer capabilities, a SPA_TYPE_OBJECT_PeerParam with
|
||||||
|
* SPA_TYPE_OBJECT_ParamDict, since 1.5.84 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/** information about a parameter */
|
/** information about a parameter */
|
||||||
|
|
|
||||||
38
spa/include/spa/param/peer-types.h
Normal file
38
spa/include/spa/param/peer-types.h
Normal file
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_PARAM_PEER_TYPES_H
|
||||||
|
#define SPA_PARAM_PEER_TYPES_H
|
||||||
|
|
||||||
|
#include <spa/utils/enum-types.h>
|
||||||
|
#include <spa/param/param-types.h>
|
||||||
|
#include <spa/param/peer.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup spa_param
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define SPA_TYPE_INFO_PeerParam SPA_TYPE_INFO_OBJECT_BASE "PeerParam"
|
||||||
|
#define SPA_TYPE_INFO_PEER_PARAM_BASE SPA_TYPE_INFO_PeerParam ":"
|
||||||
|
|
||||||
|
static const struct spa_type_info spa_type_peer_param[] = {
|
||||||
|
{ SPA_PEER_PARAM_START, SPA_TYPE_Id, SPA_TYPE_INFO_PEER_PARAM_BASE, spa_type_param, },
|
||||||
|
{ SPA_ID_INVALID, SPA_TYPE_Id, SPA_TYPE_INFO_PEER_PARAM_BASE, NULL, },
|
||||||
|
{ 0, 0, NULL, NULL },
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_PARAM_PEER_TYPES_H */
|
||||||
92
spa/include/spa/param/peer-utils.h
Normal file
92
spa/include/spa/param/peer-utils.h
Normal file
|
|
@ -0,0 +1,92 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2023 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_PARAM_PEER_PARAM_UTILS_H
|
||||||
|
#define SPA_PARAM_PEER_PARAM_UTILS_H
|
||||||
|
|
||||||
|
#include <float.h>
|
||||||
|
|
||||||
|
#include <spa/utils/dict.h>
|
||||||
|
#include <spa/pod/builder.h>
|
||||||
|
#include <spa/pod/iter.h>
|
||||||
|
#include <spa/pod/parser.h>
|
||||||
|
#include <spa/pod/compare.h>
|
||||||
|
#include <spa/param/peer.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup spa_param
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SPA_API_PEER_PARAM_UTILS
|
||||||
|
#ifdef SPA_API_IMPL
|
||||||
|
#define SPA_API_PEER_PARAM_UTILS SPA_API_IMPL
|
||||||
|
#else
|
||||||
|
#define SPA_API_PEER_PARAM_UTILS static inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SPA_API_PEER_PARAM_UTILS int
|
||||||
|
spa_peer_param_parse(const struct spa_pod *param, struct spa_peer_param_info *info,
|
||||||
|
size_t size, void **state)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
const struct spa_pod_object *obj = (const struct spa_pod_object*)param;
|
||||||
|
const struct spa_pod_prop *first, *start, *cur;
|
||||||
|
|
||||||
|
if ((res = spa_pod_parse_object(param,
|
||||||
|
SPA_TYPE_OBJECT_PeerParam, NULL)) < 0)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
first = spa_pod_prop_first(&obj->body);
|
||||||
|
start = *state ? spa_pod_prop_next((struct spa_pod_prop*)*state) : first;
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
for (cur = start; spa_pod_prop_is_inside(&obj->body, obj->pod.size, cur);
|
||||||
|
cur = spa_pod_prop_next(cur)) {
|
||||||
|
info->peer_id = cur->key;
|
||||||
|
info->param = &cur->value;
|
||||||
|
*state = (void*)cur;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
SPA_API_PEER_PARAM_UTILS void
|
||||||
|
spa_peer_param_build_start(struct spa_pod_builder *builder, struct spa_pod_frame *f, uint32_t id)
|
||||||
|
{
|
||||||
|
spa_pod_builder_push_object(builder, f, SPA_TYPE_OBJECT_PeerParam, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_PEER_PARAM_UTILS void
|
||||||
|
spa_peer_param_build_add_param(struct spa_pod_builder *builder, uint32_t peer_id,
|
||||||
|
const struct spa_pod *param)
|
||||||
|
{
|
||||||
|
spa_pod_builder_prop(builder, peer_id, 0);
|
||||||
|
if (param)
|
||||||
|
spa_pod_builder_primitive(builder, param);
|
||||||
|
else
|
||||||
|
spa_pod_builder_none(builder);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_PEER_PARAM_UTILS struct spa_pod *
|
||||||
|
spa_peer_param_build_end(struct spa_pod_builder *builder, struct spa_pod_frame *f)
|
||||||
|
{
|
||||||
|
return (struct spa_pod*)spa_pod_builder_pop(builder, f);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_PARAM_PEER_PARAM_UTILS_H */
|
||||||
37
spa/include/spa/param/peer.h
Normal file
37
spa/include/spa/param/peer.h
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2025 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_PARAM_PEER_PARAM_H
|
||||||
|
#define SPA_PARAM_PEER_PARAM_H
|
||||||
|
|
||||||
|
#include <spa/param/param.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup spa_param
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** properties for SPA_TYPE_OBJECT_PeerParam */
|
||||||
|
enum spa_peer_param {
|
||||||
|
SPA_PEER_PARAM_START, /**< id of peer as key, SPA_TYPE_Pod as value */
|
||||||
|
SPA_PEER_PARAM_END = 0xfffffffe,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct spa_peer_param_info {
|
||||||
|
uint32_t peer_id;
|
||||||
|
const struct spa_pod *param;
|
||||||
|
};
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_PARAM_PEER_PARAM_H */
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
#include <spa/pod/builder.h>
|
#include <spa/pod/builder.h>
|
||||||
#include <spa/pod/iter.h>
|
#include <spa/pod/iter.h>
|
||||||
#include <spa/pod/parser.h>
|
#include <spa/pod/parser.h>
|
||||||
|
#include <spa/pod/compare.h>
|
||||||
#include <spa/param/tag.h>
|
#include <spa/param/tag.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
@ -33,8 +34,7 @@ extern "C" {
|
||||||
SPA_API_TAG_UTILS int
|
SPA_API_TAG_UTILS int
|
||||||
spa_tag_compare(const struct spa_pod *a, const struct spa_pod *b)
|
spa_tag_compare(const struct spa_pod *a, const struct spa_pod *b)
|
||||||
{
|
{
|
||||||
return ((a == b) || (a && b && SPA_POD_SIZE(a) == SPA_POD_SIZE(b) &&
|
return spa_pod_memcmp(a, b);
|
||||||
memcmp(a, b, SPA_POD_SIZE(b)) == 0)) ? 0 : 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_API_TAG_UTILS int
|
SPA_API_TAG_UTILS int
|
||||||
|
|
|
||||||
|
|
@ -15,5 +15,7 @@
|
||||||
#include <spa/param/profile-types.h>
|
#include <spa/param/profile-types.h>
|
||||||
#include <spa/param/route-types.h>
|
#include <spa/param/route-types.h>
|
||||||
#include <spa/param/tag-types.h>
|
#include <spa/param/tag-types.h>
|
||||||
|
#include <spa/param/dict-types.h>
|
||||||
|
#include <spa/param/peer-types.h>
|
||||||
|
|
||||||
#endif /* SPA_PARAM_TYPE_INFO_H */
|
#endif /* SPA_PARAM_TYPE_INFO_H */
|
||||||
|
|
|
||||||
|
|
@ -111,8 +111,15 @@ SPA_API_POD_BODY int spa_pod_choice_n_values(uint32_t choice_type, uint32_t *min
|
||||||
SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size,
|
SPA_API_POD_BODY int spa_pod_body_from_data(void *data, size_t maxsize, off_t offset, size_t size,
|
||||||
struct spa_pod *pod, const void **body)
|
struct spa_pod *pod, const void **body)
|
||||||
{
|
{
|
||||||
if (offset < 0 || offset > (int64_t)UINT32_MAX)
|
if (offset < 0)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
/* On 32-bit platforms, off_t is a signed 32-bit type (since it tracks pointer
|
||||||
|
* width), and consequently can never exceed UINT32_MAX. Skip the upper-bound
|
||||||
|
* check on 32-bit platforms to avoid a compiler warning. */
|
||||||
|
#if __SIZEOF_POINTER__ > 4
|
||||||
|
if (offset > (int64_t)UINT32_MAX)
|
||||||
|
return -EINVAL;
|
||||||
|
#endif
|
||||||
if (size < sizeof(struct spa_pod) ||
|
if (size < sizeof(struct spa_pod) ||
|
||||||
size > maxsize ||
|
size > maxsize ||
|
||||||
maxsize - size < (uint32_t)offset)
|
maxsize - size < (uint32_t)offset)
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,13 @@ SPA_API_POD_COMPARE int spa_pod_compare_value(uint32_t type, const void *r1, con
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPA_API_POD_COMPARE int spa_pod_memcmp(const struct spa_pod *a,
|
||||||
|
const struct spa_pod *b)
|
||||||
|
{
|
||||||
|
return ((a == b) || (a && b && SPA_POD_SIZE(a) == SPA_POD_SIZE(b) &&
|
||||||
|
memcmp(a, b, SPA_POD_SIZE(b)) == 0)) ? 0 : 1;
|
||||||
|
}
|
||||||
|
|
||||||
SPA_API_POD_COMPARE int spa_pod_compare(const struct spa_pod *pod1,
|
SPA_API_POD_COMPARE int spa_pod_compare(const struct spa_pod *pod1,
|
||||||
const struct spa_pod *pod2)
|
const struct spa_pod *pod2)
|
||||||
{
|
{
|
||||||
|
|
@ -149,12 +156,8 @@ SPA_API_POD_COMPARE int spa_pod_compare(const struct spa_pod *pod1,
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SPA_TYPE_Array:
|
case SPA_TYPE_Array:
|
||||||
{
|
res = spa_pod_memcmp(pod1, pod2);
|
||||||
if (pod1->size != pod2->size)
|
|
||||||
return -EINVAL;
|
|
||||||
res = memcmp(SPA_POD_BODY(pod1), SPA_POD_BODY(pod2), pod2->size);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
if (pod1->size != pod2->size)
|
if (pod1->size != pod2->size)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,10 @@ SPA_API_POD_DYNAMIC void spa_pod_dynamic_builder_continue(struct spa_pod_dynamic
|
||||||
|
|
||||||
SPA_API_POD_DYNAMIC void spa_pod_dynamic_builder_clean(struct spa_pod_dynamic_builder *builder)
|
SPA_API_POD_DYNAMIC void spa_pod_dynamic_builder_clean(struct spa_pod_dynamic_builder *builder)
|
||||||
{
|
{
|
||||||
if (builder->data != builder->b.data)
|
if (builder->data != builder->b.data) {
|
||||||
free(builder->b.data);
|
free(builder->b.data);
|
||||||
|
builder->b.data = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_DEFINE_AUTO_CLEANUP(spa_pod_dynamic_builder, struct spa_pod_dynamic_builder, {
|
SPA_DEFINE_AUTO_CLEANUP(spa_pod_dynamic_builder, struct spa_pod_dynamic_builder, {
|
||||||
|
|
|
||||||
|
|
@ -339,9 +339,7 @@ SPA_API_POD_FILTER int spa_pod_filter_part(struct spa_pod_builder *b,
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if (pf != NULL) {
|
if (pf != NULL) {
|
||||||
if (pp->size != pf->size)
|
if (spa_pod_memcmp(pp, pf) != 0)
|
||||||
return -EINVAL;
|
|
||||||
if (memcmp(pp, pf, pp->size) != 0)
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
do_advance = true;
|
do_advance = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -62,6 +62,7 @@ struct spa_cpu { struct spa_interface iface; };
|
||||||
#define SPA_CPU_FLAG_BMI2 (1<<18) /**< Bit Manipulation Instruction Set 2 */
|
#define SPA_CPU_FLAG_BMI2 (1<<18) /**< Bit Manipulation Instruction Set 2 */
|
||||||
#define SPA_CPU_FLAG_AVX512 (1<<19) /**< AVX-512 */
|
#define SPA_CPU_FLAG_AVX512 (1<<19) /**< AVX-512 */
|
||||||
#define SPA_CPU_FLAG_SLOW_UNALIGNED (1<<20) /**< unaligned loads/stores are slow */
|
#define SPA_CPU_FLAG_SLOW_UNALIGNED (1<<20) /**< unaligned loads/stores are slow */
|
||||||
|
#define SPA_CPU_FLAG_SLOW_GATHER (1<<21) /**< gather functions are slow */
|
||||||
|
|
||||||
/* PPC specific */
|
/* PPC specific */
|
||||||
#define SPA_CPU_FLAG_ALTIVEC (1<<0) /**< standard */
|
#define SPA_CPU_FLAG_ALTIVEC (1<<0) /**< standard */
|
||||||
|
|
|
||||||
|
|
@ -41,7 +41,7 @@ struct itimerspec;
|
||||||
#define SPA_TYPE_INTERFACE_System SPA_TYPE_INFO_INTERFACE_BASE "System"
|
#define SPA_TYPE_INTERFACE_System SPA_TYPE_INFO_INTERFACE_BASE "System"
|
||||||
#define SPA_TYPE_INTERFACE_DataSystem SPA_TYPE_INFO_INTERFACE_BASE "DataSystem"
|
#define SPA_TYPE_INTERFACE_DataSystem SPA_TYPE_INFO_INTERFACE_BASE "DataSystem"
|
||||||
|
|
||||||
#define SPA_VERSION_SYSTEM 0
|
#define SPA_VERSION_SYSTEM 1
|
||||||
struct spa_system { struct spa_interface iface; };
|
struct spa_system { struct spa_interface iface; };
|
||||||
|
|
||||||
/* IO events */
|
/* IO events */
|
||||||
|
|
@ -59,11 +59,18 @@ struct spa_system { struct spa_interface iface; };
|
||||||
|
|
||||||
struct spa_poll_event {
|
struct spa_poll_event {
|
||||||
uint32_t events;
|
uint32_t events;
|
||||||
|
union {
|
||||||
void *data;
|
void *data;
|
||||||
|
uint64_t data_u64;
|
||||||
|
};
|
||||||
|
#ifdef __x86_64__
|
||||||
|
} __attribute__((packed));
|
||||||
|
#else
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
struct spa_system_methods {
|
struct spa_system_methods {
|
||||||
#define SPA_VERSION_SYSTEM_METHODS 0
|
#define SPA_VERSION_SYSTEM_METHODS 1
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
|
|
||||||
/* read/write/ioctl */
|
/* read/write/ioctl */
|
||||||
|
|
@ -151,7 +158,7 @@ SPA_API_SYSTEM int spa_system_pollfd_del(struct spa_system *object, int pfd, int
|
||||||
SPA_API_SYSTEM int spa_system_pollfd_wait(struct spa_system *object, int pfd,
|
SPA_API_SYSTEM int spa_system_pollfd_wait(struct spa_system *object, int pfd,
|
||||||
struct spa_poll_event *ev, int n_ev, int timeout)
|
struct spa_poll_event *ev, int n_ev, int timeout)
|
||||||
{
|
{
|
||||||
return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, pollfd_wait, 0, pfd, ev, n_ev, timeout);
|
return spa_api_method_fast_r(int, -ENOTSUP, spa_system, &object->iface, pollfd_wait, 1, pfd, ev, n_ev, timeout);
|
||||||
}
|
}
|
||||||
|
|
||||||
SPA_API_SYSTEM int spa_system_timerfd_create(struct spa_system *object, int clockid, int flags)
|
SPA_API_SYSTEM int spa_system_timerfd_create(struct spa_system *object, int clockid, int flags)
|
||||||
|
|
|
||||||
|
|
@ -386,6 +386,16 @@ struct spa_error_location {
|
||||||
} \
|
} \
|
||||||
} while(false)
|
} while(false)
|
||||||
|
|
||||||
|
#define spa_goto_if_fail(expr, label) \
|
||||||
|
do { \
|
||||||
|
if (SPA_UNLIKELY(!(expr))) { \
|
||||||
|
fprintf(stderr, "'%s' failed at %s:%u %s()\n", \
|
||||||
|
#expr , __FILE__, __LINE__, __func__); \
|
||||||
|
goto label; \
|
||||||
|
} \
|
||||||
|
} while(false)
|
||||||
|
|
||||||
|
|
||||||
/* spa_assert_se() is an assert which guarantees side effects of x,
|
/* spa_assert_se() is an assert which guarantees side effects of x,
|
||||||
* i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */
|
* i.e. is never optimized away, regardless of NDEBUG or FASTPATH. */
|
||||||
#ifndef __COVERITY__
|
#ifndef __COVERITY__
|
||||||
|
|
@ -457,6 +467,16 @@ struct spa_error_location {
|
||||||
_strp; \
|
_strp; \
|
||||||
})
|
})
|
||||||
|
|
||||||
|
#define spa_alloca(n, size, max_size) \
|
||||||
|
({ \
|
||||||
|
void *_res = NULL; \
|
||||||
|
if ((size_t)n > (size_t)max_size / (size_t)size) \
|
||||||
|
errno = ENOMEM; \
|
||||||
|
else \
|
||||||
|
_res = alloca((size_t)n * (size_t)size); \
|
||||||
|
_res; \
|
||||||
|
})
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* \}
|
* \}
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
#ifndef SPA_ENDIAN_H
|
#ifndef SPA_ENDIAN_H
|
||||||
#define SPA_ENDIAN_H
|
#define SPA_ENDIAN_H
|
||||||
|
|
||||||
#if defined(__FreeBSD__) || defined(__MidnightBSD__)
|
#if defined(__MidnightBSD__)
|
||||||
#include <sys/endian.h>
|
#include <sys/endian.h>
|
||||||
#define bswap_16 bswap16
|
#define bswap_16 bswap16
|
||||||
#define bswap_32 bswap32
|
#define bswap_32 bswap32
|
||||||
|
|
|
||||||
|
|
@ -89,10 +89,10 @@ extern "C" {
|
||||||
* \code{.c}
|
* \code{.c}
|
||||||
*
|
*
|
||||||
* static void bar_stdout(struct foo *f, const char *msg) {
|
* static void bar_stdout(struct foo *f, const char *msg) {
|
||||||
* printf(msg);
|
* printf("%s", msg);
|
||||||
* }
|
* }
|
||||||
* static void bar_stderr(struct foo *f, const char *msg) {
|
* static void bar_stderr(struct foo *f, const char *msg) {
|
||||||
* fprintf(stderr, msg);
|
* fprintf(stderr, "%s", msg);
|
||||||
* }
|
* }
|
||||||
*
|
*
|
||||||
* struct foo* get_foo_from_somewhere() {
|
* struct foo* get_foo_from_somewhere() {
|
||||||
|
|
|
||||||
445
spa/include/spa/utils/json-builder.h
Normal file
445
spa/include/spa/utils/json-builder.h
Normal file
|
|
@ -0,0 +1,445 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2026 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_UTILS_JSON_BUILDER_H
|
||||||
|
#define SPA_UTILS_JSON_BUILDER_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <math.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
|
|
||||||
|
#include <spa/utils/defs.h>
|
||||||
|
#include <spa/utils/ansi.h>
|
||||||
|
#include <spa/utils/json.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#else
|
||||||
|
#include <stdbool.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef SPA_API_JSON_BUILDER
|
||||||
|
#ifdef SPA_API_IMPL
|
||||||
|
#define SPA_API_JSON_BUILDER SPA_API_IMPL
|
||||||
|
#else
|
||||||
|
#define SPA_API_JSON_BUILDER static inline
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** \defgroup spa_json_builder JSON builder
|
||||||
|
* JSON builder functions
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \addtogroup spa_json_builder
|
||||||
|
* \{
|
||||||
|
*/
|
||||||
|
|
||||||
|
struct spa_json_builder {
|
||||||
|
FILE *f;
|
||||||
|
#define SPA_JSON_BUILDER_FLAG_CLOSE (1<<0)
|
||||||
|
#define SPA_JSON_BUILDER_FLAG_INDENT (1<<1)
|
||||||
|
#define SPA_JSON_BUILDER_FLAG_SPACE (1<<2)
|
||||||
|
#define SPA_JSON_BUILDER_FLAG_PRETTY (SPA_JSON_BUILDER_FLAG_INDENT|SPA_JSON_BUILDER_FLAG_SPACE)
|
||||||
|
#define SPA_JSON_BUILDER_FLAG_COLOR (1<<3)
|
||||||
|
#define SPA_JSON_BUILDER_FLAG_SIMPLE (1<<4)
|
||||||
|
#define SPA_JSON_BUILDER_FLAG_RAW (1<<5)
|
||||||
|
uint32_t flags;
|
||||||
|
uint32_t indent_off;
|
||||||
|
uint32_t level;
|
||||||
|
uint32_t indent;
|
||||||
|
uint32_t count;
|
||||||
|
const char *delim;
|
||||||
|
const char *comma;
|
||||||
|
const char *key_sep;
|
||||||
|
#define SPA_JSON_BUILDER_COLOR_NORMAL 0
|
||||||
|
#define SPA_JSON_BUILDER_COLOR_KEY 1
|
||||||
|
#define SPA_JSON_BUILDER_COLOR_LITERAL 2
|
||||||
|
#define SPA_JSON_BUILDER_COLOR_NUMBER 3
|
||||||
|
#define SPA_JSON_BUILDER_COLOR_STRING 4
|
||||||
|
#define SPA_JSON_BUILDER_COLOR_CONTAINER 5
|
||||||
|
const char *color[8];
|
||||||
|
};
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER int spa_json_builder_file(struct spa_json_builder *b, FILE *f, uint32_t flags)
|
||||||
|
{
|
||||||
|
bool color = flags & SPA_JSON_BUILDER_FLAG_COLOR;
|
||||||
|
bool simple = flags & SPA_JSON_BUILDER_FLAG_SIMPLE;
|
||||||
|
bool space = flags & SPA_JSON_BUILDER_FLAG_SPACE;
|
||||||
|
spa_zero(*b);
|
||||||
|
b->f = f;
|
||||||
|
b->flags = flags;
|
||||||
|
b->indent = 2;
|
||||||
|
b->delim = "";
|
||||||
|
b->comma = simple ? space ? "" : " " : ",";
|
||||||
|
b->key_sep = simple ? space ? " =" : "=" : ":";
|
||||||
|
b->color[0] = (color ? SPA_ANSI_RESET : "");
|
||||||
|
b->color[1] = (color ? SPA_ANSI_BRIGHT_BLUE : "");
|
||||||
|
b->color[2] = (color ? SPA_ANSI_BRIGHT_MAGENTA : "");
|
||||||
|
b->color[3] = (color ? SPA_ANSI_BRIGHT_CYAN : "");
|
||||||
|
b->color[4] = (color ? SPA_ANSI_BRIGHT_GREEN : "");
|
||||||
|
b->color[5] = (color ? SPA_ANSI_BRIGHT_YELLOW : "");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER int spa_json_builder_memstream(struct spa_json_builder *b,
|
||||||
|
char **mem, size_t *size, uint32_t flags)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
spa_zero(*b);
|
||||||
|
if ((f = open_memstream(mem, size)) == NULL)
|
||||||
|
return -errno;
|
||||||
|
return spa_json_builder_file(b, f, flags | SPA_JSON_BUILDER_FLAG_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER int spa_json_builder_membuf(struct spa_json_builder *b,
|
||||||
|
char *mem, size_t size, uint32_t flags)
|
||||||
|
{
|
||||||
|
FILE *f;
|
||||||
|
spa_zero(*b);
|
||||||
|
if ((f = fmemopen(mem, size, "w")) == NULL)
|
||||||
|
return -errno;
|
||||||
|
return spa_json_builder_file(b, f, flags | SPA_JSON_BUILDER_FLAG_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_close(struct spa_json_builder *b)
|
||||||
|
{
|
||||||
|
if (b->flags & SPA_JSON_BUILDER_FLAG_CLOSE)
|
||||||
|
fclose(b->f);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER int spa_json_builder_encode_string(struct spa_json_builder *b,
|
||||||
|
bool raw, const char *before, const char *val, int size, const char *after)
|
||||||
|
{
|
||||||
|
FILE *f = b->f;
|
||||||
|
int i, len;
|
||||||
|
if (raw) {
|
||||||
|
len = fprintf(f, "%s%.*s%s", before, size, val, after) - 1;
|
||||||
|
} else {
|
||||||
|
len = fprintf(f, "%s\"", before);
|
||||||
|
for (i = 0; i < size && val[i]; i++) {
|
||||||
|
char v = val[i];
|
||||||
|
switch (v) {
|
||||||
|
case '\n': len += fprintf(f, "\\n"); break;
|
||||||
|
case '\r': len += fprintf(f, "\\r"); break;
|
||||||
|
case '\b': len += fprintf(f, "\\b"); break;
|
||||||
|
case '\t': len += fprintf(f, "\\t"); break;
|
||||||
|
case '\f': len += fprintf(f, "\\f"); break;
|
||||||
|
case '\\':
|
||||||
|
case '"': len += fprintf(f, "\\%c", v); break;
|
||||||
|
default:
|
||||||
|
if (v > 0 && v < 0x20)
|
||||||
|
len += fprintf(f, "\\u%04x", v);
|
||||||
|
else
|
||||||
|
len += fprintf(f, "%c", v);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
len += fprintf(f, "\"%s", after);
|
||||||
|
}
|
||||||
|
return len-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER
|
||||||
|
void spa_json_builder_add_simple(struct spa_json_builder *b, const char *key, int key_len,
|
||||||
|
char type, const char *val, int val_len)
|
||||||
|
{
|
||||||
|
bool indent = b->indent_off == 0 && (b->flags & SPA_JSON_BUILDER_FLAG_INDENT);
|
||||||
|
bool space = b->flags & SPA_JSON_BUILDER_FLAG_SPACE;
|
||||||
|
bool force_raw = b->flags & SPA_JSON_BUILDER_FLAG_RAW;
|
||||||
|
bool raw = true, simple = b->flags & SPA_JSON_BUILDER_FLAG_SIMPLE;
|
||||||
|
int color;
|
||||||
|
|
||||||
|
if (val == NULL || val_len == 0) {
|
||||||
|
val = "null";
|
||||||
|
val_len = 4;
|
||||||
|
type = 'l';
|
||||||
|
}
|
||||||
|
if (type == 0) {
|
||||||
|
if (spa_json_is_container(val, val_len))
|
||||||
|
type = simple ? 'C' : 'S';
|
||||||
|
else if (val_len > 0 && (*val == '}' || *val == ']'))
|
||||||
|
type = 'e';
|
||||||
|
else if (spa_json_is_null(val, val_len) ||
|
||||||
|
spa_json_is_bool(val, val_len))
|
||||||
|
type = 'l';
|
||||||
|
else if (spa_json_is_string(val, val_len))
|
||||||
|
type = 's';
|
||||||
|
else if (spa_json_is_json_number(val, val_len))
|
||||||
|
type = 'd';
|
||||||
|
else if (simple && (spa_json_is_float(val, val_len) ||
|
||||||
|
spa_json_is_int(val, val_len)))
|
||||||
|
type = 'd';
|
||||||
|
else
|
||||||
|
type = 'S';
|
||||||
|
}
|
||||||
|
switch (type) {
|
||||||
|
case 'e':
|
||||||
|
b->level -= b->indent;
|
||||||
|
b->delim = "";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
fprintf(b->f, "%s%s%*s", b->delim, b->count == 0 ? "" : indent ? "\n" : space ? " " : "",
|
||||||
|
indent ? b->level : 0, "");
|
||||||
|
if (key) {
|
||||||
|
bool key_raw = force_raw || (simple && spa_json_make_simple_string(&key, &key_len)) ||
|
||||||
|
spa_json_is_string(key, key_len);
|
||||||
|
spa_json_builder_encode_string(b, key_raw,
|
||||||
|
b->color[1], key, key_len, b->color[0]);
|
||||||
|
fprintf(b->f, "%s%s", b->key_sep, space ? " " : "");
|
||||||
|
}
|
||||||
|
b->delim = b->comma;
|
||||||
|
switch (type) {
|
||||||
|
case 'c':
|
||||||
|
color = SPA_JSON_BUILDER_COLOR_NORMAL;
|
||||||
|
val_len = 1;
|
||||||
|
b->delim = "";
|
||||||
|
b->level += b->indent;
|
||||||
|
if (val[1] == '-') b->indent_off++;
|
||||||
|
break;
|
||||||
|
case 'e':
|
||||||
|
color = SPA_JSON_BUILDER_COLOR_NORMAL;
|
||||||
|
val_len = 1;
|
||||||
|
if (val[1] == '-') b->indent_off--;
|
||||||
|
break;
|
||||||
|
case 'l':
|
||||||
|
color = SPA_JSON_BUILDER_COLOR_LITERAL;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
color = SPA_JSON_BUILDER_COLOR_NUMBER;
|
||||||
|
break;
|
||||||
|
case 's':
|
||||||
|
color = SPA_JSON_BUILDER_COLOR_STRING;
|
||||||
|
break;
|
||||||
|
case 'C':
|
||||||
|
color = SPA_JSON_BUILDER_COLOR_CONTAINER;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
color = SPA_JSON_BUILDER_COLOR_STRING;
|
||||||
|
raw = force_raw || (simple && spa_json_make_simple_string(&val, &val_len));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
spa_json_builder_encode_string(b, raw, b->color[color], val, val_len, b->color[0]);
|
||||||
|
b->count++;
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_push(struct spa_json_builder *b,
|
||||||
|
const char *key, const char *val)
|
||||||
|
{
|
||||||
|
spa_json_builder_add_simple(b, key, INT_MAX, 'c', val, INT_MAX);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_pop(struct spa_json_builder *b,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
spa_json_builder_add_simple(b, NULL, 0, 'e', val, INT_MAX);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_null(struct spa_json_builder *b,
|
||||||
|
const char *key)
|
||||||
|
{
|
||||||
|
spa_json_builder_add_simple(b, key, INT_MAX, 'l', "null", 4);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_bool(struct spa_json_builder *b,
|
||||||
|
const char *key, bool val)
|
||||||
|
{
|
||||||
|
spa_json_builder_add_simple(b, key, INT_MAX, 'l', val ? "true" : "false", INT_MAX);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_int(struct spa_json_builder *b,
|
||||||
|
const char *key, int64_t val)
|
||||||
|
{
|
||||||
|
char str[128];
|
||||||
|
snprintf(str, sizeof(str), "%" PRIi64, val);
|
||||||
|
spa_json_builder_add_simple(b, key, INT_MAX, 'd', str, INT_MAX);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_uint(struct spa_json_builder *b,
|
||||||
|
const char *key, uint64_t val)
|
||||||
|
{
|
||||||
|
char str[128];
|
||||||
|
snprintf(str, sizeof(str), "%" PRIu64, val);
|
||||||
|
spa_json_builder_add_simple(b, key, INT_MAX, 'd', str, INT_MAX);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_double(struct spa_json_builder *b,
|
||||||
|
const char *key, double val)
|
||||||
|
{
|
||||||
|
char str[64];
|
||||||
|
spa_json_format_float(str, sizeof(str), (float)val);
|
||||||
|
spa_json_builder_add_simple(b, key, INT_MAX, 'd', str, INT_MAX);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_string(struct spa_json_builder *b,
|
||||||
|
const char *key, const char *val)
|
||||||
|
{
|
||||||
|
spa_json_builder_add_simple(b, key, INT_MAX, 'S', val, INT_MAX);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER SPA_PRINTF_FUNC(3,0)
|
||||||
|
void spa_json_builder_object_stringv(struct spa_json_builder *b,
|
||||||
|
const char *key, const char *fmt, va_list va)
|
||||||
|
{
|
||||||
|
char *val;
|
||||||
|
if (vasprintf(&val, fmt, va) > 0) {
|
||||||
|
spa_json_builder_object_string(b, key, val);
|
||||||
|
free(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER SPA_PRINTF_FUNC(3,4)
|
||||||
|
void spa_json_builder_object_stringf(struct spa_json_builder *b,
|
||||||
|
const char *key, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
spa_json_builder_object_stringv(b, key, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_value_iter(struct spa_json_builder *b,
|
||||||
|
struct spa_json *it, const char *key, int key_len, const char *val, int len)
|
||||||
|
{
|
||||||
|
struct spa_json sub;
|
||||||
|
if (spa_json_is_array(val, len)) {
|
||||||
|
spa_json_builder_add_simple(b, key, key_len, 'c', "[", 1);
|
||||||
|
spa_json_enter(it, &sub);
|
||||||
|
while ((len = spa_json_next(&sub, &val)) > 0)
|
||||||
|
spa_json_builder_object_value_iter(b, &sub, NULL, 0, val, len);
|
||||||
|
spa_json_builder_pop(b, "]");
|
||||||
|
}
|
||||||
|
else if (spa_json_is_object(val, len)) {
|
||||||
|
const char *k;
|
||||||
|
int kl;
|
||||||
|
spa_json_builder_add_simple(b, key, key_len, 'c', "{", 1);
|
||||||
|
spa_json_enter(it, &sub);
|
||||||
|
while ((kl = spa_json_next(&sub, &k)) > 0) {
|
||||||
|
if ((len = spa_json_next(&sub, &val)) < 0)
|
||||||
|
break;
|
||||||
|
spa_json_builder_object_value_iter(b, &sub, k, kl, val, len);
|
||||||
|
}
|
||||||
|
spa_json_builder_pop(b, "}");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
spa_json_builder_add_simple(b, key, key_len, 0, val, len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_value_full(struct spa_json_builder *b,
|
||||||
|
bool recurse, const char *key, int key_len, const char *val, int val_len)
|
||||||
|
{
|
||||||
|
if (!recurse || val == NULL) {
|
||||||
|
spa_json_builder_add_simple(b, key, key_len, 0, val, val_len);
|
||||||
|
} else {
|
||||||
|
struct spa_json it[1];
|
||||||
|
const char *v;
|
||||||
|
if (spa_json_begin(&it[0], val, val_len, &v) >= 0)
|
||||||
|
spa_json_builder_object_value_iter(b, &it[0], key, key_len, val, val_len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_object_value(struct spa_json_builder *b,
|
||||||
|
bool recurse, const char *key, const char *val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_value_full(b, recurse, key, key ? strlen(key) : 0,
|
||||||
|
val, val ? strlen(val) : 0);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER SPA_PRINTF_FUNC(4,5)
|
||||||
|
void spa_json_builder_object_valuef(struct spa_json_builder *b,
|
||||||
|
bool recurse, const char *key, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
char *val;
|
||||||
|
va_start(va, fmt);
|
||||||
|
if (vasprintf(&val, fmt, va) > 0) {
|
||||||
|
spa_json_builder_object_value(b, recurse, key, val);
|
||||||
|
free(val);
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* array functions */
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_push(struct spa_json_builder *b,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_push(b, NULL, val);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_null(struct spa_json_builder *b)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_null(b, NULL);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_bool(struct spa_json_builder *b,
|
||||||
|
bool val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_bool(b, NULL, val);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_int(struct spa_json_builder *b,
|
||||||
|
int64_t val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_int(b, NULL, val);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_uint(struct spa_json_builder *b,
|
||||||
|
uint64_t val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_uint(b, NULL, val);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_double(struct spa_json_builder *b,
|
||||||
|
double val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_double(b, NULL, val);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_string(struct spa_json_builder *b,
|
||||||
|
const char *val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_string(b, NULL, val);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER SPA_PRINTF_FUNC(2,3)
|
||||||
|
void spa_json_builder_array_stringf(struct spa_json_builder *b,
|
||||||
|
const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
va_start(va, fmt);
|
||||||
|
spa_json_builder_object_stringv(b, NULL, fmt, va);
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER void spa_json_builder_array_value(struct spa_json_builder *b,
|
||||||
|
bool recurse, const char *val)
|
||||||
|
{
|
||||||
|
spa_json_builder_object_value(b, recurse, NULL, val);
|
||||||
|
}
|
||||||
|
SPA_API_JSON_BUILDER SPA_PRINTF_FUNC(3,4)
|
||||||
|
void spa_json_builder_array_valuef(struct spa_json_builder *b, bool recurse, const char *fmt, ...)
|
||||||
|
{
|
||||||
|
va_list va;
|
||||||
|
char *val;
|
||||||
|
va_start(va, fmt);
|
||||||
|
if (vasprintf(&val, fmt, va) > 0) {
|
||||||
|
spa_json_builder_object_value(b, recurse, NULL, val);
|
||||||
|
free(val);
|
||||||
|
}
|
||||||
|
va_end(va);
|
||||||
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON_BUILDER char *spa_json_builder_reformat(const char *json, uint32_t flags)
|
||||||
|
{
|
||||||
|
struct spa_json_builder b;
|
||||||
|
char *mem;
|
||||||
|
size_t size;
|
||||||
|
int res;
|
||||||
|
if ((res = spa_json_builder_memstream(&b, &mem, &size, flags)) < 0) {
|
||||||
|
errno = -res;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
spa_json_builder_array_value(&b, true, json);
|
||||||
|
spa_json_builder_close(&b);
|
||||||
|
return mem;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_UTILS_JSON_BUILDER_H */
|
||||||
|
|
@ -232,7 +232,7 @@ SPA_API_JSON int spa_json_next(struct spa_json * iter, const char **value)
|
||||||
switch (cur) {
|
switch (cur) {
|
||||||
case '\0':
|
case '\0':
|
||||||
case '\t': case ' ': case '\r': case '\n':
|
case '\t': case ' ': case '\r': case '\n':
|
||||||
case '"': case '#':
|
case '"': case '#': case '{': case '[':
|
||||||
case ':': case ',': case '=': case ']': case '}':
|
case ':': case ',': case '=': case ']': case '}':
|
||||||
iter->state = __STRUCT | flag;
|
iter->state = __STRUCT | flag;
|
||||||
if (iter->depth > 0)
|
if (iter->depth > 0)
|
||||||
|
|
@ -399,6 +399,10 @@ SPA_API_JSON int spa_json_is_container(const char *val, int len)
|
||||||
{
|
{
|
||||||
return len > 0 && (*val == '{' || *val == '[');
|
return len > 0 && (*val == '{' || *val == '[');
|
||||||
}
|
}
|
||||||
|
SPA_API_JSON int spa_json_is_container_end(const char *val, int len)
|
||||||
|
{
|
||||||
|
return len > 0 && (*val == '}' || *val == ']');
|
||||||
|
}
|
||||||
|
|
||||||
/* object */
|
/* object */
|
||||||
SPA_API_JSON int spa_json_is_object(const char *val, int len)
|
SPA_API_JSON int spa_json_is_object(const char *val, int len)
|
||||||
|
|
@ -421,20 +425,11 @@ SPA_API_JSON bool spa_json_is_null(const char *val, int len)
|
||||||
/* float */
|
/* float */
|
||||||
SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
|
SPA_API_JSON int spa_json_parse_float(const char *val, int len, float *result)
|
||||||
{
|
{
|
||||||
char buf[96];
|
char buf[96], *end;
|
||||||
char *end;
|
|
||||||
int pos;
|
|
||||||
|
|
||||||
if (len <= 0 || len >= (int)sizeof(buf))
|
if (len <= 0 || len >= (int)sizeof(buf))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
for (pos = 0; pos < len; ++pos) {
|
|
||||||
switch (val[pos]) {
|
|
||||||
case '+': case '-': case '0' ... '9': case '.': case 'e': case 'E': break;
|
|
||||||
default: return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(buf, val, len);
|
memcpy(buf, val, len);
|
||||||
buf[len] = '\0';
|
buf[len] = '\0';
|
||||||
|
|
||||||
|
|
@ -462,8 +457,7 @@ SPA_API_JSON char *spa_json_format_float(char *str, int size, float val)
|
||||||
/* int */
|
/* int */
|
||||||
SPA_API_JSON int spa_json_parse_int(const char *val, int len, int *result)
|
SPA_API_JSON int spa_json_parse_int(const char *val, int len, int *result)
|
||||||
{
|
{
|
||||||
char buf[64];
|
char buf[64], *end;
|
||||||
char *end;
|
|
||||||
|
|
||||||
if (len <= 0 || len >= (int)sizeof(buf))
|
if (len <= 0 || len >= (int)sizeof(buf))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -480,6 +474,39 @@ SPA_API_JSON bool spa_json_is_int(const char *val, int len)
|
||||||
return spa_json_parse_int(val, len, &dummy);
|
return spa_json_parse_int(val, len, &dummy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPA_API_JSON bool spa_json_is_json_number(const char *val, int len)
|
||||||
|
{
|
||||||
|
static const int8_t trans[9][7] = {
|
||||||
|
/* '1-9' '0' '-' '+' '.' 'eE' other */
|
||||||
|
/* 0 */ {-1, -1, -1, -1, 6, 7, -1 }, /* after '0' */
|
||||||
|
/* 1 */ { 1, 1, -1, -1, 6, 7, -1 }, /* in integer */
|
||||||
|
/* 2 */ { 2, 2, -1, -1, -1, 7, -1 }, /* in fraction */
|
||||||
|
/* 3 */ { 3, 3, -1, -1, -1, -1, -1 }, /* in exponent */
|
||||||
|
/* 4 */ { 1, 0, 5, -1, -1, -1, -1 }, /* start */
|
||||||
|
/* 5 */ { 1, 0, -1, -1, -1, -1, -1 }, /* after '-' */
|
||||||
|
/* 6 */ { 2, 2, -1, -1, -1, -1, -1 }, /* after '.' */
|
||||||
|
/* 7 */ { 3, 3, 8, 8, -1, -1, -1 }, /* after 'e'/'E' */
|
||||||
|
/* 8 */ { 3, 3, -1, -1, -1, -1, -1 }, /* after exp sign */
|
||||||
|
};
|
||||||
|
static const int8_t char_class[128] = {
|
||||||
|
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 0-15 */
|
||||||
|
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 16-31 */
|
||||||
|
6,6,6,6,6,6,6,6,6,6,6,3,6,2,4,6, /* 32-47: + - . */
|
||||||
|
1,0,0,0,0,0,0,0,0,0,6,6,6,6,6,6, /* 48-63: 0-9 */
|
||||||
|
6,6,6,6,6,5,6,6,6,6,6,6,6,6,6,6, /* 64-79: E */
|
||||||
|
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 80-95 */
|
||||||
|
6,6,6,6,6,5,6,6,6,6,6,6,6,6,6,6, /* 96-111: e */
|
||||||
|
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, /* 112-127 */
|
||||||
|
};
|
||||||
|
int i, state = 4;
|
||||||
|
|
||||||
|
for (i = 0; i < len; i++) {
|
||||||
|
if ((state = trans[state][char_class[val[i]&0x7f]]) < 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return state < 4;
|
||||||
|
}
|
||||||
|
|
||||||
/* bool */
|
/* bool */
|
||||||
SPA_API_JSON bool spa_json_is_true(const char *val, int len)
|
SPA_API_JSON bool spa_json_is_true(const char *val, int len)
|
||||||
{
|
{
|
||||||
|
|
@ -510,6 +537,46 @@ SPA_API_JSON bool spa_json_is_string(const char *val, int len)
|
||||||
{
|
{
|
||||||
return len > 1 && *val == '"';
|
return len > 1 && *val == '"';
|
||||||
}
|
}
|
||||||
|
SPA_API_JSON bool spa_json_is_simple_string(const char *val, int size)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
static const char *REJECT = "\"\\'=:,{}[]()#";
|
||||||
|
for (i = 0; i < size && val[i]; i++) {
|
||||||
|
if (val[i] <= 0x20 || strchr(REJECT, val[i]) != NULL)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
SPA_API_JSON bool spa_json_make_simple_string(const char **val, int *len)
|
||||||
|
{
|
||||||
|
int i, l = *len;
|
||||||
|
const char *v = *val;
|
||||||
|
static const char *REJECT = "\"\\'=:,{}[]()#";
|
||||||
|
int trimmed = 0, bad = 0;
|
||||||
|
for (i = 0; i < l && v[i]; i++) {
|
||||||
|
if (i == 0 && v[0] == '\"')
|
||||||
|
trimmed++;
|
||||||
|
else if ((i+1 == l || !v[i+1]) && v[i] == '\"')
|
||||||
|
trimmed++;
|
||||||
|
else if (v[i] <= 0x20 || strchr(REJECT, v[i]) != NULL)
|
||||||
|
bad++;
|
||||||
|
}
|
||||||
|
if (trimmed == 0 && bad == 0 && i > 0)
|
||||||
|
return true;
|
||||||
|
else if (trimmed == 2) {
|
||||||
|
if (bad == 0 && i > 2 &&
|
||||||
|
!spa_json_is_null(&v[1], i-2) &&
|
||||||
|
!spa_json_is_bool(&v[1], i-2) &&
|
||||||
|
!spa_json_is_float(&v[1], i-2) &&
|
||||||
|
!spa_json_is_container(&v[1], i-2) &&
|
||||||
|
!spa_json_is_container_end(&v[1], i-2)) {
|
||||||
|
(*len) = i-2;
|
||||||
|
(*val)++;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
|
SPA_API_JSON int spa_json_parse_hex(const char *p, int num, uint32_t *res)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -121,7 +121,10 @@ SPA_API_JSON_POD int spa_json_to_pod_part(struct spa_pod_builder *b, uint32_t fl
|
||||||
spa_pod_builder_none(b);
|
spa_pod_builder_none(b);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *val = (char*)alloca(len+1);
|
char *val;
|
||||||
|
if (len > 8192)
|
||||||
|
return -ENOSPC;
|
||||||
|
val = (char*)alloca(len+1);
|
||||||
spa_json_parse_stringn(value, len, val, len+1);
|
spa_json_parse_stringn(value, len, val, len+1);
|
||||||
switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) {
|
switch (info ? info->parent : (uint32_t)SPA_TYPE_Struct) {
|
||||||
case SPA_TYPE_Id:
|
case SPA_TYPE_Id:
|
||||||
|
|
|
||||||
|
|
@ -98,15 +98,6 @@ extern "C" {
|
||||||
#define SPA_KEY_API_LIBCAMERA_ROTATION "api.libcamera.rotation" /**< rotation of the camera:
|
#define SPA_KEY_API_LIBCAMERA_ROTATION "api.libcamera.rotation" /**< rotation of the camera:
|
||||||
* "0", "90", "180" or "270" */
|
* "0", "90", "180" or "270" */
|
||||||
|
|
||||||
/** info from libcamera_capability */
|
|
||||||
#define SPA_KEY_API_LIBCAMERA_CAP_DRIVER "api.libcamera.cap.driver" /**< driver from capbility */
|
|
||||||
#define SPA_KEY_API_LIBCAMERA_CAP_CARD "api.libcamera.cap.card" /**< caps from capability */
|
|
||||||
#define SPA_KEY_API_LIBCAMERA_CAP_BUS_INFO "api.libcamera.cap.bus_info"/**< bus_info from capability */
|
|
||||||
#define SPA_KEY_API_LIBCAMERA_CAP_VERSION "api.libcamera.cap.version" /**< version from capability as %u.%u.%u */
|
|
||||||
#define SPA_KEY_API_LIBCAMERA_CAP_CAPABILITIES \
|
|
||||||
"api.libcamera.cap.capabilities" /**< capabilities from capability */
|
|
||||||
#define SPA_KEY_API_LIBCAMERA_CAP_DEVICE_CAPS \
|
|
||||||
"api.libcamera.cap.device-caps" /**< device_caps from capability */
|
|
||||||
/** info from v4l2_capability */
|
/** info from v4l2_capability */
|
||||||
#define SPA_KEY_API_V4L2_CAP_DRIVER "api.v4l2.cap.driver" /**< driver from capbility */
|
#define SPA_KEY_API_V4L2_CAP_DRIVER "api.v4l2.cap.driver" /**< driver from capbility */
|
||||||
#define SPA_KEY_API_V4L2_CAP_CARD "api.v4l2.cap.card" /**< caps from capability */
|
#define SPA_KEY_API_V4L2_CAP_CARD "api.v4l2.cap.card" /**< caps from capability */
|
||||||
|
|
|
||||||
40
spa/include/spa/utils/overflow.h
Normal file
40
spa/include/spa/utils/overflow.h
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
/* Simple Plugin API */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2026 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#ifndef SPA_UTILS_OVERFLOW_H
|
||||||
|
#define SPA_UTILS_OVERFLOW_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check for addition overflow
|
||||||
|
*
|
||||||
|
* Computes \a a + \a b and stores the result in \a *res.
|
||||||
|
* \return true if the addition overflowed, false otherwise
|
||||||
|
*/
|
||||||
|
#define spa_overflow_add(a, b, res) __builtin_add_overflow(a, b, res)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check for subtraction overflow
|
||||||
|
*
|
||||||
|
* Computes \a a - \a b and stores the result in \a *res.
|
||||||
|
* \return true if the subtraction overflowed, false otherwise
|
||||||
|
*/
|
||||||
|
#define spa_overflow_sub(a, b, res) __builtin_sub_overflow(a, b, res)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* \brief Check for multiplication overflow
|
||||||
|
*
|
||||||
|
* Computes \a a * \a b and stores the result in \a *res.
|
||||||
|
* \return true if the multiplication overflowed, false otherwise
|
||||||
|
*/
|
||||||
|
#define spa_overflow_mul(a, b, res) __builtin_mul_overflow(a, b, res)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
} /* extern "C" */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* SPA_UTILS_OVERFLOW_H */
|
||||||
|
|
@ -380,17 +380,26 @@ SPA_API_STRING void spa_strbuf_init(struct spa_strbuf *buf, char *buffer, size_t
|
||||||
buf->buffer[0] = '\0';
|
buf->buffer[0] = '\0';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SPA_PRINTF_FUNC(2, 0)
|
||||||
|
SPA_API_STRING int spa_strbuf_appendv(struct spa_strbuf *buf, const char *fmt, va_list args)
|
||||||
|
{
|
||||||
|
size_t remain = buf->maxsize - buf->pos;
|
||||||
|
int written = vsnprintf(&buf->buffer[buf->pos], remain, fmt, args);
|
||||||
|
if (written > 0)
|
||||||
|
buf->pos += SPA_MIN(remain, (size_t)written);
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
|
||||||
SPA_PRINTF_FUNC(2, 3)
|
SPA_PRINTF_FUNC(2, 3)
|
||||||
SPA_API_STRING int spa_strbuf_append(struct spa_strbuf *buf, const char *fmt, ...)
|
SPA_API_STRING int spa_strbuf_append(struct spa_strbuf *buf, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
size_t remain = buf->maxsize - buf->pos;
|
|
||||||
ssize_t written;
|
|
||||||
va_list args;
|
va_list args;
|
||||||
|
int written;
|
||||||
|
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
written = vsnprintf(&buf->buffer[buf->pos], remain, fmt, args);
|
written = spa_strbuf_appendv(buf, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
if (written > 0)
|
|
||||||
buf->pos += SPA_MIN(remain, (size_t)written);
|
|
||||||
return written;
|
return written;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
#ifndef SPA_TYPE_INFO_H
|
#ifndef SPA_TYPE_INFO_H
|
||||||
#define SPA_TYPE_INFO_H
|
#define SPA_TYPE_INFO_H
|
||||||
|
|
||||||
|
|
||||||
#include <spa/utils/defs.h>
|
#include <spa/utils/defs.h>
|
||||||
#include <spa/utils/type.h>
|
#include <spa/utils/type.h>
|
||||||
#include <spa/utils/enum-types.h>
|
#include <spa/utils/enum-types.h>
|
||||||
|
|
@ -78,6 +79,8 @@ static const struct spa_type_info spa_types[] = {
|
||||||
{ SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Latency, spa_type_param_latency },
|
{ SPA_TYPE_OBJECT_ParamLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Latency, spa_type_param_latency },
|
||||||
{ SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ProcessLatency, spa_type_param_process_latency },
|
{ SPA_TYPE_OBJECT_ParamProcessLatency, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_ProcessLatency, spa_type_param_process_latency },
|
||||||
{ SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Tag, spa_type_param_tag },
|
{ SPA_TYPE_OBJECT_ParamTag, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Tag, spa_type_param_tag },
|
||||||
|
{ SPA_TYPE_OBJECT_PeerParam, SPA_TYPE_Object, SPA_TYPE_INFO_PeerParam, spa_type_peer_param },
|
||||||
|
{ SPA_TYPE_OBJECT_ParamDict, SPA_TYPE_Object, SPA_TYPE_INFO_PARAM_Dict, spa_type_param_dict },
|
||||||
|
|
||||||
{ 0, 0, NULL, NULL }
|
{ 0, 0, NULL, NULL }
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -88,6 +88,8 @@ enum {
|
||||||
SPA_TYPE_OBJECT_ParamLatency,
|
SPA_TYPE_OBJECT_ParamLatency,
|
||||||
SPA_TYPE_OBJECT_ParamProcessLatency,
|
SPA_TYPE_OBJECT_ParamProcessLatency,
|
||||||
SPA_TYPE_OBJECT_ParamTag,
|
SPA_TYPE_OBJECT_ParamTag,
|
||||||
|
SPA_TYPE_OBJECT_PeerParam,
|
||||||
|
SPA_TYPE_OBJECT_ParamDict,
|
||||||
_SPA_TYPE_OBJECT_LAST, /**< not part of ABI */
|
_SPA_TYPE_OBJECT_LAST, /**< not part of ABI */
|
||||||
|
|
||||||
/* vendor extensions */
|
/* vendor extensions */
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,6 @@
|
||||||
#undef SPA_AUDIO_MAX_CHANNELS
|
#undef SPA_AUDIO_MAX_CHANNELS
|
||||||
|
|
||||||
#define SPA_API_IMPL SPA_EXPORT
|
#define SPA_API_IMPL SPA_EXPORT
|
||||||
#include <spa/utils/defs.h>
|
|
||||||
#include <spa/buffer/alloc.h>
|
#include <spa/buffer/alloc.h>
|
||||||
#include <spa/buffer/buffer.h>
|
#include <spa/buffer/buffer.h>
|
||||||
#include <spa/buffer/type-info.h>
|
#include <spa/buffer/type-info.h>
|
||||||
|
|
@ -126,16 +125,17 @@
|
||||||
#include <spa/param/video/raw-types.h>
|
#include <spa/param/video/raw-types.h>
|
||||||
#include <spa/param/video/raw-utils.h>
|
#include <spa/param/video/raw-utils.h>
|
||||||
#include <spa/param/video/type-info.h>
|
#include <spa/param/video/type-info.h>
|
||||||
|
#include <spa/pod/body.h>
|
||||||
#include <spa/pod/builder.h>
|
#include <spa/pod/builder.h>
|
||||||
#include <spa/pod/command.h>
|
#include <spa/pod/command.h>
|
||||||
#include <spa/pod/compare.h>
|
#include <spa/pod/compare.h>
|
||||||
#include <spa/pod/dynamic.h>
|
#include <spa/pod/dynamic.h>
|
||||||
#include <spa/pod/event.h>
|
#include <spa/pod/event.h>
|
||||||
#include <spa/pod/filter.h>
|
#include <spa/pod/filter.h>
|
||||||
#include <spa/pod/body.h>
|
|
||||||
#include <spa/pod/iter.h>
|
#include <spa/pod/iter.h>
|
||||||
#include <spa/pod/parser.h>
|
#include <spa/pod/parser.h>
|
||||||
#include <spa/pod/pod.h>
|
#include <spa/pod/pod.h>
|
||||||
|
#include <spa/pod/simplify.h>
|
||||||
#include <spa/pod/vararg.h>
|
#include <spa/pod/vararg.h>
|
||||||
#include <spa/support/cpu.h>
|
#include <spa/support/cpu.h>
|
||||||
#include <spa/support/dbus.h>
|
#include <spa/support/dbus.h>
|
||||||
|
|
@ -158,6 +158,7 @@
|
||||||
#include <spa/utils/hook.h>
|
#include <spa/utils/hook.h>
|
||||||
#include <spa/utils/json-core.h>
|
#include <spa/utils/json-core.h>
|
||||||
#include <spa/utils/json.h>
|
#include <spa/utils/json.h>
|
||||||
|
#include <spa/utils/json-builder.h>
|
||||||
#include <spa/utils/json-pod.h>
|
#include <spa/utils/json-pod.h>
|
||||||
#include <spa/utils/keys.h>
|
#include <spa/utils/keys.h>
|
||||||
#include <spa/utils/list.h>
|
#include <spa/utils/list.h>
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ struct impl_data {
|
||||||
std::unique_ptr<float *[]> play_buffer, rec_buffer, out_buffer;
|
std::unique_ptr<float *[]> play_buffer, rec_buffer, out_buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.eac.webrtc");
|
SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.aec.webrtc");
|
||||||
#undef SPA_LOG_TOPIC_DEFAULT
|
#undef SPA_LOG_TOPIC_DEFAULT
|
||||||
#define SPA_LOG_TOPIC_DEFAULT &log_topic
|
#define SPA_LOG_TOPIC_DEFAULT &log_topic
|
||||||
|
|
||||||
|
|
@ -221,6 +221,11 @@ static int webrtc_init2(void *object, const struct spa_dict *args,
|
||||||
}};
|
}};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
if (out_info->channels != 1 && rec_info->channels != out_info->channels) {
|
||||||
|
spa_log_error(impl->log, "Source channels must be equal to capture channels or 1");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(HAVE_WEBRTC)
|
#if defined(HAVE_WEBRTC)
|
||||||
auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config));
|
auto apm = std::unique_ptr<webrtc::AudioProcessing>(webrtc::AudioProcessing::Create(config));
|
||||||
#elif defined(HAVE_WEBRTC1)
|
#elif defined(HAVE_WEBRTC1)
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,11 @@ ATTRS{idVendor}=="1395", ATTRS{idProduct}=="0300", ENV{ACP_PROFILE_SET}="usb-gam
|
||||||
# Sennheiser GSP 670 USB headset
|
# Sennheiser GSP 670 USB headset
|
||||||
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="008a", ENV{ACP_PROFILE_SET}="usb-gaming-headset.conf"
|
ATTRS{idVendor}=="1395", ATTRS{idProduct}=="008a", ENV{ACP_PROFILE_SET}="usb-gaming-headset.conf"
|
||||||
|
|
||||||
|
# JBL Quantum One
|
||||||
|
ATTRS{idVendor}=="0ecb", ATTRS{idProduct}=="203a", ENV{ACP_PROFILE_SET}="usb-gaming-headset-gamefirst.conf"
|
||||||
|
# JBL Quantum 810 Wireless
|
||||||
|
ATTRS{idVendor}=="0ecb", ATTRS{idProduct}=="2069", ENV{ACP_PROFILE_SET}="usb-gaming-headset-gamefirst.conf"
|
||||||
|
|
||||||
# Audioengine HD3 powered speakers support IEC958 but don't actually
|
# Audioengine HD3 powered speakers support IEC958 but don't actually
|
||||||
# have any digital outputs.
|
# have any digital outputs.
|
||||||
ATTRS{idVendor}=="0a12", ATTRS{idProduct}=="4007", ENV{ACP_PROFILE_SET}="analog-only.conf"
|
ATTRS{idVendor}=="0a12", ATTRS{idProduct}=="4007", ENV{ACP_PROFILE_SET}="analog-only.conf"
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,9 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
|
#ifdef __linux__
|
||||||
#include <alloca.h>
|
#include <alloca.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include <spa/debug/context.h>
|
#include <spa/debug/context.h>
|
||||||
#include <spa/utils/string.h>
|
#include <spa/utils/string.h>
|
||||||
|
|
|
||||||
|
|
@ -227,6 +227,7 @@ static void init_device(pa_card *impl, pa_alsa_device *dev, pa_alsa_direction_t
|
||||||
dev->device.format.rate_mask = m->sample_spec.rate;
|
dev->device.format.rate_mask = m->sample_spec.rate;
|
||||||
dev->device.format.channels = m->channel_map.channels;
|
dev->device.format.channels = m->channel_map.channels;
|
||||||
dev->device.format.map = calloc(m->channel_map.channels, sizeof(uint32_t));
|
dev->device.format.map = calloc(m->channel_map.channels, sizeof(uint32_t));
|
||||||
|
if (dev->device.format.map != NULL)
|
||||||
channelmap_to_acp(&m->channel_map, dev->device.format.map);
|
channelmap_to_acp(&m->channel_map, dev->device.format.map);
|
||||||
pa_cvolume_reset(&dev->real_volume, dev->device.format.channels);
|
pa_cvolume_reset(&dev->real_volume, dev->device.format.channels);
|
||||||
pa_cvolume_reset(&dev->soft_volume, dev->device.format.channels);
|
pa_cvolume_reset(&dev->soft_volume, dev->device.format.channels);
|
||||||
|
|
@ -485,13 +486,11 @@ static int add_pro_profile(pa_card *impl, uint32_t index)
|
||||||
if ((n_capture == 1 && n_playback == 1) || is_firewire) {
|
if ((n_capture == 1 && n_playback == 1) || is_firewire) {
|
||||||
PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
|
PA_IDXSET_FOREACH(m, ap->output_mappings, idx) {
|
||||||
pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
|
pa_proplist_setf(m->output_proplist, "node.group", "pro-audio-%u", index);
|
||||||
pa_proplist_setf(m->output_proplist, "node.link-group", "pro-audio-%u", index);
|
|
||||||
pa_proplist_setf(m->output_proplist, "api.alsa.auto-link", "true");
|
pa_proplist_setf(m->output_proplist, "api.alsa.auto-link", "true");
|
||||||
pa_proplist_setf(m->output_proplist, "api.alsa.disable-tsched", "true");
|
pa_proplist_setf(m->output_proplist, "api.alsa.disable-tsched", "true");
|
||||||
}
|
}
|
||||||
PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
|
PA_IDXSET_FOREACH(m, ap->input_mappings, idx) {
|
||||||
pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
|
pa_proplist_setf(m->input_proplist, "node.group", "pro-audio-%u", index);
|
||||||
pa_proplist_setf(m->input_proplist, "node.link-group", "pro-audio-%u", index);
|
|
||||||
pa_proplist_setf(m->input_proplist, "api.alsa.auto-link", "true");
|
pa_proplist_setf(m->input_proplist, "api.alsa.auto-link", "true");
|
||||||
pa_proplist_setf(m->input_proplist, "api.alsa.disable-tsched", "true");
|
pa_proplist_setf(m->input_proplist, "api.alsa.disable-tsched", "true");
|
||||||
}
|
}
|
||||||
|
|
@ -1137,7 +1136,7 @@ static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask)
|
||||||
}
|
}
|
||||||
|
|
||||||
old_position = pa_proplist_gets(p->proplist, ACP_KEY_AUDIO_POSITION_DETECTED);
|
old_position = pa_proplist_gets(p->proplist, ACP_KEY_AUDIO_POSITION_DETECTED);
|
||||||
if (eld.speakers == 0) {
|
if (eld.speakers == 0 || eld.lpcm_channels == 0) {
|
||||||
changed |= old_position != NULL;
|
changed |= old_position != NULL;
|
||||||
pa_proplist_unset(p->proplist, ACP_KEY_AUDIO_POSITION_DETECTED);
|
pa_proplist_unset(p->proplist, ACP_KEY_AUDIO_POSITION_DETECTED);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -1146,32 +1145,38 @@ static int hdmi_eld_changed(snd_mixer_elem_t *melem, unsigned int mask)
|
||||||
struct spa_strbuf b;
|
struct spa_strbuf b;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
|
|
||||||
|
#define _ADD_CHANNEL_POSITION(pos) \
|
||||||
|
{ \
|
||||||
|
if (i < eld.lpcm_channels) \
|
||||||
|
positions[i++] = pos; \
|
||||||
|
}
|
||||||
|
|
||||||
if (eld.speakers & 0x01) {
|
if (eld.speakers & 0x01) {
|
||||||
positions[i++] = ACP_CHANNEL_FL;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_FL);
|
||||||
positions[i++] = ACP_CHANNEL_FR;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_FR);
|
||||||
}
|
}
|
||||||
if (eld.speakers & 0x02) {
|
if (eld.speakers & 0x02) {
|
||||||
positions[i++] = ACP_CHANNEL_LFE;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_LFE);
|
||||||
}
|
}
|
||||||
if (eld.speakers & 0x04) {
|
if (eld.speakers & 0x04) {
|
||||||
positions[i++] = ACP_CHANNEL_FC;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_FC);
|
||||||
}
|
}
|
||||||
if (eld.speakers & 0x08) {
|
if (eld.speakers & 0x08) {
|
||||||
positions[i++] = ACP_CHANNEL_RL;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_RL);
|
||||||
positions[i++] = ACP_CHANNEL_RR;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_RR);
|
||||||
}
|
}
|
||||||
/* The rest are out of order in order of what channels we would prefer to use/expose first */
|
/* The rest are out of order in order of what channels we would prefer to use/expose first */
|
||||||
if (eld.speakers & 0x40) {
|
if (eld.speakers & 0x40) {
|
||||||
/* Use SL/SR instead of RLC/RRC */
|
/* Use SL/SR instead of RLC/RRC */
|
||||||
positions[i++] = ACP_CHANNEL_SL;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_SL);
|
||||||
positions[i++] = ACP_CHANNEL_SR;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_SR);
|
||||||
}
|
}
|
||||||
if (eld.speakers & 0x20) {
|
if (eld.speakers & 0x20) {
|
||||||
positions[i++] = ACP_CHANNEL_RLC;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_RLC);
|
||||||
positions[i++] = ACP_CHANNEL_RRC;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_RRC);
|
||||||
}
|
}
|
||||||
if (eld.speakers & 0x10) {
|
if (eld.speakers & 0x10) {
|
||||||
positions[i++] = ACP_CHANNEL_RC;
|
_ADD_CHANNEL_POSITION(ACP_CHANNEL_RC);
|
||||||
}
|
}
|
||||||
while (i < eld.lpcm_channels)
|
while (i < eld.lpcm_channels)
|
||||||
positions[i++] = ACP_CHANNEL_UNKNOWN;
|
positions[i++] = ACP_CHANNEL_UNKNOWN;
|
||||||
|
|
@ -1740,6 +1745,8 @@ static int device_enable(pa_card *impl, pa_alsa_mapping *mapping, pa_alsa_device
|
||||||
dev->device.format.channels = atoi(channels);
|
dev->device.format.channels = atoi(channels);
|
||||||
free(dev->device.format.map);
|
free(dev->device.format.map);
|
||||||
dev->device.format.map = calloc(dev->device.format.channels, sizeof(uint32_t));
|
dev->device.format.map = calloc(dev->device.format.channels, sizeof(uint32_t));
|
||||||
|
if (dev->device.format.map == NULL)
|
||||||
|
break;
|
||||||
|
|
||||||
while ((position = pa_split_in_place(positions, ",", &n, &split_state)) != NULL &&
|
while ((position = pa_split_in_place(positions, ",", &n, &split_state)) != NULL &&
|
||||||
i < dev->device.format.channels) {
|
i < dev->device.format.channels) {
|
||||||
|
|
|
||||||
|
|
@ -63,6 +63,7 @@ char *pa_alsa_mixer_id_to_string(char *dst, size_t dst_len, pa_alsa_mixer_id *id
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alsa_id_decode(const char *src, char *name, int *index) {
|
static int alsa_id_decode(const char *src, char *name, int *index) {
|
||||||
|
size_t src_len = strlen(src);
|
||||||
char *idx, c;
|
char *idx, c;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
|
@ -70,7 +71,7 @@ static int alsa_id_decode(const char *src, char *name, int *index) {
|
||||||
c = src[0];
|
c = src[0];
|
||||||
/* Strip quotes in entries such as 'Speaker',1 or "Speaker",1 */
|
/* Strip quotes in entries such as 'Speaker',1 or "Speaker",1 */
|
||||||
if (c == '\'' || c == '"') {
|
if (c == '\'' || c == '"') {
|
||||||
strcpy(name, src + 1);
|
memcpy(name, src + 1, src_len);
|
||||||
for (i = 0; name[i] != '\0' && name[i] != c; i++);
|
for (i = 0; name[i] != '\0' && name[i] != c; i++);
|
||||||
idx = NULL;
|
idx = NULL;
|
||||||
if (name[i]) {
|
if (name[i]) {
|
||||||
|
|
@ -78,7 +79,7 @@ static int alsa_id_decode(const char *src, char *name, int *index) {
|
||||||
idx = strchr(name + i + 1, ',');
|
idx = strchr(name + i + 1, ',');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
strcpy(name, src);
|
memcpy(name, src, src_len + 1);
|
||||||
idx = strchr(name, ',');
|
idx = strchr(name, ',');
|
||||||
}
|
}
|
||||||
if (idx == NULL)
|
if (idx == NULL)
|
||||||
|
|
|
||||||
|
|
@ -429,14 +429,14 @@ static PA_PRINTF_FUNC(1,0) inline char *pa_vsprintf_malloc(const char *fmt, va_l
|
||||||
|
|
||||||
#define pa_fopen_cloexec(f,m) fopen(f,m"e")
|
#define pa_fopen_cloexec(f,m) fopen(f,m"e")
|
||||||
|
|
||||||
static inline char *pa_path_get_filename(const char *p)
|
static inline const char *pa_path_get_filename(const char *p)
|
||||||
{
|
{
|
||||||
char *fn;
|
const char *fn;
|
||||||
if (!p)
|
if (!p)
|
||||||
return NULL;
|
return NULL;
|
||||||
if ((fn = strrchr(p, PA_PATH_SEP_CHAR)))
|
if ((fn = strrchr(p, PA_PATH_SEP_CHAR)))
|
||||||
return fn+1;
|
return fn+1;
|
||||||
return (char*) p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool pa_is_path_absolute(const char *fn)
|
static inline bool pa_is_path_absolute(const char *fn)
|
||||||
|
|
|
||||||
|
|
@ -990,11 +990,22 @@ static void card_port_available(void *data, uint32_t index,
|
||||||
|
|
||||||
for (i = 0; i < p->n_devices; i++) {
|
for (i = 0; i < p->n_devices; i++) {
|
||||||
struct acp_device *d = p->devices[i];
|
struct acp_device *d = p->devices[i];
|
||||||
|
struct acp_port *active_port = NULL;
|
||||||
|
uint32_t j;
|
||||||
uint32_t best;
|
uint32_t best;
|
||||||
|
|
||||||
if (!(d->flags & ACP_DEVICE_ACTIVE))
|
if (!(d->flags & ACP_DEVICE_ACTIVE))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
for (j = 0; j < d->n_ports; j++) {
|
||||||
|
if (d->ports[j]->flags & ACP_PORT_ACTIVE) {
|
||||||
|
active_port = d->ports[j];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (active_port != NULL && active_port->available != ACP_AVAILABLE_NO)
|
||||||
|
continue;
|
||||||
|
|
||||||
best = acp_device_find_best_port_index(d, NULL);
|
best = acp_device_find_best_port_index(d, NULL);
|
||||||
acp_device_set_port(d, best, 0);
|
acp_device_set_port(d, best, 0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1971,7 +1971,7 @@ impl_init(const struct spa_handle_factory *factory, struct spa_handle *handle,
|
||||||
if (spa_streq(k, SPA_KEY_API_ALSA_PATH)) {
|
if (spa_streq(k, SPA_KEY_API_ALSA_PATH)) {
|
||||||
snprintf(this->props.device, sizeof(this->props.device), "%s", s);
|
snprintf(this->props.device, sizeof(this->props.device), "%s", s);
|
||||||
if ((res = parse_device(this)) < 0)
|
if ((res = parse_device(this)) < 0)
|
||||||
return res;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,8 @@ static struct card *ensure_card(uint32_t index, bool ucm, bool ucm_split)
|
||||||
return c;
|
return c;
|
||||||
|
|
||||||
c = calloc(1, sizeof(*c));
|
c = calloc(1, sizeof(*c));
|
||||||
|
if (c == NULL)
|
||||||
|
return NULL;
|
||||||
c->ref = 1;
|
c->ref = 1;
|
||||||
c->index = index;
|
c->index = index;
|
||||||
|
|
||||||
|
|
@ -714,19 +716,25 @@ int spa_alsa_parse_prop_params(struct state *state, struct spa_pod *params)
|
||||||
static ssize_t log_write(void *cookie, const char *buf, size_t size)
|
static ssize_t log_write(void *cookie, const char *buf, size_t size)
|
||||||
{
|
{
|
||||||
struct state *state = cookie;
|
struct state *state = cookie;
|
||||||
int len;
|
|
||||||
|
|
||||||
while (size > 0) {
|
if (!spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_DEBUG))
|
||||||
len = strcspn(buf, "\n");
|
return size;
|
||||||
|
|
||||||
|
for (size_t left = size; left > 0; ) {
|
||||||
|
const char *end = memchr(buf, '\n', left);
|
||||||
|
size_t len = end ? (size_t)(end - buf) : left;
|
||||||
|
|
||||||
if (len > 0)
|
if (len > 0)
|
||||||
spa_log_debug(state->log, "%.*s", (int)len, buf);
|
spa_log_debug(state->log, "%.*s", (int)len, buf);
|
||||||
buf += len + 1;
|
|
||||||
size -= len + 1;
|
buf += len + !!end;
|
||||||
|
left -= len + !!end;
|
||||||
}
|
}
|
||||||
|
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
|
||||||
static cookie_io_functions_t io_funcs = {
|
static const cookie_io_functions_t io_funcs = {
|
||||||
.write = log_write,
|
.write = log_write,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1066,7 +1074,7 @@ int spa_alsa_init(struct state *state, const struct spa_dict *info)
|
||||||
|
|
||||||
int spa_alsa_clear(struct state *state)
|
int spa_alsa_clear(struct state *state)
|
||||||
{
|
{
|
||||||
int err;
|
int err = 0;
|
||||||
struct state *follower;
|
struct state *follower;
|
||||||
|
|
||||||
spa_list_remove(&state->link);
|
spa_list_remove(&state->link);
|
||||||
|
|
@ -1092,12 +1100,8 @@ int spa_alsa_clear(struct state *state)
|
||||||
state->card = NULL;
|
state->card = NULL;
|
||||||
state->card_index = SPA_ID_INVALID;
|
state->card_index = SPA_ID_INVALID;
|
||||||
|
|
||||||
if ((err = snd_output_close(state->output)) < 0)
|
spa_clear_ptr(state->tag[0], free);
|
||||||
spa_log_warn(state->log, "output close failed: %s", snd_strerror(err));
|
spa_clear_ptr(state->tag[1], free);
|
||||||
fclose(state->log_file);
|
|
||||||
|
|
||||||
free(state->tag[0]);
|
|
||||||
free(state->tag[1]);
|
|
||||||
|
|
||||||
if (state->ctl) {
|
if (state->ctl) {
|
||||||
for (int i = 0; i < state->ctl_n_fds; i++) {
|
for (int i = 0; i < state->ctl_n_fds; i++) {
|
||||||
|
|
@ -1119,6 +1123,14 @@ int spa_alsa_clear(struct state *state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->output) {
|
||||||
|
if ((err = snd_output_close(state->output)) < 0)
|
||||||
|
spa_log_warn(state->log, "output close failed: %s", snd_strerror(err));
|
||||||
|
}
|
||||||
|
|
||||||
|
spa_clear_ptr(state->log_file, fclose);
|
||||||
|
spa_clear_ptr(state->alsa_chmap, free);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1154,25 +1166,32 @@ static int probe_pitch_ctl(struct state *state)
|
||||||
if (err < 0) {
|
if (err < 0) {
|
||||||
spa_log_debug(state->log, "%s: did not find ctl: %s",
|
spa_log_debug(state->log, "%s: did not find ctl: %s",
|
||||||
elem_name, snd_strerror(err));
|
elem_name, snd_strerror(err));
|
||||||
|
|
||||||
snd_ctl_elem_value_free(state->pitch_elem);
|
|
||||||
state->pitch_elem = NULL;
|
|
||||||
|
|
||||||
if (opened) {
|
|
||||||
snd_ctl_close(state->ctl);
|
|
||||||
state->ctl = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
snd_ctl_elem_value_set_integer(state->pitch_elem, 0, 1000000);
|
snd_ctl_elem_value_set_integer(state->pitch_elem, 0, 1000000);
|
||||||
CHECK(snd_ctl_elem_write(state->ctl, state->pitch_elem), "snd_ctl_elem_write");
|
err = snd_ctl_elem_write(state->ctl, state->pitch_elem);
|
||||||
|
if (err < 0) {
|
||||||
|
spa_log_error(state->log, "snd_ctl_elem_write: %s", snd_strerror(err));
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
state->last_rate = 1.0;
|
state->last_rate = 1.0;
|
||||||
|
|
||||||
spa_log_info(state->log, "found ctl %s", elem_name);
|
spa_log_info(state->log, "found ctl %s", elem_name);
|
||||||
err = 0;
|
|
||||||
|
snd_lib_error_set_handler(NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
if (state->pitch_elem != NULL) {
|
||||||
|
snd_ctl_elem_value_free(state->pitch_elem);
|
||||||
|
state->pitch_elem = NULL;
|
||||||
|
}
|
||||||
|
if (opened) {
|
||||||
|
snd_ctl_close(state->ctl);
|
||||||
|
state->ctl = NULL;
|
||||||
|
}
|
||||||
snd_lib_error_set_handler(NULL);
|
snd_lib_error_set_handler(NULL);
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -1664,6 +1683,69 @@ skip_channels:
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static snd_pcm_chmap_t *dup_alsa_chmap(snd_pcm_chmap_t *map)
|
||||||
|
{
|
||||||
|
snd_pcm_chmap_t *chmap;
|
||||||
|
size_t sz;
|
||||||
|
|
||||||
|
sz = sizeof(*chmap) + sizeof(*chmap->pos) * map->channels;
|
||||||
|
chmap = calloc(1, sz);
|
||||||
|
if (chmap)
|
||||||
|
memcpy(chmap, map, sz);
|
||||||
|
|
||||||
|
return chmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_alsa_chmap(snd_pcm_t *hndl, uint32_t channels, const uint32_t *position,
|
||||||
|
snd_pcm_chmap_t **chmap)
|
||||||
|
{
|
||||||
|
snd_pcm_chmap_query_t **maps = snd_pcm_query_chmaps(hndl);
|
||||||
|
size_t i, j;
|
||||||
|
int err = 0;
|
||||||
|
|
||||||
|
*chmap = NULL;
|
||||||
|
|
||||||
|
if (!maps)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* Find corresponding ALSA chmap */
|
||||||
|
for (i = 0; maps[i]; ++i) {
|
||||||
|
spa_autofree snd_pcm_chmap_t *map = NULL;
|
||||||
|
|
||||||
|
if (maps[i]->map.channels != channels)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
map = dup_alsa_chmap(&maps[i]->map);
|
||||||
|
if (!map) {
|
||||||
|
err = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
sanitize_map(map);
|
||||||
|
|
||||||
|
for (j = 0; j < channels; ++j) {
|
||||||
|
if (position[j] != chmap_position_to_channel(map->pos[j]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j < channels)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
*chmap = dup_alsa_chmap(&maps[i]->map);
|
||||||
|
if (!*chmap)
|
||||||
|
err = -ENOMEM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!maps[i])
|
||||||
|
err = -ENOENT;
|
||||||
|
|
||||||
|
snd_pcm_free_chmaps(maps);
|
||||||
|
|
||||||
|
if (err) {
|
||||||
|
free(*chmap);
|
||||||
|
*chmap = NULL;
|
||||||
|
}
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
static void debug_hw_params(struct state *state, const char *prefix, snd_pcm_hw_params_t *params)
|
static void debug_hw_params(struct state *state, const char *prefix, snd_pcm_hw_params_t *params)
|
||||||
{
|
{
|
||||||
if (SPA_UNLIKELY(spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_DEBUG))) {
|
if (SPA_UNLIKELY(spa_log_level_topic_enabled(state->log, SPA_LOG_TOPIC_DEFAULT, SPA_LOG_LEVEL_DEBUG))) {
|
||||||
|
|
@ -2036,7 +2118,9 @@ static void recalc_headroom(struct state *state)
|
||||||
uint32_t latency;
|
uint32_t latency;
|
||||||
uint32_t rate = 0;
|
uint32_t rate = 0;
|
||||||
|
|
||||||
if (state->position != NULL)
|
if (state->force_quantum && !state->following)
|
||||||
|
rate = state->rate;
|
||||||
|
else if (state->position != NULL)
|
||||||
rate = state->position->clock.target_rate.denom;
|
rate = state->position->clock.target_rate.denom;
|
||||||
|
|
||||||
if (state->use_period_size_min_as_headroom)
|
if (state->use_period_size_min_as_headroom)
|
||||||
|
|
@ -2063,8 +2147,6 @@ static void recalc_headroom(struct state *state)
|
||||||
state->headroom = 0;
|
state->headroom = 0;
|
||||||
|
|
||||||
latency = SPA_MAX(state->min_delay, SPA_MIN(state->max_delay, state->headroom));
|
latency = SPA_MAX(state->min_delay, SPA_MIN(state->max_delay, state->headroom));
|
||||||
if (rate != 0 && state->rate != 0)
|
|
||||||
latency = SPA_SCALE32_UP(latency, rate, state->rate);
|
|
||||||
|
|
||||||
if (state->is_firewire) {
|
if (state->is_firewire) {
|
||||||
/* XXX: For ALSA FireWire drivers, unlike for other ALSA drivers, buffer size
|
/* XXX: For ALSA FireWire drivers, unlike for other ALSA drivers, buffer size
|
||||||
|
|
@ -2072,6 +2154,8 @@ static void recalc_headroom(struct state *state)
|
||||||
*/
|
*/
|
||||||
latency += state->buffer_frames;
|
latency += state->buffer_frames;
|
||||||
}
|
}
|
||||||
|
if (rate != 0 && state->rate != 0)
|
||||||
|
latency = SPA_SCALE32_UP(latency, rate, state->rate);
|
||||||
|
|
||||||
state->latency[state->port_direction].min_rate =
|
state->latency[state->port_direction].min_rate =
|
||||||
state->latency[state->port_direction].max_rate = latency;
|
state->latency[state->port_direction].max_rate = latency;
|
||||||
|
|
@ -2089,7 +2173,9 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
|
||||||
unsigned int periods;
|
unsigned int periods;
|
||||||
bool match = true, planar = false;
|
bool match = true, planar = false;
|
||||||
char spdif_params[128] = "";
|
char spdif_params[128] = "";
|
||||||
|
char alsa_chmap_str[256] = "";
|
||||||
uint32_t default_period;
|
uint32_t default_period;
|
||||||
|
const uint32_t *position = NULL;
|
||||||
|
|
||||||
spa_log_debug(state->log, "opened:%d format:%d started:%d", state->opened,
|
spa_log_debug(state->log, "opened:%d format:%d started:%d", state->opened,
|
||||||
state->have_format, state->started);
|
state->have_format, state->started);
|
||||||
|
|
@ -2103,6 +2189,8 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
|
||||||
struct spa_audio_info_raw *f = &fmt->info.raw;
|
struct spa_audio_info_raw *f = &fmt->info.raw;
|
||||||
rrate = f->rate;
|
rrate = f->rate;
|
||||||
rchannels = f->channels;
|
rchannels = f->channels;
|
||||||
|
if (!SPA_FLAG_IS_SET(f->flags, SPA_AUDIO_FLAG_UNPOSITIONED))
|
||||||
|
position = f->position;
|
||||||
rformat = spa_format_to_alsa(f->format, &planar);
|
rformat = spa_format_to_alsa(f->format, &planar);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -2167,6 +2255,7 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
|
||||||
|
|
||||||
rrate = f->rate;
|
rrate = f->rate;
|
||||||
rchannels = f->channels;
|
rchannels = f->channels;
|
||||||
|
position = f->position;
|
||||||
|
|
||||||
switch (f->interleave) {
|
switch (f->interleave) {
|
||||||
case 4:
|
case 4:
|
||||||
|
|
@ -2255,6 +2344,28 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
|
||||||
planar ? "planar" : "interleaved", rchannels);
|
planar ? "planar" : "interleaved", rchannels);
|
||||||
CHECK(snd_pcm_hw_params_set_format(hndl, params, rformat), "set_format");
|
CHECK(snd_pcm_hw_params_set_format(hndl, params, rformat), "set_format");
|
||||||
|
|
||||||
|
/* prepare channel map */
|
||||||
|
{
|
||||||
|
spa_autofree snd_pcm_chmap_t *alsa_chmap = NULL;
|
||||||
|
|
||||||
|
if (state->props.use_chmap && position) {
|
||||||
|
if ((err = get_alsa_chmap(hndl, rchannels, position, &alsa_chmap)) < 0) {
|
||||||
|
struct channel_map map = { .n_pos = SPA_MIN(MAX_CHANNELS, rchannels) };
|
||||||
|
char buf[256] = "";
|
||||||
|
|
||||||
|
memcpy(map.pos, position, map.n_pos * sizeof(map.pos[0]));
|
||||||
|
position_to_string(&map, buf, sizeof(buf));
|
||||||
|
spa_log_warn(state->log, "%s: failed to get ALSA chmap '%s': %s",
|
||||||
|
state->name, buf, spa_strerror(err));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SPA_SWAP(state->alsa_chmap, alsa_chmap);
|
||||||
|
|
||||||
|
alsa_chmap_str[0] = '\0';
|
||||||
|
if (state->alsa_chmap)
|
||||||
|
snd_pcm_chmap_print(state->alsa_chmap, sizeof(alsa_chmap_str), alsa_chmap_str);
|
||||||
|
}
|
||||||
|
|
||||||
/* set the count of channels */
|
/* set the count of channels */
|
||||||
val = rchannels;
|
val = rchannels;
|
||||||
CHECK(snd_pcm_hw_params_set_channels_near(hndl, params, &val), "set_channels");
|
CHECK(snd_pcm_hw_params_set_channels_near(hndl, params, &val), "set_channels");
|
||||||
|
|
@ -2432,13 +2543,13 @@ int spa_alsa_set_format(struct state *state, struct spa_audio_info *fmt, uint32_
|
||||||
|
|
||||||
recalc_headroom(state);
|
recalc_headroom(state);
|
||||||
|
|
||||||
spa_log_info(state->log, "%s: format:%s access:%s-%s rate:%d channels:%d "
|
spa_log_info(state->log, "%s: format:%s access:%s-%s rate:%d channels:%d chmap:'%s' "
|
||||||
"buffer frames %lu, period frames %lu (min:%lu), periods %u, frame_size %zd "
|
"buffer frames %lu, period frames %lu (min:%lu), periods %u, frame_size %zd "
|
||||||
"headroom %u start-delay:%u batch:%u tsched:%u resample:%u",
|
"headroom %u start-delay:%u batch:%u tsched:%u resample:%u",
|
||||||
state->name, snd_pcm_format_name(state->format),
|
state->name, snd_pcm_format_name(state->format),
|
||||||
state->use_mmap ? "mmap" : "rw",
|
state->use_mmap ? "mmap" : "rw",
|
||||||
planar ? "planar" : "interleaved",
|
planar ? "planar" : "interleaved",
|
||||||
state->rate, state->channels, state->buffer_frames, state->period_frames,
|
state->rate, state->channels, alsa_chmap_str, state->buffer_frames, state->period_frames,
|
||||||
state->period_size_min, periods, state->frame_size, state->headroom,
|
state->period_size_min, periods, state->frame_size, state->headroom,
|
||||||
state->start_delay, state->is_batch, !state->disable_tsched, state->resample);
|
state->start_delay, state->is_batch, !state->disable_tsched, state->resample);
|
||||||
|
|
||||||
|
|
@ -2576,16 +2687,22 @@ static int spa_alsa_silence(struct state *state, snd_pcm_uframes_t silence)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
uint8_t buffer[silence * state->frame_size];
|
uint8_t buffer[1024 * 4];
|
||||||
memset(buffer, 0, silence * state->frame_size);
|
|
||||||
|
|
||||||
if (state->planar) {
|
|
||||||
void *bufs[state->channels];
|
void *bufs[state->channels];
|
||||||
|
snd_pcm_uframes_t chunk, remaining = silence;
|
||||||
|
snd_pcm_uframes_t max = sizeof(buffer) / state->frame_size;
|
||||||
|
|
||||||
|
memset(buffer, 0, sizeof(buffer));
|
||||||
for (i = 0; i < state->channels; i++)
|
for (i = 0; i < state->channels; i++)
|
||||||
bufs[i] = buffer;
|
bufs[i] = buffer;
|
||||||
snd_pcm_writen(hndl, bufs, silence);
|
|
||||||
} else {
|
while (remaining > 0) {
|
||||||
snd_pcm_writei(hndl, buffer, silence);
|
chunk = SPA_MIN(remaining, max);
|
||||||
|
if (state->planar)
|
||||||
|
snd_pcm_writen(hndl, bufs, chunk);
|
||||||
|
else
|
||||||
|
snd_pcm_writei(hndl, buffer, chunk);
|
||||||
|
remaining -= chunk;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2629,6 +2746,16 @@ static int do_prepare(struct state *state)
|
||||||
state->name, snd_strerror(err));
|
state->name, snd_strerror(err));
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (state->alsa_chmap) {
|
||||||
|
if ((err = snd_pcm_set_chmap(state->hndl, state->alsa_chmap)) < 0)
|
||||||
|
spa_log_error(state->log, "%s: snd_pcm_set_chmap error: %s",
|
||||||
|
state->name, snd_strerror(err));
|
||||||
|
|
||||||
|
/* it's enough to set chmap only on the initial prepare after hwparams */
|
||||||
|
spa_clear_ptr(state->alsa_chmap, free);
|
||||||
|
}
|
||||||
|
|
||||||
if (state->stream == SND_PCM_STREAM_PLAYBACK) {
|
if (state->stream == SND_PCM_STREAM_PLAYBACK) {
|
||||||
snd_pcm_uframes_t silence = state->start_delay + state->threshold + state->headroom;
|
snd_pcm_uframes_t silence = state->start_delay + state->threshold + state->headroom;
|
||||||
if (state->disable_tsched)
|
if (state->disable_tsched)
|
||||||
|
|
@ -2936,10 +3063,17 @@ static int update_time(struct state *state, uint64_t current_time, snd_pcm_sfram
|
||||||
}
|
}
|
||||||
|
|
||||||
if (state->rate_match) {
|
if (state->rate_match) {
|
||||||
|
/* Only set rate_match rate when matching is active. When not matching,
|
||||||
|
* set it to 1.0 to indicate no rate adjustment needed, even though DLL
|
||||||
|
* may still be running for buffer level management. */
|
||||||
|
if (state->matching) {
|
||||||
if (state->stream == SND_PCM_STREAM_PLAYBACK)
|
if (state->stream == SND_PCM_STREAM_PLAYBACK)
|
||||||
state->rate_match->rate = corr;
|
state->rate_match->rate = corr;
|
||||||
else
|
else
|
||||||
state->rate_match->rate = 1.0/corr;
|
state->rate_match->rate = 1.0/corr;
|
||||||
|
} else {
|
||||||
|
state->rate_match->rate = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
if (state->pitch_elem && state->matching)
|
if (state->pitch_elem && state->matching)
|
||||||
spa_alsa_update_rate_match(state);
|
spa_alsa_update_rate_match(state);
|
||||||
|
|
|
||||||
|
|
@ -280,6 +280,8 @@ struct state {
|
||||||
struct spa_list driver_link;
|
struct spa_list driver_link;
|
||||||
|
|
||||||
struct rt_state rt;
|
struct rt_state rt;
|
||||||
|
|
||||||
|
snd_pcm_chmap_t *alsa_chmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct spa_pod *spa_alsa_enum_propinfo(struct state *state,
|
struct spa_pod *spa_alsa_enum_propinfo(struct state *state,
|
||||||
|
|
|
||||||
|
|
@ -227,7 +227,7 @@ static void emit_port_info(struct seq_state *this, struct seq_port *port, bool f
|
||||||
if (full)
|
if (full)
|
||||||
port->info.change_mask = port->info_all;
|
port->info.change_mask = port->info_all;
|
||||||
if (port->info.change_mask) {
|
if (port->info.change_mask) {
|
||||||
struct spa_dict_item items[6];
|
struct spa_dict_item items[7];
|
||||||
uint32_t n_items = 0;
|
uint32_t n_items = 0;
|
||||||
int card_id;
|
int card_id;
|
||||||
snd_seq_port_info_t *info;
|
snd_seq_port_info_t *info;
|
||||||
|
|
@ -261,7 +261,7 @@ static void emit_port_info(struct seq_state *this, struct seq_port *port, bool f
|
||||||
if (spa_strstartswith(pn, client_name))
|
if (spa_strstartswith(pn, client_name))
|
||||||
pn += strlen(client_name);
|
pn += strlen(client_name);
|
||||||
|
|
||||||
snprintf(name, sizeof(name), "%s%s%s (%s)", prefix,
|
snprintf(name, sizeof(name), "%s%s:%s (%s)", prefix,
|
||||||
client_name, pn, dir);
|
client_name, pn, dir);
|
||||||
clean_name(name);
|
clean_name(name);
|
||||||
|
|
||||||
|
|
@ -284,6 +284,9 @@ static void emit_port_info(struct seq_state *this, struct seq_port *port, bool f
|
||||||
snprintf(card, sizeof(card), "%d", card_id);
|
snprintf(card, sizeof(card), "%d", card_id);
|
||||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD, card);
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_CARD, card);
|
||||||
}
|
}
|
||||||
|
if (this->ump)
|
||||||
|
items[n_items++] = SPA_DICT_ITEM_INIT("control.ump", "true");
|
||||||
|
|
||||||
port->info.props = &SPA_DICT_INIT(items, n_items);
|
port->info.props = &SPA_DICT_INIT(items, n_items);
|
||||||
|
|
||||||
spa_node_emit_port_info(&this->hooks,
|
spa_node_emit_port_info(&this->hooks,
|
||||||
|
|
@ -385,13 +388,29 @@ static struct seq_port *alloc_port(struct seq_state *state, struct seq_stream *s
|
||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int do_port_clear(struct spa_loop *loop, bool async, uint32_t seq,
|
||||||
|
const void *data, size_t size, void *user_data)
|
||||||
|
{
|
||||||
|
struct seq_port *port = user_data;
|
||||||
|
port->io = NULL;
|
||||||
|
if (port->mixing) {
|
||||||
|
spa_list_remove(&port->mix_link);
|
||||||
|
port->mixing = false;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static void free_port(struct seq_state *state, struct seq_stream *stream, struct seq_port *port)
|
static void free_port(struct seq_state *state, struct seq_stream *stream, struct seq_port *port)
|
||||||
{
|
{
|
||||||
stream->ports[port->id] = NULL;
|
stream->ports[port->id] = NULL;
|
||||||
spa_list_remove(&port->link);
|
spa_list_remove(&port->link);
|
||||||
|
|
||||||
|
spa_loop_locked(state->data_loop,
|
||||||
|
do_port_clear, SPA_ID_INVALID, NULL, 0, port);
|
||||||
|
|
||||||
spa_node_emit_port_info(&state->hooks,
|
spa_node_emit_port_info(&state->hooks,
|
||||||
port->direction, port->id, NULL);
|
port->direction, port->id, NULL);
|
||||||
|
|
||||||
spa_zero(*port);
|
spa_zero(*port);
|
||||||
spa_list_append(&state->free_list, &port->link);
|
spa_list_append(&state->free_list, &port->link);
|
||||||
}
|
}
|
||||||
|
|
@ -438,7 +457,7 @@ static void update_stream_port(struct seq_state *state, struct seq_stream *strea
|
||||||
struct seq_port *port = find_port(state, stream, addr);
|
struct seq_port *port = find_port(state, stream, addr);
|
||||||
|
|
||||||
if (info == NULL) {
|
if (info == NULL) {
|
||||||
spa_log_debug(state->log, "free port %d.%d", addr->client, addr->port);
|
spa_log_debug(state->log, "free port %d.%d %p", addr->client, addr->port, port);
|
||||||
if (port)
|
if (port)
|
||||||
free_port(state, stream, port);
|
free_port(state, stream, port);
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -450,7 +469,7 @@ static void update_stream_port(struct seq_state *state, struct seq_stream *strea
|
||||||
init_port(state, port, addr, snd_seq_port_info_get_type(info));
|
init_port(state, port, addr, snd_seq_port_info_get_type(info));
|
||||||
} else if (port != NULL) {
|
} else if (port != NULL) {
|
||||||
if ((caps & stream->caps) != stream->caps) {
|
if ((caps & stream->caps) != stream->caps) {
|
||||||
spa_log_debug(state->log, "free port %d.%d", addr->client, addr->port);
|
spa_log_debug(state->log, "free port %d.%d %p", addr->client, addr->port, port);
|
||||||
free_port(state, stream, port);
|
free_port(state, stream, port);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -467,8 +486,8 @@ static int on_port_info(void *data, const snd_seq_addr_t *addr, const snd_seq_po
|
||||||
struct seq_state *state = data;
|
struct seq_state *state = data;
|
||||||
|
|
||||||
if (info == NULL) {
|
if (info == NULL) {
|
||||||
update_stream_port(state, &state->streams[SPA_DIRECTION_INPUT], addr, 0, info);
|
update_stream_port(state, &state->streams[SPA_DIRECTION_INPUT], addr, 0, NULL);
|
||||||
update_stream_port(state, &state->streams[SPA_DIRECTION_OUTPUT], addr, 0, info);
|
update_stream_port(state, &state->streams[SPA_DIRECTION_OUTPUT], addr, 0, NULL);
|
||||||
} else {
|
} else {
|
||||||
unsigned int caps = snd_seq_port_info_get_capability(info);
|
unsigned int caps = snd_seq_port_info_get_capability(info);
|
||||||
|
|
||||||
|
|
@ -501,6 +520,7 @@ impl_node_port_enum_params(void *object, int seq,
|
||||||
struct seq_state *this = object;
|
struct seq_state *this = object;
|
||||||
struct seq_port *port;
|
struct seq_port *port;
|
||||||
struct spa_pod *param;
|
struct spa_pod *param;
|
||||||
|
struct spa_pod_frame f[1];
|
||||||
struct spa_pod_builder b = { 0 };
|
struct spa_pod_builder b = { 0 };
|
||||||
uint8_t buffer[1024];
|
uint8_t buffer[1024];
|
||||||
struct spa_result_node_params result;
|
struct spa_result_node_params result;
|
||||||
|
|
@ -524,10 +544,18 @@ impl_node_port_enum_params(void *object, int seq,
|
||||||
case SPA_PARAM_EnumFormat:
|
case SPA_PARAM_EnumFormat:
|
||||||
if (result.index > 0)
|
if (result.index > 0)
|
||||||
return 0;
|
return 0;
|
||||||
param = spa_pod_builder_add_object(&b,
|
spa_pod_builder_push_object(&b, &f[0],
|
||||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat,
|
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||||
|
spa_pod_builder_add(&b,
|
||||||
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
||||||
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
|
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
|
||||||
|
0);
|
||||||
|
if (port->control_types != 0) {
|
||||||
|
spa_pod_builder_add(&b,
|
||||||
|
SPA_FORMAT_CONTROL_types, SPA_POD_Int(port->control_types),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
param = spa_pod_builder_pop(&b, &f[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPA_PARAM_Format:
|
case SPA_PARAM_Format:
|
||||||
|
|
@ -535,10 +563,18 @@ impl_node_port_enum_params(void *object, int seq,
|
||||||
return -EIO;
|
return -EIO;
|
||||||
if (result.index > 0)
|
if (result.index > 0)
|
||||||
return 0;
|
return 0;
|
||||||
param = spa_pod_builder_add_object(&b,
|
spa_pod_builder_push_object(&b, &f[0],
|
||||||
SPA_TYPE_OBJECT_Format, SPA_PARAM_Format,
|
SPA_TYPE_OBJECT_Format, SPA_PARAM_EnumFormat);
|
||||||
|
spa_pod_builder_add(&b,
|
||||||
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
SPA_FORMAT_mediaType, SPA_POD_Id(SPA_MEDIA_TYPE_application),
|
||||||
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control));
|
SPA_FORMAT_mediaSubtype, SPA_POD_Id(SPA_MEDIA_SUBTYPE_control),
|
||||||
|
0);
|
||||||
|
if (port->control_types != 0) {
|
||||||
|
spa_pod_builder_add(&b,
|
||||||
|
SPA_FORMAT_CONTROL_types, SPA_POD_Int(port->control_types),
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
param = spa_pod_builder_pop(&b, &f[0]);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case SPA_PARAM_Buffers:
|
case SPA_PARAM_Buffers:
|
||||||
|
|
@ -800,7 +836,7 @@ impl_node_port_set_io(void *object,
|
||||||
info.data = data;
|
info.data = data;
|
||||||
info.size = size;
|
info.size = size;
|
||||||
|
|
||||||
spa_log_debug(this->log, "%p: io %d.%d %d %p %zd", this,
|
spa_log_debug(this->log, "%p: %p: io %d.%d %d %p %zd", this, port,
|
||||||
direction, port_id, id, data, size);
|
direction, port_id, id, data, size);
|
||||||
|
|
||||||
switch (id) {
|
switch (id) {
|
||||||
|
|
@ -821,7 +857,7 @@ static int impl_node_port_reuse_buffer(void *object, uint32_t port_id, uint32_t
|
||||||
|
|
||||||
spa_return_val_if_fail(this != NULL, -EINVAL);
|
spa_return_val_if_fail(this != NULL, -EINVAL);
|
||||||
|
|
||||||
spa_return_val_if_fail(!CHECK_PORT(this, SPA_DIRECTION_OUTPUT, port_id), -EINVAL);
|
spa_return_val_if_fail(CHECK_PORT(this, SPA_DIRECTION_OUTPUT, port_id), -EINVAL);
|
||||||
|
|
||||||
port = GET_PORT(this, SPA_DIRECTION_OUTPUT, port_id);
|
port = GET_PORT(this, SPA_DIRECTION_OUTPUT, port_id);
|
||||||
|
|
||||||
|
|
@ -955,7 +991,7 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
this->quantum_limit = 8192;
|
this->quantum_limit = 8192;
|
||||||
this->min_pool_size = 500;
|
this->min_pool_size = 500;
|
||||||
this->max_pool_size = 2000;
|
this->max_pool_size = 2000;
|
||||||
this->ump = true;
|
this->ump = false;
|
||||||
|
|
||||||
for (i = 0; info && i < info->n_items; i++) {
|
for (i = 0; info && i < info->n_items; i++) {
|
||||||
const char *k = info->items[i].key;
|
const char *k = info->items[i].key;
|
||||||
|
|
|
||||||
|
|
@ -620,9 +620,8 @@ static int process_read(struct seq_state *state)
|
||||||
{
|
{
|
||||||
struct seq_stream *stream = &state->streams[SPA_DIRECTION_OUTPUT];
|
struct seq_stream *stream = &state->streams[SPA_DIRECTION_OUTPUT];
|
||||||
const bool ump = state->ump;
|
const bool ump = state->ump;
|
||||||
uint32_t *data;
|
void *data;
|
||||||
uint8_t midi1_data[MAX_EVENT_SIZE];
|
uint8_t midi1_data[MAX_EVENT_SIZE];
|
||||||
uint32_t ump_data[MAX_EVENT_SIZE];
|
|
||||||
long size;
|
long size;
|
||||||
int res = -1;
|
int res = -1;
|
||||||
struct seq_port *port;
|
struct seq_port *port;
|
||||||
|
|
@ -633,9 +632,6 @@ static int process_read(struct seq_state *state)
|
||||||
uint64_t ev_time, diff;
|
uint64_t ev_time, diff;
|
||||||
uint32_t offset;
|
uint32_t offset;
|
||||||
void *event;
|
void *event;
|
||||||
uint8_t *midi1_ptr;
|
|
||||||
size_t midi1_size = 0;
|
|
||||||
uint64_t ump_state = 0;
|
|
||||||
snd_seq_event_type_t SPA_UNUSED type;
|
snd_seq_event_type_t SPA_UNUSED type;
|
||||||
|
|
||||||
if (ump) {
|
if (ump) {
|
||||||
|
|
@ -702,7 +698,7 @@ static int process_read(struct seq_state *state)
|
||||||
#ifdef HAVE_ALSA_UMP
|
#ifdef HAVE_ALSA_UMP
|
||||||
snd_seq_ump_event_t *ev = event;
|
snd_seq_ump_event_t *ev = event;
|
||||||
|
|
||||||
data = (uint32_t*)&ev->ump[0];
|
data = &ev->ump[0];
|
||||||
size = spa_ump_message_size(snd_ump_msg_hdr_type(ev->ump[0])) * 4;
|
size = spa_ump_message_size(snd_ump_msg_hdr_type(ev->ump[0])) * 4;
|
||||||
#else
|
#else
|
||||||
spa_assert_not_reached();
|
spa_assert_not_reached();
|
||||||
|
|
@ -715,24 +711,13 @@ static int process_read(struct seq_state *state)
|
||||||
spa_log_warn(state->log, "decode failed: %s", snd_strerror(size));
|
spa_log_warn(state->log, "decode failed: %s", snd_strerror(size));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
data = midi1_data;
|
||||||
midi1_ptr = midi1_data;
|
|
||||||
midi1_size = size;
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
|
||||||
if (!ump) {
|
|
||||||
data = ump_data;
|
|
||||||
size = spa_ump_from_midi(&midi1_ptr, &midi1_size,
|
|
||||||
ump_data, sizeof(ump_data), 0, &ump_state);
|
|
||||||
if (size <= 0)
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
spa_log_trace_fp(state->log, "event %d time:%"PRIu64" offset:%d size:%ld port:%d.%d",
|
spa_log_trace_fp(state->log, "event %d time:%"PRIu64" offset:%d size:%ld port:%d.%d",
|
||||||
type, ev_time, offset, size, addr->client, addr->port);
|
type, ev_time, offset, size, addr->client, addr->port);
|
||||||
|
|
||||||
spa_pod_builder_control(&port->builder, offset, SPA_CONTROL_UMP);
|
spa_pod_builder_control(&port->builder, offset, ump ? SPA_CONTROL_UMP : SPA_CONTROL_Midi );
|
||||||
spa_pod_builder_bytes(&port->builder, data, size);
|
spa_pod_builder_bytes(&port->builder, data, size);
|
||||||
|
|
||||||
/* make sure we can fit at least one control event of max size otherwise
|
/* make sure we can fit at least one control event of max size otherwise
|
||||||
|
|
@ -741,8 +726,6 @@ static int process_read(struct seq_state *state)
|
||||||
sizeof(struct spa_pod_control) +
|
sizeof(struct spa_pod_control) +
|
||||||
MAX_EVENT_SIZE > port->buffer->buf->datas[0].maxsize)
|
MAX_EVENT_SIZE > port->buffer->buf->datas[0].maxsize)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
} while (!ump);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
@ -819,7 +802,6 @@ static int process_write(struct seq_state *state)
|
||||||
const void *c_body;
|
const void *c_body;
|
||||||
uint64_t out_time;
|
uint64_t out_time;
|
||||||
snd_seq_real_time_t out_rt;
|
snd_seq_real_time_t out_rt;
|
||||||
bool first = true;
|
|
||||||
|
|
||||||
if (io->status != SPA_STATUS_HAVE_DATA ||
|
if (io->status != SPA_STATUS_HAVE_DATA ||
|
||||||
io->buffer_id >= port->n_buffers)
|
io->buffer_id >= port->n_buffers)
|
||||||
|
|
@ -844,9 +826,6 @@ static int process_write(struct seq_state *state)
|
||||||
size_t body_size;
|
size_t body_size;
|
||||||
uint8_t *body;
|
uint8_t *body;
|
||||||
|
|
||||||
if (c.type != SPA_CONTROL_UMP)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
body = (uint8_t*)c_body;
|
body = (uint8_t*)c_body;
|
||||||
body_size = c.value.size;
|
body_size = c.value.size;
|
||||||
|
|
||||||
|
|
@ -861,6 +840,9 @@ static int process_write(struct seq_state *state)
|
||||||
#ifdef HAVE_ALSA_UMP
|
#ifdef HAVE_ALSA_UMP
|
||||||
snd_seq_ump_event_t ev;
|
snd_seq_ump_event_t ev;
|
||||||
|
|
||||||
|
if (c.type != SPA_CONTROL_UMP)
|
||||||
|
continue;
|
||||||
|
|
||||||
snd_seq_ump_ev_clear(&ev);
|
snd_seq_ump_ev_clear(&ev);
|
||||||
snd_seq_ev_set_ump_data(&ev, body, SPA_MIN(sizeof(ev.ump), (size_t)body_size));
|
snd_seq_ev_set_ump_data(&ev, body, SPA_MIN(sizeof(ev.ump), (size_t)body_size));
|
||||||
snd_seq_ev_set_source(&ev, state->event.addr.port);
|
snd_seq_ev_set_source(&ev, state->event.addr.port);
|
||||||
|
|
@ -878,26 +860,26 @@ static int process_write(struct seq_state *state)
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
snd_seq_event_t ev;
|
snd_seq_event_t ev;
|
||||||
uint8_t data[MAX_EVENT_SIZE];
|
int size = 0;
|
||||||
int size;
|
long s;
|
||||||
uint64_t st = 0;
|
|
||||||
|
if (c.type != SPA_CONTROL_Midi)
|
||||||
|
continue;
|
||||||
|
|
||||||
while (body_size > 0) {
|
while (body_size > 0) {
|
||||||
if ((size = spa_ump_to_midi((const uint32_t **)&body, &body_size,
|
if (size == 0)
|
||||||
data, sizeof(data), &st)) <= 0)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (first)
|
|
||||||
snd_seq_ev_clear(&ev);
|
snd_seq_ev_clear(&ev);
|
||||||
|
|
||||||
if ((size = snd_midi_event_encode(stream->codec, data, size, &ev)) < 0) {
|
if ((s = snd_midi_event_encode(stream->codec, body, body_size, &ev)) < 0) {
|
||||||
spa_log_warn(state->log, "failed to encode event: %s",
|
spa_log_warn(state->log, "failed to encode event: %s",
|
||||||
snd_strerror(size));
|
snd_strerror(size));
|
||||||
snd_midi_event_reset_encode(stream->codec);
|
snd_midi_event_reset_encode(stream->codec);
|
||||||
first = true;
|
size = 0;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
first = false;
|
body += s;
|
||||||
|
body_size -= s;
|
||||||
|
size += s;
|
||||||
if (ev.type == SND_SEQ_EVENT_NONE)
|
if (ev.type == SND_SEQ_EVENT_NONE)
|
||||||
/* this can happen when the event is not complete yet, like
|
/* this can happen when the event is not complete yet, like
|
||||||
* a sysex message and we need to encode some more data. */
|
* a sysex message and we need to encode some more data. */
|
||||||
|
|
@ -913,7 +895,7 @@ static int process_write(struct seq_state *state)
|
||||||
spa_log_warn(state->log, "failed to output event: %s",
|
spa_log_warn(state->log, "failed to output event: %s",
|
||||||
snd_strerror(err));
|
snd_strerror(err));
|
||||||
}
|
}
|
||||||
first = true;
|
size = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -82,6 +82,8 @@ struct seq_port {
|
||||||
struct spa_pod_builder builder;
|
struct spa_pod_builder builder;
|
||||||
struct spa_pod_frame frame;
|
struct spa_pod_frame frame;
|
||||||
|
|
||||||
|
uint32_t control_types;
|
||||||
|
|
||||||
struct spa_audio_info current_format;
|
struct spa_audio_info current_format;
|
||||||
unsigned int have_format:1;
|
unsigned int have_format:1;
|
||||||
unsigned int active:1;
|
unsigned int active:1;
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ struct card {
|
||||||
unsigned int accessible:1;
|
unsigned int accessible:1;
|
||||||
unsigned int ignored:1;
|
unsigned int ignored:1;
|
||||||
unsigned int emitted:1;
|
unsigned int emitted:1;
|
||||||
|
unsigned int wireless_disconnected:1;
|
||||||
|
|
||||||
/* Local SPA object IDs. (Global IDs are produced by PipeWire
|
/* Local SPA object IDs. (Global IDs are produced by PipeWire
|
||||||
* out of this using its registry.) Compress-Offload or PCM
|
* out of this using its registry.) Compress-Offload or PCM
|
||||||
|
|
@ -59,6 +60,10 @@ struct card {
|
||||||
* is used because 0 is a valid ALSA card number. */
|
* is used because 0 is a valid ALSA card number. */
|
||||||
uint32_t pcm_device_id;
|
uint32_t pcm_device_id;
|
||||||
uint32_t compress_offload_device_id;
|
uint32_t compress_offload_device_id;
|
||||||
|
|
||||||
|
/* Syspath of the USB interface that has wireless_status (e.g.
|
||||||
|
* /sys/devices/.../1-5:1.3). Empty string when not applicable. */
|
||||||
|
char wireless_status_syspath[256];
|
||||||
};
|
};
|
||||||
|
|
||||||
static uint32_t calc_pcm_device_id(struct card *card)
|
static uint32_t calc_pcm_device_id(struct card *card)
|
||||||
|
|
@ -92,6 +97,8 @@ struct impl {
|
||||||
|
|
||||||
struct spa_source source;
|
struct spa_source source;
|
||||||
struct spa_source notify;
|
struct spa_source notify;
|
||||||
|
struct udev_monitor *usb_umonitor;
|
||||||
|
struct spa_source usb_source;
|
||||||
unsigned int use_acp:1;
|
unsigned int use_acp:1;
|
||||||
unsigned int expose_busy:1;
|
unsigned int expose_busy:1;
|
||||||
int use_ucm;
|
int use_ucm;
|
||||||
|
|
@ -353,6 +360,87 @@ static int check_udev_environment(struct udev *udev, const char *devname)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void check_wireless_status(struct impl *this, struct card *card)
|
||||||
|
{
|
||||||
|
char path[PATH_MAX];
|
||||||
|
char buf[32];
|
||||||
|
size_t sz;
|
||||||
|
bool was_disconnected;
|
||||||
|
|
||||||
|
if (card->wireless_status_syspath[0] == '\0')
|
||||||
|
return;
|
||||||
|
|
||||||
|
was_disconnected = card->wireless_disconnected;
|
||||||
|
|
||||||
|
spa_scnprintf(path, sizeof(path), "%s/wireless_status", card->wireless_status_syspath);
|
||||||
|
|
||||||
|
spa_autoptr(FILE) f = fopen(path, "re");
|
||||||
|
if (f == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sz = fread(buf, 1, sizeof(buf) - 1, f);
|
||||||
|
buf[sz] = '\0';
|
||||||
|
|
||||||
|
card->wireless_disconnected = spa_strstartswith(buf, "disconnected");
|
||||||
|
|
||||||
|
if (card->wireless_disconnected != was_disconnected)
|
||||||
|
spa_log_info(this->log, "card %u: wireless headset %s",
|
||||||
|
card->card_nr,
|
||||||
|
card->wireless_disconnected ? "disconnected" : "connected");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void find_wireless_status(struct impl *this, struct card *card)
|
||||||
|
{
|
||||||
|
const char *bus, *parent_syspath, *parent_sysname;
|
||||||
|
struct udev_device *parent;
|
||||||
|
struct dirent *entry;
|
||||||
|
char path[PATH_MAX];
|
||||||
|
size_t sysname_len;
|
||||||
|
|
||||||
|
bus = udev_device_get_property_value(card->udev_device, "ID_BUS");
|
||||||
|
if (!spa_streq(bus, "usb"))
|
||||||
|
return;
|
||||||
|
|
||||||
|
/* udev_device_get_parent_* returns a borrowed reference owned by the child; do not unref it. */
|
||||||
|
parent = udev_device_get_parent_with_subsystem_devtype(card->udev_device, "usb", "usb_device");
|
||||||
|
if (parent == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parent_syspath = udev_device_get_syspath(parent);
|
||||||
|
parent_sysname = udev_device_get_sysname(parent);
|
||||||
|
if (parent_syspath == NULL || parent_sysname == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sysname_len = strlen(parent_sysname);
|
||||||
|
|
||||||
|
spa_autoptr(DIR) dir = opendir(parent_syspath);
|
||||||
|
if (dir == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while ((entry = readdir(dir)) != NULL) {
|
||||||
|
/* USB interface directories are named "<sysname>:<config>.<intf>" */
|
||||||
|
if (strncmp(entry->d_name, parent_sysname, sysname_len) != 0 ||
|
||||||
|
entry->d_name[sysname_len] != ':')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
spa_scnprintf(path, sizeof(path), "%s/%s/wireless_status",
|
||||||
|
parent_syspath, entry->d_name);
|
||||||
|
if (access(path, R_OK) < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
spa_scnprintf(card->wireless_status_syspath,
|
||||||
|
sizeof(card->wireless_status_syspath),
|
||||||
|
"%s/%s", parent_syspath, entry->d_name);
|
||||||
|
|
||||||
|
check_wireless_status(this, card);
|
||||||
|
|
||||||
|
spa_log_debug(this->log, "card %u: found wireless_status at %s (%s)",
|
||||||
|
card->card_nr, card->wireless_status_syspath,
|
||||||
|
card->wireless_disconnected ? "disconnected" : "connected");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int check_pcm_device_availability(struct impl *this, struct card *card,
|
static int check_pcm_device_availability(struct impl *this, struct card *card,
|
||||||
int *num_pcm_devices)
|
int *num_pcm_devices)
|
||||||
{
|
{
|
||||||
|
|
@ -538,6 +626,9 @@ static int emit_added_object_info(struct impl *this, struct card *card)
|
||||||
if ((str = udev_device_get_property_value(udev_device, "ACP_PROFILE_SET")) && *str)
|
if ((str = udev_device_get_property_value(udev_device, "ACP_PROFILE_SET")) && *str)
|
||||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_PROFILE_SET, str);
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_PROFILE_SET, str);
|
||||||
|
|
||||||
|
if ((str = udev_device_get_property_value(udev_device, "ACP_IGNORE_DB")) && *str)
|
||||||
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_API_ALSA_IGNORE_DB, str);
|
||||||
|
|
||||||
if ((str = udev_device_get_property_value(udev_device, "SOUND_CLASS")) && *str)
|
if ((str = udev_device_get_property_value(udev_device, "SOUND_CLASS")) && *str)
|
||||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_CLASS, str);
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_CLASS, str);
|
||||||
|
|
||||||
|
|
@ -576,11 +667,14 @@ static int emit_added_object_info(struct impl *this, struct card *card)
|
||||||
if (!(str && *str)) {
|
if (!(str && *str)) {
|
||||||
str = udev_device_get_property_value(udev_device, "ID_VENDOR");
|
str = udev_device_get_property_value(udev_device, "ID_VENDOR");
|
||||||
} else {
|
} else {
|
||||||
char *t = alloca(strlen(str) + 1);
|
size_t slen = strlen(str) + 1;
|
||||||
|
if (slen <= 1024) {
|
||||||
|
char *t = alloca(slen);
|
||||||
unescape(str, t);
|
unescape(str, t);
|
||||||
str = t;
|
str = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (str && *str) {
|
if (str && *str) {
|
||||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_VENDOR_NAME, str);
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_VENDOR_NAME, str);
|
||||||
}
|
}
|
||||||
|
|
@ -598,11 +692,14 @@ static int emit_added_object_info(struct impl *this, struct card *card)
|
||||||
if (!(str && *str)) {
|
if (!(str && *str)) {
|
||||||
str = udev_device_get_property_value(udev_device, "ID_MODEL");
|
str = udev_device_get_property_value(udev_device, "ID_MODEL");
|
||||||
} else {
|
} else {
|
||||||
char *t = alloca(strlen(str) + 1);
|
size_t slen = strlen(str) + 1;
|
||||||
|
if (slen <= 1024) {
|
||||||
|
char *t = alloca(slen);
|
||||||
unescape(str, t);
|
unescape(str, t);
|
||||||
str = t;
|
str = t;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if (str && *str)
|
if (str && *str)
|
||||||
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_PRODUCT_NAME, str);
|
items[n_items++] = SPA_DICT_ITEM_INIT(SPA_KEY_DEVICE_PRODUCT_NAME, str);
|
||||||
|
|
||||||
|
|
@ -725,13 +822,17 @@ static bool check_access(struct impl *this, struct card *card)
|
||||||
|
|
||||||
static void process_card(struct impl *this, enum action action, struct card *card)
|
static void process_card(struct impl *this, enum action action, struct card *card)
|
||||||
{
|
{
|
||||||
|
switch (action) {
|
||||||
|
case ACTION_CHANGE: {
|
||||||
if (card->ignored)
|
if (card->ignored)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
switch (action) {
|
|
||||||
case ACTION_CHANGE: {
|
|
||||||
check_access(this, card);
|
check_access(this, card);
|
||||||
if (card->accessible && !card->emitted) {
|
check_wireless_status(this, card);
|
||||||
|
|
||||||
|
bool effective_accessible = card->accessible && !card->wireless_disconnected;
|
||||||
|
|
||||||
|
if (effective_accessible && !card->emitted) {
|
||||||
int res = emit_added_object_info(this, card);
|
int res = emit_added_object_info(this, card);
|
||||||
if (res < 0) {
|
if (res < 0) {
|
||||||
if (card->ignored)
|
if (card->ignored)
|
||||||
|
|
@ -750,7 +851,7 @@ static void process_card(struct impl *this, enum action action, struct card *car
|
||||||
card->card_nr);
|
card->card_nr);
|
||||||
card->unavailable = false;
|
card->unavailable = false;
|
||||||
}
|
}
|
||||||
} else if (!card->accessible && card->emitted) {
|
} else if (!effective_accessible && card->emitted) {
|
||||||
card->emitted = false;
|
card->emitted = false;
|
||||||
|
|
||||||
if (card->pcm_device_id != ID_DEVICE_NOT_SUPPORTED)
|
if (card->pcm_device_id != ID_DEVICE_NOT_SUPPORTED)
|
||||||
|
|
@ -787,8 +888,11 @@ static void process_udev_device(struct impl *this, enum action action, struct ud
|
||||||
return;
|
return;
|
||||||
|
|
||||||
card = find_card(this, card_nr);
|
card = find_card(this, card_nr);
|
||||||
if (action == ACTION_CHANGE && !card)
|
if (action == ACTION_CHANGE && !card) {
|
||||||
card = add_card(this, card_nr, udev_device);
|
card = add_card(this, card_nr, udev_device);
|
||||||
|
if (card)
|
||||||
|
find_wireless_status(this, card);
|
||||||
|
}
|
||||||
|
|
||||||
if (!card)
|
if (!card)
|
||||||
return;
|
return;
|
||||||
|
|
@ -915,6 +1019,41 @@ static void impl_on_fd_events(struct spa_source *source)
|
||||||
udev_device_unref(udev_device);
|
udev_device_unref(udev_device);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void impl_on_usb_events(struct spa_source *source)
|
||||||
|
{
|
||||||
|
struct impl *this = source->data;
|
||||||
|
struct udev_device *udev_device;
|
||||||
|
const char *action, *syspath;
|
||||||
|
unsigned int i;
|
||||||
|
|
||||||
|
udev_device = udev_monitor_receive_device(this->usb_umonitor);
|
||||||
|
if (udev_device == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if ((action = udev_device_get_action(udev_device)) == NULL)
|
||||||
|
action = "change";
|
||||||
|
|
||||||
|
if (!spa_streq(action, "change"))
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
syspath = udev_device_get_syspath(udev_device);
|
||||||
|
if (syspath == NULL)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
for (i = 0; i < this->n_cards; i++) {
|
||||||
|
struct card *card = &this->cards[i];
|
||||||
|
if (card->wireless_status_syspath[0] == '\0')
|
||||||
|
continue;
|
||||||
|
if (!spa_streq(card->wireless_status_syspath, syspath))
|
||||||
|
continue;
|
||||||
|
spa_log_debug(this->log, "wireless_status change for card %u", card->card_nr);
|
||||||
|
process_card(this, ACTION_CHANGE, card);
|
||||||
|
}
|
||||||
|
|
||||||
|
done:
|
||||||
|
udev_device_unref(udev_device);
|
||||||
|
}
|
||||||
|
|
||||||
static int start_monitor(struct impl *this)
|
static int start_monitor(struct impl *this)
|
||||||
{
|
{
|
||||||
int res;
|
int res;
|
||||||
|
|
@ -938,6 +1077,20 @@ static int start_monitor(struct impl *this)
|
||||||
spa_log_debug(this->log, "monitor %p", this->umonitor);
|
spa_log_debug(this->log, "monitor %p", this->umonitor);
|
||||||
spa_loop_add_source(this->main_loop, &this->source);
|
spa_loop_add_source(this->main_loop, &this->source);
|
||||||
|
|
||||||
|
this->usb_umonitor = udev_monitor_new_from_netlink(this->udev, "udev");
|
||||||
|
if (this->usb_umonitor != NULL) {
|
||||||
|
udev_monitor_filter_add_match_subsystem_devtype(this->usb_umonitor,
|
||||||
|
"usb", "usb_interface");
|
||||||
|
udev_monitor_enable_receiving(this->usb_umonitor);
|
||||||
|
|
||||||
|
this->usb_source.func = impl_on_usb_events;
|
||||||
|
this->usb_source.data = this;
|
||||||
|
this->usb_source.fd = udev_monitor_get_fd(this->usb_umonitor);
|
||||||
|
this->usb_source.mask = SPA_IO_IN | SPA_IO_ERR;
|
||||||
|
|
||||||
|
spa_loop_add_source(this->main_loop, &this->usb_source);
|
||||||
|
}
|
||||||
|
|
||||||
if ((res = start_inotify(this)) < 0)
|
if ((res = start_inotify(this)) < 0)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
|
@ -955,6 +1108,12 @@ static int stop_monitor(struct impl *this)
|
||||||
udev_monitor_unref(this->umonitor);
|
udev_monitor_unref(this->umonitor);
|
||||||
this->umonitor = NULL;
|
this->umonitor = NULL;
|
||||||
|
|
||||||
|
if (this->usb_umonitor != NULL) {
|
||||||
|
spa_loop_remove_source(this->main_loop, &this->usb_source);
|
||||||
|
udev_monitor_unref(this->usb_umonitor);
|
||||||
|
this->usb_umonitor = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
stop_inotify(this);
|
stop_inotify(this);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
|
|
@ -40,7 +40,7 @@ struct compress_offload_api_context* compress_offload_api_open(int card_nr, int
|
||||||
|
|
||||||
snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card_nr, device_nr);
|
snprintf(fn, sizeof(fn), "/dev/snd/comprC%uD%u", card_nr, device_nr);
|
||||||
|
|
||||||
context->fd = open(fn, O_WRONLY);
|
context->fd = open(fn, O_WRONLY | O_CLOEXEC);
|
||||||
if (context->fd < 0) {
|
if (context->fd < 0) {
|
||||||
spa_log_error(context->log, "could not open device \"%s\": %s (%d)", fn, strerror(errno), errno);
|
spa_log_error(context->log, "could not open device \"%s\": %s (%d)", fn, strerror(errno), errno);
|
||||||
goto error;
|
goto error;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,70 @@
|
||||||
|
# This file is part of PulseAudio.
|
||||||
|
#
|
||||||
|
# PulseAudio is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Lesser General Public License as
|
||||||
|
# published by the Free Software Foundation; either version 2.1 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# PulseAudio is distributed in the hope that it will be useful, but
|
||||||
|
# WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
# General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
|
# along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
; USB gaming headset.
|
||||||
|
; These headsets usually have two output devices. The first one is meant
|
||||||
|
; for general audio, and the second one is meant for chat. There is also
|
||||||
|
; a single input device for chat.
|
||||||
|
; The purpose of this unusual design is to provide separate volume
|
||||||
|
; controls for voice and other audio, which can be useful in gaming.
|
||||||
|
;
|
||||||
|
; Works with:
|
||||||
|
; JBL Quantum 810 Wireless
|
||||||
|
; JBL Quantum One
|
||||||
|
;
|
||||||
|
; Based on usb-gaming-headset.conf.
|
||||||
|
;
|
||||||
|
; See default.conf for an explanation on the directives used here.
|
||||||
|
|
||||||
|
[General]
|
||||||
|
auto-profiles = yes
|
||||||
|
|
||||||
|
[Mapping mono-chat-output]
|
||||||
|
description-key = gaming-headset-chat
|
||||||
|
device-strings = hw:%f,1,0
|
||||||
|
channel-map = mono
|
||||||
|
paths-output = usb-gaming-headset-output-mono
|
||||||
|
intended-roles = phone
|
||||||
|
|
||||||
|
[Mapping stereo-chat-output]
|
||||||
|
description-key = gaming-headset-chat
|
||||||
|
device-strings = hw:%f,1,0
|
||||||
|
channel-map = left,right
|
||||||
|
paths-output = usb-gaming-headset-output-stereo
|
||||||
|
intended-roles = phone
|
||||||
|
|
||||||
|
[Mapping mono-chat-input]
|
||||||
|
description-key = gaming-headset-chat
|
||||||
|
device-strings = hw:%f,0,0
|
||||||
|
channel-map = mono
|
||||||
|
paths-input = usb-gaming-headset-input
|
||||||
|
intended-roles = phone
|
||||||
|
|
||||||
|
[Mapping stereo-game-output]
|
||||||
|
description-key = gaming-headset-game
|
||||||
|
device-strings = hw:%f,0,0
|
||||||
|
channel-map = left,right
|
||||||
|
paths-output = usb-gaming-headset-output-stereo
|
||||||
|
direction = output
|
||||||
|
|
||||||
|
[Profile output:mono-chat+output:stereo-game+input:mono-chat]
|
||||||
|
output-mappings = mono-chat-output stereo-game-output
|
||||||
|
input-mappings = mono-chat-input
|
||||||
|
priority = 5100
|
||||||
|
|
||||||
|
[Profile output:stereo-game+output:stereo-chat+input:mono-chat]
|
||||||
|
output-mappings = stereo-game-output stereo-chat-output
|
||||||
|
input-mappings = mono-chat-input
|
||||||
|
priority = 5100
|
||||||
|
|
@ -35,6 +35,7 @@ SPA_LOG_TOPIC_DEFINE_STATIC(log_topic, "spa.audioadapter");
|
||||||
|
|
||||||
#define MAX_PORTS (SPA_AUDIO_MAX_CHANNELS+1)
|
#define MAX_PORTS (SPA_AUDIO_MAX_CHANNELS+1)
|
||||||
#define MAX_RETRY 64
|
#define MAX_RETRY 64
|
||||||
|
#define MAX_BLOCKS 4096
|
||||||
|
|
||||||
/** \cond */
|
/** \cond */
|
||||||
|
|
||||||
|
|
@ -63,7 +64,7 @@ struct impl {
|
||||||
struct spa_node *convert;
|
struct spa_node *convert;
|
||||||
struct spa_hook convert_listener;
|
struct spa_hook convert_listener;
|
||||||
uint64_t convert_port_flags;
|
uint64_t convert_port_flags;
|
||||||
char *convertname;
|
char convertname[64];
|
||||||
|
|
||||||
uint32_t n_buffers;
|
uint32_t n_buffers;
|
||||||
struct spa_buffer **buffers;
|
struct spa_buffer **buffers;
|
||||||
|
|
@ -356,6 +357,7 @@ static void emit_node_info(struct impl *this, bool full)
|
||||||
|
|
||||||
if (this->info.props)
|
if (this->info.props)
|
||||||
n_items = this->info.props->n_items;
|
n_items = this->info.props->n_items;
|
||||||
|
n_items = SPA_MIN(n_items, 1024u);
|
||||||
items = alloca((n_items + 2) * sizeof(struct spa_dict_item));
|
items = alloca((n_items + 2) * sizeof(struct spa_dict_item));
|
||||||
for (i = 0; i < n_items; i++)
|
for (i = 0; i < n_items; i++)
|
||||||
items[i] = this->info.props->items[i];
|
items[i] = this->info.props->items[i];
|
||||||
|
|
@ -513,6 +515,9 @@ static int negotiate_buffers(struct impl *this)
|
||||||
|
|
||||||
align = SPA_MAX(align, this->max_align);
|
align = SPA_MAX(align, this->max_align);
|
||||||
|
|
||||||
|
if (blocks > MAX_BLOCKS)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
datas = alloca(sizeof(struct spa_data) * blocks);
|
datas = alloca(sizeof(struct spa_data) * blocks);
|
||||||
memset(datas, 0, sizeof(struct spa_data) * blocks);
|
memset(datas, 0, sizeof(struct spa_data) * blocks);
|
||||||
aligns = alloca(sizeof(uint32_t) * blocks);
|
aligns = alloca(sizeof(uint32_t) * blocks);
|
||||||
|
|
@ -1086,6 +1091,8 @@ static int impl_node_send_command(void *object, const struct spa_command *comman
|
||||||
spa_log_debug(this->log, "%p: suspending", this);
|
spa_log_debug(this->log, "%p: suspending", this);
|
||||||
break;
|
break;
|
||||||
case SPA_NODE_COMMAND_Pause:
|
case SPA_NODE_COMMAND_Pause:
|
||||||
|
if ((res = negotiate_format(this)) < 0)
|
||||||
|
return res;
|
||||||
spa_log_debug(this->log, "%p: pausing", this);
|
spa_log_debug(this->log, "%p: pausing", this);
|
||||||
break;
|
break;
|
||||||
case SPA_NODE_COMMAND_Flush:
|
case SPA_NODE_COMMAND_Flush:
|
||||||
|
|
@ -1810,6 +1817,9 @@ impl_node_port_reuse_buffer(void *object, uint32_t port_id, uint32_t buffer_id)
|
||||||
|
|
||||||
spa_return_val_if_fail(this != NULL, -EINVAL);
|
spa_return_val_if_fail(this != NULL, -EINVAL);
|
||||||
|
|
||||||
|
if (SPA_DIRECTION_OUTPUT != this->direction)
|
||||||
|
port_id++;
|
||||||
|
|
||||||
return spa_node_port_reuse_buffer(this->target, port_id, buffer_id);
|
return spa_node_port_reuse_buffer(this->target, port_id, buffer_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1937,11 +1947,12 @@ static int load_converter(struct impl *this, const struct spa_dict *info,
|
||||||
struct spa_dict_item *items;
|
struct spa_dict_item *items;
|
||||||
struct spa_dict cinfo;
|
struct spa_dict cinfo;
|
||||||
char direction[16];
|
char direction[16];
|
||||||
uint32_t i;
|
uint32_t i, n_items;
|
||||||
|
|
||||||
items = alloca((info->n_items + 1) * sizeof(struct spa_dict_item));
|
n_items = SPA_MIN(info->n_items, 1024u);
|
||||||
|
items = alloca((n_items + 1) * sizeof(struct spa_dict_item));
|
||||||
cinfo = SPA_DICT(items, 0);
|
cinfo = SPA_DICT(items, 0);
|
||||||
for (i = 0; i < info->n_items; i++)
|
for (i = 0; i < n_items; i++)
|
||||||
items[cinfo.n_items++] = info->items[i];
|
items[cinfo.n_items++] = info->items[i];
|
||||||
|
|
||||||
snprintf(direction, sizeof(direction), "%s",
|
snprintf(direction, sizeof(direction), "%s",
|
||||||
|
|
@ -1985,7 +1996,7 @@ static int load_converter(struct impl *this, const struct spa_dict *info,
|
||||||
this->hnd_convert = hnd_convert;
|
this->hnd_convert = hnd_convert;
|
||||||
this->convert = iface_conv;
|
this->convert = iface_conv;
|
||||||
this->unload_handle = unload_handle;
|
this->unload_handle = unload_handle;
|
||||||
this->convertname = strdup(factory_name);
|
snprintf(this->convertname, sizeof(this->convertname), "%s", factory_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -2118,7 +2129,6 @@ static int impl_clear(struct spa_handle *handle)
|
||||||
spa_handle_clear(this->hnd_convert);
|
spa_handle_clear(this->hnd_convert);
|
||||||
free(this->hnd_convert);
|
free(this->hnd_convert);
|
||||||
}
|
}
|
||||||
free(this->convertname);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
clear_buffers(this);
|
clear_buffers(this);
|
||||||
|
|
|
||||||
|
|
@ -7,15 +7,18 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
#include <spa/support/plugin.h>
|
#include <spa/support/plugin.h>
|
||||||
#include <spa/support/cpu.h>
|
#include <spa/support/cpu.h>
|
||||||
#include <spa/support/loop.h>
|
#include <spa/support/loop.h>
|
||||||
#include <spa/support/log.h>
|
#include <spa/support/log.h>
|
||||||
#include <spa/support/plugin-loader.h>
|
#include <spa/support/plugin-loader.h>
|
||||||
|
#include <spa/utils/overflow.h>
|
||||||
#include <spa/utils/result.h>
|
#include <spa/utils/result.h>
|
||||||
#include <spa/utils/list.h>
|
#include <spa/utils/list.h>
|
||||||
#include <spa/utils/json.h>
|
#include <spa/utils/json.h>
|
||||||
|
#include <spa/utils/json-builder.h>
|
||||||
#include <spa/utils/names.h>
|
#include <spa/utils/names.h>
|
||||||
#include <spa/utils/string.h>
|
#include <spa/utils/string.h>
|
||||||
#include <spa/utils/ratelimit.h>
|
#include <spa/utils/ratelimit.h>
|
||||||
|
|
@ -100,6 +103,7 @@ struct props {
|
||||||
unsigned int mix_disabled:1;
|
unsigned int mix_disabled:1;
|
||||||
unsigned int resample_disabled:1;
|
unsigned int resample_disabled:1;
|
||||||
unsigned int resample_quality;
|
unsigned int resample_quality;
|
||||||
|
struct resample_config resample_config;
|
||||||
double rate;
|
double rate;
|
||||||
char wav_path[512];
|
char wav_path[512];
|
||||||
unsigned int lock_volumes:1;
|
unsigned int lock_volumes:1;
|
||||||
|
|
@ -122,6 +126,7 @@ static void props_reset(struct props *props)
|
||||||
props->mix_disabled = false;
|
props->mix_disabled = false;
|
||||||
props->resample_disabled = false;
|
props->resample_disabled = false;
|
||||||
props->resample_quality = RESAMPLE_DEFAULT_QUALITY;
|
props->resample_quality = RESAMPLE_DEFAULT_QUALITY;
|
||||||
|
spa_zero(props->resample_config);
|
||||||
props->rate = 1.0;
|
props->rate = 1.0;
|
||||||
spa_zero(props->wav_path);
|
spa_zero(props->wav_path);
|
||||||
props->lock_volumes = false;
|
props->lock_volumes = false;
|
||||||
|
|
@ -266,6 +271,7 @@ struct impl {
|
||||||
struct spa_list active_graphs;
|
struct spa_list active_graphs;
|
||||||
struct filter_graph graphs[MAX_GRAPH];
|
struct filter_graph graphs[MAX_GRAPH];
|
||||||
struct spa_process_latency_info latency;
|
struct spa_process_latency_info latency;
|
||||||
|
char *graph_descs[MAX_GRAPH];
|
||||||
|
|
||||||
int in_filter_props;
|
int in_filter_props;
|
||||||
int filter_props_count;
|
int filter_props_count;
|
||||||
|
|
@ -720,6 +726,34 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 19:
|
case 19:
|
||||||
|
*param = spa_pod_builder_add_object(b,
|
||||||
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.center-level"),
|
||||||
|
SPA_PROP_INFO_description, SPA_POD_String("Center up/downmix level"),
|
||||||
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
|
||||||
|
this->mix.center_level, 0.0, 10.0),
|
||||||
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
|
break;
|
||||||
|
case 20:
|
||||||
|
*param = spa_pod_builder_add_object(b,
|
||||||
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.surround-level"),
|
||||||
|
SPA_PROP_INFO_description, SPA_POD_String("Surround up/downmix level"),
|
||||||
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
|
||||||
|
this->mix.surround_level, 0.0, 10.0),
|
||||||
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
|
break;
|
||||||
|
case 21:
|
||||||
|
*param = spa_pod_builder_add_object(b,
|
||||||
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.lfe-level"),
|
||||||
|
SPA_PROP_INFO_description, SPA_POD_String("LFE up/downmix level"),
|
||||||
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Float(
|
||||||
|
this->mix.lfe_level, 0.0, 10.0),
|
||||||
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 22:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("channelmix.hilbert-taps"),
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.hilbert-taps"),
|
||||||
|
|
@ -728,7 +762,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
this->mix.hilbert_taps, 0, MAX_TAPS),
|
this->mix.hilbert_taps, 0, MAX_TAPS),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 20:
|
case 23:
|
||||||
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
||||||
spa_pod_builder_add(b,
|
spa_pod_builder_add(b,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("channelmix.upmix-method"),
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.upmix-method"),
|
||||||
|
|
@ -747,14 +781,14 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
spa_pod_builder_pop(b, &f[1]);
|
spa_pod_builder_pop(b, &f[1]);
|
||||||
*param = spa_pod_builder_pop(b, &f[0]);
|
*param = spa_pod_builder_pop(b, &f[0]);
|
||||||
break;
|
break;
|
||||||
case 21:
|
case 24:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_rate),
|
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_rate),
|
||||||
SPA_PROP_INFO_description, SPA_POD_String("Rate scaler"),
|
SPA_PROP_INFO_description, SPA_POD_String("Rate scaler"),
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Double(p->rate, 0.0, 10.0));
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Double(p->rate, 0.0, 10.0));
|
||||||
break;
|
break;
|
||||||
case 22:
|
case 25:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_quality),
|
SPA_PROP_INFO_id, SPA_POD_Id(SPA_PROP_quality),
|
||||||
|
|
@ -763,7 +797,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->resample_quality, 0, 14),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(p->resample_quality, 0, 14),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 23:
|
case 26:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("resample.disable"),
|
SPA_PROP_INFO_name, SPA_POD_String("resample.disable"),
|
||||||
|
|
@ -771,7 +805,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->resample_disabled),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->resample_disabled),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 24:
|
case 27:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("dither.noise"),
|
SPA_PROP_INFO_name, SPA_POD_String("dither.noise"),
|
||||||
|
|
@ -779,7 +813,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(this->dir[1].conv.noise_bits, 0, 16),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_RANGE_Int(this->dir[1].conv.noise_bits, 0, 16),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 25:
|
case 28:
|
||||||
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
spa_pod_builder_push_object(b, &f[0], SPA_TYPE_OBJECT_PropInfo, id);
|
||||||
spa_pod_builder_add(b,
|
spa_pod_builder_add(b,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("dither.method"),
|
SPA_PROP_INFO_name, SPA_POD_String("dither.method"),
|
||||||
|
|
@ -797,7 +831,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
spa_pod_builder_pop(b, &f[1]);
|
spa_pod_builder_pop(b, &f[1]);
|
||||||
*param = spa_pod_builder_pop(b, &f[0]);
|
*param = spa_pod_builder_pop(b, &f[0]);
|
||||||
break;
|
break;
|
||||||
case 26:
|
case 29:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("debug.wav-path"),
|
SPA_PROP_INFO_name, SPA_POD_String("debug.wav-path"),
|
||||||
|
|
@ -805,7 +839,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_String(p->wav_path),
|
SPA_PROP_INFO_type, SPA_POD_String(p->wav_path),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 27:
|
case 30:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("channelmix.lock-volumes"),
|
SPA_PROP_INFO_name, SPA_POD_String("channelmix.lock-volumes"),
|
||||||
|
|
@ -813,7 +847,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->lock_volumes),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->lock_volumes),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 28:
|
case 31:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.disable"),
|
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.disable"),
|
||||||
|
|
@ -821,7 +855,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->filter_graph_disabled),
|
SPA_PROP_INFO_type, SPA_POD_CHOICE_Bool(p->filter_graph_disabled),
|
||||||
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
SPA_PROP_INFO_params, SPA_POD_Bool(true));
|
||||||
break;
|
break;
|
||||||
case 29:
|
case 32:
|
||||||
*param = spa_pod_builder_add_object(b,
|
*param = spa_pod_builder_add_object(b,
|
||||||
SPA_TYPE_OBJECT_PropInfo, id,
|
SPA_TYPE_OBJECT_PropInfo, id,
|
||||||
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.N"),
|
SPA_PROP_INFO_name, SPA_POD_String("audioconvert.filter-graph.N"),
|
||||||
|
|
@ -832,7 +866,7 @@ static int node_param_prop_info(struct impl *this, uint32_t id, uint32_t index,
|
||||||
default:
|
default:
|
||||||
if (this->filter_graph[0] && this->filter_graph[0]->graph) {
|
if (this->filter_graph[0] && this->filter_graph[0]->graph) {
|
||||||
return spa_filter_graph_enum_prop_info(this->filter_graph[0]->graph,
|
return spa_filter_graph_enum_prop_info(this->filter_graph[0]->graph,
|
||||||
index - 30, b, param);
|
index - 33, b, param);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -844,6 +878,7 @@ static int node_param_props(struct impl *this, uint32_t id, uint32_t index,
|
||||||
{
|
{
|
||||||
struct props *p = &this->props;
|
struct props *p = &this->props;
|
||||||
struct spa_pod_frame f[2];
|
struct spa_pod_frame f[2];
|
||||||
|
struct filter_graph *g;
|
||||||
|
|
||||||
switch (index) {
|
switch (index) {
|
||||||
case 0:
|
case 0:
|
||||||
|
|
@ -898,6 +933,12 @@ static int node_param_props(struct impl *this, uint32_t id, uint32_t index,
|
||||||
spa_pod_builder_float(b, this->mix.rear_delay);
|
spa_pod_builder_float(b, this->mix.rear_delay);
|
||||||
spa_pod_builder_string(b, "channelmix.stereo-widen");
|
spa_pod_builder_string(b, "channelmix.stereo-widen");
|
||||||
spa_pod_builder_float(b, this->mix.widen);
|
spa_pod_builder_float(b, this->mix.widen);
|
||||||
|
spa_pod_builder_string(b, "channelmix.center-level");
|
||||||
|
spa_pod_builder_float(b, this->mix.center_level);
|
||||||
|
spa_pod_builder_string(b, "channelmix.surround-level");
|
||||||
|
spa_pod_builder_float(b, this->mix.surround_level);
|
||||||
|
spa_pod_builder_string(b, "channelmix.lfe-level");
|
||||||
|
spa_pod_builder_float(b, this->mix.lfe_level);
|
||||||
spa_pod_builder_string(b, "channelmix.hilbert-taps");
|
spa_pod_builder_string(b, "channelmix.hilbert-taps");
|
||||||
spa_pod_builder_int(b, this->mix.hilbert_taps);
|
spa_pod_builder_int(b, this->mix.hilbert_taps);
|
||||||
spa_pod_builder_string(b, "channelmix.upmix-method");
|
spa_pod_builder_string(b, "channelmix.upmix-method");
|
||||||
|
|
@ -916,8 +957,12 @@ static int node_param_props(struct impl *this, uint32_t id, uint32_t index,
|
||||||
spa_pod_builder_bool(b, p->lock_volumes);
|
spa_pod_builder_bool(b, p->lock_volumes);
|
||||||
spa_pod_builder_string(b, "audioconvert.filter-graph.disable");
|
spa_pod_builder_string(b, "audioconvert.filter-graph.disable");
|
||||||
spa_pod_builder_bool(b, p->filter_graph_disabled);
|
spa_pod_builder_bool(b, p->filter_graph_disabled);
|
||||||
spa_pod_builder_string(b, "audioconvert.filter-graph");
|
spa_list_for_each(g, &this->active_graphs, link) {
|
||||||
spa_pod_builder_string(b, "");
|
char key[64];
|
||||||
|
snprintf(key, sizeof(key), "audioconvert.filter-graph.%d", g->order);
|
||||||
|
spa_pod_builder_string(b, key);
|
||||||
|
spa_pod_builder_string(b, this->graph_descs[g->order]);
|
||||||
|
}
|
||||||
spa_pod_builder_pop(b, &f[1]);
|
spa_pod_builder_pop(b, &f[1]);
|
||||||
*param = spa_pod_builder_pop(b, &f[0]);
|
*param = spa_pod_builder_pop(b, &f[0]);
|
||||||
break;
|
break;
|
||||||
|
|
@ -951,7 +996,7 @@ static int impl_node_enum_params(void *object, int seq,
|
||||||
struct impl *this = object;
|
struct impl *this = object;
|
||||||
struct spa_pod *param;
|
struct spa_pod *param;
|
||||||
struct spa_pod_builder b = { 0 };
|
struct spa_pod_builder b = { 0 };
|
||||||
uint8_t buffer[4096];
|
uint8_t buffer[16384];
|
||||||
struct spa_result_node_params result;
|
struct spa_result_node_params result;
|
||||||
uint32_t count = 0;
|
uint32_t count = 0;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
@ -1017,9 +1062,8 @@ static int impl_node_set_io(void *object, uint32_t id, void *data, size_t size)
|
||||||
this->io_position = data;
|
this->io_position = data;
|
||||||
|
|
||||||
if (this->io_position && this->io_clock &&
|
if (this->io_position && this->io_clock &&
|
||||||
this->io_position->clock.target_rate.denom != this->io_clock->target_rate.denom &&
|
this->io_position->clock.target_rate.denom != this->io_clock->target_rate.denom) {
|
||||||
!this->props.resample_disabled) {
|
spa_log_debug(this->log, "driver %d changed rate:%u -> %u", this->io_position->clock.id,
|
||||||
spa_log_warn(this->log, "driver %d changed rate:%u -> %u", this->io_position->clock.id,
|
|
||||||
this->io_clock->target_rate.denom,
|
this->io_clock->target_rate.denom,
|
||||||
this->io_position->clock.target_rate.denom);
|
this->io_position->clock.target_rate.denom);
|
||||||
|
|
||||||
|
|
@ -1241,24 +1285,28 @@ static int ensure_tmp(struct impl *this)
|
||||||
uint32_t maxsize = this->maxsize, maxports = this->maxports;
|
uint32_t maxsize = this->maxsize, maxports = this->maxports;
|
||||||
uint32_t i;
|
uint32_t i;
|
||||||
float *empty, *scratch, *tmp[2];
|
float *empty, *scratch, *tmp[2];
|
||||||
|
size_t alloc_size;
|
||||||
|
|
||||||
|
if (spa_overflow_add((size_t)maxsize, (size_t)MAX_ALIGN, &alloc_size))
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
if (maxsize > this->scratch_size) {
|
if (maxsize > this->scratch_size) {
|
||||||
spa_log_info(this->log, "resize tmp %d -> %d", this->scratch_size, maxsize);
|
spa_log_info(this->log, "resize tmp %d -> %d", this->scratch_size, maxsize);
|
||||||
|
|
||||||
if ((empty = realloc(this->empty, maxsize + MAX_ALIGN)) != NULL)
|
if ((empty = realloc(this->empty, alloc_size)) != NULL)
|
||||||
this->empty = empty;
|
this->empty = empty;
|
||||||
if ((scratch = realloc(this->scratch, maxsize + MAX_ALIGN)) != NULL)
|
if ((scratch = realloc(this->scratch, alloc_size)) != NULL)
|
||||||
this->scratch = scratch;
|
this->scratch = scratch;
|
||||||
if (empty == NULL || scratch == NULL) {
|
if (empty == NULL || scratch == NULL) {
|
||||||
free_tmp(this);
|
free_tmp(this);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
memset(this->empty, 0, maxsize + MAX_ALIGN);
|
memset(this->empty, 0, alloc_size);
|
||||||
|
|
||||||
for (i = 0; i < this->scratch_ports; i++) {
|
for (i = 0; i < this->scratch_ports; i++) {
|
||||||
if ((tmp[0] = realloc(this->tmp[0][i], maxsize + MAX_ALIGN)) != NULL)
|
if ((tmp[0] = realloc(this->tmp[0][i], alloc_size)) != NULL)
|
||||||
this->tmp[0][i] = tmp[0];
|
this->tmp[0][i] = tmp[0];
|
||||||
if ((tmp[1] = realloc(this->tmp[1][i], maxsize + MAX_ALIGN)) != NULL)
|
if ((tmp[1] = realloc(this->tmp[1][i], alloc_size)) != NULL)
|
||||||
this->tmp[1][i] = tmp[1];
|
this->tmp[1][i] = tmp[1];
|
||||||
if (tmp[0] == NULL || tmp[1] == NULL) {
|
if (tmp[0] == NULL || tmp[1] == NULL) {
|
||||||
free_tmp(this);
|
free_tmp(this);
|
||||||
|
|
@ -1273,16 +1321,16 @@ static int ensure_tmp(struct impl *this)
|
||||||
spa_log_info(this->log, "resize ports %d -> %d", this->scratch_ports, maxports);
|
spa_log_info(this->log, "resize ports %d -> %d", this->scratch_ports, maxports);
|
||||||
|
|
||||||
for (i = this->scratch_ports; i < maxports; i++) {
|
for (i = this->scratch_ports; i < maxports; i++) {
|
||||||
if ((tmp[0] = malloc(maxsize + MAX_ALIGN)) != NULL)
|
if ((tmp[0] = malloc(alloc_size)) != NULL)
|
||||||
this->tmp[0][i] = tmp[0];
|
this->tmp[0][i] = tmp[0];
|
||||||
if ((tmp[1] = malloc(maxsize + MAX_ALIGN)) != NULL)
|
if ((tmp[1] = malloc(alloc_size)) != NULL)
|
||||||
this->tmp[1][i] = tmp[1];
|
this->tmp[1][i] = tmp[1];
|
||||||
if (tmp[0] == NULL || tmp[1] == NULL) {
|
if (tmp[0] == NULL || tmp[1] == NULL) {
|
||||||
free_tmp(this);
|
free_tmp(this);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
this->tmp_datas[0][i] = SPA_PTR_ALIGN(this->tmp[0][i], MAX_ALIGN, void);
|
this->tmp_datas[0][i] = SPA_PTR_ALIGN(this->tmp[0][i], MAX_ALIGN, void);
|
||||||
this->tmp_datas[0][i] = SPA_PTR_ALIGN(this->tmp[0][i], MAX_ALIGN, void);
|
this->tmp_datas[1][i] = SPA_PTR_ALIGN(this->tmp[1][i], MAX_ALIGN, void);
|
||||||
}
|
}
|
||||||
this->scratch_ports = maxports;
|
this->scratch_ports = maxports;
|
||||||
}
|
}
|
||||||
|
|
@ -1342,6 +1390,14 @@ static int do_sync_filter_graph(struct spa_loop *loop, bool async, uint32_t seq,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sync_filter_graph(struct impl *impl)
|
||||||
|
{
|
||||||
|
if (impl->data_loop)
|
||||||
|
spa_loop_locked(impl->data_loop, do_sync_filter_graph, 0, NULL, 0, impl);
|
||||||
|
else
|
||||||
|
do_sync_filter_graph(NULL, false, 0, NULL, 0, impl);
|
||||||
|
}
|
||||||
|
|
||||||
static void clean_filter_handles(struct impl *impl, bool force)
|
static void clean_filter_handles(struct impl *impl, bool force)
|
||||||
{
|
{
|
||||||
struct filter_graph *g, *t;
|
struct filter_graph *g, *t;
|
||||||
|
|
@ -1399,6 +1455,7 @@ static int load_filter_graph(struct impl *impl, const char *graph, int order)
|
||||||
g->removing = true;
|
g->removing = true;
|
||||||
spa_log_info(impl->log, "removing filter-graph order:%d", order);
|
spa_log_info(impl->log, "removing filter-graph order:%d", order);
|
||||||
}
|
}
|
||||||
|
free(impl->graph_descs[order]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (graph != NULL && graph[0] != '\0') {
|
if (graph != NULL && graph[0] != '\0') {
|
||||||
|
|
@ -1424,12 +1481,14 @@ static int load_filter_graph(struct impl *impl, const char *graph, int order)
|
||||||
spa_list_remove(&pending->link);
|
spa_list_remove(&pending->link);
|
||||||
insert_graph(&impl->active_graphs, pending);
|
insert_graph(&impl->active_graphs, pending);
|
||||||
|
|
||||||
|
impl->graph_descs[order] = spa_json_builder_reformat(graph, 0);
|
||||||
|
|
||||||
spa_log_info(impl->log, "loading filter-graph order:%d", order);
|
spa_log_info(impl->log, "loading filter-graph order:%d", order);
|
||||||
}
|
}
|
||||||
if (impl->setup)
|
if (impl->setup)
|
||||||
res = setup_filter_graphs(impl, false);
|
res = setup_filter_graphs(impl, false);
|
||||||
|
|
||||||
spa_loop_locked(impl->data_loop, do_sync_filter_graph, 0, NULL, 0, impl);
|
sync_filter_graph(impl);
|
||||||
|
|
||||||
if (impl->in_filter_props == 0)
|
if (impl->in_filter_props == 0)
|
||||||
clean_filter_handles(impl, false);
|
clean_filter_handles(impl, false);
|
||||||
|
|
@ -1470,6 +1529,12 @@ static int audioconvert_set_param(struct impl *this, const char *k, const char *
|
||||||
spa_atof(s, &this->mix.rear_delay);
|
spa_atof(s, &this->mix.rear_delay);
|
||||||
else if (spa_streq(k, "channelmix.stereo-widen"))
|
else if (spa_streq(k, "channelmix.stereo-widen"))
|
||||||
spa_atof(s, &this->mix.widen);
|
spa_atof(s, &this->mix.widen);
|
||||||
|
else if (spa_streq(k, "channelmix.center-level"))
|
||||||
|
spa_atof(s, &this->mix.center_level);
|
||||||
|
else if (spa_streq(k, "channelmix.surround-level"))
|
||||||
|
spa_atof(s, &this->mix.surround_level);
|
||||||
|
else if (spa_streq(k, "channelmix.lfe-level"))
|
||||||
|
spa_atof(s, &this->mix.lfe_level);
|
||||||
else if (spa_streq(k, "channelmix.hilbert-taps"))
|
else if (spa_streq(k, "channelmix.hilbert-taps"))
|
||||||
spa_atou32(s, &this->mix.hilbert_taps, 0);
|
spa_atou32(s, &this->mix.hilbert_taps, 0);
|
||||||
else if (spa_streq(k, "channelmix.upmix-method"))
|
else if (spa_streq(k, "channelmix.upmix-method"))
|
||||||
|
|
@ -1478,6 +1543,16 @@ static int audioconvert_set_param(struct impl *this, const char *k, const char *
|
||||||
this->props.resample_quality = atoi(s);
|
this->props.resample_quality = atoi(s);
|
||||||
else if (spa_streq(k, "resample.disable"))
|
else if (spa_streq(k, "resample.disable"))
|
||||||
this->props.resample_disabled = spa_atob(s);
|
this->props.resample_disabled = spa_atob(s);
|
||||||
|
else if (spa_streq(k, "resample.window"))
|
||||||
|
this->props.resample_config.window = resample_window_from_label(s);
|
||||||
|
else if (spa_streq(k, "resample.cutoff"))
|
||||||
|
spa_atod(s, &this->props.resample_config.cutoff);
|
||||||
|
else if (spa_streq(k, "resample.n-taps"))
|
||||||
|
spa_atou32(s, &this->props.resample_config.n_taps, 0);
|
||||||
|
else if (spa_strstartswith(k, "resample.param.")) {
|
||||||
|
uint32_t idx = resample_param_from_label(k+strlen("resample.param."));
|
||||||
|
spa_atod(s, &this->props.resample_config.params[idx]);
|
||||||
|
}
|
||||||
else if (spa_streq(k, "dither.noise"))
|
else if (spa_streq(k, "dither.noise"))
|
||||||
spa_atou32(s, &this->dir[1].conv.noise_bits, 0);
|
spa_atou32(s, &this->dir[1].conv.noise_bits, 0);
|
||||||
else if (spa_streq(k, "dither.method"))
|
else if (spa_streq(k, "dither.method"))
|
||||||
|
|
@ -1488,6 +1563,10 @@ static int audioconvert_set_param(struct impl *this, const char *k, const char *
|
||||||
}
|
}
|
||||||
else if (spa_streq(k, "channelmix.lock-volumes"))
|
else if (spa_streq(k, "channelmix.lock-volumes"))
|
||||||
this->props.lock_volumes = spa_atob(s);
|
this->props.lock_volumes = spa_atob(s);
|
||||||
|
else if (spa_streq(k, "audioconvert.filter-graph.disable")) {
|
||||||
|
if (!*disable_filter)
|
||||||
|
*disable_filter = spa_atob(s);
|
||||||
|
}
|
||||||
else if (spa_strstartswith(k, "audioconvert.filter-graph.")) {
|
else if (spa_strstartswith(k, "audioconvert.filter-graph.")) {
|
||||||
int order = atoi(k + strlen("audioconvert.filter-graph."));
|
int order = atoi(k + strlen("audioconvert.filter-graph."));
|
||||||
if ((res = load_filter_graph(this, s, order)) < 0) {
|
if ((res = load_filter_graph(this, s, order)) < 0) {
|
||||||
|
|
@ -1495,10 +1574,6 @@ static int audioconvert_set_param(struct impl *this, const char *k, const char *
|
||||||
order, spa_strerror(res));
|
order, spa_strerror(res));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (spa_streq(k, "audioconvert.filter-graph.disable")) {
|
|
||||||
if (!*disable_filter)
|
|
||||||
*disable_filter = spa_atob(s);
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
return 0;
|
return 0;
|
||||||
return 1;
|
return 1;
|
||||||
|
|
@ -1617,7 +1692,7 @@ static struct spa_pod *generate_ramp_seq(struct impl *this, struct volume_ramp_p
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
float pos = (samples == 0) ? end :
|
float pos = (samples == 0) ? end :
|
||||||
SPA_CLAMP(start + (end - start) * offs / samples,
|
SPA_CLAMPF(start + (end - start) * offs / samples,
|
||||||
SPA_MIN(start, end), SPA_MAX(start, end));
|
SPA_MIN(start, end), SPA_MAX(start, end));
|
||||||
float vas = get_volume_at_scale(vrp, pos);
|
float vas = get_volume_at_scale(vrp, pos);
|
||||||
|
|
||||||
|
|
@ -2095,7 +2170,7 @@ static int setup_in_convert(struct impl *this)
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
spa_log_debug(this->log, "%p: got converter features %08x:%08x passthrough:%d remap:%d %s", this,
|
spa_log_debug(this->log, "%p: got converter features %08x:%08x passthrough:%d remap:%d %s", this,
|
||||||
this->cpu_flags, in->conv.cpu_flags, in->conv.is_passthrough,
|
this->cpu_flags, in->conv.func_cpu_flags, in->conv.is_passthrough,
|
||||||
remap, in->conv.func_name);
|
remap, in->conv.func_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2190,10 +2265,12 @@ static void set_volume(struct impl *this)
|
||||||
|
|
||||||
static char *format_position(char *str, size_t len, uint32_t channels, uint32_t *position)
|
static char *format_position(char *str, size_t len, uint32_t channels, uint32_t *position)
|
||||||
{
|
{
|
||||||
uint32_t i, idx = 0;
|
uint32_t i;
|
||||||
char buf[8];
|
char buf[8];
|
||||||
|
struct spa_strbuf b;
|
||||||
|
spa_strbuf_init(&b, str, len);
|
||||||
for (i = 0; i < channels; i++)
|
for (i = 0; i < channels; i++)
|
||||||
idx += snprintf(str + idx, len - idx, "%s%s", i == 0 ? "" : " ",
|
spa_strbuf_append(&b, "%s%s", i == 0 ? "" : " ",
|
||||||
spa_type_audio_channel_make_short_name(position[i],
|
spa_type_audio_channel_make_short_name(position[i],
|
||||||
buf, sizeof(buf), "UNK"));
|
buf, sizeof(buf), "UNK"));
|
||||||
return str;
|
return str;
|
||||||
|
|
@ -2252,7 +2329,7 @@ static int setup_channelmix(struct impl *this, uint32_t channels, uint32_t *posi
|
||||||
set_volume(this);
|
set_volume(this);
|
||||||
|
|
||||||
spa_log_debug(this->log, "%p: got channelmix features %08x:%08x flags:%08x %s",
|
spa_log_debug(this->log, "%p: got channelmix features %08x:%08x flags:%08x %s",
|
||||||
this, this->cpu_flags, this->mix.cpu_flags,
|
this, this->cpu_flags, this->mix.func_cpu_flags,
|
||||||
this->mix.flags, this->mix.func_name);
|
this->mix.flags, this->mix.func_name);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -2289,6 +2366,7 @@ static int setup_resample(struct impl *this)
|
||||||
this->resample.o_rate = out->format.info.raw.rate;
|
this->resample.o_rate = out->format.info.raw.rate;
|
||||||
this->resample.log = this->log;
|
this->resample.log = this->log;
|
||||||
this->resample.quality = this->props.resample_quality;
|
this->resample.quality = this->props.resample_quality;
|
||||||
|
this->resample.config = this->props.resample_config;
|
||||||
this->resample.cpu_flags = this->cpu_flags;
|
this->resample.cpu_flags = this->cpu_flags;
|
||||||
|
|
||||||
this->rate_adjust = this->props.rate != 1.0;
|
this->rate_adjust = this->props.rate != 1.0;
|
||||||
|
|
@ -2299,7 +2377,7 @@ static int setup_resample(struct impl *this)
|
||||||
res = resample_native_init(&this->resample);
|
res = resample_native_init(&this->resample);
|
||||||
|
|
||||||
spa_log_debug(this->log, "%p: got resample features %08x:%08x %s",
|
spa_log_debug(this->log, "%p: got resample features %08x:%08x %s",
|
||||||
this, this->cpu_flags, this->resample.cpu_flags,
|
this, this->cpu_flags, this->resample.func_cpu_flags,
|
||||||
this->resample.func_name);
|
this->resample.func_name);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
@ -2391,7 +2469,7 @@ static int setup_out_convert(struct impl *this)
|
||||||
|
|
||||||
spa_log_debug(this->log, "%p: got converter features %08x:%08x quant:%d:%d"
|
spa_log_debug(this->log, "%p: got converter features %08x:%08x quant:%d:%d"
|
||||||
" passthrough:%d remap:%d %s", this,
|
" passthrough:%d remap:%d %s", this,
|
||||||
this->cpu_flags, out->conv.cpu_flags, out->conv.method,
|
this->cpu_flags, out->conv.func_cpu_flags, out->conv.method,
|
||||||
out->conv.noise_bits, out->conv.is_passthrough, remap, out->conv.func_name);
|
out->conv.noise_bits, out->conv.is_passthrough, remap, out->conv.func_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
@ -2425,7 +2503,7 @@ static uint32_t resample_update_rate_match(struct impl *this, bool passthrough,
|
||||||
match_size = resample_out_len(&this->resample, size);
|
match_size = resample_out_len(&this->resample, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
delay = (uint32_t)round(fdelay);
|
delay = lround(fdelay);
|
||||||
delay_frac = (int32_t)((fdelay - delay) * 1e9);
|
delay_frac = (int32_t)((fdelay - delay) * 1e9);
|
||||||
}
|
}
|
||||||
match_size -= SPA_MIN(match_size, queued);
|
match_size -= SPA_MIN(match_size, queued);
|
||||||
|
|
@ -2532,6 +2610,8 @@ static int setup_convert(struct impl *this)
|
||||||
this->setup = true;
|
this->setup = true;
|
||||||
this->recalc = true;
|
this->recalc = true;
|
||||||
|
|
||||||
|
sync_filter_graph(this);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2548,6 +2628,7 @@ static void reset_node(struct impl *this)
|
||||||
resample_reset(&this->resample);
|
resample_reset(&this->resample);
|
||||||
this->in_offset = 0;
|
this->in_offset = 0;
|
||||||
this->out_offset = 0;
|
this->out_offset = 0;
|
||||||
|
this->setup = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int impl_node_send_command(void *object, const struct spa_command *command)
|
static int impl_node_send_command(void *object, const struct spa_command *command)
|
||||||
|
|
@ -2568,9 +2649,11 @@ static int impl_node_send_command(void *object, const struct spa_command *comman
|
||||||
break;
|
break;
|
||||||
case SPA_NODE_COMMAND_Suspend:
|
case SPA_NODE_COMMAND_Suspend:
|
||||||
reset_node(this);
|
reset_node(this);
|
||||||
this->setup = false;
|
this->started = false;
|
||||||
SPA_FALLTHROUGH;
|
break;
|
||||||
case SPA_NODE_COMMAND_Pause:
|
case SPA_NODE_COMMAND_Pause:
|
||||||
|
if ((res = setup_convert(this)) < 0)
|
||||||
|
return res;
|
||||||
this->started = false;
|
this->started = false;
|
||||||
break;
|
break;
|
||||||
case SPA_NODE_COMMAND_Flush:
|
case SPA_NODE_COMMAND_Flush:
|
||||||
|
|
@ -4211,6 +4294,7 @@ static void free_dir(struct dir *dir)
|
||||||
static int impl_clear(struct spa_handle *handle)
|
static int impl_clear(struct spa_handle *handle)
|
||||||
{
|
{
|
||||||
struct impl *this;
|
struct impl *this;
|
||||||
|
int i;
|
||||||
|
|
||||||
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
spa_return_val_if_fail(handle != NULL, -EINVAL);
|
||||||
|
|
||||||
|
|
@ -4222,6 +4306,10 @@ static int impl_clear(struct spa_handle *handle)
|
||||||
free_tmp(this);
|
free_tmp(this);
|
||||||
|
|
||||||
clean_filter_handles(this, true);
|
clean_filter_handles(this, true);
|
||||||
|
for (i = 0; i < MAX_GRAPH; i++) {
|
||||||
|
if (this->graph_descs[i])
|
||||||
|
free(this->graph_descs[i]);
|
||||||
|
}
|
||||||
|
|
||||||
if (this->resample.free)
|
if (this->resample.free)
|
||||||
resample_free(&this->resample);
|
resample_free(&this->resample);
|
||||||
|
|
@ -4276,18 +4364,13 @@ impl_init(const struct spa_handle_factory *factory,
|
||||||
struct filter_graph *g = &this->graphs[i];
|
struct filter_graph *g = &this->graphs[i];
|
||||||
g->impl = this;
|
g->impl = this;
|
||||||
spa_list_append(&this->free_graphs, &g->link);
|
spa_list_append(&this->free_graphs, &g->link);
|
||||||
|
this->graph_descs[i] = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
this->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
|
this->rate_limit.interval = 2 * SPA_NSEC_PER_SEC;
|
||||||
this->rate_limit.burst = 1;
|
this->rate_limit.burst = 1;
|
||||||
|
|
||||||
this->mix.options = CHANNELMIX_OPTION_UPMIX | CHANNELMIX_OPTION_MIX_LFE;
|
channelmix_reset(&this->mix);
|
||||||
this->mix.upmix = CHANNELMIX_UPMIX_NONE;
|
|
||||||
this->mix.log = this->log;
|
|
||||||
this->mix.lfe_cutoff = 0.0f;
|
|
||||||
this->mix.fc_cutoff = 0.0f;
|
|
||||||
this->mix.rear_delay = 0.0f;
|
|
||||||
this->mix.widen = 0.0f;
|
|
||||||
|
|
||||||
for (i = 0; info && i < info->n_items; i++) {
|
for (i = 0; info && i < info->n_items; i++) {
|
||||||
const char *k = info->items[i].key;
|
const char *k = info->items[i].key;
|
||||||
|
|
|
||||||
|
|
@ -51,9 +51,9 @@ static void run_test1(const char *name, const char *impl, bool in_packed, bool o
|
||||||
void *op[n_channels];
|
void *op[n_channels];
|
||||||
struct timespec ts;
|
struct timespec ts;
|
||||||
uint64_t count, t1, t2;
|
uint64_t count, t1, t2;
|
||||||
struct convert conv;
|
struct convert conv = {
|
||||||
|
.n_channels = n_channels,
|
||||||
conv.n_channels = n_channels;
|
};
|
||||||
|
|
||||||
for (j = 0; j < n_channels; j++) {
|
for (j = 0; j < n_channels; j++) {
|
||||||
ip[j] = &samp_in[j * n_samples * 4];
|
ip[j] = &samp_in[j * n_samples * 4];
|
||||||
|
|
|
||||||
|
|
@ -39,7 +39,7 @@ static const int in_rates[] = { 44100, 44100, 48000, 96000, 22050, 96000 };
|
||||||
static const int out_rates[] = { 44100, 48000, 44100, 48000, 48000, 44100 };
|
static const int out_rates[] = { 44100, 48000, 44100, 48000, 48000, 44100 };
|
||||||
|
|
||||||
|
|
||||||
#define MAX_RESAMPLER 5
|
#define MAX_RESAMPLER 10
|
||||||
#define MAX_SIZES SPA_N_ELEMENTS(sample_sizes)
|
#define MAX_SIZES SPA_N_ELEMENTS(sample_sizes)
|
||||||
#define MAX_RATES SPA_N_ELEMENTS(in_rates)
|
#define MAX_RATES SPA_N_ELEMENTS(in_rates)
|
||||||
#define MAX_RESULTS MAX_RESAMPLER * MAX_SIZES * MAX_RATES
|
#define MAX_RESULTS MAX_RESAMPLER * MAX_SIZES * MAX_RATES
|
||||||
|
|
@ -123,7 +123,9 @@ int main(int argc, char *argv[])
|
||||||
r.o_rate = out_rates[i];
|
r.o_rate = out_rates[i];
|
||||||
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
||||||
resample_native_init(&r);
|
resample_native_init(&r);
|
||||||
run_test("native", "c", &r);
|
run_test("full", "c", &r);
|
||||||
|
resample_update_rate(&r, 1.001);
|
||||||
|
run_test("inter", "c", &r);
|
||||||
resample_free(&r);
|
resample_free(&r);
|
||||||
}
|
}
|
||||||
#if defined (HAVE_SSE)
|
#if defined (HAVE_SSE)
|
||||||
|
|
@ -136,7 +138,9 @@ int main(int argc, char *argv[])
|
||||||
r.o_rate = out_rates[i];
|
r.o_rate = out_rates[i];
|
||||||
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
||||||
resample_native_init(&r);
|
resample_native_init(&r);
|
||||||
run_test("native", "sse", &r);
|
run_test("full", "sse", &r);
|
||||||
|
resample_update_rate(&r, 1.001);
|
||||||
|
run_test("inter", "sse", &r);
|
||||||
resample_free(&r);
|
resample_free(&r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -151,22 +155,26 @@ int main(int argc, char *argv[])
|
||||||
r.o_rate = out_rates[i];
|
r.o_rate = out_rates[i];
|
||||||
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
||||||
resample_native_init(&r);
|
resample_native_init(&r);
|
||||||
run_test("native", "ssse3", &r);
|
run_test("full", "ssse3", &r);
|
||||||
|
resample_update_rate(&r, 1.001);
|
||||||
|
run_test("inter", "ssse3", &r);
|
||||||
resample_free(&r);
|
resample_free(&r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined (HAVE_AVX) && defined(HAVE_FMA)
|
#if defined (HAVE_AVX2) && defined(HAVE_FMA)
|
||||||
if (SPA_FLAG_IS_SET(cpu_flags, SPA_CPU_FLAG_AVX | SPA_CPU_FLAG_FMA3)) {
|
if (SPA_FLAG_IS_SET(cpu_flags, SPA_CPU_FLAG_AVX2 | SPA_CPU_FLAG_FMA3)) {
|
||||||
for (i = 0; i < SPA_N_ELEMENTS(in_rates); i++) {
|
for (i = 0; i < SPA_N_ELEMENTS(in_rates); i++) {
|
||||||
spa_zero(r);
|
spa_zero(r);
|
||||||
r.channels = 2;
|
r.channels = 2;
|
||||||
r.cpu_flags = SPA_CPU_FLAG_AVX | SPA_CPU_FLAG_FMA3;
|
r.cpu_flags = SPA_CPU_FLAG_AVX2 | SPA_CPU_FLAG_FMA3;
|
||||||
r.i_rate = in_rates[i];
|
r.i_rate = in_rates[i];
|
||||||
r.o_rate = out_rates[i];
|
r.o_rate = out_rates[i];
|
||||||
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
r.quality = RESAMPLE_DEFAULT_QUALITY;
|
||||||
resample_native_init(&r);
|
resample_native_init(&r);
|
||||||
run_test("native", "avx", &r);
|
run_test("full", "avx2", &r);
|
||||||
|
resample_update_rate(&r, 1.001);
|
||||||
|
run_test("inter", "avx2", &r);
|
||||||
resample_free(&r);
|
resample_free(&r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
63
spa/plugins/audioconvert/channelmix-ops-avx.c
Normal file
63
spa/plugins/audioconvert/channelmix-ops-avx.c
Normal file
|
|
@ -0,0 +1,63 @@
|
||||||
|
/* Spa */
|
||||||
|
/* SPDX-FileCopyrightText: Copyright © 2018 Wim Taymans */
|
||||||
|
/* SPDX-License-Identifier: MIT */
|
||||||
|
|
||||||
|
#include "channelmix-ops.h"
|
||||||
|
|
||||||
|
#include <immintrin.h>
|
||||||
|
#include <float.h>
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
|
static inline void clear_avx(float *d, uint32_t n_samples)
|
||||||
|
{
|
||||||
|
memset(d, 0, n_samples * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void copy_avx(float *d, const float *s, uint32_t n_samples)
|
||||||
|
{
|
||||||
|
spa_memcpy(d, s, n_samples * sizeof(float));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vol_avx(float *d, const float *s, float vol, uint32_t n_samples)
|
||||||
|
{
|
||||||
|
uint32_t n, unrolled;
|
||||||
|
if (vol == 0.0f) {
|
||||||
|
clear_avx(d, n_samples);
|
||||||
|
} else if (vol == 1.0f) {
|
||||||
|
copy_avx(d, s, n_samples);
|
||||||
|
} else {
|
||||||
|
__m256 t[4];
|
||||||
|
const __m256 v = _mm256_set1_ps(vol);
|
||||||
|
|
||||||
|
if (SPA_IS_ALIGNED(d, 32) &&
|
||||||
|
SPA_IS_ALIGNED(s, 32))
|
||||||
|
unrolled = n_samples & ~31;
|
||||||
|
else
|
||||||
|
unrolled = 0;
|
||||||
|
|
||||||
|
for(n = 0; n < unrolled; n += 32) {
|
||||||
|
t[0] = _mm256_load_ps(&s[n]);
|
||||||
|
t[1] = _mm256_load_ps(&s[n+8]);
|
||||||
|
t[2] = _mm256_load_ps(&s[n+16]);
|
||||||
|
t[3] = _mm256_load_ps(&s[n+24]);
|
||||||
|
_mm256_store_ps(&d[n], _mm256_mul_ps(t[0], v));
|
||||||
|
_mm256_store_ps(&d[n+8], _mm256_mul_ps(t[1], v));
|
||||||
|
_mm256_store_ps(&d[n+16], _mm256_mul_ps(t[2], v));
|
||||||
|
_mm256_store_ps(&d[n+24], _mm256_mul_ps(t[3], v));
|
||||||
|
}
|
||||||
|
for(; n < n_samples; n++) {
|
||||||
|
__m128 v = _mm_set1_ps(vol);
|
||||||
|
_mm_store_ss(&d[n], _mm_mul_ss(_mm_load_ss(&s[n]), v));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void channelmix_copy_avx(struct channelmix *mix, void * SPA_RESTRICT dst[],
|
||||||
|
const void * SPA_RESTRICT src[], uint32_t n_samples)
|
||||||
|
{
|
||||||
|
uint32_t i, n_dst = mix->dst_chan;
|
||||||
|
float **d = (float **)dst;
|
||||||
|
const float **s = (const float **)src;
|
||||||
|
for (i = 0; i < n_dst; i++)
|
||||||
|
vol_avx(d[i], s[i], mix->matrix[i][i], n_samples);
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue