Compare commits
2325 Commits
original_w
...
1.2.0
Author | SHA1 | Date | |
---|---|---|---|
0145cf5668 | |||
921fb23c8d | |||
eb3ec5dc36 | |||
35ad4712bb | |||
fe7f2317de | |||
b5bbdae317 | |||
cec4e326c8 | |||
eccbdc1655 | |||
08485f255a | |||
be8e35cbcf | |||
843dde1a68 | |||
f018ef1d81 | |||
6b43ddf920 | |||
242ec5dfd0 | |||
b354f38bfb | |||
983aa8cebc | |||
619f1254fd | |||
b5b52770ee | |||
7fd98c8c5c | |||
39bfba673b | |||
5adb53d990 | |||
f3dcf5c320 | |||
2ce7d943fa | |||
60f57bf206 | |||
221e0f232b | |||
46c78f6463 | |||
40c68933e1 | |||
81b8f183c2 | |||
03f0faf378 | |||
f316b2c8ca | |||
6c3ef7a6ed | |||
4ce3816f48 | |||
397155983d | |||
9c28143dfb | |||
ed354cfa6f | |||
dcdfe7969a | |||
6d414698e8 | |||
70cf4557f7 | |||
b0e18286df | |||
85c7a05978 | |||
33c8e34456 | |||
4bc6608e87 | |||
f967a8d87a | |||
d757b817b1 | |||
9f89a21cfb | |||
aaf696e8d7 | |||
efa305eeec | |||
eb43e39a81 | |||
c4687816c1 | |||
8cce5bd889 | |||
66dd4b4581 | |||
9689ce5202 | |||
818b9d87b8 | |||
0f2aca62f3 | |||
1e57fb4609 | |||
0b64b4ac97 | |||
460bada88f | |||
330598ddf2 | |||
8f36355817 | |||
ccf741da00 | |||
c3917c61d3 | |||
d869c5ee2d | |||
c89394822a | |||
1836344fab | |||
25e2a8013e | |||
757ec01ea4 | |||
a07480fd9a | |||
e77b0f4a67 | |||
909a969e04 | |||
edace3d451 | |||
5b1000df87 | |||
fae281a507 | |||
cbcba5807f | |||
3fa3aac766 | |||
981948b708 | |||
c41b303130 | |||
6589c9dbe1 | |||
acc70b6449 | |||
81925986a6 | |||
83d01553e3 | |||
f2a97415b9 | |||
95b4510c3a | |||
81ed1a9ebb | |||
b2e15c559e | |||
c10fdd2a53 | |||
9efe41a2b1 | |||
4b36aca6fc | |||
cb29fc251c | |||
78dcdd5715 | |||
6fbe6b4983 | |||
284059a920 | |||
0403ebff5c | |||
6129b92277 | |||
1ff3c174c2 | |||
e5b120311d | |||
1c937e147e | |||
1d2ee127e0 | |||
ee9b602e4f | |||
72f925e537 | |||
bf37dee78b | |||
72920135e9 | |||
66cf940523 | |||
ca0f7af1d0 | |||
d9db74e565 | |||
3218e0b8aa | |||
c8ebbb505a | |||
9ca5e0ebd6 | |||
f3b05c6318 | |||
f9f0bdde12 | |||
6014ce8921 | |||
b9f43654cd | |||
7c43c78c4b | |||
efa7faaa2a | |||
f9df35ffd4 | |||
01260d66c8 | |||
51453662e2 | |||
120328ce12 | |||
869f971ced | |||
73d326037c | |||
4a4901fa38 | |||
47e78579d4 | |||
54a1cae352 | |||
4c1777dc19 | |||
42b315ef86 | |||
3bb4f48faf | |||
ee3d934529 | |||
aecb79a4d4 | |||
5032f4b66d | |||
0f1feb9d47 | |||
be6f533437 | |||
c3d393252b | |||
bb56eb8db2 | |||
1e8527da68 | |||
2b3123c7cb | |||
8e945d4149 | |||
3ccb4a11d2 | |||
dd7255a9d2 | |||
307e944911 | |||
175e140f86 | |||
ad59b1b3b7 | |||
5256409ddf | |||
65950565b6 | |||
66492ff40a | |||
52df289230 | |||
1845fa3f39 | |||
fa49e59200 | |||
d0d3e67174 | |||
c5a314810e | |||
f8f2740c77 | |||
1c91c6dcc1 | |||
11a3606070 | |||
75aac5969a | |||
459a99cbf8 | |||
c07d9ecf92 | |||
99c7093a1a | |||
223c2d1709 | |||
6db80ec51a | |||
207ada70fd | |||
c50da15bfd | |||
ab99b8e476 | |||
7d7cec1ec3 | |||
de14fa4b93 | |||
355b47760c | |||
aeca8265c3 | |||
b242f09d5d | |||
ad396fa970 | |||
2bcb62e706 | |||
be093b8b05 | |||
eb76ec4a9f | |||
f03a6c127e | |||
5bb14a8997 | |||
bb77d2ce0a | |||
8531d5e4ab | |||
320521a74a | |||
5e7a0a38aa | |||
e6dd1e0fde | |||
0277ae8722 | |||
12c032112b | |||
4e61ed3645 | |||
6a59369c62 | |||
0039d5fdcb | |||
40075c1adb | |||
7a4ed3b383 | |||
2479c2207a | |||
48eb754170 | |||
ddcdd550fd | |||
a48a5e366b | |||
8b34e6c689 | |||
e71cd01522 | |||
2ecefcecd5 | |||
5d8fd9ae95 | |||
f5c2525f22 | |||
34065e455f | |||
b142233d4e | |||
e9b2007863 | |||
455b2ce1f1 | |||
d0ee6f7d3e | |||
5b0aa274eb | |||
234cbf0fa8 | |||
4fd5a62980 | |||
ba97f76737 | |||
f3d1084b60 | |||
6c2ba7bc1d | |||
2be58503c6 | |||
17a78ffa79 | |||
322582d29b | |||
5fd303f4a2 | |||
46d7fa7347 | |||
845f937fa3 | |||
85a58eefa9 | |||
8923b90b3e | |||
a9d9206d2e | |||
a374e93ee8 | |||
bcf05e00f7 | |||
b35d1908c7 | |||
d824cc375e | |||
d04ab43977 | |||
9cd730dc9a | |||
a16ad952c4 | |||
3f7a93acfc | |||
bdf1ed4709 | |||
ebc935c1a9 | |||
5b92c317c1 | |||
48dc75c728 | |||
3e7eb09f3e | |||
9baebf444d | |||
83feb2c0e0 | |||
33a942707c | |||
e206b83e74 | |||
970be58e9c | |||
2e326573d0 | |||
49a069f0ee | |||
a580989639 | |||
c46b3275a9 | |||
0258a75650 | |||
979f11f40a | |||
a04f198ade | |||
8a54ef4cd0 | |||
7ec592ce3d | |||
6e0e271294 | |||
7427a65f18 | |||
39d49ca991 | |||
31a30532a7 | |||
2190fd7c5a | |||
981053a7c7 | |||
2d8ae33542 | |||
ced6153aa7 | |||
4a1676bb81 | |||
6af115f4f0 | |||
8550f10d88 | |||
3b8961c8c6 | |||
eb55167add | |||
ae8061ee77 | |||
4f0d4983ca | |||
d34ac58e73 | |||
ee8688345e | |||
4aba612760 | |||
e709ca0e77 | |||
6bd3fdf6f4 | |||
4b969fa3b2 | |||
1020c9bac9 | |||
002827cbf4 | |||
a676e203c7 | |||
87b9a52fcb | |||
2d2f9bed40 | |||
e37bc0573d | |||
301b3b59a5 | |||
40c78940ef | |||
a006d8c125 | |||
0c9d37e381 | |||
dc848a7006 | |||
093ad6cd0d | |||
fd26acca68 | |||
3daf005c81 | |||
1b31c5fc90 | |||
0206a6f94c | |||
484b829b90 | |||
ad8877f83c | |||
e205953bfc | |||
8a7182f9d5 | |||
f86487f459 | |||
7fc7fe5e82 | |||
3057c3ffd7 | |||
282ba4d095 | |||
1b4b87b14e | |||
55254b1c44 | |||
cd935c0dcb | |||
a17690dc91 | |||
fe1a1207e6 | |||
041e8930bf | |||
d9fe604171 | |||
290f67735d | |||
0fa8774493 | |||
53c5c0f045 | |||
11568256ed | |||
2152184bf9 | |||
f8971ac704 | |||
540198b12a | |||
48d498941e | |||
318cb728e1 | |||
f481c3f8e3 | |||
af553c422d | |||
7115d5c951 | |||
7642341b2e | |||
29bce9e07a | |||
35dcff90ea | |||
bc193c834c | |||
3bc39a9ca3 | |||
4a77d2cc38 | |||
a7e2aae292 | |||
c6e01eed1a | |||
118335b2b6 | |||
0c7b0d2eaa | |||
cb8ec3c760 | |||
e408c66702 | |||
d97d66c787 | |||
96ada02e38 | |||
ae729990ca | |||
afc4fc2d00 | |||
25d04f4cbc | |||
5a60869f8e | |||
7962da9454 | |||
4691987cc4 | |||
05985ff46a | |||
159c231884 | |||
86e64225bd | |||
1156916631 | |||
a6ed578a0f | |||
8c5546ad90 | |||
f3ed4a719a | |||
2da2a57e13 | |||
6de91c0c4e | |||
cc3e43c6cd | |||
d04cf5f5a1 | |||
b7e38960c0 | |||
1e684f9bf1 | |||
259d036083 | |||
71b0fa968b | |||
6ad3a80fc6 | |||
b1cfe79ddd | |||
5e6508cd47 | |||
5f5881cdfa | |||
f6b0e37664 | |||
1bc5633b27 | |||
1c23fdf3ff | |||
bd29f9c572 | |||
89cd17042a | |||
8b5cf9983e | |||
04a5e6705f | |||
77de488521 | |||
52b535c608 | |||
05ea11f5d1 | |||
e8cf014903 | |||
1968e15237 | |||
da698e7a3c | |||
b9db64d4f9 | |||
51af299aa2 | |||
440b3a3822 | |||
5ec0005f81 | |||
11b0d2d90a | |||
322a52e854 | |||
1b8153c461 | |||
dae32f2e95 | |||
b4c2923dd2 | |||
68739724d4 | |||
4993a56235 | |||
cb3cb50cbd | |||
7e4671afe4 | |||
19c8432371 | |||
9351e4793c | |||
1f91908e06 | |||
907359df82 | |||
e210c3a667 | |||
9c4d7377d0 | |||
8ce1192811 | |||
d18a4c83ac | |||
bbad34cec3 | |||
22ec80c8ea | |||
5487861da1 | |||
ebd4d93908 | |||
fcbaa4f22a | |||
c0ca216e4d | |||
a9990f1f41 | |||
b877d8439a | |||
6cca37a9df | |||
7a2f62a307 | |||
1932890dd0 | |||
02e699c597 | |||
46d742a12c | |||
b3e99e0a3d | |||
96cce831ef | |||
3e00a4f390 | |||
0abd121fda | |||
b605927207 | |||
3696272ef7 | |||
5a7c12dfac | |||
170b720e48 | |||
c6962b4f42 | |||
8e7b758ef8 | |||
1b9e77982d | |||
2d142e45ed | |||
620ba11565 | |||
e297cffbfe | |||
af211739fb | |||
a86a2f31cd | |||
6796699e35 | |||
df72147b93 | |||
65443eb0ba | |||
29c0f7148a | |||
e1dd9d32f4 | |||
287a04be94 | |||
20cd3f6efe | |||
69237c0bb4 | |||
383c08ed48 | |||
19496d46a3 | |||
6ddced4689 | |||
4cbce9c840 | |||
b01792c3d2 | |||
5f7daba3b2 | |||
a90f77e545 | |||
d50d08ad2c | |||
deeaccba12 | |||
62e67afc9c | |||
c9d303c43e | |||
5fc8672dd6 | |||
acee318dae | |||
8fa1796037 | |||
2a82f4e452 | |||
341e254640 | |||
d872152cc8 | |||
3b9763eee5 | |||
cfeab98620 | |||
792f76f831 | |||
c58ebfa657 | |||
c50473fea5 | |||
f1619b81fe | |||
364c7eb505 | |||
9dcf342b13 | |||
d573561c67 | |||
37e7331627 | |||
b25a673829 | |||
916f19ac60 | |||
620771eaf2 | |||
161408dbf4 | |||
e0985c3802 | |||
3d20e3ed80 | |||
6af0ad0262 | |||
b4460f4f70 | |||
ff9f771e1b | |||
4c5ec23ba7 | |||
1b44229ec3 | |||
2e28694b49 | |||
2ba2ec38e0 | |||
a3cfde02c4 | |||
a14f247859 | |||
45e9bd12a5 | |||
190c90ccdf | |||
60df3afe26 | |||
4e14b29537 | |||
3814200452 | |||
a9dbedee6d | |||
8671f98c14 | |||
400ed3541d | |||
03315d7960 | |||
d123232f28 | |||
eab1c6ce80 | |||
fdbb76bca1 | |||
c0b7cf5f8d | |||
37d89c074b | |||
2b1dc76e48 | |||
e0b289b6a5 | |||
d81f0ae96c | |||
6bd47cf914 | |||
c7db144f7b | |||
d0ddf72b10 | |||
92cce78320 | |||
1871fc359a | |||
a92ead3261 | |||
094f470ebb | |||
06b6054071 | |||
0537e23e38 | |||
7a0c934af5 | |||
e787336fc4 | |||
71acad3b4f | |||
c389d3b619 | |||
ccdb010e9d | |||
6a9bbf7bc9 | |||
ccba3e8597 | |||
beb3d696c9 | |||
54142f4f15 | |||
b6ed06dff4 | |||
36c4a16fb5 | |||
1b44c31a89 | |||
45d4d868d7 | |||
e9cb5d54be | |||
7dcafab2c1 | |||
baef88bd94 | |||
ad3ed1e626 | |||
0a76801a03 | |||
3164683e74 | |||
4e7f02fc2c | |||
0231d98ab8 | |||
6822475674 | |||
412e0a51c7 | |||
91c4d6f568 | |||
d8b3974728 | |||
5cd9d386a6 | |||
f6f0a87002 | |||
8c767be53a | |||
bccb87e660 | |||
0c1dc70217 | |||
388d9d46fe | |||
2785f43c6a | |||
45a70a1079 | |||
2d823b2945 | |||
65758a0098 | |||
ea96038201 | |||
ed3d84b974 | |||
710a18aae3 | |||
f69d78926e | |||
4199a583f8 | |||
dfaecdb357 | |||
631232fe7c | |||
f9772faa6f | |||
4e32d724c4 | |||
c5df6a1527 | |||
ed258cc9a0 | |||
437943c26c | |||
d15d9d8c76 | |||
436010ffe3 | |||
679f99d701 | |||
1eff7a3b69 | |||
54a34b2084 | |||
f8beae5f46 | |||
9beb3b9168 | |||
770fd749cd | |||
683a711b49 | |||
bd31fa5149 | |||
7f3d421b25 | |||
44250f9719 | |||
c2e8ac516c | |||
dd5ab32b47 | |||
361ed55b93 | |||
8b24eff72e | |||
18e8ca5e43 | |||
0ab6729fcc | |||
0e64f15e65 | |||
058463a9b3 | |||
bd7e5b7166 | |||
d0d946e09f | |||
86278ff44d | |||
039b57d28b | |||
27c16c3720 | |||
3aa238727e | |||
4316832b95 | |||
bec61465c9 | |||
012952f6f3 | |||
872c7a4bfd | |||
d65743f2ea | |||
c5585e290a | |||
54fde2c1c0 | |||
d612792593 | |||
0d77aaff26 | |||
b06a629ffb | |||
a29d72d67f | |||
1a6f738c97 | |||
50e19085b0 | |||
e70ff075ca | |||
34b369b200 | |||
fc5d560345 | |||
e8ad4588ce | |||
74aea63b9b | |||
a750726459 | |||
eb8b8c4a5a | |||
1956907d6d | |||
8f49337b81 | |||
5e37b75cfb | |||
c09f17579c | |||
06d4b24b09 | |||
9492bbebbb | |||
ad5166cf9e | |||
0714ce5703 | |||
2eec29db05 | |||
3122077603 | |||
518588885c | |||
8271eddefb | |||
404f995e39 | |||
8fcfa689ae | |||
f488a01c78 | |||
06361754b3 | |||
b7688c3c97 | |||
691d88f841 | |||
9aebeb51f8 | |||
8d2763930b | |||
409370aba2 | |||
9175629838 | |||
3c0a26eaa8 | |||
496e771e17 | |||
c8496a2547 | |||
d3ba866800 | |||
8267aa8d9d | |||
c2617fcfaf | |||
1112334ea8 | |||
578f165bdc | |||
a664770881 | |||
c0193e677c | |||
819790cbc8 | |||
b2d4046d8a | |||
28b1abfa40 | |||
a72a11d3c7 | |||
2d37f63f2c | |||
48a9c76c18 | |||
7f9c0539bb | |||
e61dde7d0e | |||
d998ab5c61 | |||
49640b5e33 | |||
391069653a | |||
830d7ae656 | |||
48c594fdae | |||
29a161b7b7 | |||
9b1659d3dd | |||
dbf23baa45 | |||
3d97d362b5 | |||
8ea4d11e9c | |||
48f26d00d6 | |||
3b60e0b737 | |||
3e4ba42aab | |||
cda43b5c5c | |||
ae76470612 | |||
5e51beac46 | |||
8acfb8c1cf | |||
ad0ca114f5 | |||
3f3f5eacfe | |||
dd2fda54d1 | |||
7d88d83c36 | |||
5068bcd347 | |||
024a6684ce | |||
aad757df36 | |||
690eed5d58 | |||
c3d459558a | |||
fb457ce9f1 | |||
a8c93fd8d1 | |||
f23fa59ac3 | |||
e926611307 | |||
1cc4b13ba6 | |||
fdfaed005b | |||
0cf67d5e2c | |||
0fd172edc3 | |||
64f827d235 | |||
1e72485425 | |||
7097dc1cd8 | |||
8cf9b509c1 | |||
17c20d12e0 | |||
8422a33081 | |||
75418baf06 | |||
9f17c941d1 | |||
779aa33a4a | |||
7aa0f8b35d | |||
3b670016be | |||
ad5daaae95 | |||
16d0e1a0d7 | |||
4df5f19bd6 | |||
a1c024bfe2 | |||
2d72055070 | |||
331e9627d6 | |||
ed6594401c | |||
d9578cc5f4 | |||
2c6b0e3d30 | |||
b0c7abe362 | |||
346f2af2fb | |||
902fc666c2 | |||
3a1e5ee73c | |||
a083042002 | |||
ce48892173 | |||
5cfacac6c0 | |||
4758672c94 | |||
23fceb2998 | |||
e5bd78fd0c | |||
8c4b9dd08a | |||
0517a59308 | |||
ba3a68c3fa | |||
d920540021 | |||
47ecc26f28 | |||
689cd49694 | |||
b60a8a1af0 | |||
8de70cd523 | |||
25db7c716d | |||
88020b894e | |||
ee687d4e27 | |||
b318b5e88a | |||
8a25718d29 | |||
617bed91c4 | |||
9357d57a28 | |||
5d291b5b36 | |||
01c58327aa | |||
635bf55465 | |||
732985c529 | |||
9c5858e1e5 | |||
1fed499b7f | |||
d99669b3aa | |||
e548d6a5de | |||
8806dc538e | |||
f6f01ebee5 | |||
1d9ab1494f | |||
7054ec5d59 | |||
d72027e630 | |||
99fe232a21 | |||
dd2f0629d3 | |||
ffcf5c0c27 | |||
3226c01f60 | |||
54fb58755d | |||
d9b662106c | |||
53faca64c0 | |||
c23acc1513 | |||
8e4716f241 | |||
e8fca853df | |||
d6d6d97a13 | |||
e66be7c12d | |||
56a42498a5 | |||
bda718cbee | |||
13eaee5ee9 | |||
44270af88f | |||
bb680293a1 | |||
1ee75295e5 | |||
5e1c4391c6 | |||
998092f377 | |||
dea07cd49b | |||
e3f99d6985 | |||
081b63def3 | |||
3c91f3cc2f | |||
61a5250792 | |||
881637811f | |||
142ca578ec | |||
ad8ff1c2f7 | |||
8372f198db | |||
2a5448f5c1 | |||
c8695a8e62 | |||
477b457be9 | |||
58b35ec0f9 | |||
9b2947827a | |||
ae0748952f | |||
bee0f67efd | |||
f81cf3570a | |||
612345f0b2 | |||
b2e8fc5ad5 | |||
b997e83095 | |||
4a86af69d1 | |||
bf31a27dca | |||
366f7247f2 | |||
a5bdf6c3ac | |||
7e60efeae2 | |||
15940d0a2e | |||
d126c3acef | |||
a880b1f6f9 | |||
49577953c6 | |||
4b03ced1f7 | |||
66dc4e5772 | |||
ad0a5c27db | |||
40e531c0da | |||
8b52988dcd | |||
862a251295 | |||
faad38f72d | |||
9258e76468 | |||
e11bbbf494 | |||
4b94126dc3 | |||
4e429d047d | |||
1d9b2729ef | |||
999d32fd8a | |||
642552cc08 | |||
a0d219d120 | |||
68a1abd37e | |||
bcab2b2288 | |||
b8868cb55a | |||
f29f7b20e3 | |||
ae1287b8a2 | |||
185fdb67cb | |||
0ed69ef2f7 | |||
655b6849b7 | |||
39757b00b2 | |||
64b7b485b3 | |||
f0dc2f8ebe | |||
55e1aa5857 | |||
fe45d139ad | |||
181855e7a4 | |||
5d3d6423ed | |||
6e60247026 | |||
6e416d0839 | |||
ee8d896d60 | |||
db83256bcf | |||
23bf1df72a | |||
413c02f272 | |||
502d324cd4 | |||
3246e5ab3a | |||
c59c5b76d8 | |||
297d6b540d | |||
e917b920c8 | |||
a0eeea8fe3 | |||
0f81964598 | |||
9c52219ca3 | |||
8a73f2c9df | |||
98da3a6d99 | |||
667fe596dc | |||
f3444a4edb | |||
946866319c | |||
8be0092f61 | |||
3f94832d00 | |||
41f9407024 | |||
13215960c4 | |||
9f702f5d14 | |||
992a5c33a2 | |||
ae217f9ded | |||
00631d7349 | |||
163ebcd327 | |||
a31b246924 | |||
a8ef3a0e6a | |||
b9f0c91ced | |||
966a404700 | |||
885e361bab | |||
a65f15869b | |||
1b36baad88 | |||
3273716706 | |||
2c3586a92a | |||
74a4f5b272 | |||
747a5ce7ef | |||
e3aa3fa4c6 | |||
132bd2b445 | |||
2334ad1d5b | |||
57efdff43e | |||
c5323f8d54 | |||
7f3071336b | |||
db98590985 | |||
a90ef4efec | |||
b27c03c1c4 | |||
502546f9d3 | |||
113c06fae4 | |||
73b75edc14 | |||
5337c20744 | |||
f4629804ff | |||
2783091cea | |||
91be89e44e | |||
57e5923a4d | |||
9d89cbceed | |||
a2d731503f | |||
3e69c71ed5 | |||
44f4532452 | |||
c1245308bd | |||
a1cbc45b88 | |||
90f319ebda | |||
9674af10ce | |||
5a77b6a8e5 | |||
53553fcce2 | |||
1730ef27da | |||
57a6db5df2 | |||
32fe01f128 | |||
b85d801121 | |||
daa499ab93 | |||
68fcb8522e | |||
341b94b9ff | |||
f4b9decd23 | |||
cf0c6e7f9d | |||
29703d10b2 | |||
abb0813948 | |||
2c3146314b | |||
eb34c45145 | |||
993aa87776 | |||
ca183c7c5a | |||
71043d4305 | |||
eb981c04e9 | |||
ecf934864a | |||
686eeb706b | |||
fa3b5cd7e6 | |||
94575d2212 | |||
ca9e9601ab | |||
06f3499b6d | |||
2df527ed20 | |||
2c7c41cded | |||
1083d51e18 | |||
40c07ebb57 | |||
efe80a75f5 | |||
1bd6aa73f3 | |||
4b61192b36 | |||
664c6e049f | |||
db3d662dae | |||
dee050f338 | |||
ae00a14a35 | |||
86fdbe45e9 | |||
b04dcc18d0 | |||
1cc88ff362 | |||
3435052e27 | |||
4c3d037e58 | |||
f83790a5be | |||
11bb04419b | |||
519b02da79 | |||
fdbbbcb64c | |||
0fb4ae4fc0 | |||
181511bc8e | |||
e062412e60 | |||
bdb6d75f83 | |||
433111124f | |||
23080dbe22 | |||
05096c2a16 | |||
5559cded85 | |||
9f45e8880a | |||
dc128662da | |||
dc3fd24903 | |||
b2efa81b0d | |||
2c04d40c53 | |||
fcff9d16ff | |||
eef61f9d1e | |||
8f9f9e8397 | |||
d0e7747c7f | |||
9e45cfd02a | |||
aa66e69c15 | |||
9bf4b149aa | |||
5474973752 | |||
3e30ab57a6 | |||
9d6099b6d8 | |||
a7f667779a | |||
f71240c9a6 | |||
f8fc61e9bd | |||
a8011e3a1a | |||
e8fcf05775 | |||
cfb6fb5b30 | |||
fb68ca3c66 | |||
6af19f44e8 | |||
3291dbe8d2 | |||
efac5b0449 | |||
519155a12f | |||
603c3df1b6 | |||
05ca541a8e | |||
917884b5f5 | |||
22a2bd1de1 | |||
af4923c741 | |||
ac4401175f | |||
71c649b016 | |||
cbdb143966 | |||
8c105b0c40 | |||
8e760a0fcc | |||
6f46e4d376 | |||
bee6ddc843 | |||
a3fd931931 | |||
e2fa293c74 | |||
c4ed481ce2 | |||
e6ea3832fc | |||
9a8c0ce442 | |||
49ec66e27c | |||
2b6456168e | |||
e6cbe6ffc8 | |||
00d496086e | |||
1894ed50d1 | |||
7ad5ca03b0 | |||
b380187453 | |||
2022c53fad | |||
46b7660e2d | |||
e90b10abfd | |||
8710a2a1d3 | |||
b3fbf89f57 | |||
a8bd13f7e6 | |||
daf2848c4d | |||
0614637342 | |||
865ffb28af | |||
8b89d1e062 | |||
e4cf95856e | |||
74be25f656 | |||
b5d56eaec2 | |||
8bb6e91597 | |||
d72f2d9e5c | |||
781b4383d6 | |||
017bbc3748 | |||
69a5e0bc5d | |||
2579b9be26 | |||
9bfef01438 | |||
c0d4b2f6a5 | |||
529e9c3c60 | |||
504c256b3e | |||
91572c56e2 | |||
3b229b95b6 | |||
0f4b8dc794 | |||
e700f0a9e4 | |||
c85400063c | |||
dc03639cad | |||
e6a04aa5e9 | |||
1bc3830e5e | |||
93f7195429 | |||
d04e0d2a2a | |||
259eef2e68 | |||
ad5e610cec | |||
a37aec3bdf | |||
1cec386c18 | |||
ce39de14e8 | |||
3975073efd | |||
f31685e4e7 | |||
a856c27fe4 | |||
0435225a29 | |||
be757c7968 | |||
9b977ac878 | |||
37344c0cb8 | |||
ff25fa25dd | |||
ac0e44857c | |||
9f17f1bc17 | |||
1faa61ad50 | |||
815831b1ed | |||
6c70e19c63 | |||
4a8e9472ab | |||
5d4f3b8d90 | |||
f37c7baefb | |||
efca3520ab | |||
cc385f851f | |||
349604ac50 | |||
eaaa214dc9 | |||
e3e94ad14e | |||
c1347de1f0 | |||
71a2352d2b | |||
34414de4e5 | |||
ff34e793a0 | |||
31295efbff | |||
a3285d5943 | |||
b9e19421c1 | |||
6a6d4a3c9b | |||
82825fee41 | |||
2018dd444f | |||
35243fb62e | |||
fa08f1e2cf | |||
e10a52b39e | |||
c947204356 | |||
994bf7439b | |||
97f3642262 | |||
0e8aece991 | |||
39a473c8c2 | |||
b9e6ffe03d | |||
9f9a5ceaa3 | |||
36cf6097b3 | |||
45c0d05fec | |||
3cd6af9ef9 | |||
d12af6d203 | |||
5f5cafe5ca | |||
d45cc207ad | |||
6e3a13e0d2 | |||
0d6e9a5b9f | |||
7d509eeb48 | |||
87ba4ea524 | |||
42f975a926 | |||
63c31eba22 | |||
626fa7681b | |||
d412d482b2 | |||
cf2f7377ab | |||
6c8cadace6 | |||
320f64a611 | |||
bfc3684d75 | |||
19a4a37144 | |||
f2d284989b | |||
3f01fc6d67 | |||
d4396cc61a | |||
298da694ca | |||
a5bc7850a0 | |||
f6e0cf2b71 | |||
9a5286ca24 | |||
e10143b6db | |||
6fe41f8e02 | |||
e8068a8795 | |||
e8ee94d13b | |||
2411929455 | |||
bec02795b8 | |||
b5bc63e76b | |||
1aa487ff1a | |||
f47ebb2adb | |||
f90670f477 | |||
95ac5aeb7d | |||
9be0664e14 | |||
805039ec02 | |||
322ebb1baa | |||
325eab35a9 | |||
32105538c5 | |||
820ca16cd9 | |||
45e3c910da | |||
d609acc6aa | |||
02b4822be8 | |||
c16a1b4726 | |||
d1cea95eb4 | |||
53eefa7c80 | |||
b06732dbf5 | |||
22feb8dd1c | |||
56f976e495 | |||
f830c7efa6 | |||
04d6515337 | |||
f78a68d53f | |||
c8687f2f8d | |||
1884b89a6e | |||
008787a938 | |||
f41814c6ca | |||
055269504b | |||
dea5b15656 | |||
6650438d2f | |||
4204e4d9e2 | |||
9e41d49d46 | |||
6aa25760c5 | |||
1bff6d1289 | |||
23c69fb5a3 | |||
b158e0d17d | |||
c9dd33ba57 | |||
bc000451cc | |||
47da9a9d70 | |||
66703cb5e1 | |||
0066b4dbfd | |||
18d8b81f70 | |||
8d52bde6b0 | |||
dd3bf121c1 | |||
cfc3f926fe | |||
6f8c8a3b66 | |||
1c2125f969 | |||
0030c6d656 | |||
7e5ea6e065 | |||
49383e757f | |||
0cd0a1085a | |||
5bc69b6fa4 | |||
ddb5fe51b3 | |||
56debcd08a | |||
de34856d57 | |||
80c25f459c | |||
ccb322016e | |||
08ba0c7b02 | |||
7f57e4f45c | |||
f0b3a50c23 | |||
e51dbac2c5 | |||
f4c43ffab6 | |||
69a12650d2 | |||
8c5a7a087f | |||
5a938b8c0b | |||
448e266097 | |||
da3f59fb9b | |||
ef2ec1e1c5 | |||
031c937c0c | |||
c6ec21747b | |||
b54be3384d | |||
62ee2ca445 | |||
03b2f83981 | |||
20f0a5cd6c | |||
640f438c4c | |||
b068fb5756 | |||
645ace75c3 | |||
0518ff9358 | |||
a65fd7916e | |||
a77108dd0c | |||
7234ff4309 | |||
7ea8c8f7c6 | |||
c8e5b4f822 | |||
780d51286a | |||
2252547fc1 | |||
7e5409160e | |||
9b187140ff | |||
77ae13723d | |||
9efc839128 | |||
660301a43b | |||
11fd918d62 | |||
de67d36cd6 | |||
1f8b2f7909 | |||
d9bc03d1fc | |||
369a61ec59 | |||
c54f19282a | |||
174e9afa7b | |||
e53f1f60eb | |||
7eb0a8cf7e | |||
0e6518915d | |||
e0129fd0f7 | |||
929cf5e230 | |||
d6512e0a86 | |||
480b728c06 | |||
9e323a08ff | |||
75f4f0bfe0 | |||
2eece08d27 | |||
b930bb432d | |||
83ff417f4d | |||
bead51db69 | |||
bf171bbfda | |||
8ca068c98f | |||
a696cc4ed8 | |||
0a2a28cb34 | |||
0f20f1fcdc | |||
9a61f90fec | |||
5a88856825 | |||
0e4f772c69 | |||
8278ece803 | |||
eebe33f896 | |||
61d03b38b9 | |||
c0f447ca20 | |||
81465d69cc | |||
1e84ced9a9 | |||
3479148b86 | |||
017ad818ef | |||
09caae2fcc | |||
ae295d72ae | |||
16c59c3245 | |||
ea65ef0100 | |||
379e39aa3e | |||
835501a5f4 | |||
c87cfed525 | |||
ebd1e04414 | |||
1019ed5793 | |||
adcac7b54a | |||
d3a3078504 | |||
ac18a76c14 | |||
66b5f17d38 | |||
9763f302f3 | |||
1359da5b14 | |||
063d22f88c | |||
7681830256 | |||
3371697e18 | |||
bfe6c00f90 | |||
e90973bcd4 | |||
e0648d63ad | |||
564c1e26b6 | |||
27d6802dfc | |||
d2a4f2bc46 | |||
d24abd436e | |||
305adc94fa | |||
d9db693aec | |||
d64f08490a | |||
a982c86794 | |||
6c307d885f | |||
048210d7da | |||
d2be712de8 | |||
3a8256e3bc | |||
385c241858 | |||
a1da591218 | |||
f1d9a4a28c | |||
29b3f530d2 | |||
e1f83727b7 | |||
17f4f671a6 | |||
4b8ef29775 | |||
5377087848 | |||
1fedd0e50f | |||
6cac3b4d39 | |||
d9292587ec | |||
cf4f1dce32 | |||
1299f5e9cc | |||
48b177defa | |||
63475dda78 | |||
9dd7a7e653 | |||
b624bef345 | |||
a03176223a | |||
98cb1a8389 | |||
ddbc844954 | |||
d22ab23771 | |||
0a60b505b8 | |||
2b4799591f | |||
048aab682f | |||
e557d46c0d | |||
10d6309608 | |||
7d41fc8b06 | |||
2483398b0f | |||
a94209a2bc | |||
db7b4f195e | |||
b0f7fd5d00 | |||
96b1de1856 | |||
9366d67218 | |||
8df885b727 | |||
11cf2a96e2 | |||
f62bd8be36 | |||
813474b5d6 | |||
508ea2cf96 | |||
a37e5ac93f | |||
2c1ec7df74 | |||
4971bee67c | |||
eaa41c3256 | |||
5606646064 | |||
59a7842c6d | |||
149ad8dcc6 | |||
3a5e227ab5 | |||
3202f48f8e | |||
3a455a0452 | |||
f2288ceb49 | |||
dba4f91c77 | |||
1f565355ec | |||
af1cfee754 | |||
9563adacf7 | |||
fc7188145b | |||
ceafcbf850 | |||
7fbd024ed5 | |||
66a4f29911 | |||
eab3bf780e | |||
efa9771ad7 | |||
e2cacc1fa0 | |||
93b8f75cc3 | |||
a6a29b7032 | |||
981d3b6673 | |||
8e313517d1 | |||
beed0c1a70 | |||
d98abe42bc | |||
52367e53f5 | |||
acb392e56c | |||
ac136313cb | |||
e92a91663d | |||
26ba8ca999 | |||
e409c37158 | |||
2f2d52df85 | |||
0868e643c9 | |||
1bfe768601 | |||
3405bc485b | |||
6ff1b7d20a | |||
3504c8b54e | |||
e01a12a945 | |||
8c8445eb3b | |||
7a3043559f | |||
54812f0de1 | |||
28c1425a8f | |||
a96690c8bd | |||
e5196c6af9 | |||
19518da2e2 | |||
b956a0dcd6 | |||
20023e3989 | |||
d9a818525d | |||
b8f7686a6d | |||
5013af2117 | |||
02a6326605 | |||
1441b9610c | |||
56f3f089a1 | |||
1764abe65f | |||
33762574c3 | |||
f1dc9af651 | |||
25a7bbd86a | |||
6a8168025d | |||
26321ab68b | |||
449b3b3986 | |||
39f9d4c273 | |||
bb1b561c47 | |||
907787cfdc | |||
e61d3a22a3 | |||
fb90a4e54b | |||
5282b5f8df | |||
9942b3baf2 | |||
b874583931 | |||
2f011ea249 | |||
a4ebf87263 | |||
dd492fa63c | |||
4dc10fb6a3 | |||
4a2b81c793 | |||
e064352621 | |||
b58357741a | |||
2198c00d00 | |||
978eea400d | |||
a828f61c72 | |||
4e67be8a3c | |||
623f21f769 | |||
34838abfa9 | |||
280e39d9c4 | |||
2df56ad8b9 | |||
5ab2f02f63 | |||
0120b33a25 | |||
9622cd6a2a | |||
78ccaa7d65 | |||
4f07c62cc9 | |||
520ddbb034 | |||
0a16500133 | |||
681a583711 | |||
aa4362fe9f | |||
0c12d07a26 | |||
f474ab94d2 | |||
5ba77012a7 | |||
a573fa0b93 | |||
9a86bc23be | |||
c90b415c8b | |||
4287387a5e | |||
32bd1bb4aa | |||
1023087c8a | |||
5843aec342 | |||
f52bf560ec | |||
05a4139f94 | |||
116e20335e | |||
5e6b45eaec | |||
aa38340415 | |||
4d157d275a | |||
70818836de | |||
1f70b93310 | |||
4c604bf400 | |||
7fe694ba0a | |||
eb9059a711 | |||
da4917998d | |||
99b4a25de7 | |||
899445d586 | |||
2de0cbc6c0 | |||
7948d1f27a | |||
bcb8a2315c | |||
ddfd85c586 | |||
0e8715b5a1 | |||
1b2e237816 | |||
6d43126fa5 | |||
3c0146b1c4 | |||
893a56aa83 | |||
f7c9fbcc22 | |||
aa29836039 | |||
c30740c4e3 | |||
d07cbb2b10 | |||
8fdf263e4b | |||
4d67b684e4 | |||
d06e9151b9 | |||
366def0235 | |||
2301141b44 | |||
112eda2021 | |||
d9e15357f3 | |||
70ba0cd618 | |||
78704885d7 | |||
513b477fac | |||
6c3bb0b520 | |||
c2e85ce9a6 | |||
3f742c7b1a | |||
b7831b824a | |||
f0ef5bb371 | |||
29566430a6 | |||
a3126b060d | |||
2ef80eee1d | |||
65a0320cea | |||
199dfe106a | |||
056a8a3289 | |||
1d5f450f74 | |||
7914202df3 | |||
a6b5984dce | |||
fd9e913a49 | |||
2b7d6738f1 | |||
f81e53e455 | |||
3011e62fad | |||
54dc412c4a | |||
0e9bb45d89 | |||
6493fb86c1 | |||
df21a1eed6 | |||
c5a5d25320 | |||
7efe254a66 | |||
d71dc35239 | |||
ab9df41a21 | |||
16639c0b5b | |||
2d86483907 | |||
24a4d03eff | |||
0d93186066 | |||
69b43b40b5 | |||
16d5db00af | |||
b87f7017d1 | |||
8a053f47d4 | |||
895d8019e3 | |||
25755d09dd | |||
a7345bb16f | |||
0bffc2b3dd | |||
14382e012f | |||
0e19a40968 | |||
4aac5c9584 | |||
8a2356580a | |||
4e4266f1c4 | |||
cfea251d60 | |||
d1ef1810bf | |||
25b287344f | |||
f30cf3fecd | |||
236f3d2058 | |||
14634af83c | |||
4b7ac0e299 | |||
cc5c130f49 | |||
d5c2f8414e | |||
c83d8580ba | |||
7562dc8ecb | |||
37e74f9027 | |||
7cae383127 | |||
b25e61ae9a | |||
885d02ceca | |||
b3a5a36d9c | |||
5076f79aaa | |||
9768fa7c50 | |||
92cd65b66f | |||
541c38151f | |||
7948b7bfa1 | |||
05485ba8e3 | |||
2505e95d1c | |||
135e9ae7b9 | |||
8ed6dbe5d1 | |||
752cd42ad7 | |||
fbf74a1286 | |||
55e1a97d43 | |||
8a03951713 | |||
1a1ad670ee | |||
5273131b25 | |||
d74b79f585 | |||
e1af089658 | |||
34ee5d8e3b | |||
68e8a77b1d | |||
edded220b5 | |||
1581c659af | |||
ca5889f925 | |||
6e6861479d | |||
8e87aa0342 | |||
97cb51d990 | |||
d2ce27eeab | |||
00a7b7877c | |||
c387fe0fe9 | |||
fea2cd1cc5 | |||
7742d7a048 | |||
e37e2f4540 | |||
4deb4c781e | |||
5da2047935 | |||
fb82daf936 | |||
ede40e4a68 | |||
3852f28fd4 | |||
c385fd635b | |||
b9ac887eed | |||
a2dc2b3085 | |||
6ab77f958c | |||
4928f80929 | |||
687e504af4 | |||
14b293e0cb | |||
beb59da6a6 | |||
c2702e02a9 | |||
6b4509fca5 | |||
8abfe059b7 | |||
10523dbbd7 | |||
b8c71109b8 | |||
9cc850e578 | |||
0e47f2d92a | |||
fbcfb550a2 | |||
a388acdf03 | |||
d36be799d0 | |||
c325368be8 | |||
388218f9df | |||
6b2656efae | |||
278fab268f | |||
bd8b8ca410 | |||
fb7422e5a8 | |||
a70c51193b | |||
fa75cac7f5 | |||
de3694248a | |||
9f06149ae3 | |||
437e28c3a9 | |||
cad6175db0 | |||
af053b9ac4 | |||
0a20cb5e41 | |||
aa9737498a | |||
42191f4e77 | |||
451eb99f8a | |||
b110705f45 | |||
36e94d4e3c | |||
4e98bbc1c9 | |||
c3b13b224c | |||
5f388fd38d | |||
9bc161c140 | |||
dbb7c0cde3 | |||
52e517dfc3 | |||
37ffb2a02c | |||
91b3713dad | |||
c53ac1aa4f | |||
c4166997be | |||
f0f9455c6e | |||
7bc78425cd | |||
d1dc14d9e5 | |||
521755b9f2 | |||
ad565c5a2b | |||
ebba6e1ada | |||
0b7b5d985f | |||
b948e06a4f | |||
eaa98b0d64 | |||
16b3c11678 | |||
c92929a32d | |||
46c3e5077d | |||
dc12c54ae6 | |||
bdc43455a5 | |||
42eeb00a0f | |||
5951d2a874 | |||
9a5aba7313 | |||
d94914629f | |||
216ede189c | |||
0191ed7ad6 | |||
8036758857 | |||
41bc168a38 | |||
14ea326f43 | |||
fcc907d488 | |||
2869fc3642 | |||
dc1fb3b607 | |||
1258180805 | |||
b35958c6eb | |||
152737e8f6 | |||
840f624b21 | |||
cd1f8a7cb1 | |||
49c333b88a | |||
8fc981c8a0 | |||
4b60b7e046 | |||
92254c8c4d | |||
34312dd402 | |||
b63a991008 | |||
4f36df6324 | |||
05af69f7b2 | |||
641907893c | |||
7e2c2ad323 | |||
4e3d6527dd | |||
5b9344dee9 | |||
6157aba1ec | |||
f06f1265d8 | |||
1f68ecd9f4 | |||
877f0e4c28 | |||
af7437ab04 | |||
f1e5e9a765 | |||
136b668f8f | |||
24032f4f5a | |||
18a63a6e7b | |||
ae98e6bc56 | |||
b142180f94 | |||
f826002ea8 | |||
12be082523 | |||
470fc43646 | |||
c12a4ecb80 | |||
ea5b5dc8fb | |||
79ab37e6a0 | |||
0f1d219002 | |||
7bf4c48733 | |||
d7aaf0d00e | |||
758b15e887 | |||
c3d89bd4bf | |||
ad5683279e | |||
14198aaa17 | |||
976c15d29a | |||
ba9a9096bf | |||
cbd87abc3d | |||
5a57648eec | |||
b7538dcdd0 | |||
aee1642ef6 | |||
ac92df2149 | |||
44c1edb2dd | |||
2ea8812fda | |||
922a5ed607 | |||
98e227c102 | |||
5a0398ceb5 | |||
ebb7398446 | |||
e0501cff0f | |||
0e528c9267 | |||
0f8c86a26c | |||
f05ac31dc4 | |||
2bb877a84b | |||
887cc3a88a | |||
52199dd800 | |||
94b486cf2e | |||
db508fc4f7 | |||
12e5d2f6f3 | |||
4859cb5db8 | |||
83ad9d616f | |||
2a0ee83c12 | |||
5379d8cc3d | |||
9187bb4371 | |||
c8c5ce8105 | |||
15d351258f | |||
5fdc5489a1 | |||
a30841cdf6 | |||
aad904f1a1 | |||
8eb067b810 | |||
108402a281 | |||
de958ca091 | |||
42828dbf65 | |||
036442aa69 | |||
e60c332c24 | |||
406d06fef2 | |||
9aa6f72152 | |||
70347d1ef9 | |||
42789ed561 | |||
092a2e5ca0 | |||
9c82a80273 | |||
57dab75832 | |||
6297b8f277 | |||
6bcdd4007a | |||
d0d0ba6ba7 | |||
550637ddef | |||
2bb2f65776 | |||
420e21b078 | |||
71b8d72da3 | |||
86ceb7a274 | |||
489d2390c8 | |||
1a3a5b43a0 | |||
e5724620a8 | |||
2c4c88e30d | |||
f92c49cee6 | |||
8371d3b67a | |||
ca4d9771cc | |||
15a2e63866 | |||
eec35f07c3 | |||
11cfca5211 | |||
46b5e9034f | |||
7793609fa4 | |||
6f9ba6c290 | |||
4d0d316fdd | |||
b5c5bcb9f1 | |||
8fe9bf6292 | |||
9923f5b18e | |||
292fe80acf | |||
5b08dae28d | |||
33dd6937b4 | |||
a34cb3db8a | |||
10de50d251 | |||
3bbcaa1329 | |||
e1d2ed8867 | |||
8ee0d7c0e8 | |||
721ac5e2a3 | |||
88a410a9c0 | |||
0e8116b743 | |||
ef1435cef7 | |||
f7ff798238 | |||
f012c1180c | |||
5a2e8d8f80 | |||
364d3473a2 | |||
1a092a1e24 | |||
8248c60aa0 | |||
f4106ee427 | |||
4e99a3ad07 | |||
57a61f0c40 | |||
61988e3297 | |||
5c8da76d9a | |||
3b32dc37c8 | |||
7a6d021e18 | |||
21cb0e8feb | |||
527eccd3c6 | |||
57ec4e09ad | |||
9164a3ed3a | |||
37086bc6c7 | |||
1d1851dc76 | |||
ac841221b6 | |||
c8ddb121d0 | |||
ba5613cf62 | |||
af4acd5623 | |||
19eb5c73e7 | |||
94ff6cc800 | |||
adf4f5a738 | |||
1e6088ca1d | |||
9d01b2306c | |||
fc8d3d8f11 | |||
15b860af36 | |||
90d990bdfb | |||
2cfeb6b6d6 | |||
42f9fb52ed | |||
11c2c8afe3 | |||
fe39c2712d | |||
b774e75f2c | |||
147c108570 | |||
53de54120e | |||
fa097bf57e | |||
917eb4fdf1 | |||
a8df774e50 | |||
0b98ce1ef2 | |||
c6bbdffea0 | |||
481918ab5b | |||
b27caf2405 | |||
d5b7338531 | |||
9246500c95 | |||
91669a7fda | |||
c7eb67129a | |||
98901ac668 | |||
7dde793f9e | |||
07de82ae82 | |||
9f710cb70e | |||
dab62a04df | |||
de51e266f6 | |||
5375580104 | |||
964d9e873d | |||
7e8e644e6c | |||
6bde623698 | |||
5ba89035b4 | |||
a9b99fa0ff | |||
6619a1b4a6 | |||
a36f106c72 | |||
097f8a2b82 | |||
bcbb911b24 | |||
f18efb2344 | |||
497d98363f | |||
367bf666fc | |||
7489a3bb9d | |||
2a6c7863b1 | |||
bf27f51049 | |||
6ba74a0c30 | |||
ada94f69c3 | |||
dc5ac081ce | |||
8a46922e77 | |||
5fdffb5e0c | |||
9f6a4891ed | |||
41d23c66a4 | |||
9163f3d30e | |||
d49fff65e4 | |||
95253e40bd | |||
af1a99c130 | |||
1638fde181 | |||
52ea2e88e9 | |||
d4d8699fc5 | |||
e8d60e2dc0 | |||
944e9df7cc | |||
cd2da582c4 | |||
1e28fc5018 | |||
a24cb3e04a | |||
13f27a76ff | |||
39120d9413 | |||
fe08228204 | |||
c7eb5c430c | |||
70e2a99274 | |||
52b945cd64 | |||
07a8e6bf92 | |||
afa322a83b | |||
d3ac44c526 | |||
5bbee1e1d7 | |||
58da0e8a60 | |||
713b6119d0 | |||
ebf2804d63 | |||
3b77753829 | |||
eb29d0ac99 | |||
6cdec05cde | |||
7ef0ef0d7c | |||
dd7d262bd3 | |||
13d7686258 | |||
91b8c55de9 | |||
00c5467a89 | |||
cc32e28b36 | |||
72329a8a2a | |||
a102ee181a | |||
778591d460 | |||
6bc928b5b6 | |||
0b2c457030 | |||
93d4e629d1 | |||
d53d3b7a51 | |||
72062c8570 | |||
de90219406 | |||
de179d070d | |||
f45857f79b | |||
eda556ef03 | |||
ea67340cab | |||
5b61f8c7a3 | |||
70d8fe82b3 | |||
fce8c294d3 | |||
8541f79ebc | |||
ec4fd401cb | |||
98217b1745 | |||
378c574eed | |||
e5193f3460 | |||
60e90575ac | |||
78ffa6f184 | |||
f9f50e734f | |||
2e75bac90c | |||
8c2f081cb0 | |||
6adbc6c291 | |||
db663fe134 | |||
2e394dc2cb | |||
b80fd9c023 | |||
3e25f1ec42 | |||
351f63f0b8 | |||
9f90d01dc6 | |||
71d815cf08 | |||
a168136102 | |||
e9f9bbb9c0 | |||
3e8e2182a8 | |||
2025ccb366 | |||
6ae934e461 | |||
7431e4d7c0 | |||
eb0f54e79d | |||
08e9520019 | |||
630a542ed6 | |||
774b71f8f0 | |||
5903ae1603 | |||
1c72e9ac50 | |||
b662c547f3 | |||
fac19e09cd | |||
5a3e2a2575 | |||
eed520daac | |||
4a7b42202e | |||
f292ba55c1 | |||
fef6f3bbd1 | |||
af9fcbc38d | |||
bd9cdc1cba | |||
be21d4c9ac | |||
b29d3c575d | |||
39a4366eab | |||
4c2979d242 | |||
4407146962 | |||
c3bcb17312 | |||
1b95807ac6 | |||
240074bdc5 | |||
46162dadbe | |||
455001a759 | |||
31881ce472 | |||
9669b4e365 | |||
d0c0ee2981 | |||
12a341e607 | |||
020445743c | |||
cc98c94b2b | |||
00febdf255 | |||
cbc7b73b1d | |||
42c59a3aa0 | |||
5f703a043b | |||
76fe11741a | |||
2c4add6aad | |||
6cb7e65231 | |||
2d1bcf221c | |||
a761559fd3 | |||
b27eb4a173 | |||
01fabd0342 | |||
6911ca407e | |||
68fbc436f2 | |||
ecb754ab29 | |||
41bd018191 | |||
bfcbd0265a | |||
45479b9f65 | |||
a68ba01320 | |||
ba03243527 | |||
22f4504629 | |||
bf59ed34cf | |||
d8bc2cab2e | |||
f8dcff788b | |||
4be34e4dc1 | |||
b1742dafc2 | |||
e24de8334f | |||
ae87185ad0 | |||
72f92a1c2b | |||
8b9121a5c1 | |||
cfb4208db2 | |||
52afe3fb02 | |||
57975b6f96 | |||
b4ffc6e2f0 | |||
1ed69de5b0 | |||
6ec85aa349 | |||
671509df3b | |||
2edeffb761 | |||
428a9ca509 | |||
cf273021ab | |||
ecbae5af2d | |||
15c28b130d | |||
996422ff4b | |||
e231c07c80 | |||
3e8e0c9224 | |||
c6c4012a36 | |||
30512e347a | |||
6f983ccb6b | |||
3814767e28 | |||
243e73064a | |||
8df4f9ce52 | |||
b0b2df5422 | |||
5b6edd110d | |||
392c226cbe | |||
7689d1a2e2 | |||
711bd18d06 | |||
98f1545fca | |||
8d47259f78 | |||
311f22f6ba | |||
5bcad1ef2f | |||
be05b54053 | |||
6ff55e1279 | |||
338a19373c | |||
bc5b16b5e3 | |||
a11875145b | |||
25a1d06dcb | |||
d87e5da75c | |||
6d44aa3f58 | |||
08cf8977f7 | |||
942ee637b0 | |||
aac618bfee | |||
2dcdad3a49 | |||
db8d4cd3fe | |||
de22169ea8 | |||
b24e56803c | |||
5530c96f8e | |||
1d8fea891a | |||
707fcdb1ab | |||
1a2f6b4970 | |||
4409a369fa | |||
272c305ec2 | |||
a81c5f44a2 | |||
2a09462f6f | |||
fdd74e2e09 | |||
5cc67aba15 | |||
62e9a39557 | |||
fadcb9b43f | |||
24d134ad6c | |||
faaef9d9f8 | |||
c5cc364918 | |||
ed9057e780 | |||
9bdeda7814 | |||
e4ef364aa8 | |||
379251d29d | |||
cf8b84925e | |||
f07bc9e6de | |||
94533e277c | |||
73102053dc | |||
5fab3e3d36 | |||
54bcba195d | |||
7e757c005c | |||
82eaff5da6 | |||
1eb28d6aee | |||
bdbe45e322 | |||
34a8311647 | |||
cf45caa762 | |||
5b72728aa2 | |||
67f3dc7430 | |||
b40af9bbdc | |||
cc66ffd6f3 | |||
5a7ef65c56 | |||
46ac0ecc77 | |||
cc6561bdda | |||
3022406f63 | |||
66382eb50f | |||
21591ad6b8 | |||
88bbb76752 | |||
765f075576 | |||
6b93973d9b | |||
439da266a9 | |||
0207374592 | |||
7beb773a37 | |||
4b3a68f4cd | |||
3dbc6ffb2b | |||
bf5e2bcc84 | |||
b80e85638a | |||
12c92928fa | |||
e5dffc3d9f | |||
fe84a39097 | |||
55c8ce7cf0 | |||
cbb65e8d79 | |||
2053e5f521 | |||
f53b51a208 | |||
e63569e3e9 | |||
2fed83659f | |||
ef90e3e048 | |||
5fbbd897b5 | |||
b0056a4677 | |||
d467d79bdf | |||
92321a3b4e | |||
766300bdff | |||
8214fdb24d | |||
42aae4c03a | |||
441738e569 | |||
5337ddba8d | |||
d1eaab7711 | |||
8f7f34c190 | |||
e40b400f6f | |||
3b5883dd55 | |||
785d439605 | |||
ff98b172c4 | |||
30d8b1327b | |||
74dddcb8ad | |||
6e7d99376d | |||
98c5e9e15b | |||
fa08009c50 | |||
ce662796e3 | |||
accf2a34ff | |||
a15e625692 | |||
7689e31640 | |||
8c2cefe304 | |||
eb9bc5f8dc | |||
9c927d9001 | |||
2d6b0f1877 | |||
6c2488f052 | |||
479c49b02e | |||
c0a0a642f9 | |||
35f8daee29 | |||
e15dc1ce11 | |||
79062ff3d6 | |||
fc5abd38cc | |||
6900810f5d | |||
2fae8ffa70 | |||
ea9feeefd2 | |||
f09f730bff | |||
25b0e86f09 | |||
18b65f769f | |||
abd5cf0795 | |||
6e08a428d6 | |||
a1856482ff | |||
a7a032dc8f | |||
4493f369dd | |||
f1098801e2 | |||
a15341fdcf | |||
c94331bf24 | |||
7dcfead843 | |||
0bb8b5349d | |||
30b46c4cdd | |||
69c3a63794 | |||
dd1def149c | |||
a6f294f361 | |||
6d5c8491e4 | |||
420b0c60d7 | |||
9f2b715d9f | |||
f490fbc2c9 | |||
95c117973f | |||
9a25c68d9a | |||
935e79c9c2 | |||
efc5b936f8 | |||
c19337d65c | |||
2470c2bfa6 | |||
acbf2939c9 | |||
8edc7c1374 | |||
d606c85443 | |||
5ada234f64 | |||
fdd2dd1b40 | |||
d2f524bf90 | |||
5887522dce | |||
688bd769dd | |||
649450a24c | |||
2bf2fcd685 | |||
d57f9de21e | |||
596c868b9d | |||
8a8768ed1d | |||
32c76beaa2 | |||
cb0b950d34 | |||
2536d9f747 | |||
438efa655f | |||
ad9855a791 | |||
58e819606a | |||
bab8ec1eaa | |||
c6aa5c3a3c | |||
c7503f87d7 | |||
561ff95436 | |||
2201daaa20 | |||
94afa94428 | |||
83273636f6 | |||
30b56c553e | |||
8b5dc8b3ad | |||
d1f46c8f55 | |||
d0cecbdfd7 | |||
1a257064f7 | |||
182a8af57f | |||
af315e1671 | |||
ceea2475a1 | |||
c22d10d0de | |||
849337c55d | |||
25bc788595 | |||
48baea3304 | |||
a6d7209a45 | |||
eb1b1ba22f | |||
d8a7dfbdbd | |||
fa2d82ac13 | |||
284646ee6c | |||
3f05565b7b | |||
089964a5eb | |||
31b8dd4fd5 | |||
892c92eb1d | |||
d0d5dffe79 | |||
823a4a35f0 | |||
e61c0dcc12 | |||
f5f23e6fbc | |||
3b2b51f07c | |||
272caa7100 | |||
2324a2c837 | |||
893f69ad18 | |||
a4a306374d | |||
f283a1ad68 | |||
0e205ec1d9 | |||
c3411b8856 | |||
7e0591f0a6 | |||
1f6f755d7f | |||
08edcd44ef | |||
84ddcbb74d | |||
f16a5f92e6 | |||
a66b540254 | |||
a8b2e21a5a | |||
72bf698d95 | |||
7a54cf25d1 | |||
96468f9258 | |||
231e4e72d9 | |||
3b04465106 | |||
4e9ef89276 | |||
8af8f93434 | |||
7362e48cf3 | |||
efa0c060fe | |||
adf62bc2ca | |||
3a89f52028 | |||
c7d969c96e | |||
2053a6b16b | |||
e1d54bdf1d | |||
761ca1132d | |||
2010a38411 | |||
94516ef341 | |||
cde3ff703a | |||
b852fcc167 | |||
f9c14addcc | |||
a9d5fcf82a | |||
b6e59e9b11 | |||
e8a1a40dc0 | |||
4b2100b593 | |||
a38872b2d0 | |||
e422ca4d9b | |||
f49086a527 | |||
aa7212c642 | |||
0c59caa230 | |||
4934e91e74 | |||
546249e950 | |||
b7fc6a9c87 | |||
2121739925 | |||
908e3036e0 | |||
f565b4dbcd | |||
7100d43d9e | |||
14f932eea8 | |||
05f6fff8f6 | |||
725615fbe5 | |||
1846605184 | |||
224c895718 | |||
8a7aeca6b9 | |||
7893216cce | |||
a36eb55680 | |||
8091831b1f | |||
3a669294d7 | |||
e79c830db5 | |||
92abef7172 | |||
eb758685a1 | |||
bb6b00a998 | |||
edadc383ff | |||
0629e6c777 | |||
e6150e4aca | |||
ff8f03c983 | |||
0ab14f63cb | |||
8e195a0de9 | |||
7d4111fec8 | |||
bd27d91529 | |||
9e0c2580d2 | |||
35757168d4 | |||
3f7ba343a2 | |||
a6c845de16 | |||
b1596cbb60 | |||
4496fcc8b0 | |||
cffb65e37d | |||
117d0483f7 | |||
03049b79dd | |||
5e67f036b4 | |||
9812d38eee | |||
5733a5be9f | |||
2ddfa4d4f6 | |||
2408d77f15 | |||
823995d4ba | |||
a85a6c694c | |||
17a362fe7a | |||
85be2e97a1 | |||
ddf9123e8b | |||
da37d03104 | |||
210fe5352f | |||
697e177f00 | |||
dd6c7bb2ea | |||
3c5aa89469 | |||
fbe43a1715 | |||
b34c1138b9 | |||
de84dc71e8 | |||
d5f17d66d9 | |||
8617997e23 | |||
c7e4d6b976 | |||
b9d2654669 | |||
dc44c9ed61 | |||
1c4543b7bf | |||
dac35ae526 | |||
0a22978660 | |||
abb5b65217 | |||
b91d24f8d2 | |||
475631a06f | |||
981ca755c6 | |||
e15359a106 | |||
6243a297c0 | |||
859e3931c6 | |||
52098cf9f9 | |||
1108cd9a96 | |||
dd3a970497 | |||
b17364e701 | |||
7427fa3608 | |||
1cf4a879f7 | |||
08e0a0af19 | |||
b3d5f924c3 | |||
bbd6412e3d | |||
56ef86aab6 | |||
bd627d77b7 | |||
6eb37b989f | |||
7550a6294e | |||
80d387743a | |||
56dcd00e82 | |||
425517d576 | |||
bd7cd01359 | |||
f5d9306c37 | |||
4cd23cf445 | |||
35930f79f1 | |||
9fc77c2804 | |||
fa05249a9d | |||
7eaada4726 | |||
cb187fd3c2 | |||
df9646aaf9 | |||
e937f2bca3 | |||
efb6e9c6cd | |||
f44ff3715f | |||
7732b3f685 | |||
1c2810ccb8 | |||
a4313c3340 | |||
628731cba4 | |||
30f8244abf | |||
142a4c87bd | |||
cb0d59de61 | |||
0da62dad82 | |||
854ac6d5f1 | |||
0f86796e75 | |||
7481399908 | |||
716542107f | |||
6c82c36915 | |||
f05afc4b0a | |||
6ec21e6716 | |||
1f909080db | |||
89690d214d | |||
bd8e665198 | |||
6294797466 | |||
7bec9eaa87 | |||
8c0a818549 | |||
d5b5fc3798 | |||
a2766bcc2e | |||
9953c7d1e1 | |||
8d10fc573f | |||
dea09d8eaa | |||
74930ba253 | |||
28f84c5188 | |||
b2b04dc65f | |||
a712d5ca3e | |||
a60521420b | |||
896fd0c178 | |||
075fee46b7 | |||
4f6a9249e8 | |||
51b9d1289a | |||
27571bd63a | |||
3e2c20b204 | |||
8ab42ce944 | |||
d1ce737886 | |||
7e08c8f28e | |||
aa03def329 | |||
7f90c0a67a | |||
bf4c70dfef | |||
ac6e001fd6 | |||
89740b1a93 | |||
aa959cdc93 | |||
6d5a7ffefc | |||
95acf40eb6 | |||
7700214e5f | |||
49e3bd3b80 | |||
fba07c521a | |||
9569fbd72e | |||
0a389256eb | |||
ddac30db63 |
7
.dockerignore
Normal file
7
.dockerignore
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
.git
|
||||||
|
.gitignore
|
||||||
|
.idea
|
||||||
|
**/*.pyc
|
||||||
|
**/*.swp
|
||||||
|
black-env
|
||||||
|
debian
|
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
29
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior.
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Installation method**
|
||||||
|
How did you install OpenWebRX? (Raspberry Pi SD card image, Debian / Ubuntu packages, Docker image, manually?)
|
||||||
|
|
||||||
|
**Versions**
|
||||||
|
What version of OpenWebRX are you running? (Check on startup, or see `owrx/version.py`. If a `-dev` version is used, ideally state the commit the issue is appearing on)
|
||||||
|
|
||||||
|
**Log messages**
|
||||||
|
Are there any relevant messages relating to the bug in the output / log of OpenWebRX? (On most installations, the log should be available using the command `sudo journalctl -u openwebrx`)
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
5
.github/ISSUE_TEMPLATE/config.yml
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
blank_issues_enabled: false
|
||||||
|
contact_links:
|
||||||
|
- name: General support request or other project-relasted question
|
||||||
|
url: https://groups.io/g/openwebrx
|
||||||
|
about: Request help on the community mailing list
|
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
20
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: feature
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Before posting a new feature request, please check if a similar idea has already been listed
|
||||||
|
* on the issue tracker
|
||||||
|
* on the [OpenWebRX github project](https://github.com/users/jketterl/projects/1).
|
||||||
|
|
||||||
|
In the latter case, please only proceed if you have additional information about the feature, and please let us know that there's already a card there.
|
||||||
|
|
||||||
|
**Feature description**
|
||||||
|
Please describe in plain words what functionality you'd like to see in OpenWebRX, and why you think it's useful.
|
||||||
|
|
||||||
|
**Target audience**
|
||||||
|
Please let us know if you think that this feature is of particular interest for a particular group of users (e.g. hams, SWLs, DXers, ...)
|
6
.gitignore
vendored
6
.gitignore
vendored
@ -1,3 +1,5 @@
|
|||||||
*.pyc
|
**/*.pyc
|
||||||
*.swp
|
**/*.swp
|
||||||
tags
|
tags
|
||||||
|
.idea
|
||||||
|
packages
|
||||||
|
211
CHANGELOG.md
Normal file
211
CHANGELOG.md
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
**1.2.0**
|
||||||
|
- Major rewrite of all demodulation components to make use of the new csdr/pycsdr and digiham/pydigiham demodulator
|
||||||
|
modules
|
||||||
|
- Preliminary display of M17 callsign information
|
||||||
|
- New devices supported:
|
||||||
|
- Blade RF
|
||||||
|
|
||||||
|
**1.1.0**
|
||||||
|
- Reworked most graphical elements as SVGs for faster loadtimes and crispier display on hi-dpi displays
|
||||||
|
- Updated pipelines to match changes in digiham
|
||||||
|
- Changed D-Star and NXDN integrations to use new decoders from digiham
|
||||||
|
- Added D-Star and NXDN metadata display
|
||||||
|
|
||||||
|
**1.0.0**
|
||||||
|
- Introduced `squelch_auto_margin` config option that allows configuring the auto squelch level
|
||||||
|
- Removed `port` configuration option; `rtltcp_compat` takes the port number with the new connectors
|
||||||
|
- Added support for new WSJT-X modes FST4, FST4W (only available with WSJT-X 2.3) and Q65 (only avilable with
|
||||||
|
WSJT-X 2.4)
|
||||||
|
- Added support for demodulating M17 digital voice signals using m17-cxx-demod
|
||||||
|
- New reporting infrastructure, allowing WSPR and FST4W spots to be sent to wsprnet.org
|
||||||
|
- Add some basic filtering capabilities to the map
|
||||||
|
- New arguments to the `openwebrx` command-line to facilitate the administration of users (try `openwebrx admin`)
|
||||||
|
- Default bandwidth changes:
|
||||||
|
- "WFM" changed to 150kHz
|
||||||
|
- "Packet" (APRS) changed to 12.5kHz
|
||||||
|
- Configuration rework:
|
||||||
|
- New: fully web-based configuration interface
|
||||||
|
- System configuration parameters have been moved to a new, separate `openwebrx.conf` file
|
||||||
|
- Remaining parameters are now editable in the web configuration
|
||||||
|
- Existing `config_webrx.py` files will still be read, but changes made in the web configuration will be written to
|
||||||
|
a new storage system
|
||||||
|
- Added upload of avatar and panorama image via web configuration
|
||||||
|
- New devices supported:
|
||||||
|
- HPSDR devices (Hermes Lite 2) thanks to @jancona
|
||||||
|
- BBRF103 / RX666 / RX888 devices supported by libsddc
|
||||||
|
- R&S devices using the EB200 or Ammos protocols
|
||||||
|
|
||||||
|
**0.20.3**
|
||||||
|
- Fix a compatibility issue with python versions <= 3.6
|
||||||
|
|
||||||
|
**0.20.2**
|
||||||
|
- Fix a security problem that allowed arbitrary commands to be executed on the receiver
|
||||||
|
([See github issue #215](https://github.com/jketterl/openwebrx/issues/215))
|
||||||
|
|
||||||
|
**0.20.1**
|
||||||
|
- Remove broken OSM map fallback
|
||||||
|
|
||||||
|
**0.20.0**
|
||||||
|
- Added the ability to sign multiple keys in a single request, thus enabling multiple users to claim a single receiver
|
||||||
|
on receiverbook.de
|
||||||
|
- Fixed file descriptor leaks to prevent "too many open files" errors
|
||||||
|
- Add new demodulator chain for FreeDV
|
||||||
|
- Added new HD audio streaming mode along with a new WFM demodulator
|
||||||
|
- Reworked AGC code for better results in AM, SSB and digital modes
|
||||||
|
- Added support for demodulation of "Digital Radio Mondiale" (DRM) broadcast using the "dream" decoder.
|
||||||
|
- New default waterfall color scheme
|
||||||
|
- Prototype of a continuous automatic waterfall calibration mode
|
||||||
|
- New devices supported:
|
||||||
|
- FunCube Dongle Pro+ (`"type": "fcdpp"`)
|
||||||
|
- Support for connections to rtl_tcp (`"type": "rtl_tcp"`)
|
||||||
|
|
||||||
|
**0.19.1**
|
||||||
|
- Added ability to authenticate receivers with listing sites using "receiver id" tokens
|
||||||
|
|
||||||
|
**0.19.0**
|
||||||
|
- Fix direwolf connection setup by implementing a retry loop
|
||||||
|
- Pass direct sampling mode changes for rtl_sdr_soapy to owrx_connector
|
||||||
|
- OSM maps instead of Google when google_maps_api_key is not set (thanks @jquagga)
|
||||||
|
- Improved logic to pass parameters to soapy devices.
|
||||||
|
- `rtl_sdr_soapy`: added support for `bias_tee`
|
||||||
|
- `sdrplay`: added support for `bias_tee`, `rf_notch` and `dab_notch`
|
||||||
|
- `airspy`: added support for `bitpack`
|
||||||
|
- Added support for Perseus-SDR devices, (thanks @amontefusco)
|
||||||
|
- Property System has been rewritten so that defaults on sdr behave as expected
|
||||||
|
- Waterfall range auto-adjustment now only takes the center 80% of the spectrum into account, which should work better
|
||||||
|
with SDRs that oversample or have rather flat filter curves towards the spectrum edges
|
||||||
|
- Bugfix for negative network usage
|
||||||
|
- FiFi SDR: prevent arecord from shutting down after 2GB of data has been sent
|
||||||
|
- Added support for bias tee control on rtl_sdr devices
|
||||||
|
- All connector driven SDRs now support `"rf_gain": "auto"` to enable AGC
|
||||||
|
- `rtl_sdr` type now also supports the `direct_sampling` option
|
||||||
|
- Added decoding implementation for for digimode "JS8Call"
|
||||||
|
(requires an installation of [js8call](http://js8call.com/) and
|
||||||
|
[the js8py library](https://github.com/jketterl/js8py))
|
||||||
|
- Reorganization of the frontend demodulator code
|
||||||
|
- Improve receiver load time by concatenating javascript assets
|
||||||
|
- Docker images migrated to Debian slim images; This was necessary to allow the use of function multiversioning in
|
||||||
|
csdr and owrx_connector to allow the images to run on a wider range of CPUs
|
||||||
|
- Docker containers have been updated to include the SDRplay driver version 3
|
||||||
|
- HackRF support is now based on SoapyHackRF
|
||||||
|
- Removed sdr.hu server listing support since the site has been shut down
|
||||||
|
- Added support for Radioberry 2 Rasbperry Pi SDR Cape
|
||||||
|
|
||||||
|
**0.18.0**
|
||||||
|
- Support for SoapyRemote
|
||||||
|
|
||||||
|
**2020-02-08**
|
||||||
|
- Compression, resampling and filtering in the frontend have been rewritten in javascript, sdr.js has been removed
|
||||||
|
- Decoding of Pocsag modulation is now possible
|
||||||
|
- Removed the 3D waterfall since it had no real application and required ~1MB of javascript code to be downloaded
|
||||||
|
- Improved the frontend handling of the "too many users" scenario
|
||||||
|
- PSK63 digimode is now available (same decoding pipeline as PSK31, but with adopted parameters)
|
||||||
|
- The frequency can now be manipulated with the mousewheel, which should allow the user to tune more precise. The tuning
|
||||||
|
step size is determined by the digit the mouse cursor is hovering over.
|
||||||
|
- Clicking on the frequency now opens an input for direct frequency selection
|
||||||
|
- URL hashes have been fixed and improved: They are now updated automatically, so a shared URL will include frequency
|
||||||
|
and demodulator, which allows for improved sharing and linking.
|
||||||
|
- New daylight scheduler for background decoding, allows profiles to be selected by local sunrise / sunset times
|
||||||
|
- New devices supported:
|
||||||
|
- LimeSDR (`"type": "lime_sdr"`)
|
||||||
|
- PlutoSDR (`"type": "pluto_sdr"`)
|
||||||
|
- RTL_SDR via Soapy (`"type": "rtl_sdr_soapy"`) on special request to allow use of the direct sampling mode
|
||||||
|
|
||||||
|
**2020-01-04**
|
||||||
|
- The [owrx_connector](https://github.com/jketterl/owrx_connector) is now the default way of communicating with sdr
|
||||||
|
devices. The old sdr types have been replaced, all `_connector` suffixes on the type must be removed!
|
||||||
|
- The sources have been refactored, making it a lot easier to add support for other devices
|
||||||
|
- SDR device failure handling has been improved, including user feedback
|
||||||
|
- New devices supported:
|
||||||
|
- FiFiSDR (`"type": "fifi_sdr"`)
|
||||||
|
|
||||||
|
**2019-12-15**
|
||||||
|
- wsjt-x updated to 2.1.2
|
||||||
|
- The rtl_tcp compatibility mode of the owrx_connector is now configurable using the `rtltcp_compat` flag
|
||||||
|
|
||||||
|
**2019-12-10**
|
||||||
|
- added support for airspyhf devices (Airspy HF+ / Discovery)
|
||||||
|
|
||||||
|
**2019-12-05**
|
||||||
|
- explicit device filter for soapy devices for multi-device setups
|
||||||
|
|
||||||
|
**2019-12-03**
|
||||||
|
- compatibility fixes for safari browsers (ios and mac)
|
||||||
|
|
||||||
|
**2019-11-24**
|
||||||
|
- There is now a new way to interface with SDR hardware, .
|
||||||
|
They talk directly to the hardware (no rtl_sdr / rx_sdr necessary) and offer I/Q data on a socket, just like nmux
|
||||||
|
did before. They additionally offer a control socket that allows openwebrx to control the SDR parameters directly,
|
||||||
|
without the need for repeated restarts. This allows for quicker profile changes, and also reduces the risk of your
|
||||||
|
SDR hardware from failing during the switchover. See `config_webrx.py` for further information and instructions.
|
||||||
|
- Offset tuning using the `lfo_offset` has been reworked in a way that `center_freq` has to be set to the frequency you
|
||||||
|
actually want to listen to. If you're using an `lfo_offset` already, you will probably need to change its sign.
|
||||||
|
- `initial_squelch_level` can now be set on each profile.
|
||||||
|
- As usual, plenty of fixes and improvements.
|
||||||
|
|
||||||
|
**2019-10-27**
|
||||||
|
- Part of the frontend code has been reworked
|
||||||
|
- Audio buffer minimums have been completely stripped. As a result, you should get better latency. Unfortunately,
|
||||||
|
this also means there will be some skipping when audio starts.
|
||||||
|
- Now also supports AudioWorklets (for those browser that have it). The Raspberry Pi image has been updated to include
|
||||||
|
https due to the SecureContext requirement.
|
||||||
|
- Mousewheel controls for the receiver sliders
|
||||||
|
- Error handling for failed SDR devices
|
||||||
|
|
||||||
|
**2019-09-29**
|
||||||
|
- One of the most-requested features is finally coming to OpenWebRX: Bookmarks (sometimes also referred to as labels).
|
||||||
|
There's two kinds of bookmarks available:
|
||||||
|
- Serverside bookmarks that are set up by the receiver administrator. Check the file `bookmarks.json` for examples!
|
||||||
|
- Clientside bookmarks which every user can store for themselves. They are stored in the browser's localStorage.
|
||||||
|
- Some more bugs in the websocket handling have been fixed.
|
||||||
|
|
||||||
|
**2019-09-25**
|
||||||
|
- Automatic reporting of spots to [pskreporter](https://pskreporter.info/) is now possible. Please have a look at the
|
||||||
|
configuration on how to set it up.
|
||||||
|
- Websocket communication has been overhauled in large parts. It should now be more reliable, and failing connections
|
||||||
|
should now have no impact on other users.
|
||||||
|
- Profile scheduling allows to set up band-hopping if you are running background services.
|
||||||
|
- APRS now has the ability to show symbols on the map, if a corresponding symbol set has been installed. Check the
|
||||||
|
config!
|
||||||
|
- Debug logging has been disabled in a handful of modules, expect vastly reduced output on the shell.
|
||||||
|
|
||||||
|
**2019-09-13**
|
||||||
|
- New set of APRS-related features
|
||||||
|
- Decode Packet transmissions using [direwolf](https://github.com/wb2osz/direwolf) (1k2 only for now)
|
||||||
|
- APRS packets are mostly decoded and shown both in a new panel and on the map
|
||||||
|
- APRS is also available as a background service
|
||||||
|
- direwolfs I-gate functionality can be enabled, which allows your receiver to work as a receive-only I-gate for the
|
||||||
|
APRS network in the background
|
||||||
|
- Demodulation for background services has been optimized to use less total bandwidth, saving CPU
|
||||||
|
- More metrics have been added; they can be used together with collectd and its curl_json plugin for now, with some
|
||||||
|
limitations.
|
||||||
|
|
||||||
|
**2019-07-21**
|
||||||
|
- Latest Features:
|
||||||
|
- More WSJT-X modes have been added, including the new FT4 mode
|
||||||
|
- I started adding a bandplan feature, the first thing visible is the "dial" indicator that brings you right to the
|
||||||
|
dial frequency for digital modes
|
||||||
|
- fixed some bugs in the websocket communication which broke the map
|
||||||
|
|
||||||
|
**2019-07-13**
|
||||||
|
- Latest Features:
|
||||||
|
- FT8 Integration (using wsjt-x demodulators)
|
||||||
|
- New Map Feature that shows both decoded grid squares from FT8 and Locations decoded from YSF digital voice
|
||||||
|
- New Feature report that will show what functionality is available
|
||||||
|
- There's a new Raspbian SD Card image available (see below)
|
||||||
|
|
||||||
|
**2019-06-30**
|
||||||
|
- I have done some major rework on the openwebrx core, and I am planning to continue adding more features in the near
|
||||||
|
future. Please check this place for updates.
|
||||||
|
- My work has not been accepted into the upstream repository, so you will need to chose between my fork and the official
|
||||||
|
version.
|
||||||
|
- I have enabled the issue tracker on this project, so feel free to file bugs or suggest enhancements there!
|
||||||
|
- This version sports the following new and amazing features:
|
||||||
|
- Support of multiple SDR devices simultaneously
|
||||||
|
- Support for multiple profiles per SDR that allow the user to listen to different frequencies
|
||||||
|
- Support for digital voice decoding
|
||||||
|
- Feature detection that will disable functionality when dependencies are not available (if you're missing the digital
|
||||||
|
buttons, this is probably why)
|
||||||
|
- Raspbian SD Card Images and Docker builds available (see below)
|
||||||
|
- I am currently working on the feature set for a stable release, but you are more than welcome to test development
|
||||||
|
versions!
|
@ -1,15 +0,0 @@
|
|||||||
First of all, thank you for taking the time to contribute to this project!
|
|
||||||
|
|
||||||
Before I can accept your contributions, I need a signed copy of the Individual Contributor License Agreement (ICLA) from you, which is available <a href="ICLA.txt">here</a>.
|
|
||||||
|
|
||||||
The ICLA is needed because it will allow me to dual license the OpenWebRX project under AGPL and a commercial license.
|
|
||||||
I will also apply dual licensing to csdr, but only those parts that are original work (e.g. without the parts enabled by `-DUSE_IMA_ADPCM`; code taken from other projects is clearly separable).
|
|
||||||
|
|
||||||
However, even if there is commercial interest in the projects, I promise to keep them as open as possible, keeping my original intention to provide an open-source web-based SDR receiver software to the amateur radio operators and SDR enthusiasts.
|
|
||||||
|
|
||||||
This contributor agreement is based on the one of Apache Software Foundation, with some modifications. (You can review differences <a href="https://gist.github.com/ha7ilm/9e981006d24659e336c7/revisions">here</a>).
|
|
||||||
When you contribute for the first time, I will send you the ICLA. Replying with only the information requested and the text "I Agree" is sufficient.
|
|
||||||
|
|
||||||
Thanks,
|
|
||||||
|
|
||||||
Andras, HA7ILM
|
|
@ -1,5 +0,0 @@
|
|||||||
This is a list of the great people who contributed code to the OpenWebRX repository. (Names are sorted alphabetically.)
|
|
||||||
|
|
||||||
Gnoxter <gnoxter@linuxlounge.net>
|
|
||||||
John Seamons, ZL/KF6VO <jks@jks.com>
|
|
||||||
|
|
128
ICLA.txt
128
ICLA.txt
@ -1,128 +0,0 @@
|
|||||||
Individual Contributor License Agreement ("Agreement")
|
|
||||||
|
|
||||||
In order to clarify the intellectual property license granted
|
|
||||||
with Contributions from any person or entity, Retzler András
|
|
||||||
(hereinafter referred to as "Project Owner") must have a
|
|
||||||
Contributor License Agreement ("CLA") on file that has
|
|
||||||
been signed by each Contributor, indicating agreement to the license
|
|
||||||
terms below. This license is for your protection as a Contributor as
|
|
||||||
well as the protection of the Project Owner; it does not change your
|
|
||||||
rights to use your own Contributions for any other purpose.
|
|
||||||
Please read this document carefully before signing and keep a copy
|
|
||||||
for your records.
|
|
||||||
|
|
||||||
Full name: ______________________________________________________
|
|
||||||
|
|
||||||
(optional) Public name: _________________________________________
|
|
||||||
|
|
||||||
Mailing Address: ________________________________________________
|
|
||||||
|
|
||||||
________________________________________________
|
|
||||||
|
|
||||||
Country: ______________________________________________________
|
|
||||||
|
|
||||||
(optional) Telephone: ___________________________________________
|
|
||||||
|
|
||||||
E-Mail: ______________________________________________________
|
|
||||||
|
|
||||||
You accept and agree to the following terms and conditions for Your
|
|
||||||
present and future Contributions submitted to the Project Owner.
|
|
||||||
|
|
||||||
Except for the license granted herein to the Project Owner and recipients
|
|
||||||
of software distributed by the Project Owner, You reserve all right, title,
|
|
||||||
and interest in and to Your Contributions.
|
|
||||||
|
|
||||||
1. Definitions.
|
|
||||||
|
|
||||||
"You" (or "Your") shall mean the copyright owner or legal entity
|
|
||||||
authorized by the copyright owner that is making this Agreement
|
|
||||||
with the Project Owner. For legal entities, the entity making a
|
|
||||||
Contribution and all other entities that control, are controlled
|
|
||||||
by, or are under common control with that entity are considered to
|
|
||||||
be a single Contributor. For the purposes of this definition,
|
|
||||||
"control" means (i) the power, direct or indirect, to cause the
|
|
||||||
direction or management of such entity, whether by contract or
|
|
||||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
||||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
||||||
|
|
||||||
"Contribution" shall mean any original work of authorship,
|
|
||||||
including any modifications or additions to an existing work, that
|
|
||||||
is intentionally submitted by You to the Project Owner for inclusion
|
|
||||||
in, or documentation of, any of the products owned or managed by
|
|
||||||
the Project Owner (the "Work"). For the purposes of this definition,
|
|
||||||
"submitted" means any form of electronic, verbal, or written
|
|
||||||
communication sent to the Project Owner or its representatives,
|
|
||||||
including but not limited to communication on electronic mailing
|
|
||||||
lists, source code control systems, and issue tracking systems that
|
|
||||||
are managed by, or on behalf of, the Project Owner for the purpose of
|
|
||||||
discussing and improving the Work, but excluding communication that
|
|
||||||
is conspicuously marked or otherwise designated in writing by You
|
|
||||||
as "Not a Contribution."
|
|
||||||
|
|
||||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
||||||
this Agreement, You hereby grant to the Project Owner and to
|
|
||||||
recipients of software distributed by the Project Owner a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
copyright license to reproduce, prepare derivative works of,
|
|
||||||
publicly display, publicly perform, sublicense, and distribute Your
|
|
||||||
Contributions and such derivative works.
|
|
||||||
|
|
||||||
3. Grant of Patent License. Subject to the terms and conditions of
|
|
||||||
this Agreement, You hereby grant to the Project Owner and to
|
|
||||||
recipients of software distributed by the Project Owner a perpetual,
|
|
||||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
||||||
(except as stated in this section) patent license to make, have
|
|
||||||
made, use, offer to sell, sell, import, and otherwise transfer the
|
|
||||||
Work, where such license applies only to those patent claims
|
|
||||||
licensable by You that are necessarily infringed by Your
|
|
||||||
Contribution(s) alone or by combination of Your Contribution(s)
|
|
||||||
with the Work to which such Contribution(s) was submitted. If any
|
|
||||||
entity institutes patent litigation against You or any other entity
|
|
||||||
(including a cross-claim or counterclaim in a lawsuit) alleging
|
|
||||||
that your Contribution, or the Work to which you have contributed,
|
|
||||||
constitutes direct or contributory patent infringement, then any
|
|
||||||
patent licenses granted to that entity under this Agreement for
|
|
||||||
that Contribution or Work shall terminate as of the date such
|
|
||||||
litigation is filed.
|
|
||||||
|
|
||||||
4. You represent that you are legally entitled to grant the above
|
|
||||||
license. If your employer(s) has rights to intellectual property
|
|
||||||
that you create that includes your Contributions, you represent
|
|
||||||
that you have received permission to make Contributions on behalf
|
|
||||||
of that employer, that your employer has waived such rights for
|
|
||||||
your Contributions to the Project Owner, or that your employer has
|
|
||||||
executed a separate Corporate CLA with the Project Owner.
|
|
||||||
|
|
||||||
5. You represent that each of Your Contributions is Your original
|
|
||||||
creation (see section 7 for submissions on behalf of others). You
|
|
||||||
represent that Your Contribution submissions include complete
|
|
||||||
details of any third-party license or other restriction (including,
|
|
||||||
but not limited to, related patents and trademarks) of which you
|
|
||||||
are personally aware and which are associated with any part of Your
|
|
||||||
Contributions.
|
|
||||||
|
|
||||||
6. You are not expected to provide support for Your Contributions,
|
|
||||||
except to the extent You desire to provide support. You may provide
|
|
||||||
support for free, for a fee, or not at all. Unless required by
|
|
||||||
applicable law or agreed to in writing, You provide Your
|
|
||||||
Contributions on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS
|
|
||||||
OF ANY KIND, either express or implied, including, without
|
|
||||||
limitation, any warranties or conditions of TITLE, NON-
|
|
||||||
INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE.
|
|
||||||
|
|
||||||
7. Should You wish to submit work that is not Your original creation,
|
|
||||||
You may submit it to the Project Owner separately from any
|
|
||||||
Contribution, identifying the complete details of its source and of
|
|
||||||
any license or other restriction (including, but not limited to,
|
|
||||||
related patents, trademarks, and license agreements) of which you
|
|
||||||
are personally aware, and conspicuously marking the work as
|
|
||||||
"Submitted on behalf of a third-party: [named here]".
|
|
||||||
|
|
||||||
8. You agree to notify the Project Owner of any facts or circumstances of
|
|
||||||
which you become aware that would make these representations
|
|
||||||
inaccurate in any respect.
|
|
||||||
|
|
||||||
Please sign: __________________________________ Date: ________________
|
|
||||||
|
|
||||||
Text derived from the Apache Individual Contributor License Agreement
|
|
||||||
("Agreement") V2.0, available at http://apache.org/licenses/icla.txt
|
|
99
README.md
99
README.md
@ -1,76 +1,47 @@
|
|||||||
OpenWebRX
|
OpenWebRX
|
||||||
=========
|
=========
|
||||||
|
|
||||||
[:floppy_disk: Setup guide for Ubuntu](http://blog.sdr.hu/2015/06/30/quick-setup-openwebrx.html) | [:blue_book: Knowledge base on the Wiki](https://github.com/simonyiszk/openwebrx/wiki/) | [:earth_americas: Receivers on SDR.hu](http://sdr.hu/)
|
|
||||||
|
|
||||||
OpenWebRX is a multi-user SDR receiver software with a web interface.
|
OpenWebRX is a multi-user SDR receiver software with a web interface.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
It has the following features:
|
It has the following features:
|
||||||
|
|
||||||
- <a href="https://github.com/simonyiszk/csdr">csdr</a> based demodulators (AM/FM/SSB/CW/BPSK31),
|
- [csdr](https://github.com/jketterl/csdr) based demodulators (AM/FM/SSB/CW/BPSK31/BPSK63)
|
||||||
- filter passband can be set from GUI,
|
- filter passband can be set from GUI
|
||||||
- waterfall display can be shifted back in time,
|
- it extensively uses HTML5 features like WebSocket, Web Audio API, and Canvas
|
||||||
- it extensively uses HTML5 features like WebSocket, Web Audio API, and <canvas>,
|
- it works in Google Chrome, Chromium and Mozilla Firefox
|
||||||
- it works in Google Chrome, Chromium (above version 37) and Mozilla Firefox (above version 28),
|
- supports a wide range of [SDR hardware](https://github.com/jketterl/openwebrx/wiki/Supported-Hardware#sdr-devices)
|
||||||
- currently supports RTL-SDR, HackRF, SDRplay, AirSpy and many other devices, see the <a href="https://github.com/simonyiszk/openwebrx/wiki/">OpenWebRX Wiki</a>,
|
- Multiple SDR devices can be used simultaneously
|
||||||
- it has a 3D waterfall display:
|
- [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag, D-Star, NXDN)
|
||||||
|
- [wsjt-x](https://physics.princeton.edu/pulsar/k1jt/wsjtx.html) based demodulators (FT8, FT4, WSPR, JT65, JT9, FST4,
|
||||||

|
FST4W)
|
||||||
|
- [direwolf](https://github.com/wb2osz/direwolf) based demodulation of APRS packets
|
||||||
**News (2015-08-18)**
|
- [JS8Call](http://js8call.com/) support
|
||||||
- My BSc. thesis written on OpenWebRX is <a href="https://sdr.hu/static/bsc-thesis.pdf">available here.</a>
|
- [DRM](https://github.com/jketterl/openwebrx/wiki/DRM-demodulator-notes) support
|
||||||
- Several bugs were fixed to improve reliability and stability.
|
- [FreeDV](https://github.com/jketterl/openwebrx/wiki/FreeDV-demodulator-notes) support
|
||||||
- OpenWebRX now supports compression of audio and waterfall stream, so the required network uplink bandwidth has been decreased from 2 Mbit/s to about 200 kbit/s per client! (Measured with the default settings. It is also dependent on `fft_size`.)
|
- M17 support based on [m17-cxx-demod](https://github.com/mobilinkd/m17-cxx-demod)
|
||||||
- OpenWebRX now uses <a href="https://github.com/simonyiszk/csdr#sdrjs">sdr.js</a> (*libcsdr* compiled to JavaScript) for some client-side DSP tasks.
|
|
||||||
- Receivers can now be listed on <a href="http://sdr.hu/">SDR.hu</a>.
|
|
||||||
- License for OpenWebRX is now Affero GPL v3.
|
|
||||||
|
|
||||||
**News (2016-02-14)**
|
|
||||||
- The DDC in *csdr* has been manually optimized for ARM NEON, so it runs around 3 times faster on the Raspberry Pi 2 than before.
|
|
||||||
- Also we use *ncat* instead of *rtl_mus*, and it is 3 times faster in some cases.
|
|
||||||
- OpenWebRX now supports URLs like: `http://localhost:8073/#freq=145555000,mod=usb`
|
|
||||||
- UI improvements were made, thanks to John Seamons and Gnoxter.
|
|
||||||
|
|
||||||
**News (2017-04-04)**
|
|
||||||
- *ncat* has been replaced with a custom implementation called *nmux* due to a bug that caused regular crashes on some machines. The *nmux* tool is part of the *csdr* package.
|
|
||||||
- Most consumer SDR devices are supported via <a href="https://github.com/rxseger/rx_tools">rx_tools</a>, see the <a href="https://github.com/simonyiszk/openwebrx/wiki/Using-rx_tools-with-OpenWebRX">OpenWebRX Wiki</a> on that.
|
|
||||||
|
|
||||||
**News (2017-07-12)**
|
|
||||||
- OpenWebRX now has a BPSK31 demodulator and a 3D waterfall display.
|
|
||||||
|
|
||||||
> When upgrading OpenWebRX, please make sure that you also upgrade *csdr*!
|
|
||||||
|
|
||||||
## OpenWebRX servers on SDR.hu
|
|
||||||
|
|
||||||
[SDR.hu](http://sdr.hu) is a site which lists the active, public OpenWebRX servers. Your receiver [can also be part of it](http://sdr.hu/openwebrx), if you want.
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
OpenWebRX currently requires Linux and python 2.7 to run.
|
The following methods of setting up a receiver are currently available:
|
||||||
|
|
||||||
First you will need to install the dependencies:
|
- Raspberry Pi SD card images
|
||||||
|
- Debian repository
|
||||||
|
- Docker images
|
||||||
|
- Manual installation
|
||||||
|
|
||||||
- <a href="https://github.com/simonyiszk/csdr">libcsdr</a>
|
Please checkout the [setup guide on the wiki](https://github.com/jketterl/openwebrx/wiki/Setup-Guide) for more details
|
||||||
- <a href="http://sdr.osmocom.org/trac/wiki/rtl-sdr">rtl-sdr</a>
|
on the respective methods.
|
||||||
|
|
||||||
After cloning this repository and connecting an RTL-SDR dongle to your computer, you can run the server:
|
## Community
|
||||||
|
|
||||||
python openwebrx.py
|
If you have trouble setting up or configuring your receiver, you have some great idea you want to see implemented, or
|
||||||
|
you just generally want to have some OpenWebRX-related chat, come visit us over on
|
||||||
|
[our groups.io group](https://groups.io/g/openwebrx).
|
||||||
|
|
||||||
You can now open the GUI at <a href="http://localhost:8073">http://localhost:8073</a>.
|
If you want to hang out, chat, or get in touch directly with the developers, receiver operators or users, feel free to
|
||||||
|
drop by in [our Discord server](https://discord.gg/gnE9hPz).
|
||||||
Please note that the server is also listening on the following ports (on localhost only):
|
|
||||||
|
|
||||||
- port 4951 for the multi-user I/Q server.
|
|
||||||
|
|
||||||
Now the next step is to customize the parameters of your server in `config_webrx.py`.
|
|
||||||
|
|
||||||
Actually, if you do something cool with OpenWebRX, please drop me a mail:
|
|
||||||
*Andras Retzler, HA7ILM <randras@sdr.hu>*
|
|
||||||
|
|
||||||
## Usage tips
|
## Usage tips
|
||||||
|
|
||||||
@ -80,16 +51,10 @@ The filter envelope can be dragged at its ends and moved around to set the passb
|
|||||||
|
|
||||||
However, if you hold down the shift key, you can drag the center line (BFO) or the whole passband (PBS).
|
However, if you hold down the shift key, you can drag the center line (BFO) or the whole passband (PBS).
|
||||||
|
|
||||||
## Setup tips
|
|
||||||
|
|
||||||
If you have any problems installing OpenWebRX, you should check out the <a href="https://github.com/simonyiszk/openwebrx/wiki">Wiki</a> about it, which has a page on the <a href="https://github.com/simonyiszk/openwebrx/wiki/Common-problems-and-their-solutions">common problems and their solutions</a>.
|
|
||||||
|
|
||||||
Sometimes the actual error message is not at the end of the terminal output, you may have to look at the whole output to find it.
|
|
||||||
|
|
||||||
If you want to run OpenWebRX on a remote server instead of *localhost*, do not forget to set *server_hostname* in `config_webrx.py`.
|
|
||||||
|
|
||||||
## Licensing
|
## Licensing
|
||||||
|
|
||||||
OpenWebRX is available under Affero GPL v3 license (<a href="https://tldrlegal.com/license/gnu-affero-general-public-license-v3-(agpl-3.0)">summary</a>).
|
OpenWebRX is available under Affero GPL v3 license
|
||||||
|
([summary](https://tldrlegal.com/license/gnu-affero-general-public-license-v3-(agpl-3.0))).
|
||||||
|
|
||||||
OpenWebRX is also available under a commercial license on request. Please contact me at the address *<randras@sdr.hu>* for licensing options.
|
OpenWebRX is also available under a commercial license on request. Please contact me at the address
|
||||||
|
*<randras@sdr.hu>* for licensing options.
|
||||||
|
367
bands.json
Normal file
367
bands.json
Normal file
@ -0,0 +1,367 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "2190m",
|
||||||
|
"lower_bound": 135700,
|
||||||
|
"upper_bound": 137800,
|
||||||
|
"frequencies": {
|
||||||
|
"fst4": 136000,
|
||||||
|
"fst4w": 136000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "630m",
|
||||||
|
"lower_bound": 472000,
|
||||||
|
"upper_bound": 479000,
|
||||||
|
"frequencies": {
|
||||||
|
"fst4": 474200,
|
||||||
|
"fst4w": 474200
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "160m",
|
||||||
|
"lower_bound": 1810000,
|
||||||
|
"upper_bound": 2000000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 1838000,
|
||||||
|
"ft8": 1840000,
|
||||||
|
"wspr": 1836600,
|
||||||
|
"jt65": 1838000,
|
||||||
|
"jt9": 1839000,
|
||||||
|
"js8": 1842000,
|
||||||
|
"fst4": 1839000,
|
||||||
|
"fst4w": 1836800
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "80m",
|
||||||
|
"lower_bound": 3500000,
|
||||||
|
"upper_bound": 3800000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 3580000,
|
||||||
|
"ft8": 3573000,
|
||||||
|
"wspr": 3568600,
|
||||||
|
"jt65": 3570000,
|
||||||
|
"jt9": 3572000,
|
||||||
|
"ft4": [3568000, 3575000],
|
||||||
|
"js8": 3578000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "60m",
|
||||||
|
"lower_bound": 5351500,
|
||||||
|
"upper_bound": 5366500,
|
||||||
|
"frequencies": {
|
||||||
|
"ft8": 5357000,
|
||||||
|
"wspr": [5287200, 5364700]
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "40m",
|
||||||
|
"lower_bound": 7000000,
|
||||||
|
"upper_bound": 7200000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 7040000,
|
||||||
|
"ft8": 7074000,
|
||||||
|
"wspr": 7038600,
|
||||||
|
"jt65": 7076000,
|
||||||
|
"jt9": 7078000,
|
||||||
|
"ft4": 7047500,
|
||||||
|
"js8": 7078000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "30m",
|
||||||
|
"lower_bound": 10100000,
|
||||||
|
"upper_bound": 10150000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 10141000,
|
||||||
|
"ft8": 10136000,
|
||||||
|
"wspr": 10138700,
|
||||||
|
"jt65": 10138000,
|
||||||
|
"jt9": 10140000,
|
||||||
|
"ft4": 10140000,
|
||||||
|
"js8": 10130000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "20m",
|
||||||
|
"lower_bound": 14000000,
|
||||||
|
"upper_bound": 14350000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 14070000,
|
||||||
|
"ft8": 14074000,
|
||||||
|
"wspr": 14095600,
|
||||||
|
"jt65": 14076000,
|
||||||
|
"jt9": 14078000,
|
||||||
|
"ft4": 14080000,
|
||||||
|
"js8": 14078000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "17m",
|
||||||
|
"lower_bound": 18068000,
|
||||||
|
"upper_bound": 18168000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 18098000,
|
||||||
|
"ft8": 18100000,
|
||||||
|
"wspr": 18104600,
|
||||||
|
"jt65": 18102000,
|
||||||
|
"jt9": 18104000,
|
||||||
|
"ft4": 18104000,
|
||||||
|
"js8": 18104000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "15m",
|
||||||
|
"lower_bound": 21000000,
|
||||||
|
"upper_bound": 21450000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 21070000,
|
||||||
|
"ft8": 21074000,
|
||||||
|
"wspr": 21094600,
|
||||||
|
"jt65": 21076000,
|
||||||
|
"jt9": 21078000,
|
||||||
|
"ft4": 21140000,
|
||||||
|
"js8": 21078000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "12m",
|
||||||
|
"lower_bound": 24890000,
|
||||||
|
"upper_bound": 24990000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 24920000,
|
||||||
|
"ft8": 24915000,
|
||||||
|
"wspr": 24924600,
|
||||||
|
"jt65": 24917000,
|
||||||
|
"jt9": 24919000,
|
||||||
|
"ft4": 24919000,
|
||||||
|
"js8": 24922000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "10m",
|
||||||
|
"lower_bound": 28000000,
|
||||||
|
"upper_bound": 29700000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": [28070000, 28120000],
|
||||||
|
"ft8": 28074000,
|
||||||
|
"wspr": 28124600,
|
||||||
|
"jt65": 28076000,
|
||||||
|
"jt9": 28078000,
|
||||||
|
"ft4": 28180000,
|
||||||
|
"js8": 28078000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "6m",
|
||||||
|
"lower_bound": 50030000,
|
||||||
|
"upper_bound": 51000000,
|
||||||
|
"frequencies": {
|
||||||
|
"bpsk31": 50305000,
|
||||||
|
"ft8": 50313000,
|
||||||
|
"wspr": 50293000,
|
||||||
|
"jt65": 50310000,
|
||||||
|
"jt9": 50312000,
|
||||||
|
"ft4": 50318000,
|
||||||
|
"js8": 50318000,
|
||||||
|
"q65": [50211000, 50275000]
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "4m",
|
||||||
|
"lower_bound": 70150000,
|
||||||
|
"upper_bound": 70200000,
|
||||||
|
"frequencies": {
|
||||||
|
"wspr": 70091000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "2m",
|
||||||
|
"lower_bound": 144000000,
|
||||||
|
"upper_bound": 146000000,
|
||||||
|
"frequencies": {
|
||||||
|
"wspr": 144489000,
|
||||||
|
"ft8": 144174000,
|
||||||
|
"ft4": 144170000,
|
||||||
|
"jt65": 144120000,
|
||||||
|
"packet": 144800000,
|
||||||
|
"q65": 144116000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "70cm",
|
||||||
|
"lower_bound": 430000000,
|
||||||
|
"upper_bound": 440000000,
|
||||||
|
"frequencies": {
|
||||||
|
"pocsag": 439987500,
|
||||||
|
"q65": 432065000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "23cm",
|
||||||
|
"lower_bound": 1240000000,
|
||||||
|
"upper_bound": 1300000000,
|
||||||
|
"frequencies": {
|
||||||
|
"q65": 1296065000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "13cm",
|
||||||
|
"lower_bound": 2320000000,
|
||||||
|
"upper_bound": 2450000000,
|
||||||
|
"frequencies": {
|
||||||
|
"q65": [2301065000, 2304065000, 2320065000]
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "9cm",
|
||||||
|
"lower_bound": 3400000000,
|
||||||
|
"upper_bound": 3475000000,
|
||||||
|
"frequencies": {
|
||||||
|
"q65": 3400065000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "6cm",
|
||||||
|
"lower_bound": 5650000000,
|
||||||
|
"upper_bound": 5850000000,
|
||||||
|
"frequencies": {
|
||||||
|
"q65": 5760200000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "3cm",
|
||||||
|
"lower_bound": 10000000000,
|
||||||
|
"upper_bound": 10500000000,
|
||||||
|
"frequencies": {
|
||||||
|
"q65": 10368200000
|
||||||
|
},
|
||||||
|
"tags": ["hamradio"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "120m Broadcast",
|
||||||
|
"lower_bound": 2300000,
|
||||||
|
"upper_bound": 2495000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "90m Broadcast",
|
||||||
|
"lower_bound": 3200000,
|
||||||
|
"upper_bound": 3400000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "75m Broadcast",
|
||||||
|
"lower_bound": 3900000,
|
||||||
|
"upper_bound": 4000000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "60m Broadcast",
|
||||||
|
"lower_bound": 4750000,
|
||||||
|
"upper_bound": 4995000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "49m Broadcast",
|
||||||
|
"lower_bound": 5900000,
|
||||||
|
"upper_bound": 6200000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "41m Broadcast",
|
||||||
|
"lower_bound": 7200000,
|
||||||
|
"upper_bound": 7450000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "31m Broadcast",
|
||||||
|
"lower_bound": 9400000,
|
||||||
|
"upper_bound": 9900000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "25m Broadcast",
|
||||||
|
"lower_bound": 11600000,
|
||||||
|
"upper_bound": 12100000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "22m Broadcast",
|
||||||
|
"lower_bound": 13570000,
|
||||||
|
"upper_bound": 13870000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "19m Broadcast",
|
||||||
|
"lower_bound": 15100000,
|
||||||
|
"upper_bound": 15830000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "16m Broadcast",
|
||||||
|
"lower_bound": 17480000,
|
||||||
|
"upper_bound": 17900000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "15m Broadcast",
|
||||||
|
"lower_bound": 18900000,
|
||||||
|
"upper_bound": 19020000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "13m Broadcast",
|
||||||
|
"lower_bound": 21450000,
|
||||||
|
"upper_bound": 21850000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "11m Broadcast",
|
||||||
|
"lower_bound": 25670000,
|
||||||
|
"upper_bound": 26100000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "FM Broadcast",
|
||||||
|
"lower_bound": 87500000,
|
||||||
|
"upper_bound": 108000000,
|
||||||
|
"tags": ["broadcast"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "11m CB",
|
||||||
|
"lower_bound": 26965000,
|
||||||
|
"upper_bound": 27405000,
|
||||||
|
"frequencies": {
|
||||||
|
"js8": 27245000
|
||||||
|
},
|
||||||
|
"tags": ["public"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "PMR446",
|
||||||
|
"lower_bound": 446000000,
|
||||||
|
"upper_bound": 446200000,
|
||||||
|
"tags": ["public"]
|
||||||
|
}
|
||||||
|
]
|
456
config_webrx.py
456
config_webrx.py
@ -6,6 +6,7 @@ config_webrx: configuration options for OpenWebRX
|
|||||||
This file is part of OpenWebRX,
|
This file is part of OpenWebRX,
|
||||||
an open-source SDR receiver software with a web UI.
|
an open-source SDR receiver software with a web UI.
|
||||||
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
|
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
|
||||||
|
Copyright (c) 2019-2021 by Jakob Ketterl <dd5jfk@darc.de>
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU Affero General Public License as
|
it under the terms of the GNU Affero General Public License as
|
||||||
@ -31,59 +32,80 @@ config_webrx: configuration options for OpenWebRX
|
|||||||
and use them for running your web service with OpenWebRX.)
|
and use them for running your web service with OpenWebRX.)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# NOTE: you can find additional information about configuring OpenWebRX in the Wiki:
|
"""
|
||||||
# https://github.com/simonyiszk/openwebrx/wiki
|
DEPRECATION notice
|
||||||
|
|
||||||
# ==== Server settings ====
|
As of OpenWebRX 0.21, the configuration system has been completely overhauled.
|
||||||
web_port=8073
|
The configuration of OpenWebRX should now be done in the new web-based
|
||||||
server_hostname="localhost" # If this contains an incorrect value, the web UI may freeze on load (it can't open websocket)
|
configuration interface exclusively.
|
||||||
max_clients=20
|
|
||||||
|
|
||||||
# ==== Web GUI configuration ====
|
Existing configurations can still be used, but their values will be migrated
|
||||||
receiver_name="[Callsign]"
|
to the new storage infrastructure as soon as the web configuration is used to
|
||||||
receiver_location="Budapest, Hungary"
|
edit them.
|
||||||
receiver_qra="JN97ML"
|
|
||||||
receiver_asl=200
|
The new configuration storage is not intended to be edited manually.
|
||||||
receiver_ant="Longwire"
|
|
||||||
receiver_device="RTL-SDR"
|
|
||||||
receiver_admin="example@example.com"
|
|
||||||
receiver_gps=(47.000000,19.000000)
|
|
||||||
photo_height=350
|
|
||||||
photo_title="Panorama of Budapest from Schönherz Zoltán Dormitory"
|
|
||||||
photo_desc="""
|
|
||||||
You can add your own background photo and receiver information.<br />
|
|
||||||
Receiver is operated by: <a href="mailto:%[RX_ADMIN]">%[RX_ADMIN]</a><br/>
|
|
||||||
Device: %[RX_DEVICE]<br />
|
|
||||||
Antenna: %[RX_ANT]<br />
|
|
||||||
Website: <a href="http://localhost" target="_blank">http://localhost</a>
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# ==== sdr.hu listing ====
|
# configuration version. please only modify if you're able to perform the associated migration steps.
|
||||||
# If you want your ham receiver to be listed publicly on sdr.hu, then take the following steps:
|
version = 7
|
||||||
# 1. Register at: http://sdr.hu/register
|
|
||||||
# 2. You will get an unique key by email. Copy it and paste here:
|
# NOTE: you can find additional information about configuring OpenWebRX in the Wiki:
|
||||||
sdrhu_key = ""
|
# https://github.com/jketterl/openwebrx/wiki/Configuration-guide
|
||||||
# 3. Set this setting to True to enable listing:
|
|
||||||
sdrhu_public_listing = False
|
# ==== Server settings ====
|
||||||
|
#max_clients = 20
|
||||||
|
|
||||||
|
# ==== Web GUI configuration ====
|
||||||
|
#receiver_name = "[Callsign]"
|
||||||
|
#receiver_location = "Budapest, Hungary"
|
||||||
|
#receiver_asl = 200
|
||||||
|
#receiver_admin = "example@example.com"
|
||||||
|
#receiver_gps = {"lat": 47.000000, "lon": 19.000000}
|
||||||
|
#photo_title = "Panorama of Budapest from Schönherz Zoltán Dormitory"
|
||||||
|
# photo_desc allows you to put pretty much any HTML you like into the receiver description.
|
||||||
|
# The lines below should give you some examples of what's possible.
|
||||||
|
#photo_desc = """
|
||||||
|
#You can add your own background photo and receiver information.<br />
|
||||||
|
#Receiver is operated by: <a href="mailto:openwebrx@localhost" target="_blank">Receiver Operator</a><br/>
|
||||||
|
#Device: Receiver Device<br />
|
||||||
|
#Antenna: Receiver Antenna<br />
|
||||||
|
#Website: <a href="http://localhost" target="_blank">http://localhost</a>
|
||||||
|
#"""
|
||||||
|
|
||||||
|
# ==== Public receiver listings ====
|
||||||
|
# You can publish your receiver on online receiver directories, like https://www.receiverbook.de
|
||||||
|
# You will receive a receiver key from the directory that will authenticate you as the operator of this receiver.
|
||||||
|
# Please note that you not share your receiver keys publicly since anyone that obtains your receiver key can take over
|
||||||
|
# your public listing.
|
||||||
|
# Your receiver keys should be placed into this array:
|
||||||
|
#receiver_keys = []
|
||||||
|
# If you list your receiver on multiple sites, you can place all your keys into the array above, or you can append
|
||||||
|
# keys to the arraylike this:
|
||||||
|
# receiver_keys += ["my-receiver-key"]
|
||||||
|
|
||||||
|
# If you're not sure, simply copy & paste the code you received from your listing site below this line:
|
||||||
|
|
||||||
# ==== DSP/RX settings ====
|
# ==== DSP/RX settings ====
|
||||||
fft_fps=9
|
#fft_fps = 9
|
||||||
fft_size=4096 #Should be power of 2
|
#fft_size = 4096 # Should be power of 2
|
||||||
fft_voverlap_factor=0.3 #If fft_voverlap_factor is above 0, multiple FFTs will be used for creating a line on the diagram.
|
#fft_voverlap_factor = (
|
||||||
|
# 0.3 # If fft_voverlap_factor is above 0, multiple FFTs will be used for creating a line on the diagram.
|
||||||
|
#)
|
||||||
|
|
||||||
# samp_rate = 250000
|
#audio_compression = "adpcm" # valid values: "adpcm", "none"
|
||||||
samp_rate = 2400000
|
#fft_compression = "adpcm" # valid values: "adpcm", "none"
|
||||||
center_freq = 144250000
|
|
||||||
rf_gain = 5 #in dB. For an RTL-SDR, rf_gain=0 will set the tuner to auto gain mode, else it will be in manual gain mode.
|
|
||||||
ppm = 0
|
|
||||||
|
|
||||||
audio_compression="adpcm" #valid values: "adpcm", "none"
|
# Tau setting for WFM (broadcast FM) deemphasis\
|
||||||
fft_compression="adpcm" #valid values: "adpcm", "none"
|
# Quote from wikipedia https://en.wikipedia.org/wiki/FM_broadcasting#Pre-emphasis_and_de-emphasis
|
||||||
|
# "In most of the world a 50 µs time constant is used. In the Americas and South Korea, 75 µs is used"
|
||||||
|
# Enable one of the following lines, depending on your location:
|
||||||
|
# wfm_deemphasis_tau = 75e-6 # for US and South Korea
|
||||||
|
#wfm_deemphasis_tau = 50e-6 # for the rest of the world
|
||||||
|
|
||||||
digimodes_enable=True #Decoding digimodes come with higher CPU usage.
|
#digimodes_fft_size = 2048
|
||||||
digimodes_fft_size=1024
|
|
||||||
|
|
||||||
start_rtl_thread=True
|
# enables lookup of DMR ids using the radioid api
|
||||||
|
#digital_voice_dmr_id_lookup = True
|
||||||
|
|
||||||
"""
|
"""
|
||||||
Note: if you experience audio underruns while CPU usage is 100%, you can:
|
Note: if you experience audio underruns while CPU usage is 100%, you can:
|
||||||
@ -96,121 +118,269 @@ Note: if you experience audio underruns while CPU usage is 100%, you can:
|
|||||||
# ==== I/Q sources ====
|
# ==== I/Q sources ====
|
||||||
# (Uncomment the appropriate by removing # characters at the beginning of the corresponding lines.)
|
# (Uncomment the appropriate by removing # characters at the beginning of the corresponding lines.)
|
||||||
|
|
||||||
#################################################################################################
|
###############################################################################
|
||||||
# Is my SDR hardware supported? #
|
# Is my SDR hardware supported? #
|
||||||
# Check here: https://github.com/simonyiszk/openwebrx/wiki#guides-for-receiver-hardware-support #
|
# Check here: https://github.com/jketterl/openwebrx/wiki/Supported-Hardware #
|
||||||
#################################################################################################
|
###############################################################################
|
||||||
|
|
||||||
# You can use other SDR hardware as well, by giving your own command that outputs the I/Q samples... Some examples of configuration are available here (default is RTL-SDR):
|
# Currently supported types of sdr receivers:
|
||||||
|
# "rtl_sdr", "rtl_sdr_soapy", "sdrplay", "hackrf", "airspy", "airspyhf", "fifi_sdr",
|
||||||
|
# "perseussdr", "lime_sdr", "pluto_sdr", "soapy_remote", "hpsdr", "uhd",
|
||||||
|
# "radioberry", "fcdpp", "rtl_tcp", "sddc", "runds"
|
||||||
|
|
||||||
# >> RTL-SDR via rtl_sdr
|
# For more details on specific types, please checkout the wiki:
|
||||||
start_rtl_command="rtl_sdr -s {samp_rate} -f {center_freq} -p {ppm} -g {rf_gain} -".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate, ppm=ppm)
|
# https://github.com/jketterl/openwebrx/wiki/Supported-Hardware#sdr-devices
|
||||||
format_conversion="csdr convert_u8_f"
|
|
||||||
|
|
||||||
#lna_gain=8
|
#sdrs = {
|
||||||
#rf_amp=1
|
# "rtlsdr": {
|
||||||
#start_rtl_command="hackrf_transfer -s {samp_rate} -f {center_freq} -g {rf_gain} -l{lna_gain} -a{rf_amp} -r-".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate, ppm=ppm, rf_amp=rf_amp, lna_gain=lna_gain)
|
# "name": "RTL-SDR USB Stick",
|
||||||
#format_conversion="csdr convert_s8_f"
|
# "type": "rtl_sdr",
|
||||||
"""
|
# "ppm": 0,
|
||||||
To use a HackRF, compile the HackRF host tools from its "stdout" branch:
|
# # you can change this if you use an upconverter. formula is:
|
||||||
git clone https://github.com/mossmann/hackrf/
|
# # center_freq + lfo_offset = actual frequency on the sdr
|
||||||
cd hackrf
|
# # "lfo_offset": 0,
|
||||||
git fetch
|
# "profiles": {
|
||||||
git checkout origin/stdout
|
# "70cm": {
|
||||||
cd host
|
# "name": "70cm Relais",
|
||||||
mkdir build
|
# "center_freq": 438800000,
|
||||||
cd build
|
# "rf_gain": 29,
|
||||||
cmake .. -DINSTALL_UDEV_RULES=ON
|
# "samp_rate": 2400000,
|
||||||
make
|
# "start_freq": 439275000,
|
||||||
sudo make install
|
# "start_mod": "nfm",
|
||||||
"""
|
# },
|
||||||
|
# "2m": {
|
||||||
# >> Sound card SDR (needs ALSA)
|
# "name": "2m komplett",
|
||||||
# I did not have the chance to properly test it.
|
# "center_freq": 145000000,
|
||||||
#samp_rate = 96000
|
# "rf_gain": 29,
|
||||||
#start_rtl_command="arecord -f S16_LE -r {samp_rate} -c2 -".format(samp_rate=samp_rate)
|
# "samp_rate": 2048000,
|
||||||
#format_conversion="csdr convert_s16_f | csdr gain_ff 30"
|
# "start_freq": 145725000,
|
||||||
|
# "start_mod": "nfm",
|
||||||
# >> /dev/urandom test signal source
|
# },
|
||||||
# samp_rate = 2400000
|
# },
|
||||||
# start_rtl_command="cat /dev/urandom | (pv -qL `python -c 'print int({samp_rate} * 2.2)'` 2>&1)".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate)
|
# },
|
||||||
# format_conversion="csdr convert_u8_f"
|
# "airspy": {
|
||||||
|
# "name": "Airspy HF+",
|
||||||
# >> Pre-recorded raw I/Q file as signal source
|
# "type": "airspyhf",
|
||||||
# You will have to correctly specify: samp_rate, center_freq, format_conversion in order to correctly play an I/Q file.
|
# "ppm": 0,
|
||||||
#start_rtl_command="(while true; do cat my_iq_file.raw; done) | csdr flowcontrol {sr} 20 ".format(sr=samp_rate*2*1.05)
|
# "rf_gain": "auto",
|
||||||
#format_conversion="csdr convert_u8_f"
|
# "profiles": {
|
||||||
|
# "20m": {
|
||||||
#>> The rx_sdr command works with a variety of SDR harware: RTL-SDR, HackRF, SDRplay, UHD, Airspy, Red Pitaya, audio devices, etc.
|
# "name": "20m",
|
||||||
# It will auto-detect your SDR hardware if the following tools are installed:
|
# "center_freq": 14150000,
|
||||||
# * the vendor provided driver and library,
|
# "samp_rate": 384000,
|
||||||
# * the vendor-specific SoapySDR wrapper library,
|
# "start_freq": 14070000,
|
||||||
# * and SoapySDR itself.
|
# "start_mod": "usb",
|
||||||
# Check out this article on the OpenWebRX Wiki: https://github.com/simonyiszk/openwebrx/wiki/Using-rx_tools-with-OpenWebRX/
|
# },
|
||||||
#start_rtl_command="rx_sdr -F CF32 -s {samp_rate} -f {center_freq} -p {ppm} -g {rf_gain} -".format(rf_gain=rf_gain, center_freq=center_freq, samp_rate=samp_rate, ppm=ppm)
|
# "30m": {
|
||||||
#format_conversion=""
|
# "name": "30m",
|
||||||
|
# "center_freq": 10125000,
|
||||||
# >> gr-osmosdr signal source using GNU Radio (follow this guide: https://github.com/simonyiszk/openwebrx/wiki/Using-GrOsmoSDR-as-signal-source)
|
# "samp_rate": 192000,
|
||||||
#start_rtl_command="cat /tmp/osmocom_fifo"
|
# "start_freq": 10142000,
|
||||||
#format_conversion=""
|
# "start_mod": "usb",
|
||||||
|
# },
|
||||||
# ==== Misc settings ====
|
# "40m": {
|
||||||
|
# "name": "40m",
|
||||||
shown_center_freq = center_freq #you can change this if you use an upconverter
|
# "center_freq": 7100000,
|
||||||
|
# "samp_rate": 256000,
|
||||||
client_audio_buffer_size = 5
|
# "start_freq": 7070000,
|
||||||
#increasing client_audio_buffer_size will:
|
# "start_mod": "lsb",
|
||||||
# - also increase the latency
|
# },
|
||||||
# - decrease the chance of audio underruns
|
# "80m": {
|
||||||
|
# "name": "80m",
|
||||||
start_freq = center_freq
|
# "center_freq": 3650000,
|
||||||
start_mod = "nfm" #nfm, am, lsb, usb, cw
|
# "samp_rate": 384000,
|
||||||
|
# "start_freq": 3570000,
|
||||||
iq_server_port = 4951 #TCP port for ncat to listen on. It will send I/Q data over its connections, for internal use in OpenWebRX. It is only accessible from the localhost by default.
|
# "start_mod": "lsb",
|
||||||
|
# },
|
||||||
#access_log = "~/openwebrx_access.log"
|
# "49m": {
|
||||||
|
# "name": "49m Broadcast",
|
||||||
|
# "center_freq": 6050000,
|
||||||
|
# "samp_rate": 384000,
|
||||||
|
# "start_freq": 6070000,
|
||||||
|
# "start_mod": "am",
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
# "sdrplay": {
|
||||||
|
# "name": "SDRPlay RSP2",
|
||||||
|
# "type": "sdrplay",
|
||||||
|
# "ppm": 0,
|
||||||
|
# "antenna": "Antenna A",
|
||||||
|
# "profiles": {
|
||||||
|
# "20m": {
|
||||||
|
# "name": "20m",
|
||||||
|
# "center_freq": 14150000,
|
||||||
|
# "rf_gain": 0,
|
||||||
|
# "samp_rate": 500000,
|
||||||
|
# "start_freq": 14070000,
|
||||||
|
# "start_mod": "usb",
|
||||||
|
# },
|
||||||
|
# "30m": {
|
||||||
|
# "name": "30m",
|
||||||
|
# "center_freq": 10125000,
|
||||||
|
# "rf_gain": 0,
|
||||||
|
# "samp_rate": 250000,
|
||||||
|
# "start_freq": 10142000,
|
||||||
|
# "start_mod": "usb",
|
||||||
|
# },
|
||||||
|
# "40m": {
|
||||||
|
# "name": "40m",
|
||||||
|
# "center_freq": 7100000,
|
||||||
|
# "rf_gain": 0,
|
||||||
|
# "samp_rate": 500000,
|
||||||
|
# "start_freq": 7070000,
|
||||||
|
# "start_mod": "lsb",
|
||||||
|
# },
|
||||||
|
# "80m": {
|
||||||
|
# "name": "80m",
|
||||||
|
# "center_freq": 3650000,
|
||||||
|
# "rf_gain": 0,
|
||||||
|
# "samp_rate": 500000,
|
||||||
|
# "start_freq": 3570000,
|
||||||
|
# "start_mod": "lsb",
|
||||||
|
# },
|
||||||
|
# "49m": {
|
||||||
|
# "name": "49m Broadcast",
|
||||||
|
# "center_freq": 6000000,
|
||||||
|
# "rf_gain": 0,
|
||||||
|
# "samp_rate": 500000,
|
||||||
|
# "start_freq": 6070000,
|
||||||
|
# "start_mod": "am",
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
# },
|
||||||
|
#}
|
||||||
|
|
||||||
# ==== Color themes ====
|
# ==== Color themes ====
|
||||||
|
|
||||||
#A guide is available to help you set these values: https://github.com/simonyiszk/openwebrx/wiki/Calibrating-waterfall-display-levels
|
### google turbo colormap (see: https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html)
|
||||||
|
#waterfall_scheme = "GoogleTurboWaterfall"
|
||||||
|
|
||||||
|
### original theme by teejez:
|
||||||
|
#waterfall_scheme = "TeejeezWaterfall"
|
||||||
|
|
||||||
### default theme by teejez:
|
|
||||||
waterfall_colors = "[0x000000ff,0x0000ffff,0x00ffffff,0x00ff00ff,0xffff00ff,0xff0000ff,0xff00ffff,0xffffffff]"
|
|
||||||
waterfall_min_level = -88 #in dB
|
|
||||||
waterfall_max_level = -20
|
|
||||||
waterfall_auto_level_margin = (5, 40)
|
|
||||||
### old theme by HA7ILM:
|
### old theme by HA7ILM:
|
||||||
#waterfall_colors = "[0x000000ff,0x2e6893ff, 0x69a5d0ff, 0x214b69ff, 0x9dc4e0ff, 0xfff775ff, 0xff8a8aff, 0xb20000ff]"
|
#waterfall_scheme = "Ha7ilmWaterfall"
|
||||||
#waterfall_min_level = -115 #in dB
|
|
||||||
#waterfall_max_level = 0
|
|
||||||
#waterfall_auto_level_margin = (20, 30)
|
|
||||||
##For the old colors, you might also want to set [fft_voverlap_factor] to 0.
|
##For the old colors, you might also want to set [fft_voverlap_factor] to 0.
|
||||||
|
|
||||||
|
### custom waterfall schemes can be configured like this:
|
||||||
|
#waterfall_scheme = "CustomWaterfall"
|
||||||
|
#waterfall_colors = [0x0000FF, 0x00FF00, 0xFF0000]
|
||||||
|
|
||||||
|
### Waterfall calibration
|
||||||
|
#waterfall_levels = {"min": -88, "max": -20} # in dB
|
||||||
|
|
||||||
|
#waterfall_auto_levels = {"min": 3, "max": 10}
|
||||||
|
#waterfall_auto_min_range = 50
|
||||||
|
|
||||||
# Note: When the auto waterfall level button is clicked, the following happens:
|
# Note: When the auto waterfall level button is clicked, the following happens:
|
||||||
# [waterfall_min_level] = [current_min_power_level] - [waterfall_auto_level_margin[0]]
|
# [waterfall_levels.min] = [current_min_power_level] - [waterfall_auto_levels["min"]]
|
||||||
# [waterfall_max_level] = [current_max_power_level] + [waterfall_auto_level_margin[1]]
|
# [waterfall_levels.max] = [current_max_power_level] + [waterfall_auto_levels["max"]]
|
||||||
#
|
#
|
||||||
# ___|____________________________________|____________________________________|____________________________________|___> signal power
|
# ___|__________________________________|____________________________________|__________________________________|___> signal power
|
||||||
# \_waterfall_auto_level_margin[0]_/ |__ current_min_power_level | \_waterfall_auto_level_margin[1]_/
|
# \_waterfall_auto_levels["min"]_/ |__ current_min_power_level | \_waterfall_auto_levels["max"]_/
|
||||||
# current_max_power_level __|
|
# current_max_power_level __|
|
||||||
|
|
||||||
# 3D view settings
|
# This setting allows you to modify the precision of the frequency displays in OpenWebRX.
|
||||||
mathbox_waterfall_frequency_resolution = 128 #bins
|
# Set this to exponent of 10 to select the most precise digit in Hz you'd like to see
|
||||||
mathbox_waterfall_history_length = 10 #seconds
|
# examples:
|
||||||
mathbox_waterfall_colors = "[0x000000ff,0x2e6893ff, 0x69a5d0ff, 0x214b69ff, 0x9dc4e0ff, 0xfff775ff, 0xff8a8aff, 0xb20000ff]"
|
# a value of 2 selects 10^2 = 100Hz tuning precision (default):
|
||||||
|
#tuning_precision = 2
|
||||||
|
# a value of 1 selects 10^1 = 10Hz tuning precision:
|
||||||
|
#tuning_precision = 1
|
||||||
|
|
||||||
# === Experimental settings ===
|
# This setting tells the auto-squelch the offset to add to the current signal level to use as the new squelch level.
|
||||||
#Warning! The settings below are very experimental.
|
# Lowering this setting will give you a more sensitive squelch, but it may also cause unwanted squelch openings when
|
||||||
csdr_dynamic_bufsize = False # This allows you to change the buffering mode of csdr.
|
# using the auto squelch.
|
||||||
csdr_print_bufsizes = False # This prints the buffer sizes used for csdr processes.
|
#squelch_auto_margin = 10 # in dB
|
||||||
csdr_through = False # Setting this True will print out how much data is going into the DSP chains.
|
|
||||||
|
|
||||||
nmux_memory = 50 #in megabytes. This sets the approximate size of the circular buffer used by nmux.
|
#google_maps_api_key = ""
|
||||||
|
|
||||||
#Look up external IP address automatically from icanhazip.com, and use it as [server_hostname]
|
# how long should positions be visible on the map?
|
||||||
"""
|
# they will start fading out after half of that
|
||||||
print "[openwebrx-config] Detecting external IP address..."
|
# in seconds; default: 2 hours
|
||||||
import urllib2
|
#map_position_retention_time = 2 * 60 * 60
|
||||||
server_hostname=urllib2.urlopen("http://icanhazip.com").read()[:-1]
|
|
||||||
print "[openwebrx-config] External IP address detected:", server_hostname
|
# decoder queue configuration
|
||||||
"""
|
# due to the nature of some operating modes (ft8, ft8, jt9, jt65, wspr and js8), the data is recorded for a given amount
|
||||||
|
# of time (6 seconds up to 2 minutes) and decoded at the end. this can lead to very high peak loads.
|
||||||
|
# to mitigate this, the recordings will be queued and processed in sequence.
|
||||||
|
# the number of workers will limit the total amount of work (one worker will losely occupy one cpu / thread)
|
||||||
|
#decoding_queue_workers = 2
|
||||||
|
# the maximum queue length will cause decodes to be dumped if the workers cannot keep up
|
||||||
|
# if you are running background services, make sure this number is high enough to accept the task influx during peaks
|
||||||
|
# i.e. this should be higher than the number of decoding services running at the same time
|
||||||
|
#decoding_queue_length = 10
|
||||||
|
|
||||||
|
# wsjt decoding depth will allow more results, but will also consume more cpu
|
||||||
|
#wsjt_decoding_depth = 3
|
||||||
|
# can also be set for each mode separately
|
||||||
|
# jt65 seems to be somewhat prone to erroneous decodes, this setting handles that to some extent
|
||||||
|
#wsjt_decoding_depths = {"jt65": 1}
|
||||||
|
|
||||||
|
# FST4 can be transmitted in different intervals. This setting determines which intervals will be decoded.
|
||||||
|
# available values (in seconds): 15, 30, 60, 120, 300, 900, 1800
|
||||||
|
#fst4_enabled_intervals = [15, 30]
|
||||||
|
|
||||||
|
# FST4W can be transmitted in different intervals. This setting determines which intervals will be decoded.
|
||||||
|
# available values (in seconds): 120, 300, 900, 1800
|
||||||
|
#fst4w_enabled_intervals = [120, 300]
|
||||||
|
|
||||||
|
# Q65 allows many combinations of intervals and submodes. This setting determines which combinations will be decoded.
|
||||||
|
# Please use the mode letter followed by the decode interval in seconds to specify the combinations. For example:
|
||||||
|
#q65_enabled_combinations = ["A30", "E120", "C60"]
|
||||||
|
|
||||||
|
# JS8 comes in different speeds: normal, slow, fast, turbo. This setting controls which ones are enabled.
|
||||||
|
#js8_enabled_profiles = ["normal", "slow"]
|
||||||
|
# JS8 decoding depth; higher value will get more results, but will also consume more cpu
|
||||||
|
#js8_decoding_depth = 3
|
||||||
|
|
||||||
|
# Enable background service for decoding digital data. You can find more information at:
|
||||||
|
# https://github.com/jketterl/openwebrx/wiki/Background-decoding
|
||||||
|
#services_enabled = False
|
||||||
|
#services_decoders = ["ft8", "ft4", "wspr", "packet"]
|
||||||
|
|
||||||
|
# === aprs igate settings ===
|
||||||
|
# If you want to share your APRS decodes with the aprs network, configure these settings accordingly.
|
||||||
|
# Make sure that you have set services_enabled to true and customize services_decoders to your needs.
|
||||||
|
#aprs_callsign = "N0CALL"
|
||||||
|
#aprs_igate_enabled = False
|
||||||
|
#aprs_igate_server = "euro.aprs2.net"
|
||||||
|
#aprs_igate_password = ""
|
||||||
|
# beacon uses the receiver_gps setting, so if you enable this, make sure the location is correct there
|
||||||
|
#aprs_igate_beacon = False
|
||||||
|
|
||||||
|
# Uncomment the following to customize gateway beacon details reported to the aprs network
|
||||||
|
# Plese see Dire Wolf's documentation on PBEACON configuration for complete details:
|
||||||
|
# https://github.com/wb2osz/direwolf/raw/master/doc/User-Guide.pdf
|
||||||
|
|
||||||
|
# Symbol in its two-character form as specified by the APRS spec at http://www.aprs.org/symbols/symbols-new.txt
|
||||||
|
# Default: Receive only IGate (do not send msgs back to RF)
|
||||||
|
# aprs_igate_symbol = "R&"
|
||||||
|
|
||||||
|
# Custom comment about igate
|
||||||
|
# Default: OpenWebRX APRS gateway
|
||||||
|
# aprs_igate_comment = "OpenWebRX APRS gateway"
|
||||||
|
|
||||||
|
# Antenna Height and Gain details
|
||||||
|
# Unspecified by default
|
||||||
|
# Antenna height above average terrain (HAAT) in meters
|
||||||
|
# aprs_igate_height = "5"
|
||||||
|
# Antenna gain in dBi
|
||||||
|
# aprs_igate_gain = "0"
|
||||||
|
# Antenna direction (N, NE, E, SE, S, SW, W, NW). Omnidirectional by default
|
||||||
|
# aprs_igate_dir = "NE"
|
||||||
|
|
||||||
|
# === PSK Reporter settings ===
|
||||||
|
# enable this if you want to upload all ft8, ft4 etc spots to pskreporter.info
|
||||||
|
# this also uses the receiver_gps setting from above, so make sure it contains a correct locator
|
||||||
|
#pskreporter_enabled = False
|
||||||
|
#pskreporter_callsign = "N0CALL"
|
||||||
|
# optional antenna information, uncomment to enable
|
||||||
|
#pskreporter_antenna_information = "Dipole"
|
||||||
|
|
||||||
|
# === WSPRNet reporting settings
|
||||||
|
# enable this if you want to upload WSPR spots to wsprnet.ort
|
||||||
|
# in addition to these settings also make sure that receiver_gps contains your correct location
|
||||||
|
#wsprnet_enabled = False
|
||||||
|
#wsprnet_callsign = "N0CALL"
|
||||||
|
424
csdr.py
424
csdr.py
@ -1,424 +0,0 @@
|
|||||||
"""
|
|
||||||
OpenWebRX csdr plugin: do the signal processing with csdr
|
|
||||||
|
|
||||||
This file is part of OpenWebRX,
|
|
||||||
an open-source SDR receiver software with a web UI.
|
|
||||||
Copyright (c) 2013-2015 by Andras Retzler <randras@sdr.hu>
|
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
|
||||||
it under the terms of the GNU Affero General Public License as
|
|
||||||
published by the Free Software Foundation, either version 3 of the
|
|
||||||
License, or (at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License
|
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
"""
|
|
||||||
|
|
||||||
import subprocess
|
|
||||||
import time
|
|
||||||
import os
|
|
||||||
import code
|
|
||||||
import signal
|
|
||||||
import fcntl
|
|
||||||
|
|
||||||
class dsp:
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
self.samp_rate = 250000
|
|
||||||
self.output_rate = 11025 #this is default, and cannot be set at the moment
|
|
||||||
self.fft_size = 1024
|
|
||||||
self.fft_fps = 5
|
|
||||||
self.offset_freq = 0
|
|
||||||
self.low_cut = -4000
|
|
||||||
self.high_cut = 4000
|
|
||||||
self.bpf_transition_bw = 320 #Hz, and this is a constant
|
|
||||||
self.ddc_transition_bw_rate = 0.15 # of the IF sample rate
|
|
||||||
self.running = False
|
|
||||||
self.secondary_processes_running = False
|
|
||||||
self.audio_compression = "none"
|
|
||||||
self.fft_compression = "none"
|
|
||||||
self.demodulator = "nfm"
|
|
||||||
self.name = "csdr"
|
|
||||||
self.format_conversion = "csdr convert_u8_f"
|
|
||||||
self.base_bufsize = 512
|
|
||||||
self.nc_port = 4951
|
|
||||||
self.csdr_dynamic_bufsize = False
|
|
||||||
self.csdr_print_bufsizes = False
|
|
||||||
self.csdr_through = False
|
|
||||||
self.squelch_level = 0
|
|
||||||
self.fft_averages = 50
|
|
||||||
self.iqtee = False
|
|
||||||
self.iqtee2 = False
|
|
||||||
self.secondary_demodulator = None
|
|
||||||
self.secondary_fft_size = 1024
|
|
||||||
self.secondary_process_fft = None
|
|
||||||
self.secondary_process_demod = None
|
|
||||||
self.pipe_names=["bpf_pipe", "shift_pipe", "squelch_pipe", "smeter_pipe", "iqtee_pipe", "iqtee2_pipe"]
|
|
||||||
self.secondary_pipe_names=["secondary_shift_pipe"]
|
|
||||||
self.secondary_offset_freq = 1000
|
|
||||||
|
|
||||||
def chain(self,which):
|
|
||||||
any_chain_base="nc -v 127.0.0.1 {nc_port} | "
|
|
||||||
if self.csdr_dynamic_bufsize: any_chain_base+="csdr setbuf {start_bufsize} | "
|
|
||||||
if self.csdr_through: any_chain_base+="csdr through | "
|
|
||||||
any_chain_base+=self.format_conversion+(" | " if self.format_conversion!="" else "") ##"csdr flowcontrol {flowcontrol} auto 1.5 10 | "
|
|
||||||
if which == "fft":
|
|
||||||
fft_chain_base = any_chain_base+"csdr fft_cc {fft_size} {fft_block_size} | " + \
|
|
||||||
("csdr logpower_cf -70 | " if self.fft_averages == 0 else "csdr logaveragepower_cf -70 {fft_size} {fft_averages} | ") + \
|
|
||||||
"csdr fft_exchange_sides_ff {fft_size}"
|
|
||||||
if self.fft_compression=="adpcm":
|
|
||||||
return fft_chain_base+" | csdr compress_fft_adpcm_f_u8 {fft_size}"
|
|
||||||
else:
|
|
||||||
return fft_chain_base
|
|
||||||
chain_begin=any_chain_base+"csdr shift_addition_cc --fifo {shift_pipe} | csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING | csdr bandpass_fir_fft_cc --fifo {bpf_pipe} {bpf_transition_bw} HAMMING | csdr squelch_and_smeter_cc --fifo {squelch_pipe} --outfifo {smeter_pipe} 5 1 | "
|
|
||||||
if self.secondary_demodulator:
|
|
||||||
chain_begin+="csdr tee {iqtee_pipe} | "
|
|
||||||
chain_begin+="csdr tee {iqtee2_pipe} | "
|
|
||||||
chain_end = ""
|
|
||||||
if self.audio_compression=="adpcm":
|
|
||||||
chain_end = " | csdr encode_ima_adpcm_i16_u8"
|
|
||||||
if which == "nfm": return chain_begin + "csdr fmdemod_quadri_cf | csdr limit_ff | csdr old_fractional_decimator_ff {last_decimation} | csdr deemphasis_nfm_ff 11025 | csdr fastagc_ff 1024 | csdr convert_f_s16"+chain_end
|
|
||||||
elif which == "am": return chain_begin + "csdr amdemod_cf | csdr fastdcblock_ff | csdr old_fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_s16"+chain_end
|
|
||||||
elif which == "ssb": return chain_begin + "csdr realpart_cf | csdr old_fractional_decimator_ff {last_decimation} | csdr agc_ff | csdr limit_ff | csdr convert_f_s16"+chain_end
|
|
||||||
|
|
||||||
def secondary_chain(self, which):
|
|
||||||
secondary_chain_base="cat {input_pipe} | "
|
|
||||||
if which == "fft":
|
|
||||||
return secondary_chain_base+"csdr realpart_cf | csdr fft_fc {secondary_fft_input_size} {secondary_fft_block_size} | csdr logpower_cf -70 " + (" | csdr compress_fft_adpcm_f_u8 {secondary_fft_size}" if self.fft_compression=="adpcm" else "")
|
|
||||||
elif which == "bpsk31":
|
|
||||||
return secondary_chain_base + "csdr shift_addition_cc --fifo {secondary_shift_pipe} | " + \
|
|
||||||
"csdr bandpass_fir_fft_cc $(csdr '=-(31.25)/{if_samp_rate}') $(csdr '=(31.25)/{if_samp_rate}') $(csdr '=31.25/{if_samp_rate}') | " + \
|
|
||||||
"csdr simple_agc_cc 0.001 0.5 | " + \
|
|
||||||
"csdr timing_recovery_cc GARDNER {secondary_samples_per_bits} 0.5 2 --add_q | " + \
|
|
||||||
"CSDR_FIXED_BUFSIZE=1 csdr dbpsk_decoder_c_u8 | " + \
|
|
||||||
"CSDR_FIXED_BUFSIZE=1 csdr psk31_varicode_decoder_u8_u8"
|
|
||||||
|
|
||||||
def set_secondary_demodulator(self, what):
|
|
||||||
self.secondary_demodulator = what
|
|
||||||
|
|
||||||
def secondary_fft_block_size(self):
|
|
||||||
return (self.samp_rate/self.decimation)/(self.fft_fps*2) #*2 is there because we do FFT on real signal here
|
|
||||||
|
|
||||||
def secondary_decimation(self):
|
|
||||||
return 1 #currently unused
|
|
||||||
|
|
||||||
def secondary_bpf_cutoff(self):
|
|
||||||
if self.secondary_demodulator == "bpsk31":
|
|
||||||
return (31.25/2) / self.if_samp_rate()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def secondary_bpf_transition_bw(self):
|
|
||||||
if self.secondary_demodulator == "bpsk31":
|
|
||||||
return (31.25/2) / self.if_samp_rate()
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def secondary_samples_per_bits(self):
|
|
||||||
if self.secondary_demodulator == "bpsk31":
|
|
||||||
return int(round(self.if_samp_rate()/31.25))&~3
|
|
||||||
return 0
|
|
||||||
|
|
||||||
def secondary_bw(self):
|
|
||||||
if self.secondary_demodulator == "bpsk31":
|
|
||||||
return 31.25
|
|
||||||
|
|
||||||
def start_secondary_demodulator(self):
|
|
||||||
if(not self.secondary_demodulator): return
|
|
||||||
print "[openwebrx] starting secondary demodulator from IF input sampled at %d"%self.if_samp_rate()
|
|
||||||
secondary_command_fft=self.secondary_chain("fft")
|
|
||||||
secondary_command_demod=self.secondary_chain(self.secondary_demodulator)
|
|
||||||
self.try_create_pipes(self.secondary_pipe_names, secondary_command_demod + secondary_command_fft)
|
|
||||||
|
|
||||||
secondary_command_fft=secondary_command_fft.format( \
|
|
||||||
input_pipe=self.iqtee_pipe, \
|
|
||||||
secondary_fft_input_size=self.secondary_fft_size, \
|
|
||||||
secondary_fft_size=self.secondary_fft_size, \
|
|
||||||
secondary_fft_block_size=self.secondary_fft_block_size(), \
|
|
||||||
)
|
|
||||||
secondary_command_demod=secondary_command_demod.format( \
|
|
||||||
input_pipe=self.iqtee2_pipe, \
|
|
||||||
secondary_shift_pipe=self.secondary_shift_pipe, \
|
|
||||||
secondary_decimation=self.secondary_decimation(), \
|
|
||||||
secondary_samples_per_bits=self.secondary_samples_per_bits(), \
|
|
||||||
secondary_bpf_cutoff=self.secondary_bpf_cutoff(), \
|
|
||||||
secondary_bpf_transition_bw=self.secondary_bpf_transition_bw(), \
|
|
||||||
if_samp_rate=self.if_samp_rate()
|
|
||||||
)
|
|
||||||
|
|
||||||
print "[openwebrx-dsp-plugin:csdr] secondary command (fft) =", secondary_command_fft
|
|
||||||
print "[openwebrx-dsp-plugin:csdr] secondary command (demod) =", secondary_command_demod
|
|
||||||
#code.interact(local=locals())
|
|
||||||
my_env=os.environ.copy()
|
|
||||||
#if self.csdr_dynamic_bufsize: my_env["CSDR_DYNAMIC_BUFSIZE_ON"]="1";
|
|
||||||
if self.csdr_print_bufsizes: my_env["CSDR_PRINT_BUFSIZES"]="1";
|
|
||||||
self.secondary_process_fft = subprocess.Popen(secondary_command_fft, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setpgrp, env=my_env)
|
|
||||||
print "[openwebrx-dsp-plugin:csdr] Popen on secondary command (fft)"
|
|
||||||
self.secondary_process_demod = subprocess.Popen(secondary_command_demod, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setpgrp, env=my_env) #TODO digimodes
|
|
||||||
print "[openwebrx-dsp-plugin:csdr] Popen on secondary command (demod)" #TODO digimodes
|
|
||||||
self.secondary_processes_running = True
|
|
||||||
|
|
||||||
#open control pipes for csdr and send initialization data
|
|
||||||
# print "==========> 1"
|
|
||||||
if self.secondary_shift_pipe != None: #TODO digimodes
|
|
||||||
# print "==========> 2", self.secondary_shift_pipe
|
|
||||||
self.secondary_shift_pipe_file=open(self.secondary_shift_pipe,"w") #TODO digimodes
|
|
||||||
# print "==========> 3"
|
|
||||||
self.set_secondary_offset_freq(self.secondary_offset_freq) #TODO digimodes
|
|
||||||
# print "==========> 4"
|
|
||||||
|
|
||||||
self.set_pipe_nonblocking(self.secondary_process_demod.stdout)
|
|
||||||
self.set_pipe_nonblocking(self.secondary_process_fft.stdout)
|
|
||||||
|
|
||||||
def set_secondary_offset_freq(self, value):
|
|
||||||
self.secondary_offset_freq=value
|
|
||||||
if self.secondary_processes_running:
|
|
||||||
self.secondary_shift_pipe_file.write("%g\n"%(-float(self.secondary_offset_freq)/self.if_samp_rate()))
|
|
||||||
self.secondary_shift_pipe_file.flush()
|
|
||||||
|
|
||||||
def stop_secondary_demodulator(self):
|
|
||||||
if self.secondary_processes_running == False: return
|
|
||||||
self.try_delete_pipes(self.secondary_pipe_names)
|
|
||||||
if self.secondary_process_fft: os.killpg(os.getpgid(self.secondary_process_fft.pid), signal.SIGTERM)
|
|
||||||
if self.secondary_process_demod: os.killpg(os.getpgid(self.secondary_process_demod.pid), signal.SIGTERM)
|
|
||||||
self.secondary_processes_running = False
|
|
||||||
|
|
||||||
def read_secondary_demod(self, size):
|
|
||||||
return self.secondary_process_demod.stdout.read(size)
|
|
||||||
|
|
||||||
def read_secondary_fft(self, size):
|
|
||||||
return self.secondary_process_fft.stdout.read(size)
|
|
||||||
|
|
||||||
def get_secondary_demodulator(self):
|
|
||||||
return self.secondary_demodulator
|
|
||||||
|
|
||||||
def set_secondary_fft_size(self,secondary_fft_size):
|
|
||||||
#to change this, restart is required
|
|
||||||
self.secondary_fft_size=secondary_fft_size
|
|
||||||
|
|
||||||
def set_audio_compression(self,what):
|
|
||||||
self.audio_compression = what
|
|
||||||
|
|
||||||
def set_fft_compression(self,what):
|
|
||||||
self.fft_compression = what
|
|
||||||
|
|
||||||
def get_fft_bytes_to_read(self):
|
|
||||||
if self.fft_compression=="none": return self.fft_size*4
|
|
||||||
if self.fft_compression=="adpcm": return (self.fft_size/2)+(10/2)
|
|
||||||
|
|
||||||
def get_secondary_fft_bytes_to_read(self):
|
|
||||||
if self.fft_compression=="none": return self.secondary_fft_size*4
|
|
||||||
if self.fft_compression=="adpcm": return (self.secondary_fft_size/2)+(10/2)
|
|
||||||
|
|
||||||
def set_samp_rate(self,samp_rate):
|
|
||||||
#to change this, restart is required
|
|
||||||
self.samp_rate=samp_rate
|
|
||||||
self.decimation=1
|
|
||||||
while self.samp_rate/(self.decimation+1)>self.output_rate:
|
|
||||||
self.decimation+=1
|
|
||||||
self.last_decimation=float(self.if_samp_rate())/self.output_rate
|
|
||||||
|
|
||||||
def if_samp_rate(self):
|
|
||||||
return self.samp_rate/self.decimation
|
|
||||||
|
|
||||||
def get_name(self):
|
|
||||||
return self.name
|
|
||||||
|
|
||||||
def get_output_rate(self):
|
|
||||||
return self.output_rate
|
|
||||||
|
|
||||||
def set_output_rate(self,output_rate):
|
|
||||||
self.output_rate=output_rate
|
|
||||||
self.set_samp_rate(self.samp_rate) #as it depends on output_rate
|
|
||||||
|
|
||||||
def set_demodulator(self,demodulator):
|
|
||||||
#to change this, restart is required
|
|
||||||
self.demodulator=demodulator
|
|
||||||
|
|
||||||
def get_demodulator(self):
|
|
||||||
return self.demodulator
|
|
||||||
|
|
||||||
def set_fft_size(self,fft_size):
|
|
||||||
#to change this, restart is required
|
|
||||||
self.fft_size=fft_size
|
|
||||||
|
|
||||||
def set_fft_fps(self,fft_fps):
|
|
||||||
#to change this, restart is required
|
|
||||||
self.fft_fps=fft_fps
|
|
||||||
|
|
||||||
def set_fft_averages(self,fft_averages):
|
|
||||||
#to change this, restart is required
|
|
||||||
self.fft_averages=fft_averages
|
|
||||||
|
|
||||||
def fft_block_size(self):
|
|
||||||
if self.fft_averages == 0: return self.samp_rate/self.fft_fps
|
|
||||||
else: return self.samp_rate/self.fft_fps/self.fft_averages
|
|
||||||
|
|
||||||
def set_format_conversion(self,format_conversion):
|
|
||||||
self.format_conversion=format_conversion
|
|
||||||
|
|
||||||
def set_offset_freq(self,offset_freq):
|
|
||||||
self.offset_freq=offset_freq
|
|
||||||
if self.running:
|
|
||||||
self.shift_pipe_file.write("%g\n"%(-float(self.offset_freq)/self.samp_rate))
|
|
||||||
self.shift_pipe_file.flush()
|
|
||||||
|
|
||||||
def set_bpf(self,low_cut,high_cut):
|
|
||||||
self.low_cut=low_cut
|
|
||||||
self.high_cut=high_cut
|
|
||||||
if self.running:
|
|
||||||
self.bpf_pipe_file.write( "%g %g\n"%(float(self.low_cut)/self.if_samp_rate(), float(self.high_cut)/self.if_samp_rate()) )
|
|
||||||
self.bpf_pipe_file.flush()
|
|
||||||
|
|
||||||
def get_bpf(self):
|
|
||||||
return [self.low_cut, self.high_cut]
|
|
||||||
|
|
||||||
def set_squelch_level(self, squelch_level):
|
|
||||||
self.squelch_level=squelch_level
|
|
||||||
if self.running:
|
|
||||||
self.squelch_pipe_file.write( "%g\n"%(float(self.squelch_level)) )
|
|
||||||
self.squelch_pipe_file.flush()
|
|
||||||
|
|
||||||
def get_smeter_level(self):
|
|
||||||
if self.running:
|
|
||||||
line=self.smeter_pipe_file.readline()
|
|
||||||
return float(line[:-1])
|
|
||||||
|
|
||||||
def mkfifo(self,path):
|
|
||||||
try:
|
|
||||||
os.unlink(path)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
os.mkfifo(path)
|
|
||||||
|
|
||||||
def ddc_transition_bw(self):
|
|
||||||
return self.ddc_transition_bw_rate*(self.if_samp_rate()/float(self.samp_rate))
|
|
||||||
|
|
||||||
def try_create_pipes(self, pipe_names, command_base):
|
|
||||||
# print "try_create_pipes"
|
|
||||||
for pipe_name in pipe_names:
|
|
||||||
# print "\t"+pipe_name
|
|
||||||
if "{"+pipe_name+"}" in command_base:
|
|
||||||
setattr(self, pipe_name, self.pipe_base_path+pipe_name)
|
|
||||||
self.mkfifo(getattr(self, pipe_name))
|
|
||||||
else:
|
|
||||||
setattr(self, pipe_name, None)
|
|
||||||
|
|
||||||
def try_delete_pipes(self, pipe_names):
|
|
||||||
for pipe_name in pipe_names:
|
|
||||||
pipe_path = getattr(self,pipe_name,None)
|
|
||||||
if pipe_path:
|
|
||||||
try: os.unlink(pipe_path)
|
|
||||||
except Exception as e: print "[openwebrx-dsp-plugin:csdr] try_delete_pipes() ::", e
|
|
||||||
|
|
||||||
def set_pipe_nonblocking(self, pipe):
|
|
||||||
flags = fcntl.fcntl(pipe, fcntl.F_GETFL)
|
|
||||||
fcntl.fcntl(pipe, fcntl.F_SETFL, flags | os.O_NONBLOCK)
|
|
||||||
|
|
||||||
def start(self):
|
|
||||||
command_base=self.chain(self.demodulator)
|
|
||||||
|
|
||||||
#create control pipes for csdr
|
|
||||||
self.pipe_base_path="/tmp/openwebrx_pipe_{myid}_".format(myid=id(self))
|
|
||||||
# self.bpf_pipe = self.shift_pipe = self.squelch_pipe = self.smeter_pipe = None
|
|
||||||
|
|
||||||
self.try_create_pipes(self.pipe_names, command_base)
|
|
||||||
|
|
||||||
# if "{bpf_pipe}" in command_base:
|
|
||||||
# self.bpf_pipe=pipe_base_path+"bpf"
|
|
||||||
# self.mkfifo(self.bpf_pipe)
|
|
||||||
# if "{shift_pipe}" in command_base:
|
|
||||||
# self.shift_pipe=pipe_base_path+"shift"
|
|
||||||
# self.mkfifo(self.shift_pipe)
|
|
||||||
# if "{squelch_pipe}" in command_base:
|
|
||||||
# self.squelch_pipe=pipe_base_path+"squelch"
|
|
||||||
# self.mkfifo(self.squelch_pipe)
|
|
||||||
# if "{smeter_pipe}" in command_base:
|
|
||||||
# self.smeter_pipe=pipe_base_path+"smeter"
|
|
||||||
# self.mkfifo(self.smeter_pipe)
|
|
||||||
# if "{iqtee_pipe}" in command_base:
|
|
||||||
# self.iqtee_pipe=pipe_base_path+"iqtee"
|
|
||||||
# self.mkfifo(self.iqtee_pipe)
|
|
||||||
# if "{iqtee2_pipe}" in command_base:
|
|
||||||
# self.iqtee2_pipe=pipe_base_path+"iqtee2"
|
|
||||||
# self.mkfifo(self.iqtee2_pipe)
|
|
||||||
|
|
||||||
#run the command
|
|
||||||
command=command_base.format( bpf_pipe=self.bpf_pipe, shift_pipe=self.shift_pipe, decimation=self.decimation, \
|
|
||||||
last_decimation=self.last_decimation, fft_size=self.fft_size, fft_block_size=self.fft_block_size(), fft_averages=self.fft_averages, \
|
|
||||||
bpf_transition_bw=float(self.bpf_transition_bw)/self.if_samp_rate(), ddc_transition_bw=self.ddc_transition_bw(), \
|
|
||||||
flowcontrol=int(self.samp_rate*2), start_bufsize=self.base_bufsize*self.decimation, nc_port=self.nc_port, \
|
|
||||||
squelch_pipe=self.squelch_pipe, smeter_pipe=self.smeter_pipe, iqtee_pipe=self.iqtee_pipe, iqtee2_pipe=self.iqtee2_pipe )
|
|
||||||
|
|
||||||
print "[openwebrx-dsp-plugin:csdr] Command =",command
|
|
||||||
#code.interact(local=locals())
|
|
||||||
my_env=os.environ.copy()
|
|
||||||
if self.csdr_dynamic_bufsize: my_env["CSDR_DYNAMIC_BUFSIZE_ON"]="1";
|
|
||||||
if self.csdr_print_bufsizes: my_env["CSDR_PRINT_BUFSIZES"]="1";
|
|
||||||
self.process = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True, preexec_fn=os.setpgrp, env=my_env)
|
|
||||||
self.running = True
|
|
||||||
|
|
||||||
#open control pipes for csdr and send initialization data
|
|
||||||
if self.bpf_pipe != None:
|
|
||||||
self.bpf_pipe_file=open(self.bpf_pipe,"w")
|
|
||||||
self.set_bpf(self.low_cut,self.high_cut)
|
|
||||||
if self.shift_pipe != None:
|
|
||||||
self.shift_pipe_file=open(self.shift_pipe,"w")
|
|
||||||
self.set_offset_freq(self.offset_freq)
|
|
||||||
if self.squelch_pipe != None:
|
|
||||||
self.squelch_pipe_file=open(self.squelch_pipe,"w")
|
|
||||||
self.set_squelch_level(self.squelch_level)
|
|
||||||
if self.smeter_pipe != None:
|
|
||||||
self.smeter_pipe_file=open(self.smeter_pipe,"r")
|
|
||||||
self.set_pipe_nonblocking(self.smeter_pipe_file)
|
|
||||||
|
|
||||||
self.start_secondary_demodulator()
|
|
||||||
|
|
||||||
def read(self,size):
|
|
||||||
return self.process.stdout.read(size)
|
|
||||||
|
|
||||||
def stop(self):
|
|
||||||
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
|
|
||||||
self.stop_secondary_demodulator()
|
|
||||||
#if(self.process.poll()!=None):return # returns None while subprocess is running
|
|
||||||
#while(self.process.poll()==None):
|
|
||||||
# #self.process.kill()
|
|
||||||
# print "killproc",os.getpgid(self.process.pid),self.process.pid
|
|
||||||
# os.killpg(self.process.pid, signal.SIGTERM)
|
|
||||||
#
|
|
||||||
# time.sleep(0.1)
|
|
||||||
|
|
||||||
self.try_delete_pipes(self.pipe_names)
|
|
||||||
|
|
||||||
# if self.bpf_pipe:
|
|
||||||
# try: os.unlink(self.bpf_pipe)
|
|
||||||
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.bpf_pipe
|
|
||||||
# if self.shift_pipe:
|
|
||||||
# try: os.unlink(self.shift_pipe)
|
|
||||||
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.shift_pipe
|
|
||||||
# if self.squelch_pipe:
|
|
||||||
# try: os.unlink(self.squelch_pipe)
|
|
||||||
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.squelch_pipe
|
|
||||||
# if self.smeter_pipe:
|
|
||||||
# try: os.unlink(self.smeter_pipe)
|
|
||||||
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.smeter_pipe
|
|
||||||
# if self.iqtee_pipe:
|
|
||||||
# try: os.unlink(self.iqtee_pipe)
|
|
||||||
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.iqtee_pipe
|
|
||||||
# if self.iqtee2_pipe:
|
|
||||||
# try: os.unlink(self.iqtee2_pipe)
|
|
||||||
# except: print "[openwebrx-dsp-plugin:csdr] stop() :: unlink failed: " + self.iqtee2_pipe
|
|
||||||
|
|
||||||
self.running = False
|
|
||||||
|
|
||||||
def restart(self):
|
|
||||||
self.stop()
|
|
||||||
self.start()
|
|
||||||
|
|
||||||
def __del__(self):
|
|
||||||
self.stop()
|
|
||||||
del(self.process)
|
|
0
csdr/__init__.py
Normal file
0
csdr/__init__.py
Normal file
142
csdr/chain/__init__.py
Normal file
142
csdr/chain/__init__.py
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
from csdr.module import Module
|
||||||
|
from pycsdr.modules import Buffer
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from typing import Union, Callable, Optional
|
||||||
|
|
||||||
|
|
||||||
|
class Chain(Module):
|
||||||
|
def __init__(self, workers):
|
||||||
|
super().__init__()
|
||||||
|
self.workers = workers
|
||||||
|
for i in range(1, len(self.workers)):
|
||||||
|
self._connect(self.workers[i - 1], self.workers[i])
|
||||||
|
|
||||||
|
def empty(self):
|
||||||
|
return not self.workers
|
||||||
|
|
||||||
|
def _connect(self, w1, w2, buffer: Optional[Buffer] = None) -> None:
|
||||||
|
if buffer is None:
|
||||||
|
buffer = Buffer(w1.getOutputFormat())
|
||||||
|
w1.setWriter(buffer)
|
||||||
|
w2.setReader(buffer.getReader())
|
||||||
|
|
||||||
|
def setReader(self, reader):
|
||||||
|
if self.reader is reader:
|
||||||
|
return
|
||||||
|
super().setReader(reader)
|
||||||
|
if self.workers:
|
||||||
|
self.workers[0].setReader(reader)
|
||||||
|
|
||||||
|
def setWriter(self, writer):
|
||||||
|
if self.writer is writer:
|
||||||
|
return
|
||||||
|
super().setWriter(writer)
|
||||||
|
if self.workers:
|
||||||
|
self.workers[-1].setWriter(writer)
|
||||||
|
|
||||||
|
def indexOf(self, search: Union[Callable, object]) -> int:
|
||||||
|
def searchFn(x):
|
||||||
|
if callable(search):
|
||||||
|
return search(x)
|
||||||
|
else:
|
||||||
|
return x is search
|
||||||
|
|
||||||
|
try:
|
||||||
|
return next(i for i, v in enumerate(self.workers) if searchFn(v))
|
||||||
|
except StopIteration:
|
||||||
|
return -1
|
||||||
|
|
||||||
|
def replace(self, index, newWorker):
|
||||||
|
if index >= len(self.workers):
|
||||||
|
raise IndexError("Index {} does not exist".format(index))
|
||||||
|
|
||||||
|
self.workers[index].stop()
|
||||||
|
self.workers[index] = newWorker
|
||||||
|
|
||||||
|
error = None
|
||||||
|
|
||||||
|
if index == 0:
|
||||||
|
if self.reader is not None:
|
||||||
|
newWorker.setReader(self.reader)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
previousWorker = self.workers[index - 1]
|
||||||
|
self._connect(previousWorker, newWorker)
|
||||||
|
except ValueError as e:
|
||||||
|
# store error for later raising, but still attempt the second connection
|
||||||
|
error = e
|
||||||
|
|
||||||
|
if index == len(self.workers) - 1:
|
||||||
|
if self.writer is not None:
|
||||||
|
newWorker.setWriter(self.writer)
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
nextWorker = self.workers[index + 1]
|
||||||
|
self._connect(newWorker, nextWorker)
|
||||||
|
except ValueError as e:
|
||||||
|
error = e
|
||||||
|
|
||||||
|
if error is not None:
|
||||||
|
raise error
|
||||||
|
|
||||||
|
def append(self, newWorker):
|
||||||
|
previousWorker = None
|
||||||
|
if self.workers:
|
||||||
|
previousWorker = self.workers[-1]
|
||||||
|
|
||||||
|
self.workers.append(newWorker)
|
||||||
|
|
||||||
|
if previousWorker:
|
||||||
|
self._connect(previousWorker, newWorker)
|
||||||
|
elif self.reader is not None:
|
||||||
|
newWorker.setReader(self.reader)
|
||||||
|
|
||||||
|
if self.writer is not None:
|
||||||
|
newWorker.setWriter(self.writer)
|
||||||
|
|
||||||
|
def insert(self, newWorker):
|
||||||
|
nextWorker = None
|
||||||
|
if self.workers:
|
||||||
|
nextWorker = self.workers[0]
|
||||||
|
|
||||||
|
self.workers.insert(0, newWorker)
|
||||||
|
|
||||||
|
if nextWorker:
|
||||||
|
self._connect(newWorker, nextWorker)
|
||||||
|
elif self.writer is not None:
|
||||||
|
newWorker.setWriter(self.writer)
|
||||||
|
|
||||||
|
if self.reader is not None:
|
||||||
|
newWorker.setReader(self.reader)
|
||||||
|
|
||||||
|
def remove(self, index):
|
||||||
|
removedWorker = self.workers[index]
|
||||||
|
self.workers.remove(removedWorker)
|
||||||
|
removedWorker.stop()
|
||||||
|
|
||||||
|
if index == 0:
|
||||||
|
if self.reader is not None and len(self.workers):
|
||||||
|
self.workers[0].setReader(self.reader)
|
||||||
|
elif index == len(self.workers):
|
||||||
|
if self.writer is not None:
|
||||||
|
self.workers[-1].setWriter(self.writer)
|
||||||
|
else:
|
||||||
|
previousWorker = self.workers[index - 1]
|
||||||
|
nextWorker = self.workers[index]
|
||||||
|
self._connect(previousWorker, nextWorker)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
for w in self.workers:
|
||||||
|
w.stop()
|
||||||
|
|
||||||
|
def getInputFormat(self) -> Format:
|
||||||
|
if self.workers:
|
||||||
|
return self.workers[0].getInputFormat()
|
||||||
|
else:
|
||||||
|
raise BufferError("getInputFormat on empty chain")
|
||||||
|
|
||||||
|
def getOutputFormat(self) -> Format:
|
||||||
|
if self.workers:
|
||||||
|
return self.workers[-1].getOutputFormat()
|
||||||
|
else:
|
||||||
|
raise BufferError("getOutputFormat on empty chain")
|
76
csdr/chain/analog.py
Normal file
76
csdr/chain/analog.py
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, HdAudio, DeemphasisTauChain
|
||||||
|
from pycsdr.modules import AmDemod, DcBlock, FmDemod, Limit, NfmDeemphasis, Agc, WfmDeemphasis, FractionalDecimator, RealPart
|
||||||
|
from pycsdr.types import Format, AgcProfile
|
||||||
|
|
||||||
|
|
||||||
|
class Am(BaseDemodulatorChain):
|
||||||
|
def __init__(self):
|
||||||
|
agc = Agc(Format.FLOAT)
|
||||||
|
agc.setProfile(AgcProfile.SLOW)
|
||||||
|
agc.setInitialGain(200)
|
||||||
|
workers = [
|
||||||
|
AmDemod(),
|
||||||
|
DcBlock(),
|
||||||
|
agc,
|
||||||
|
]
|
||||||
|
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
|
||||||
|
class NFm(BaseDemodulatorChain):
|
||||||
|
def __init__(self, sampleRate: int):
|
||||||
|
self.sampleRate = sampleRate
|
||||||
|
agc = Agc(Format.FLOAT)
|
||||||
|
agc.setProfile(AgcProfile.SLOW)
|
||||||
|
agc.setMaxGain(3)
|
||||||
|
workers = [
|
||||||
|
FmDemod(),
|
||||||
|
Limit(),
|
||||||
|
NfmDeemphasis(sampleRate),
|
||||||
|
agc,
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def setSampleRate(self, sampleRate: int) -> None:
|
||||||
|
if sampleRate == self.sampleRate:
|
||||||
|
return
|
||||||
|
self.sampleRate = sampleRate
|
||||||
|
self.replace(2, NfmDeemphasis(sampleRate))
|
||||||
|
|
||||||
|
|
||||||
|
class WFm(BaseDemodulatorChain, FixedIfSampleRateChain, DeemphasisTauChain, HdAudio):
|
||||||
|
def __init__(self, sampleRate: int, tau: float):
|
||||||
|
self.sampleRate = sampleRate
|
||||||
|
self.tau = tau
|
||||||
|
workers = [
|
||||||
|
FmDemod(),
|
||||||
|
Limit(),
|
||||||
|
FractionalDecimator(Format.FLOAT, 200000.0 / self.sampleRate, prefilter=True),
|
||||||
|
WfmDeemphasis(self.sampleRate, self.tau),
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def getFixedIfSampleRate(self):
|
||||||
|
return 200000
|
||||||
|
|
||||||
|
def setDeemphasisTau(self, tau: float) -> None:
|
||||||
|
if tau == self.tau:
|
||||||
|
return
|
||||||
|
self.tau = tau
|
||||||
|
self.replace(3, WfmDeemphasis(self.sampleRate, self.tau))
|
||||||
|
|
||||||
|
def setSampleRate(self, sampleRate: int) -> None:
|
||||||
|
if sampleRate == self.sampleRate:
|
||||||
|
return
|
||||||
|
self.sampleRate = sampleRate
|
||||||
|
self.replace(2, FractionalDecimator(Format.FLOAT, 200000.0 / self.sampleRate, prefilter=True))
|
||||||
|
self.replace(3, WfmDeemphasis(self.sampleRate, self.tau))
|
||||||
|
|
||||||
|
|
||||||
|
class Ssb(BaseDemodulatorChain):
|
||||||
|
def __init__(self):
|
||||||
|
workers = [
|
||||||
|
RealPart(),
|
||||||
|
Agc(Format.FLOAT),
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
72
csdr/chain/clientaudio.py
Normal file
72
csdr/chain/clientaudio.py
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
from csdr.chain import Chain
|
||||||
|
from pycsdr.modules import AudioResampler, Convert, AdpcmEncoder, Limit
|
||||||
|
from pycsdr.types import Format
|
||||||
|
|
||||||
|
|
||||||
|
class Converter(Chain):
|
||||||
|
def __init__(self, format: Format, inputRate: int, clientRate: int):
|
||||||
|
workers = []
|
||||||
|
if inputRate != clientRate:
|
||||||
|
# we only have an audio resampler for float ATM so if we need to resample, we need to convert
|
||||||
|
if format != Format.FLOAT:
|
||||||
|
workers += [Convert(format, Format.FLOAT)]
|
||||||
|
workers += [AudioResampler(inputRate, clientRate), Limit(), Convert(Format.FLOAT, Format.SHORT)]
|
||||||
|
elif format != Format.SHORT:
|
||||||
|
workers += [Convert(format, Format.SHORT)]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
|
||||||
|
class ClientAudioChain(Chain):
|
||||||
|
def __init__(self, format: Format, inputRate: int, clientRate: int, compression: str):
|
||||||
|
self.format = format
|
||||||
|
self.inputRate = inputRate
|
||||||
|
self.clientRate = clientRate
|
||||||
|
workers = []
|
||||||
|
converter = self._buildConverter()
|
||||||
|
if not converter.empty():
|
||||||
|
workers += [converter]
|
||||||
|
if compression == "adpcm":
|
||||||
|
workers += [AdpcmEncoder(sync=True)]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def _buildConverter(self):
|
||||||
|
return Converter(self.format, self.inputRate, self.clientRate)
|
||||||
|
|
||||||
|
def _updateConverter(self):
|
||||||
|
converter = self._buildConverter()
|
||||||
|
index = self.indexOf(lambda x: isinstance(x, Converter))
|
||||||
|
if converter.empty():
|
||||||
|
if index >= 0:
|
||||||
|
self.remove(index)
|
||||||
|
else:
|
||||||
|
if index >= 0:
|
||||||
|
self.replace(index, converter)
|
||||||
|
else:
|
||||||
|
self.insert(converter)
|
||||||
|
|
||||||
|
def setFormat(self, format: Format) -> None:
|
||||||
|
if format == self.format:
|
||||||
|
return
|
||||||
|
self.format = format
|
||||||
|
self._updateConverter()
|
||||||
|
|
||||||
|
def setInputRate(self, inputRate: int) -> None:
|
||||||
|
if inputRate == self.inputRate:
|
||||||
|
return
|
||||||
|
self.inputRate = inputRate
|
||||||
|
self._updateConverter()
|
||||||
|
|
||||||
|
def setClientRate(self, clientRate: int) -> None:
|
||||||
|
if clientRate == self.clientRate:
|
||||||
|
return
|
||||||
|
self.clientRate = clientRate
|
||||||
|
self._updateConverter()
|
||||||
|
|
||||||
|
def setAudioCompression(self, compression: str) -> None:
|
||||||
|
index = self.indexOf(lambda x: isinstance(x, AdpcmEncoder))
|
||||||
|
if compression == "adpcm":
|
||||||
|
if index < 0:
|
||||||
|
self.append(AdpcmEncoder(sync=True))
|
||||||
|
else:
|
||||||
|
if index >= 0:
|
||||||
|
self.remove(index)
|
73
csdr/chain/demodulator.py
Normal file
73
csdr/chain/demodulator.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
from csdr.chain import Chain
|
||||||
|
from abc import ABC, ABCMeta, abstractmethod
|
||||||
|
from pycsdr.modules import Writer
|
||||||
|
|
||||||
|
|
||||||
|
class FixedAudioRateChain(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def getFixedAudioRate(self) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class FixedIfSampleRateChain(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def getFixedIfSampleRate(self) -> int:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DialFrequencyReceiver(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def setDialFrequency(self, frequency: int) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
# marker interface
|
||||||
|
class HdAudio:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class MetaProvider(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def setMetaWriter(self, writer: Writer) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SlotFilterChain(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def setSlotFilter(self, filter: int) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SecondarySelectorChain(ABC):
|
||||||
|
def getBandwidth(self) -> float:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DeemphasisTauChain(ABC):
|
||||||
|
@abstractmethod
|
||||||
|
def setDeemphasisTau(self, tau: float) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class BaseDemodulatorChain(Chain):
|
||||||
|
def supportsSquelch(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setSampleRate(self, sampleRate: int) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class SecondaryDemodulator(Chain):
|
||||||
|
def supportsSquelch(self) -> bool:
|
||||||
|
return True
|
||||||
|
|
||||||
|
def setSampleRate(self, sampleRate: int) -> None:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ServiceDemodulator(SecondaryDemodulator, FixedAudioRateChain, metaclass=ABCMeta):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class DemodulatorError(Exception):
|
||||||
|
pass
|
111
csdr/chain/digiham.py
Normal file
111
csdr/chain/digiham.py
Normal file
@ -0,0 +1,111 @@
|
|||||||
|
from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain, DialFrequencyReceiver, MetaProvider, SlotFilterChain, DemodulatorError
|
||||||
|
from pycsdr.modules import FmDemod, Agc, Writer, Buffer
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from digiham.modules import DstarDecoder, DcBlock, FskDemodulator, GfskDemodulator, DigitalVoiceFilter, MbeSynthesizer, NarrowRrcFilter, NxdnDecoder, DmrDecoder, WideRrcFilter, YsfDecoder
|
||||||
|
from digiham.ambe import Modes, ServerError
|
||||||
|
from owrx.meta import MetaParser
|
||||||
|
|
||||||
|
|
||||||
|
class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, DialFrequencyReceiver, MetaProvider):
|
||||||
|
def __init__(self, fskDemodulator, decoder, mbeMode, filter=None, codecserver: str = ""):
|
||||||
|
self.decoder = decoder
|
||||||
|
if codecserver is None:
|
||||||
|
codecserver = ""
|
||||||
|
agc = Agc(Format.SHORT)
|
||||||
|
agc.setMaxGain(30)
|
||||||
|
agc.setInitialGain(3)
|
||||||
|
workers = [FmDemod(), DcBlock()]
|
||||||
|
if filter is not None:
|
||||||
|
workers += [filter]
|
||||||
|
try:
|
||||||
|
mbeSynthesizer = MbeSynthesizer(mbeMode, codecserver)
|
||||||
|
except ConnectionError as ce:
|
||||||
|
raise DemodulatorError("Connection to codecserver failed: {}".format(ce))
|
||||||
|
except ServerError as se:
|
||||||
|
raise DemodulatorError("Codecserver error: {}".format(se))
|
||||||
|
workers += [
|
||||||
|
fskDemodulator,
|
||||||
|
decoder,
|
||||||
|
mbeSynthesizer,
|
||||||
|
DigitalVoiceFilter(),
|
||||||
|
agc
|
||||||
|
]
|
||||||
|
self.metaParser = None
|
||||||
|
self.dialFrequency = None
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def getFixedIfSampleRate(self):
|
||||||
|
return 48000
|
||||||
|
|
||||||
|
def getFixedAudioRate(self):
|
||||||
|
return 8000
|
||||||
|
|
||||||
|
def setMetaWriter(self, writer: Writer) -> None:
|
||||||
|
if self.metaParser is None:
|
||||||
|
self.metaParser = MetaParser()
|
||||||
|
buffer = Buffer(Format.CHAR)
|
||||||
|
self.decoder.setMetaWriter(buffer)
|
||||||
|
self.metaParser.setReader(buffer.getReader())
|
||||||
|
if self.dialFrequency is not None:
|
||||||
|
self.metaParser.setDialFrequency(self.dialFrequency)
|
||||||
|
self.metaParser.setWriter(writer)
|
||||||
|
|
||||||
|
def supportsSquelch(self):
|
||||||
|
return False
|
||||||
|
|
||||||
|
def setDialFrequency(self, frequency: int) -> None:
|
||||||
|
self.dialFrequency = frequency
|
||||||
|
if self.metaParser is None:
|
||||||
|
return
|
||||||
|
self.metaParser.setDialFrequency(frequency)
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self.metaParser is not None:
|
||||||
|
self.metaParser.stop()
|
||||||
|
super().stop()
|
||||||
|
|
||||||
|
|
||||||
|
class Dstar(DigihamChain):
|
||||||
|
def __init__(self, codecserver: str = ""):
|
||||||
|
super().__init__(
|
||||||
|
fskDemodulator=FskDemodulator(samplesPerSymbol=10),
|
||||||
|
decoder=DstarDecoder(),
|
||||||
|
mbeMode=Modes.DStarMode,
|
||||||
|
codecserver=codecserver
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Nxdn(DigihamChain):
|
||||||
|
def __init__(self, codecserver: str = ""):
|
||||||
|
super().__init__(
|
||||||
|
fskDemodulator=GfskDemodulator(samplesPerSymbol=20),
|
||||||
|
decoder=NxdnDecoder(),
|
||||||
|
mbeMode=Modes.NxdnMode,
|
||||||
|
filter=NarrowRrcFilter(),
|
||||||
|
codecserver=codecserver
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class Dmr(DigihamChain, SlotFilterChain):
|
||||||
|
def __init__(self, codecserver: str = ""):
|
||||||
|
super().__init__(
|
||||||
|
fskDemodulator=GfskDemodulator(samplesPerSymbol=10),
|
||||||
|
decoder=DmrDecoder(),
|
||||||
|
mbeMode=Modes.DmrMode,
|
||||||
|
filter=WideRrcFilter(),
|
||||||
|
codecserver=codecserver,
|
||||||
|
)
|
||||||
|
|
||||||
|
def setSlotFilter(self, slotFilter: int) -> None:
|
||||||
|
self.decoder.setSlotFilter(slotFilter)
|
||||||
|
|
||||||
|
|
||||||
|
class Ysf(DigihamChain):
|
||||||
|
def __init__(self, codecserver: str = ""):
|
||||||
|
super().__init__(
|
||||||
|
fskDemodulator=GfskDemodulator(samplesPerSymbol=10),
|
||||||
|
decoder=YsfDecoder(),
|
||||||
|
mbeMode=Modes.YsfMode,
|
||||||
|
filter=WideRrcFilter(),
|
||||||
|
codecserver=codecserver
|
||||||
|
)
|
91
csdr/chain/digimodes.py
Normal file
91
csdr/chain/digimodes.py
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
from csdr.chain.demodulator import ServiceDemodulator, SecondaryDemodulator, DialFrequencyReceiver, SecondarySelectorChain
|
||||||
|
from owrx.audio.chopper import AudioChopper, AudioChopperParser
|
||||||
|
from owrx.aprs.kiss import KissDeframer
|
||||||
|
from owrx.aprs import Ax25Parser, AprsParser
|
||||||
|
from pycsdr.modules import Convert, FmDemod, Agc, TimingRecovery, DBPskDecoder, VaricodeDecoder
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from owrx.aprs.module import DirewolfModule
|
||||||
|
from digiham.modules import FskDemodulator, PocsagDecoder
|
||||||
|
from owrx.pocsag import PocsagParser
|
||||||
|
|
||||||
|
|
||||||
|
class AudioChopperDemodulator(ServiceDemodulator, DialFrequencyReceiver):
|
||||||
|
def __init__(self, mode: str, parser: AudioChopperParser):
|
||||||
|
self.chopper = AudioChopper(mode, parser)
|
||||||
|
workers = [Convert(Format.FLOAT, Format.SHORT), self.chopper]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def getFixedAudioRate(self):
|
||||||
|
return 12000
|
||||||
|
|
||||||
|
def setDialFrequency(self, frequency: int) -> None:
|
||||||
|
self.chopper.setDialFrequency(frequency)
|
||||||
|
|
||||||
|
|
||||||
|
class PacketDemodulator(ServiceDemodulator, DialFrequencyReceiver):
|
||||||
|
def __init__(self, service: bool = False):
|
||||||
|
self.parser = AprsParser()
|
||||||
|
workers = [
|
||||||
|
FmDemod(),
|
||||||
|
Convert(Format.FLOAT, Format.SHORT),
|
||||||
|
DirewolfModule(service=service),
|
||||||
|
KissDeframer(),
|
||||||
|
Ax25Parser(),
|
||||||
|
self.parser,
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def supportsSquelch(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getFixedAudioRate(self) -> int:
|
||||||
|
return 48000
|
||||||
|
|
||||||
|
def setDialFrequency(self, frequency: int) -> None:
|
||||||
|
self.parser.setDialFrequency(frequency)
|
||||||
|
|
||||||
|
|
||||||
|
class PocsagDemodulator(ServiceDemodulator, DialFrequencyReceiver):
|
||||||
|
def __init__(self):
|
||||||
|
self.parser = PocsagParser()
|
||||||
|
workers = [
|
||||||
|
FmDemod(),
|
||||||
|
FskDemodulator(samplesPerSymbol=40, invert=True),
|
||||||
|
PocsagDecoder(),
|
||||||
|
self.parser,
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def supportsSquelch(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getFixedAudioRate(self) -> int:
|
||||||
|
return 48000
|
||||||
|
|
||||||
|
def setDialFrequency(self, frequency: int) -> None:
|
||||||
|
self.parser.setDialFrequency(frequency)
|
||||||
|
|
||||||
|
|
||||||
|
class PskDemodulator(SecondaryDemodulator, SecondarySelectorChain):
|
||||||
|
def __init__(self, baudRate: float):
|
||||||
|
self.baudRate = baudRate
|
||||||
|
# this is an assumption, we will adjust in setSampleRate
|
||||||
|
self.sampleRate = 12000
|
||||||
|
secondary_samples_per_bits = int(round(self.sampleRate / self.baudRate)) & ~3
|
||||||
|
workers = [
|
||||||
|
Agc(Format.COMPLEX_FLOAT),
|
||||||
|
TimingRecovery(secondary_samples_per_bits, 0.5, 2, useQ=True),
|
||||||
|
DBPskDecoder(),
|
||||||
|
VaricodeDecoder(),
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def getBandwidth(self):
|
||||||
|
return self.baudRate
|
||||||
|
|
||||||
|
def setSampleRate(self, sampleRate: int) -> None:
|
||||||
|
if sampleRate == self.sampleRate:
|
||||||
|
return
|
||||||
|
self.sampleRate = sampleRate
|
||||||
|
secondary_samples_per_bits = int(round(self.sampleRate / self.baudRate)) & ~3
|
||||||
|
self.replace(1, TimingRecovery(secondary_samples_per_bits, 0.5, 2, useQ=True))
|
19
csdr/chain/drm.py
Normal file
19
csdr/chain/drm.py
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain
|
||||||
|
from pycsdr.modules import Convert, Downmix
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from csdr.module.drm import DrmModule
|
||||||
|
|
||||||
|
|
||||||
|
class Drm(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain):
|
||||||
|
def __init__(self):
|
||||||
|
workers = [Convert(Format.COMPLEX_FLOAT, Format.COMPLEX_SHORT), DrmModule(), Downmix()]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def supportsSquelch(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def getFixedIfSampleRate(self) -> int:
|
||||||
|
return 48000
|
||||||
|
|
||||||
|
def getFixedAudioRate(self) -> int:
|
||||||
|
return 48000
|
14
csdr/chain/dummy.py
Normal file
14
csdr/chain/dummy.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from pycsdr.types import Format
|
||||||
|
from csdr.chain import Module
|
||||||
|
|
||||||
|
|
||||||
|
class DummyDemodulator(Module):
|
||||||
|
def __init__(self, outputFormat: Format):
|
||||||
|
self.outputFormat = outputFormat
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def getInputFormat(self) -> Format:
|
||||||
|
return Format.COMPLEX_FLOAT
|
||||||
|
|
||||||
|
def getOutputFormat(self) -> Format:
|
||||||
|
return self.outputFormat
|
96
csdr/chain/fft.py
Normal file
96
csdr/chain/fft.py
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
from csdr.chain import Chain
|
||||||
|
from pycsdr.modules import Fft, LogPower, LogAveragePower, FftSwap, FftAdpcm
|
||||||
|
|
||||||
|
|
||||||
|
class FftAverager(Chain):
|
||||||
|
def __init__(self, fft_size, fft_averages):
|
||||||
|
self.fftSize = fft_size
|
||||||
|
self.fftAverages = fft_averages
|
||||||
|
workers = [self._getWorker()]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def setFftAverages(self, fft_averages):
|
||||||
|
if self.fftAverages == fft_averages:
|
||||||
|
return
|
||||||
|
self.fftAverages = fft_averages
|
||||||
|
self.replace(0, self._getWorker())
|
||||||
|
|
||||||
|
def _getWorker(self):
|
||||||
|
if self.fftAverages == 0:
|
||||||
|
return LogPower(add_db=-70)
|
||||||
|
else:
|
||||||
|
return LogAveragePower(add_db=-70, fft_size=self.fftSize, avg_number=self.fftAverages)
|
||||||
|
|
||||||
|
|
||||||
|
class FftChain(Chain):
|
||||||
|
def __init__(self, samp_rate, fft_size, fft_v_overlap_factor, fft_fps, fft_compression):
|
||||||
|
self.sampleRate = samp_rate
|
||||||
|
self.vOverlapFactor = fft_v_overlap_factor
|
||||||
|
self.fps = fft_fps
|
||||||
|
self.size = fft_size
|
||||||
|
|
||||||
|
self.blockSize = 0
|
||||||
|
|
||||||
|
self.fft = Fft(size=self.size, every_n_samples=self.blockSize)
|
||||||
|
self.averager = FftAverager(fft_size=self.size, fft_averages=10)
|
||||||
|
self.fftExchangeSides = FftSwap(fft_size=self.size)
|
||||||
|
workers = [
|
||||||
|
self.fft,
|
||||||
|
self.averager,
|
||||||
|
self.fftExchangeSides,
|
||||||
|
]
|
||||||
|
self.compressFftAdpcm = None
|
||||||
|
if fft_compression == "adpcm":
|
||||||
|
self.compressFftAdpcm = FftAdpcm(fft_size=self.size)
|
||||||
|
workers += [self.compressFftAdpcm]
|
||||||
|
|
||||||
|
self._updateParameters()
|
||||||
|
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def _setBlockSize(self, fft_block_size):
|
||||||
|
if self.blockSize == int(fft_block_size):
|
||||||
|
return
|
||||||
|
self.blockSize = int(fft_block_size)
|
||||||
|
self.fft.setEveryNSamples(self.blockSize)
|
||||||
|
|
||||||
|
def setVOverlapFactor(self, fft_v_overlap_factor):
|
||||||
|
if self.vOverlapFactor == fft_v_overlap_factor:
|
||||||
|
return
|
||||||
|
self.vOverlapFactor = fft_v_overlap_factor
|
||||||
|
self._updateParameters()
|
||||||
|
|
||||||
|
def setFps(self, fft_fps):
|
||||||
|
if self.fps == fft_fps:
|
||||||
|
return
|
||||||
|
self.fps = fft_fps
|
||||||
|
self._updateParameters()
|
||||||
|
|
||||||
|
def setSampleRate(self, samp_rate):
|
||||||
|
if self.sampleRate == samp_rate:
|
||||||
|
return
|
||||||
|
self.sampleRate = samp_rate
|
||||||
|
self._updateParameters()
|
||||||
|
|
||||||
|
def _updateParameters(self):
|
||||||
|
fftAverages = 0
|
||||||
|
|
||||||
|
if self.vOverlapFactor > 0:
|
||||||
|
fftAverages = int(round(1.0 * self.sampleRate / self.size / self.fps / (1.0 - self.vOverlapFactor)))
|
||||||
|
self.averager.setFftAverages(fftAverages)
|
||||||
|
|
||||||
|
if fftAverages == 0:
|
||||||
|
self._setBlockSize(self.sampleRate / self.fps)
|
||||||
|
else:
|
||||||
|
self._setBlockSize(self.sampleRate / self.fps / fftAverages)
|
||||||
|
|
||||||
|
def setCompression(self, compression: str) -> None:
|
||||||
|
if compression == "adpcm" and not self.compressFftAdpcm:
|
||||||
|
self.compressFftAdpcm = FftAdpcm(self.size)
|
||||||
|
# should always be at the end
|
||||||
|
self.append(self.compressFftAdpcm)
|
||||||
|
elif compression == "none" and self.compressFftAdpcm:
|
||||||
|
self.compressFftAdpcm.stop()
|
||||||
|
self.compressFftAdpcm = None
|
||||||
|
# should always be at that position (right?)
|
||||||
|
self.remove(3)
|
28
csdr/chain/freedv.py
Normal file
28
csdr/chain/freedv.py
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain
|
||||||
|
from csdr.module.freedv import FreeDVModule
|
||||||
|
from pycsdr.modules import RealPart, Agc, Convert
|
||||||
|
from pycsdr.types import Format
|
||||||
|
|
||||||
|
|
||||||
|
class FreeDV(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain):
|
||||||
|
def __init__(self):
|
||||||
|
agc = Agc(Format.SHORT)
|
||||||
|
agc.setMaxGain(30)
|
||||||
|
agc.setInitialGain(3)
|
||||||
|
workers = [
|
||||||
|
RealPart(),
|
||||||
|
Agc(Format.FLOAT),
|
||||||
|
Convert(Format.FLOAT, Format.SHORT),
|
||||||
|
FreeDVModule(),
|
||||||
|
agc,
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def getFixedIfSampleRate(self) -> int:
|
||||||
|
return 8000
|
||||||
|
|
||||||
|
def getFixedAudioRate(self) -> int:
|
||||||
|
return 8000
|
||||||
|
|
||||||
|
def supportsSquelch(self) -> bool:
|
||||||
|
return False
|
30
csdr/chain/m17.py
Normal file
30
csdr/chain/m17.py
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, MetaProvider
|
||||||
|
from csdr.module.m17 import M17Module
|
||||||
|
from pycsdr.modules import FmDemod, Limit, Convert, Writer
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from digiham.modules import DcBlock
|
||||||
|
|
||||||
|
|
||||||
|
class M17(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, MetaProvider):
|
||||||
|
def __init__(self):
|
||||||
|
self.module = M17Module()
|
||||||
|
workers = [
|
||||||
|
FmDemod(),
|
||||||
|
DcBlock(),
|
||||||
|
Limit(),
|
||||||
|
Convert(Format.FLOAT, Format.SHORT),
|
||||||
|
self.module,
|
||||||
|
]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def getFixedIfSampleRate(self) -> int:
|
||||||
|
return 48000
|
||||||
|
|
||||||
|
def getFixedAudioRate(self) -> int:
|
||||||
|
return 8000
|
||||||
|
|
||||||
|
def supportsSquelch(self) -> bool:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def setMetaWriter(self, writer: Writer) -> None:
|
||||||
|
self.module.setMetaWriter(writer)
|
160
csdr/chain/selector.py
Normal file
160
csdr/chain/selector.py
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
from csdr.chain import Chain
|
||||||
|
from pycsdr.modules import Shift, FirDecimate, Bandpass, Squelch, FractionalDecimator, Writer
|
||||||
|
from pycsdr.types import Format
|
||||||
|
import math
|
||||||
|
|
||||||
|
|
||||||
|
class Decimator(Chain):
|
||||||
|
def __init__(self, inputRate: int, outputRate: int):
|
||||||
|
if outputRate > inputRate:
|
||||||
|
raise ValueError("impossible decimation: cannot upsample {} to {}".format(inputRate, outputRate))
|
||||||
|
self.inputRate = inputRate
|
||||||
|
self.outputRate = outputRate
|
||||||
|
|
||||||
|
decimation, fraction = self._getDecimation(outputRate)
|
||||||
|
transition = 0.15 * (outputRate / float(self.inputRate))
|
||||||
|
# set the cutoff on the fist decimation stage lower so that the resulting output
|
||||||
|
# is already prepared for the second (fractional) decimation stage.
|
||||||
|
# this spares us a second filter.
|
||||||
|
cutoff = 0.5 * decimation / (self.inputRate / outputRate)
|
||||||
|
|
||||||
|
workers = [
|
||||||
|
FirDecimate(decimation, transition, cutoff),
|
||||||
|
]
|
||||||
|
|
||||||
|
if fraction != 1.0:
|
||||||
|
workers += [FractionalDecimator(Format.COMPLEX_FLOAT, fraction)]
|
||||||
|
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def _getDecimation(self, outputRate: int) -> (int, float):
|
||||||
|
d = self.inputRate / outputRate
|
||||||
|
dInt = int(d)
|
||||||
|
dFloat = float(self.inputRate / dInt) / outputRate
|
||||||
|
return dInt, dFloat
|
||||||
|
|
||||||
|
def _reconfigure(self):
|
||||||
|
decimation, fraction = self._getDecimation(self.outputRate)
|
||||||
|
transition = 0.15 * (self.outputRate / float(self.inputRate))
|
||||||
|
cutoff = 0.5 * decimation / (self.inputRate / self.outputRate)
|
||||||
|
self.replace(0, FirDecimate(decimation, transition, cutoff))
|
||||||
|
index = self.indexOf(lambda x: isinstance(x, FractionalDecimator))
|
||||||
|
if fraction != 1.0:
|
||||||
|
decimator = FractionalDecimator(Format.COMPLEX_FLOAT, fraction)
|
||||||
|
if index >= 0:
|
||||||
|
self.replace(index, decimator)
|
||||||
|
else:
|
||||||
|
self.append(decimator)
|
||||||
|
elif index >= 0:
|
||||||
|
self.remove(index)
|
||||||
|
|
||||||
|
def setOutputRate(self, outputRate: int) -> None:
|
||||||
|
if outputRate == self.outputRate:
|
||||||
|
return
|
||||||
|
self.outputRate = outputRate
|
||||||
|
self._reconfigure()
|
||||||
|
|
||||||
|
def setInputRate(self, inputRate: int) -> None:
|
||||||
|
if inputRate == self.inputRate:
|
||||||
|
return
|
||||||
|
self.inputRate = inputRate
|
||||||
|
self._reconfigure()
|
||||||
|
|
||||||
|
|
||||||
|
class Selector(Chain):
|
||||||
|
def __init__(self, inputRate: int, outputRate: int, withSquelch: bool = True):
|
||||||
|
self.inputRate = inputRate
|
||||||
|
self.outputRate = outputRate
|
||||||
|
self.frequencyOffset = 0
|
||||||
|
|
||||||
|
self.shift = Shift(0.0)
|
||||||
|
|
||||||
|
self.decimation = Decimator(inputRate, outputRate)
|
||||||
|
|
||||||
|
self.bandpass = self._buildBandpass()
|
||||||
|
self.bandpassCutoffs = None
|
||||||
|
self.setBandpass(-4000, 4000)
|
||||||
|
|
||||||
|
workers = [self.shift, self.decimation, self.bandpass]
|
||||||
|
|
||||||
|
if withSquelch:
|
||||||
|
self.readings_per_second = 4
|
||||||
|
# s-meter readings are available every 1024 samples
|
||||||
|
# the reporting interval is measured in those 1024-sample blocks
|
||||||
|
self.squelch = Squelch(5, int(outputRate / (self.readings_per_second * 1024)))
|
||||||
|
workers += [self.squelch]
|
||||||
|
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def _buildBandpass(self) -> Bandpass:
|
||||||
|
bp_transition = 320.0 / self.outputRate
|
||||||
|
return Bandpass(transition=bp_transition, use_fft=True)
|
||||||
|
|
||||||
|
def setFrequencyOffset(self, offset: int) -> None:
|
||||||
|
if offset == self.frequencyOffset:
|
||||||
|
return
|
||||||
|
self.frequencyOffset = offset
|
||||||
|
self._updateShift()
|
||||||
|
|
||||||
|
def _updateShift(self):
|
||||||
|
shift = -self.frequencyOffset / self.inputRate
|
||||||
|
self.shift.setRate(shift)
|
||||||
|
|
||||||
|
def _convertToLinear(self, db: float) -> float:
|
||||||
|
return float(math.pow(10, db / 10))
|
||||||
|
|
||||||
|
def setSquelchLevel(self, level: float) -> None:
|
||||||
|
self.squelch.setSquelchLevel(self._convertToLinear(level))
|
||||||
|
|
||||||
|
def setBandpass(self, lowCut: float, highCut: float) -> None:
|
||||||
|
self.bandpassCutoffs = [lowCut, highCut]
|
||||||
|
scaled = [x / self.outputRate for x in self.bandpassCutoffs]
|
||||||
|
self.bandpass.setBandpass(*scaled)
|
||||||
|
|
||||||
|
def setLowCut(self, lowCut: float) -> None:
|
||||||
|
self.bandpassCutoffs[0] = lowCut
|
||||||
|
self.setBandpass(*self.bandpassCutoffs)
|
||||||
|
|
||||||
|
def setHighCut(self, highCut: float) -> None:
|
||||||
|
self.bandpassCutoffs[1] = highCut
|
||||||
|
self.setBandpass(*self.bandpassCutoffs)
|
||||||
|
|
||||||
|
def setPowerWriter(self, writer: Writer) -> None:
|
||||||
|
self.squelch.setPowerWriter(writer)
|
||||||
|
|
||||||
|
def setOutputRate(self, outputRate: int) -> None:
|
||||||
|
if outputRate == self.outputRate:
|
||||||
|
return
|
||||||
|
self.outputRate = outputRate
|
||||||
|
|
||||||
|
self.decimation.setOutputRate(outputRate)
|
||||||
|
self.squelch.setReportInterval(int(outputRate / (self.readings_per_second * 1024)))
|
||||||
|
self.bandpass = self._buildBandpass()
|
||||||
|
self.setBandpass(*self.bandpassCutoffs)
|
||||||
|
self.replace(2, self.bandpass)
|
||||||
|
|
||||||
|
def setInputRate(self, inputRate: int) -> None:
|
||||||
|
if inputRate == self.inputRate:
|
||||||
|
return
|
||||||
|
self.inputRate = inputRate
|
||||||
|
self.decimation.setInputRate(inputRate)
|
||||||
|
self._updateShift()
|
||||||
|
|
||||||
|
|
||||||
|
class SecondarySelector(Chain):
|
||||||
|
def __init__(self, sampleRate: int, bandwidth: float):
|
||||||
|
self.sampleRate = sampleRate
|
||||||
|
self.frequencyOffset = 0
|
||||||
|
self.shift = Shift(0.0)
|
||||||
|
cutoffRate = bandwidth / sampleRate
|
||||||
|
self.bandpass = Bandpass(-cutoffRate, cutoffRate, cutoffRate, use_fft=True)
|
||||||
|
workers = [self.shift, self.bandpass]
|
||||||
|
super().__init__(workers)
|
||||||
|
|
||||||
|
def setFrequencyOffset(self, offset: int) -> None:
|
||||||
|
if offset == self.frequencyOffset:
|
||||||
|
return
|
||||||
|
self.frequencyOffset = offset
|
||||||
|
if self.frequencyOffset is None:
|
||||||
|
return
|
||||||
|
self.shift.setRate(-offset / self.sampleRate)
|
136
csdr/module/__init__.py
Normal file
136
csdr/module/__init__.py
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
from pycsdr.modules import Module as BaseModule
|
||||||
|
from pycsdr.modules import Reader, Writer
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from abc import ABCMeta, abstractmethod
|
||||||
|
from threading import Thread
|
||||||
|
from io import BytesIO
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from functools import partial
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
|
||||||
|
class Module(BaseModule, metaclass=ABCMeta):
|
||||||
|
def __init__(self):
|
||||||
|
self.reader = None
|
||||||
|
self.writer = None
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
def setReader(self, reader: Reader) -> None:
|
||||||
|
self.reader = reader
|
||||||
|
|
||||||
|
def setWriter(self, writer: Writer) -> None:
|
||||||
|
self.writer = writer
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def getInputFormat(self) -> Format:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def getOutputFormat(self) -> Format:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def pump(self, read, write):
|
||||||
|
def copy():
|
||||||
|
while True:
|
||||||
|
data = None
|
||||||
|
try:
|
||||||
|
data = read()
|
||||||
|
except ValueError:
|
||||||
|
pass
|
||||||
|
except BrokenPipeError:
|
||||||
|
break
|
||||||
|
if data is None or isinstance(data, bytes) and len(data) == 0:
|
||||||
|
break
|
||||||
|
write(data)
|
||||||
|
|
||||||
|
return copy
|
||||||
|
|
||||||
|
|
||||||
|
class AutoStartModule(Module, metaclass=ABCMeta):
|
||||||
|
def _checkStart(self) -> None:
|
||||||
|
if self.reader is not None and self.writer is not None:
|
||||||
|
self.start()
|
||||||
|
|
||||||
|
def setReader(self, reader: Reader) -> None:
|
||||||
|
super().setReader(reader)
|
||||||
|
self._checkStart()
|
||||||
|
|
||||||
|
def setWriter(self, writer: Writer) -> None:
|
||||||
|
super().setWriter(writer)
|
||||||
|
self._checkStart()
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def start(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ThreadModule(AutoStartModule, Thread, metaclass=ABCMeta):
|
||||||
|
def __init__(self):
|
||||||
|
self.doRun = True
|
||||||
|
super().__init__()
|
||||||
|
Thread.__init__(self)
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def run(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
self.doRun = False
|
||||||
|
self.reader.stop()
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
Thread.start(self)
|
||||||
|
|
||||||
|
|
||||||
|
class PickleModule(ThreadModule):
|
||||||
|
def getInputFormat(self) -> Format:
|
||||||
|
return Format.CHAR
|
||||||
|
|
||||||
|
def getOutputFormat(self) -> Format:
|
||||||
|
return Format.CHAR
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
while self.doRun:
|
||||||
|
data = self.reader.read()
|
||||||
|
if data is None:
|
||||||
|
self.doRun = False
|
||||||
|
break
|
||||||
|
io = BytesIO(data.tobytes())
|
||||||
|
try:
|
||||||
|
while True:
|
||||||
|
output = self.process(pickle.load(io))
|
||||||
|
if output is not None:
|
||||||
|
self.writer.write(pickle.dumps(output))
|
||||||
|
except EOFError:
|
||||||
|
pass
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def process(self, input):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class PopenModule(AutoStartModule, metaclass=ABCMeta):
|
||||||
|
def __init__(self):
|
||||||
|
self.process = None
|
||||||
|
super().__init__()
|
||||||
|
|
||||||
|
@abstractmethod
|
||||||
|
def getCommand(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def _getProcess(self):
|
||||||
|
return Popen(self.getCommand(), stdin=PIPE, stdout=PIPE)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
self.process = self._getProcess()
|
||||||
|
# resume in case the reader has been stop()ed before
|
||||||
|
self.reader.resume()
|
||||||
|
Thread(target=self.pump(self.reader.read, self.process.stdin.write)).start()
|
||||||
|
Thread(target=self.pump(partial(self.process.stdout.read, 1024), self.writer.write)).start()
|
||||||
|
|
||||||
|
def stop(self):
|
||||||
|
if self.process is not None:
|
||||||
|
self.process.terminate()
|
||||||
|
self.process.wait()
|
||||||
|
self.process = None
|
||||||
|
self.reader.stop()
|
14
csdr/module/drm.py
Normal file
14
csdr/module/drm.py
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
from csdr.module import PopenModule
|
||||||
|
from pycsdr.types import Format
|
||||||
|
|
||||||
|
|
||||||
|
class DrmModule(PopenModule):
|
||||||
|
def getInputFormat(self) -> Format:
|
||||||
|
return Format.COMPLEX_FLOAT
|
||||||
|
|
||||||
|
def getOutputFormat(self) -> Format:
|
||||||
|
return Format.SHORT
|
||||||
|
|
||||||
|
def getCommand(self):
|
||||||
|
# dream -c 6 --sigsrate 48000 --audsrate 48000 -I - -O -
|
||||||
|
return ["dream", "-c", "6", "--sigsrate", "48000", "--audsrate", "48000", "-I", "-", "-O", "-"]
|
13
csdr/module/freedv.py
Normal file
13
csdr/module/freedv.py
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
from pycsdr.types import Format
|
||||||
|
from csdr.module import PopenModule
|
||||||
|
|
||||||
|
|
||||||
|
class FreeDVModule(PopenModule):
|
||||||
|
def getInputFormat(self) -> Format:
|
||||||
|
return Format.SHORT
|
||||||
|
|
||||||
|
def getOutputFormat(self) -> Format:
|
||||||
|
return Format.SHORT
|
||||||
|
|
||||||
|
def getCommand(self):
|
||||||
|
return ["freedv_rx", "1600", "-", "-"]
|
58
csdr/module/m17.py
Normal file
58
csdr/module/m17.py
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
from csdr.module import PopenModule
|
||||||
|
from pycsdr.types import Format
|
||||||
|
from pycsdr.modules import Writer
|
||||||
|
from subprocess import Popen, PIPE
|
||||||
|
from threading import Thread
|
||||||
|
|
||||||
|
import re
|
||||||
|
import pickle
|
||||||
|
|
||||||
|
|
||||||
|
class M17Module(PopenModule):
|
||||||
|
lsfRegex = re.compile("SRC: ([a-zA-Z0-9]+), DEST: ([a-zA-Z0-9]+)")
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__()
|
||||||
|
self.metawriter = None
|
||||||
|
|
||||||
|
def getInputFormat(self) -> Format:
|
||||||
|
return Format.SHORT
|
||||||
|
|
||||||
|
def getOutputFormat(self) -> Format:
|
||||||
|
return Format.SHORT
|
||||||
|
|
||||||
|
def getCommand(self):
|
||||||
|
return ["m17-demod", "-l"]
|
||||||
|
|
||||||
|
def _getProcess(self):
|
||||||
|
return Popen(self.getCommand(), stdin=PIPE, stdout=PIPE, stderr=PIPE)
|
||||||
|
|
||||||
|
def start(self):
|
||||||
|
super().start()
|
||||||
|
Thread(target=self._readOutput).start()
|
||||||
|
|
||||||
|
def _readOutput(self):
|
||||||
|
while True:
|
||||||
|
line = self.process.stderr.readline()
|
||||||
|
if not line:
|
||||||
|
break
|
||||||
|
self.parseOutput(line.decode())
|
||||||
|
|
||||||
|
def parseOutput(self, line):
|
||||||
|
if self.metawriter is None:
|
||||||
|
return
|
||||||
|
matches = self.lsfRegex.match(line)
|
||||||
|
msg = {"protocol": "M17"}
|
||||||
|
if matches:
|
||||||
|
# fake sync
|
||||||
|
msg["sync"] = "voice"
|
||||||
|
msg["source"] = matches.group(1)
|
||||||
|
msg["destination"] = matches.group(2)
|
||||||
|
elif line.startswith("EOS"):
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
self.metawriter.write(pickle.dumps(msg))
|
||||||
|
|
||||||
|
def setMetaWriter(self, writer: Writer) -> None:
|
||||||
|
self.metawriter = writer
|
227
debian/changelog
vendored
Normal file
227
debian/changelog
vendored
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
openwebrx (1.2.0) bullseye jammy; urgency=low
|
||||||
|
|
||||||
|
* Major rewrite of all demodulation components to make use of the new
|
||||||
|
csdr/pycsdr and digiham/pydigiham demodulator modules
|
||||||
|
* Preliminary display of M17 callsign information
|
||||||
|
* New devices supported:
|
||||||
|
- Blade RF
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Wed, 15 Jun 2022 16:20:00 +0000
|
||||||
|
|
||||||
|
openwebrx (1.1.0) buster hirsute; urgency=low
|
||||||
|
|
||||||
|
* Reworked most graphical elements as SVGs for faster loadtimes and crispier
|
||||||
|
display on hi-dpi displays
|
||||||
|
* Updated pipelines to match changes in digiham
|
||||||
|
* Changed D-Star and NXDN integrations to use new decoder from digiham
|
||||||
|
* Added D-Star and NXDN metadata display
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Mon, 02 Aug 2021 16:24:00 +0000
|
||||||
|
|
||||||
|
openwebrx (1.0.0) buster hirsute; urgency=low
|
||||||
|
* Introduced `squelch_auto_margin` config option that allows configuring the
|
||||||
|
auto squelch level
|
||||||
|
* Removed `port` configuration option; `rtltcp_compat` takes the port number
|
||||||
|
with the new connectors
|
||||||
|
* Added support for new WSJT-X modes FST4, FST4W (only available with WSJT-X
|
||||||
|
2.3) and Q65 (only available with WSJT-X 2.4)
|
||||||
|
* Added support for demodulating M17 digital voice signals using
|
||||||
|
m17-cxx-demod
|
||||||
|
* New reporting infrastructure, allowing WSPR and FST4W spots to be sent to
|
||||||
|
wsprnet.org
|
||||||
|
* Add some basic filtering capabilities to the map
|
||||||
|
* New arguments to the `openwebrx` command-line to facilitate the
|
||||||
|
administration of users (try `openwebrx admin`)
|
||||||
|
* New command-line tool `openwebrx-admin` that facilitates the
|
||||||
|
administration of users
|
||||||
|
* Default bandwidth changes:
|
||||||
|
- "WFM" changed to 150kHz
|
||||||
|
- "Packet" (APRS) changed to 12.5kHz
|
||||||
|
* Configuration rework:
|
||||||
|
- New: fully web-based configuration interface
|
||||||
|
- System configuration parameters have been moved to a new, separate
|
||||||
|
`openwebrx.conf` file
|
||||||
|
- Remaining parameters are now editable in the web configuration
|
||||||
|
- Existing `config_webrx.py` files will still be read, but changes made in
|
||||||
|
the web configuration will be written to a new storage system
|
||||||
|
- Added upload of avatar and panorama image via web configuration
|
||||||
|
* New devices supported:
|
||||||
|
- HPSDR devices (Hermes Lite 2) thanks to @jancona
|
||||||
|
- BBRF103 / RX666 / RX888 devices supported by libsddc
|
||||||
|
- R&S devices using the EB200 or Ammos protocols
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Thu, 06 May 2021 17:22:00 +0000
|
||||||
|
|
||||||
|
openwebrx (0.20.3) buster focal; urgency=low
|
||||||
|
|
||||||
|
* Fix a compatibility issue with python versions <= 3.6
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Tue, 26 Jan 2021 15:28:00 +0000
|
||||||
|
|
||||||
|
openwebrx (0.20.2) buster focal; urgency=high
|
||||||
|
|
||||||
|
* Fix a security problem that allowed arbitrary commands to be executed on
|
||||||
|
the receiver (See github issue #215:
|
||||||
|
https://github.com/jketterl/openwebrx/issues/215)
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Sun, 24 Jan 2021 22:50:00 +0000
|
||||||
|
|
||||||
|
openwebrx (0.20.1) buster focal; urgency=low
|
||||||
|
|
||||||
|
* Remove broken OSM map fallback
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Mon, 30 Nov 2020 17:29:00 +0000
|
||||||
|
|
||||||
|
openwebrx (0.20.0) buster focal; urgency=low
|
||||||
|
|
||||||
|
* Added the ability to sign multiple keys in a single request, thus enabling
|
||||||
|
multiple users to claim a single receiver on receiverbook.de
|
||||||
|
* Fixed file descriptor leaks to prevent "too many open files" errors
|
||||||
|
* Add new demodulator chain for FreeDV
|
||||||
|
* Added new HD audio streaming mode along with a new WFM demodulator
|
||||||
|
* Reworked AGC code for better results in AM, SSB and digital modes
|
||||||
|
* Added support for demodulation of "Digital Radio Mondiale" (DRM) broadcast
|
||||||
|
using the "dream" decoder.
|
||||||
|
* New default waterfall color scheme
|
||||||
|
* Prototype of a continuous automatic waterfall calibration mode
|
||||||
|
* New devices supported:
|
||||||
|
- FunCube Dongle Pro+ (`"type": "fcdpp"`)
|
||||||
|
- Support for connections to rtl_tcp (`"type": "rtl_tcp"`)
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Sun, 11 Oct 2020 13:02:00 +0000
|
||||||
|
|
||||||
|
openwebrx (0.19.1) buster focal; urgency=low
|
||||||
|
|
||||||
|
* Added ability to authenticate receivers with listing sites using
|
||||||
|
"receiver id" tokens
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Sat, 13 Jun 2020 16:46:00 +0000
|
||||||
|
|
||||||
|
openwebrx (0.19.0) buster focal; urgency=low
|
||||||
|
* Fix direwolf connection setup by implementing a retry loop
|
||||||
|
* Pass direct sampling mode changes for rtl_sdr_soapy to owrx_connector
|
||||||
|
* OSM maps instead of Google when google_maps_api_key is not set (thanks
|
||||||
|
@jquagga)
|
||||||
|
* Improved logic to pass parameters to soapy devices.
|
||||||
|
- `rtl_sdr_soapy`: added support for `bias_tee`
|
||||||
|
- `sdrplay`: added support for `bias_tee`, `rf_notch` and `dab_notch`
|
||||||
|
- `airspy`: added support for `bitpack`
|
||||||
|
* Added support for Perseus-SDR devices, (thanks @amontefusco)
|
||||||
|
* Property System has been rewritten so that defaults on sdr behave as
|
||||||
|
expected
|
||||||
|
* Waterfall range auto-adjustment now only takes the center 80% of the
|
||||||
|
spectrum into account, which should work better with SDRs that oversample
|
||||||
|
or have rather flat filter curves towards the spectrum edges
|
||||||
|
* Bugfix for negative network usage
|
||||||
|
* FiFi SDR: prevent arecord from shutting down after 2GB of data has been
|
||||||
|
sent
|
||||||
|
* Added support for bias tee control on rtl_sdr devices
|
||||||
|
* All connector driven SDRs now support `"rf_gain": "auto"` to enable AGC
|
||||||
|
* `rtl_sdr` type now also supports the `direct_sampling` option
|
||||||
|
* Added decoding implementation for for digimode "JS8Call" (requires an
|
||||||
|
installation of js8call and the js8py library)
|
||||||
|
* Reorganization of the frontend demodulator code
|
||||||
|
* Improve receiver load time by concatenating javascript assets
|
||||||
|
* HackRF support is now based on SoapyHackRF
|
||||||
|
* Removed sdr.hu server listing support since the site has been shut down
|
||||||
|
* Added support for Radioberry 2 Rasbperry Pi SDR Cape
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Mon, 01 Jun 2020 17:02:00 +0000
|
||||||
|
|
||||||
|
openwebrx (0.18.0) buster; urgency=low
|
||||||
|
|
||||||
|
* Compression, resampling and filtering in the frontend have been rewritten
|
||||||
|
in javascript, sdr.js has been removed
|
||||||
|
* Decoding of Pocsag modulation is now possible
|
||||||
|
* Removed the 3D waterfall since it had no real application and required ~1MB
|
||||||
|
of javascript code to be downloaded
|
||||||
|
* Improved the frontend handling of the "too many users" scenario
|
||||||
|
* PSK63 digimode is now available (same decoding pipeline as PSK31, but with
|
||||||
|
adopted parameters)
|
||||||
|
* The frequency can now be manipulated with the mousewheel, which should
|
||||||
|
allow the user to tune more precise. The tuning step size is determined by
|
||||||
|
the digit the mouse cursor is hovering over.
|
||||||
|
* Clicking on the frequency now opens an input for direct frequency selection
|
||||||
|
* URL hashes have been fixed and improved: They are now updated
|
||||||
|
automatically, so a shared URL will include frequency and demodulator,
|
||||||
|
which allows for improved sharing and linking.
|
||||||
|
* New daylight scheduler for background decoding, allows profiles to be
|
||||||
|
selected by local sunrise / sunset times
|
||||||
|
* The owrx_connector is now the default way of communicating with sdr
|
||||||
|
devices. The old sdr types have been replaced, all `_connector` suffixes on
|
||||||
|
the type must be removed!
|
||||||
|
* The sources have been refactored, making it a lot easier to add support for
|
||||||
|
other devices
|
||||||
|
* SDR device failure handling has been improved, including user feedback
|
||||||
|
* New devices supported:
|
||||||
|
* wsjt-x updated to 2.1.2
|
||||||
|
* The rtl_tcp compatibility mode of the owrx_connector is now configurable
|
||||||
|
using the `rtltcp_compat` flag
|
||||||
|
* explicit device filter for soapy devices for multi-device setups
|
||||||
|
* compatibility fixes for safari browsers (ios and mac)
|
||||||
|
* Offset tuning using the `lfo_offset` has been reworked in a way that
|
||||||
|
`center_freq` has to be set to the frequency you actually want to listen
|
||||||
|
to. If you're using an `lfo_offset` already, you will probably need to
|
||||||
|
change its sign.
|
||||||
|
* `initial_squelch_level` can now be set on each profile.
|
||||||
|
* Part of the frontend code has been reworked
|
||||||
|
- Audio buffer minimums have been completely stripped. As a result, you
|
||||||
|
should get better latency. Unfortunately, this also means there will be
|
||||||
|
some skipping when audio starts.
|
||||||
|
- Now also supports AudioWorklets (for those browser that have it).
|
||||||
|
- Mousewheel controls for the receiver sliders
|
||||||
|
* Error handling for failed SDR devices
|
||||||
|
* One of the most-requested features is finally coming to OpenWebRX:
|
||||||
|
Bookmarks (sometimes also referred to as labels).
|
||||||
|
There's two kinds of bookmarks available:
|
||||||
|
- Serverside bookmarks that are set up by the receiver administrator.
|
||||||
|
Check the file `bookmarks.json` for examples!
|
||||||
|
- Clientside bookmarks which every user can store for themselves. They are
|
||||||
|
stored in the browser's localStorage.
|
||||||
|
* Automatic reporting of spots to [pskreporter](https://pskreporter.info/) is
|
||||||
|
now possible. Please have a look at the configuration on how to set it up.
|
||||||
|
* Websocket communication has been overhauled in large parts. It should now
|
||||||
|
be more reliable, and failing connections should now have no impact on
|
||||||
|
other users.
|
||||||
|
* Profile scheduling allows to set up band-hopping if you are running
|
||||||
|
background services.
|
||||||
|
* APRS now has the ability to show symbols on the map, if a corresponding
|
||||||
|
symbol set has been installed. Check the config!
|
||||||
|
* Debug logging has been disabled in a handful of modules, expect vastly
|
||||||
|
reduced output on the shell.
|
||||||
|
* New set of APRS-related features
|
||||||
|
- Decode Packet transmissions using direwolf (1k2 only for now)
|
||||||
|
- APRS packets are mostly decoded and shown both in a new panel and on the
|
||||||
|
map
|
||||||
|
- APRS is also available as a background service
|
||||||
|
- direwolfs I-gate functionality can be enabled, which allows your receiver
|
||||||
|
to work as a receive-only I-gate for the APRS network in the background
|
||||||
|
* Demodulation for background services has been optimized to use less total
|
||||||
|
bandwidth, saving CPU
|
||||||
|
* More metrics have been added; they can be used together with collectd and
|
||||||
|
its curl_json plugin for now, with some limitations.
|
||||||
|
* New bandplan feature, the first thing visible is the "dial" indicator that
|
||||||
|
brings you right to the dial frequency for digital modes
|
||||||
|
* fixed some bugs in the websocket communication which broke the map
|
||||||
|
* WSJT-X integration (FT8, FT4, WSPR, JT65, JT9 using wsjt-x demodulators)
|
||||||
|
* New Map Feature that shows both decoded grid squares from FT8 and Locations
|
||||||
|
decoded from YSF digital voice
|
||||||
|
* New Feature report that will show what functionality is available
|
||||||
|
* major rework on the openwebrx core
|
||||||
|
* Support of multiple SDR devices simultaneously
|
||||||
|
* Support for multiple profiles per SDR that allow the user to listen to
|
||||||
|
different frequencies
|
||||||
|
* Support for digital voice decoding
|
||||||
|
* Feature detection that will disable functionality when dependencies are not
|
||||||
|
available (if you're missing the digital
|
||||||
|
buttons, this is probably why)
|
||||||
|
* Support added for the following SDR sources:
|
||||||
|
- LimeSDR (`"type": "lime_sdr"`)
|
||||||
|
- PlutoSDR (`"type": "pluto_sdr"`)
|
||||||
|
- RTL_SDR via Soapy (`"type": "rtl_sdr_soapy"`) on special request to allow
|
||||||
|
use of the direct sampling mode
|
||||||
|
- SoapyRemote (`"type": "soapy_remote"`)
|
||||||
|
- FiFiSDR (`"type": "fifi_sdr"`)
|
||||||
|
- airspyhf devices (Airspy HF+ / Discovery) (`"type": "airspyhf"`)
|
||||||
|
|
||||||
|
-- Jakob Ketterl <jakob.ketterl@gmx.de> Tue, 18 Feb 2020 20:09:00 +0000
|
1
debian/compat
vendored
Normal file
1
debian/compat
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
10
|
16
debian/control
vendored
Normal file
16
debian/control
vendored
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
Source: openwebrx
|
||||||
|
Maintainer: Jakob Ketterl <jakob.ketterl@gmx.de>
|
||||||
|
Section: hamradio
|
||||||
|
Priority: optional
|
||||||
|
Standards-Version: 4.2.0
|
||||||
|
Build-Depends: debhelper (>= 11), dh-python, python3-all (>= 3.5), python3-setuptools
|
||||||
|
Homepage: https://www.openwebrx.de/
|
||||||
|
Vcs-Browser: https://github.com/jketterl/openwebrx
|
||||||
|
Vcs-Git: https://github.com/jketterl/openwebrx.git
|
||||||
|
|
||||||
|
Package: openwebrx
|
||||||
|
Architecture: all
|
||||||
|
Depends: adduser, python3 (>= 3.5), python3-pkg-resources, owrx-connector (>= 0.5), soapysdr-tools, python3-csdr (>= 0.18), ${python3:Depends}, ${misc:Depends}
|
||||||
|
Recommends: python3-digiham (>= 0.6), direwolf (>= 1.4), wsjtx, js8call, runds-connector (>= 0.2), hpsdrconnector, aprs-symbols, m17-demod, js8call, python3-js8py (>= 0.1), nmux (>= 0.18), codecserver (>= 0.1)
|
||||||
|
Description: multi-user web sdr
|
||||||
|
Open source, multi-user SDR receiver with a web interface
|
8
debian/openwebrx.config
vendored
Executable file
8
debian/openwebrx.config
vendored
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
. /usr/share/debconf/confmodule
|
||||||
|
|
||||||
|
db_get openwebrx/admin_user_configured
|
||||||
|
if [ "${1:-}" = "reconfigure" ] || [ "${RET}" != true ]; then
|
||||||
|
db_input high openwebrx/admin_user_password || true
|
||||||
|
db_go
|
||||||
|
fi
|
1
debian/openwebrx.dirs
vendored
Normal file
1
debian/openwebrx.dirs
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/etc/openwebrx/openwebrx.conf.d
|
3
debian/openwebrx.install
vendored
Normal file
3
debian/openwebrx.install
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
bands.json etc/openwebrx/
|
||||||
|
openwebrx.conf etc/openwebrx/
|
||||||
|
systemd/openwebrx.service lib/systemd/system/
|
59
debian/openwebrx.postinst
vendored
Executable file
59
debian/openwebrx.postinst
vendored
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
. /usr/share/debconf/confmodule
|
||||||
|
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
OWRX_USER="openwebrx"
|
||||||
|
OWRX_DATADIR="/var/lib/openwebrx"
|
||||||
|
OWRX_USERS_FILE="${OWRX_DATADIR}/users.json"
|
||||||
|
OWRX_SETTINGS_FILE="${OWRX_DATADIR}/settings.json"
|
||||||
|
OWRX_BOOKMARKS_FILE="${OWRX_DATADIR}/bookmarks.json"
|
||||||
|
|
||||||
|
case "$1" in
|
||||||
|
configure|reconfigure)
|
||||||
|
adduser --system --group --no-create-home --home /nonexistent --quiet "${OWRX_USER}"
|
||||||
|
usermod -aG plugdev "${OWRX_USER}"
|
||||||
|
|
||||||
|
# create OpenWebRX data directory and set the correct permissions
|
||||||
|
if [ ! -d "${OWRX_DATADIR}" ] && [ ! -L "${OWRX_DATADIR}" ]; then mkdir "${OWRX_DATADIR}"; fi
|
||||||
|
chown "${OWRX_USER}". ${OWRX_DATADIR}
|
||||||
|
|
||||||
|
# create empty config files now to avoid permission problems later
|
||||||
|
if [ ! -e "${OWRX_USERS_FILE}" ]; then
|
||||||
|
echo "[]" > "${OWRX_USERS_FILE}"
|
||||||
|
chown "${OWRX_USER}". "${OWRX_USERS_FILE}"
|
||||||
|
chmod 0600 "${OWRX_USERS_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "${OWRX_SETTINGS_FILE}" ]; then
|
||||||
|
echo "{}" > "${OWRX_SETTINGS_FILE}"
|
||||||
|
chown "${OWRX_USER}". "${OWRX_SETTINGS_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -e "${OWRX_BOOKMARKS_FILE}" ]; then
|
||||||
|
touch "${OWRX_BOOKMARKS_FILE}"
|
||||||
|
chown "${OWRX_USER}". "${OWRX_BOOKMARKS_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
db_get openwebrx/admin_user_password
|
||||||
|
if [ ! -z "${RET}" ]; then
|
||||||
|
if ! openwebrx admin --silent hasuser admin; then
|
||||||
|
# create initial openwebrx user
|
||||||
|
OWRX_PASSWORD="${RET}" openwebrx admin --noninteractive adduser admin
|
||||||
|
else
|
||||||
|
# change existing user's password
|
||||||
|
OWRX_PASSWORD="${RET}" openwebrx admin --noninteractive resetpassword admin
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
# remove password from debconf database
|
||||||
|
db_unregister openwebrx/admin_user_password
|
||||||
|
# set a marker that admin is configured to avoid future questions
|
||||||
|
db_set openwebrx/admin_user_configured true
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
echo "postinst called with unknown argument '$1'" 1>&2
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
#DEBHELPER#
|
8
debian/openwebrx.postrm
vendored
Executable file
8
debian/openwebrx.postrm
vendored
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh -e
|
||||||
|
|
||||||
|
if [ "$1" = purge ] && [ -e /usr/share/debconf/confmodule ]; then
|
||||||
|
. /usr/share/debconf/confmodule
|
||||||
|
db_purge
|
||||||
|
fi
|
||||||
|
|
||||||
|
#DEBHELPER#
|
23
debian/openwebrx.templates
vendored
Normal file
23
debian/openwebrx.templates
vendored
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
Template: openwebrx/admin_user_password
|
||||||
|
Type: password
|
||||||
|
Description: OpenWebRX "admin" user password:
|
||||||
|
The system can create a user for the OpenWebRX web configuration interface for
|
||||||
|
you. Using this user, you will be able to log into the "settings" area of
|
||||||
|
OpenWebRX to configure your receiver conveniently through your browser.
|
||||||
|
.
|
||||||
|
The name of the created user will be "admin".
|
||||||
|
.
|
||||||
|
If you do not wish to create a web admin user right now, you can leave this
|
||||||
|
empty for now. You can return to this prompt at a later time by running the
|
||||||
|
command "sudo dpkg-reconfigure openwebrx".
|
||||||
|
.
|
||||||
|
You can also use the "openwebrx admin" command to create, delete or manage
|
||||||
|
existing users. More information is available in by running the command
|
||||||
|
"openwebrx admin --help".
|
||||||
|
|
||||||
|
Template: openwebrx/admin_user_configured
|
||||||
|
Type: boolean
|
||||||
|
Default: false
|
||||||
|
Description: OpenWebRX "admin" user previously configured?
|
||||||
|
Marker used internally by the config scripts to remember if an admin user has
|
||||||
|
been created.
|
8
debian/rules
vendored
Executable file
8
debian/rules
vendored
Executable file
@ -0,0 +1,8 @@
|
|||||||
|
#!/usr/bin/make -f
|
||||||
|
export PYBUILD_NAME=openwebrx
|
||||||
|
|
||||||
|
%:
|
||||||
|
dh $@ --with python3 --buildsystem=pybuild --with systemd
|
||||||
|
|
||||||
|
override_dh_strip_nondeterminism:
|
||||||
|
dh_strip_nondeterminism -X.png
|
1
debian/source/format
vendored
Normal file
1
debian/source/format
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
3.0 (native)
|
97
docker.sh
Executable file
97
docker.sh
Executable file
@ -0,0 +1,97 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
IMAGES="openwebrx-rtlsdr openwebrx-sdrplay openwebrx-hackrf openwebrx-airspy openwebrx-rtlsdr-soapy openwebrx-plutosdr openwebrx-limesdr openwebrx-soapyremote openwebrx-perseus openwebrx-fcdpp openwebrx-radioberry openwebrx-uhd openwebrx-rtltcp openwebrx-runds openwebrx-hpsdr openwebrx-bladerf openwebrx-full openwebrx"
|
||||||
|
ALL_ARCHS="x86_64 armv7l aarch64"
|
||||||
|
TAG=${TAG:-"latest"}
|
||||||
|
ARCHTAG="${TAG}-${ARCH}"
|
||||||
|
|
||||||
|
usage () {
|
||||||
|
echo "Usage: ${0} [command]"
|
||||||
|
echo "Available commands:"
|
||||||
|
echo " help Show this usage information"
|
||||||
|
echo " build Build all docker images"
|
||||||
|
echo " push Push built docker images to the docker hub"
|
||||||
|
echo " manifest Compile the docker hub manifest (combines arm and x86 tags into one)"
|
||||||
|
echo " tag Tag a release"
|
||||||
|
}
|
||||||
|
|
||||||
|
build () {
|
||||||
|
# build the base images
|
||||||
|
docker build --pull -t openwebrx-base:${ARCHTAG} -f docker/Dockerfiles/Dockerfile-base .
|
||||||
|
docker build --build-arg ARCHTAG=${ARCHTAG} -t openwebrx-soapysdr-base:${ARCHTAG} -f docker/Dockerfiles/Dockerfile-soapysdr .
|
||||||
|
|
||||||
|
for image in ${IMAGES}; do
|
||||||
|
i=${image:10}
|
||||||
|
# "openwebrx" is a special image that gets tag-aliased later on
|
||||||
|
if [[ ! -z "${i}" ]] ; then
|
||||||
|
docker build --build-arg ARCHTAG=$ARCHTAG -t jketterl/${image}:${ARCHTAG} -f docker/Dockerfiles/Dockerfile-${i} .
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# tag openwebrx alias image
|
||||||
|
docker tag jketterl/openwebrx-full:${ARCHTAG} jketterl/openwebrx:${ARCHTAG}
|
||||||
|
}
|
||||||
|
|
||||||
|
push () {
|
||||||
|
for image in ${IMAGES}; do
|
||||||
|
docker push jketterl/${image}:${ARCHTAG}
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
manifest () {
|
||||||
|
for image in ${IMAGES}; do
|
||||||
|
# there's no docker manifest rm command, and the create --amend does not work, so we have to clean up manually
|
||||||
|
rm -rf "${HOME}/.docker/manifests/docker.io_jketterl_${image}-${TAG}"
|
||||||
|
IMAGE_LIST=""
|
||||||
|
for a in ${ALL_ARCHS}; do
|
||||||
|
IMAGE_LIST="${IMAGE_LIST} jketterl/${image}:${TAG}-${a}"
|
||||||
|
done
|
||||||
|
docker manifest create jketterl/${image}:${TAG} ${IMAGE_LIST}
|
||||||
|
docker manifest push --purge jketterl/${image}:${TAG}
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
tag () {
|
||||||
|
if [[ -x ${1:-} || -z ${2:-} ]] ; then
|
||||||
|
echo "Usage: ${0} tag [SRC_TAG] [TARGET_TAG]"
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
local SRC_TAG=${1}
|
||||||
|
local TARGET_TAG=${2}
|
||||||
|
|
||||||
|
for image in ${IMAGES}; do
|
||||||
|
# there's no docker manifest rm command, and the create --amend does not work, so we have to clean up manually
|
||||||
|
rm -rf "${HOME}/.docker/manifests/docker.io_jketterl_${image}-${TARGET_TAG}"
|
||||||
|
IMAGE_LIST=""
|
||||||
|
for a in ${ALL_ARCHS}; do
|
||||||
|
docker pull jketterl/${image}:${SRC_TAG}-${a}
|
||||||
|
docker tag jketterl/${image}:${SRC_TAG}-${a} jketterl/${image}:${TARGET_TAG}-${a}
|
||||||
|
docker push jketterl/${image}:${TARGET_TAG}-${a}
|
||||||
|
IMAGE_LIST="${IMAGE_LIST} jketterl/${image}:${TARGET_TAG}-${a}"
|
||||||
|
done
|
||||||
|
docker manifest create jketterl/${image}:${TARGET_TAG} ${IMAGE_LIST}
|
||||||
|
docker manifest push --purge jketterl/${image}:${TARGET_TAG}
|
||||||
|
docker pull jketterl/${image}:${TARGET_TAG}
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
case ${1:-} in
|
||||||
|
build)
|
||||||
|
build
|
||||||
|
;;
|
||||||
|
push)
|
||||||
|
push
|
||||||
|
;;
|
||||||
|
manifest)
|
||||||
|
manifest
|
||||||
|
;;
|
||||||
|
tag)
|
||||||
|
tag ${@:2}
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
usage
|
||||||
|
;;
|
||||||
|
esac
|
8
docker/Dockerfiles/Dockerfile-airspy
Normal file
8
docker/Dockerfiles/Dockerfile-airspy
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-airspy.sh /
|
||||||
|
RUN /install-dependencies-airspy.sh &&\
|
||||||
|
rm /install-dependencies-airspy.sh
|
||||||
|
|
||||||
|
ADD . /opt/openwebrx
|
28
docker/Dockerfiles/Dockerfile-base
Normal file
28
docker/Dockerfiles/Dockerfile-base
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
FROM debian:bullseye-slim
|
||||||
|
|
||||||
|
COPY docker/files/js8call/js8call-hamlib.patch \
|
||||||
|
docker/files/wsjtx/wsjtx.patch \
|
||||||
|
docker/files/wsjtx/wsjtx-hamlib.patch \
|
||||||
|
docker/files/dream/dream.patch \
|
||||||
|
docker/files/direwolf/direwolf-hamlib.patch \
|
||||||
|
docker/scripts/install-dependencies.sh /
|
||||||
|
RUN /install-dependencies.sh && \
|
||||||
|
rm /install-dependencies.sh && \
|
||||||
|
rm /*.patch
|
||||||
|
COPY docker/scripts/install-owrx-tools.sh /
|
||||||
|
RUN /install-owrx-tools.sh && \
|
||||||
|
rm /install-owrx-tools.sh
|
||||||
|
|
||||||
|
COPY docker/files/services/codecserver /etc/services.d/codecserver
|
||||||
|
|
||||||
|
ENTRYPOINT ["/init"]
|
||||||
|
|
||||||
|
WORKDIR /opt/openwebrx
|
||||||
|
|
||||||
|
VOLUME /etc/openwebrx
|
||||||
|
VOLUME /var/lib/openwebrx
|
||||||
|
|
||||||
|
ENV S6_CMD_ARG0="/opt/openwebrx/docker/scripts/run.sh"
|
||||||
|
CMD []
|
||||||
|
|
||||||
|
EXPOSE 8073
|
8
docker/Dockerfiles/Dockerfile-bladerf
Normal file
8
docker/Dockerfiles/Dockerfile-bladerf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-bladerf.sh /
|
||||||
|
RUN /install-dependencies-bladerf.sh &&\
|
||||||
|
rm /install-dependencies-bladerf.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-fcdpp
Normal file
8
docker/Dockerfiles/Dockerfile-fcdpp
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-fcdpp.sh /
|
||||||
|
RUN /install-dependencies-fcdpp.sh &&\
|
||||||
|
rm /install-dependencies-fcdpp.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
31
docker/Dockerfiles/Dockerfile-full
Normal file
31
docker/Dockerfiles/Dockerfile-full
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-*.sh \
|
||||||
|
docker/files/sdrplay/install-lib.*.patch \
|
||||||
|
docker/scripts/install-connectors.sh /
|
||||||
|
|
||||||
|
RUN /install-dependencies-rtlsdr.sh &&\
|
||||||
|
/install-dependencies-soapysdr.sh &&\
|
||||||
|
/install-dependencies-hackrf.sh &&\
|
||||||
|
/install-dependencies-sdrplay.sh &&\
|
||||||
|
/install-dependencies-airspy.sh &&\
|
||||||
|
/install-dependencies-rtlsdr-soapy.sh &&\
|
||||||
|
/install-dependencies-plutosdr.sh &&\
|
||||||
|
/install-dependencies-limesdr.sh &&\
|
||||||
|
/install-dependencies-soapyremote.sh &&\
|
||||||
|
/install-dependencies-perseus.sh &&\
|
||||||
|
/install-dependencies-fcdpp.sh &&\
|
||||||
|
/install-dependencies-radioberry.sh &&\
|
||||||
|
/install-dependencies-uhd.sh &&\
|
||||||
|
/install-dependencies-hpsdr.sh &&\
|
||||||
|
/install-dependencies-bladerf.sh &&\
|
||||||
|
/install-connectors.sh &&\
|
||||||
|
/install-dependencies-runds.sh &&\
|
||||||
|
rm /install-dependencies-*.sh &&\
|
||||||
|
rm /install-lib.*.patch && \
|
||||||
|
rm /install-connectors.sh
|
||||||
|
|
||||||
|
COPY docker/files/services/sdrplay /etc/services.d/sdrplay
|
||||||
|
|
||||||
|
ADD . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-hackrf
Normal file
8
docker/Dockerfiles/Dockerfile-hackrf
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-hackrf.sh /
|
||||||
|
RUN /install-dependencies-hackrf.sh &&\
|
||||||
|
rm /install-dependencies-hackrf.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
9
docker/Dockerfiles/Dockerfile-hpsdr
Normal file
9
docker/Dockerfiles/Dockerfile-hpsdr
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-hpsdr.sh /
|
||||||
|
|
||||||
|
RUN /install-dependencies-hpsdr.sh &&\
|
||||||
|
rm /install-dependencies-hpsdr.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-limesdr
Normal file
8
docker/Dockerfiles/Dockerfile-limesdr
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-limesdr.sh /
|
||||||
|
RUN /install-dependencies-limesdr.sh &&\
|
||||||
|
rm /install-dependencies-limesdr.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-perseus
Normal file
8
docker/Dockerfiles/Dockerfile-perseus
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-perseus.sh /
|
||||||
|
RUN /install-dependencies-perseus.sh &&\
|
||||||
|
rm /install-dependencies-perseus.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-plutosdr
Normal file
8
docker/Dockerfiles/Dockerfile-plutosdr
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-plutosdr.sh /
|
||||||
|
RUN /install-dependencies-plutosdr.sh &&\
|
||||||
|
rm /install-dependencies-plutosdr.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-radioberry
Normal file
8
docker/Dockerfiles/Dockerfile-radioberry
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-radioberry.sh /
|
||||||
|
RUN /install-dependencies-radioberry.sh &&\
|
||||||
|
rm /install-dependencies-radioberry.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
12
docker/Dockerfiles/Dockerfile-rtlsdr
Normal file
12
docker/Dockerfiles/Dockerfile-rtlsdr
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-rtlsdr.sh \
|
||||||
|
docker/scripts/install-connectors.sh /
|
||||||
|
|
||||||
|
RUN /install-dependencies-rtlsdr.sh &&\
|
||||||
|
rm /install-dependencies-rtlsdr.sh &&\
|
||||||
|
/install-connectors.sh &&\
|
||||||
|
rm /install-connectors.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-rtlsdr-soapy
Normal file
8
docker/Dockerfiles/Dockerfile-rtlsdr-soapy
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-rtlsdr-soapy.sh /
|
||||||
|
RUN /install-dependencies-rtlsdr-soapy.sh &&\
|
||||||
|
rm /install-dependencies-rtlsdr-soapy.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
9
docker/Dockerfiles/Dockerfile-rtltcp
Normal file
9
docker/Dockerfiles/Dockerfile-rtltcp
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-connectors.sh /
|
||||||
|
|
||||||
|
RUN /install-connectors.sh &&\
|
||||||
|
rm /install-connectors.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
12
docker/Dockerfiles/Dockerfile-runds
Normal file
12
docker/Dockerfiles/Dockerfile-runds
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-connectors.sh \
|
||||||
|
docker/scripts/install-dependencies-runds.sh /
|
||||||
|
|
||||||
|
RUN /install-connectors.sh &&\
|
||||||
|
rm /install-connectors.sh && \
|
||||||
|
/install-dependencies-runds.sh && \
|
||||||
|
rm /install-dependencies-runds.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
12
docker/Dockerfiles/Dockerfile-sdrplay
Normal file
12
docker/Dockerfiles/Dockerfile-sdrplay
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-sdrplay.sh \
|
||||||
|
docker/files/sdrplay/install-lib.*.patch /
|
||||||
|
RUN /install-dependencies-sdrplay.sh &&\
|
||||||
|
rm /install-dependencies-sdrplay.sh &&\
|
||||||
|
rm /install-lib.*.patch
|
||||||
|
|
||||||
|
COPY docker/files/services/sdrplay /etc/services.d/sdrplay
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
8
docker/Dockerfiles/Dockerfile-soapyremote
Normal file
8
docker/Dockerfiles/Dockerfile-soapyremote
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-soapyremote.sh /
|
||||||
|
RUN /install-dependencies-soapyremote.sh &&\
|
||||||
|
rm /install-dependencies-soapyremote.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
9
docker/Dockerfiles/Dockerfile-soapysdr
Normal file
9
docker/Dockerfiles/Dockerfile-soapysdr
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-soapysdr.sh \
|
||||||
|
docker/scripts/install-connectors.sh /
|
||||||
|
RUN /install-dependencies-soapysdr.sh &&\
|
||||||
|
rm /install-dependencies-soapysdr.sh &&\
|
||||||
|
/install-connectors.sh &&\
|
||||||
|
rm /install-connectors.sh
|
8
docker/Dockerfiles/Dockerfile-uhd
Normal file
8
docker/Dockerfiles/Dockerfile-uhd
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
ARG ARCHTAG
|
||||||
|
FROM openwebrx-soapysdr-base:$ARCHTAG
|
||||||
|
|
||||||
|
COPY docker/scripts/install-dependencies-uhd.sh /
|
||||||
|
RUN /install-dependencies-uhd.sh &&\
|
||||||
|
rm /install-dependencies-uhd.sh
|
||||||
|
|
||||||
|
COPY . /opt/openwebrx
|
20
docker/files/direwolf/direwolf-hamlib.patch
Normal file
20
docker/files/direwolf/direwolf-hamlib.patch
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
diff --git a/CMakeLists.txt b/CMakeLists.txt
|
||||||
|
index 9e710f5..da90b43 100644
|
||||||
|
--- a/CMakeLists.txt
|
||||||
|
+++ b/CMakeLists.txt
|
||||||
|
@@ -257,13 +257,8 @@ else()
|
||||||
|
set(GPSD_LIBRARIES "")
|
||||||
|
endif()
|
||||||
|
|
||||||
|
-find_package(hamlib)
|
||||||
|
-if(HAMLIB_FOUND)
|
||||||
|
- set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DUSE_HAMLIB")
|
||||||
|
-else()
|
||||||
|
- set(HAMLIB_INCLUDE_DIRS "")
|
||||||
|
- set(HAMLIB_LIBRARIES "")
|
||||||
|
-endif()
|
||||||
|
+set(HAMLIB_INCLUDE_DIRS "")
|
||||||
|
+set(HAMLIB_LIBRARIES "")
|
||||||
|
|
||||||
|
if(LINUX)
|
||||||
|
find_package(ALSA REQUIRED)
|
96
docker/files/dream/dream.patch
Normal file
96
docker/files/dream/dream.patch
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
--- dream.pro.org 2020-09-04 22:51:51.579926191 +0200
|
||||||
|
+++ dream.pro 2020-09-04 22:52:57.609434707 +0200
|
||||||
|
@@ -70,9 +70,6 @@
|
||||||
|
exists(/opt/local/include/speex/speex_preprocess.h) {
|
||||||
|
CONFIG += speexdsp
|
||||||
|
}
|
||||||
|
- exists(/opt/local/include/hamlib/rig.h) {
|
||||||
|
- CONFIG += hamlib
|
||||||
|
- }
|
||||||
|
contains(QT_VERSION, ^4\\.7.*) {
|
||||||
|
QT += phonon opengl svg
|
||||||
|
DEFINES -= QWT_NO_SVG
|
||||||
|
@@ -138,12 +135,6 @@
|
||||||
|
packagesExist(sndfile) {
|
||||||
|
CONFIG += sndfile
|
||||||
|
}
|
||||||
|
- packagesExist(hamlib) {
|
||||||
|
- CONFIG += hamlib
|
||||||
|
- }
|
||||||
|
- packagesExist(gpsd) {
|
||||||
|
- CONFIG += gps
|
||||||
|
- }
|
||||||
|
packagesExist(pcap) {
|
||||||
|
CONFIG += pcap
|
||||||
|
}
|
||||||
|
@@ -159,14 +150,6 @@
|
||||||
|
exists(/usr/local/include/sndfile.h) {
|
||||||
|
CONFIG += sndfile
|
||||||
|
}
|
||||||
|
- exists(/usr/include/hamlib/rig.h) | \
|
||||||
|
- exists(/usr/local/include/hamlib/rig.h) {
|
||||||
|
- CONFIG += hamlib
|
||||||
|
- }
|
||||||
|
- exists(/usr/include/gps.h) | \
|
||||||
|
- exists(/usr/local/include/gps.h) {
|
||||||
|
- CONFIG += gps
|
||||||
|
- }
|
||||||
|
exists(/usr/include/pcap.h) | \
|
||||||
|
exists(/usr/local/include/pcap.h) {
|
||||||
|
CONFIG += pcap
|
||||||
|
@@ -194,9 +177,6 @@
|
||||||
|
exists($$OUT_PWD/include/speex/speex_preprocess.h) {
|
||||||
|
CONFIG += speexdsp
|
||||||
|
}
|
||||||
|
- exists($$OUT_PWD/include/hamlib/rig.h) {
|
||||||
|
- CONFIG += hamlib
|
||||||
|
- }
|
||||||
|
exists($$OUT_PWD/include/pcap.h) {
|
||||||
|
CONFIG += pcap
|
||||||
|
}
|
||||||
|
@@ -225,7 +205,7 @@
|
||||||
|
LIBS += -lz
|
||||||
|
}
|
||||||
|
}
|
||||||
|
-exists($$OUT_PWD/include/neaacdec.h) {
|
||||||
|
+exists(/usr/include/neaacdec.h) {
|
||||||
|
DEFINES += HAVE_LIBFAAD \
|
||||||
|
USE_FAAD2_LIBRARY
|
||||||
|
LIBS += -lfaad_drm
|
||||||
|
@@ -257,11 +237,6 @@
|
||||||
|
win32:LIBS += libspeexdsp.lib
|
||||||
|
message("with libspeexdsp")
|
||||||
|
}
|
||||||
|
-gps {
|
||||||
|
- DEFINES += HAVE_LIBGPS
|
||||||
|
- unix:LIBS += -lgps
|
||||||
|
- message("with gps")
|
||||||
|
-}
|
||||||
|
pcap {
|
||||||
|
DEFINES += HAVE_LIBPCAP
|
||||||
|
unix:LIBS += -lpcap
|
||||||
|
@@ -269,24 +244,6 @@
|
||||||
|
win32-g++:LIBS += -lwpcap -lpacket
|
||||||
|
message("with pcap")
|
||||||
|
}
|
||||||
|
-hamlib {
|
||||||
|
- DEFINES += HAVE_LIBHAMLIB
|
||||||
|
- macx:LIBS += -framework IOKit
|
||||||
|
- unix:LIBS += -lhamlib
|
||||||
|
- win32:LIBS += libhamlib-2.lib
|
||||||
|
- HEADERS += src/util/Hamlib.h
|
||||||
|
- SOURCES += src/util/Hamlib.cpp
|
||||||
|
- qt {
|
||||||
|
- HEADERS += src/util-QT/Rig.h
|
||||||
|
- SOURCES += src/util-QT/Rig.cpp
|
||||||
|
- }
|
||||||
|
- gui {
|
||||||
|
- HEADERS += src/GUI-QT/RigDlg.h
|
||||||
|
- SOURCES += src/GUI-QT/RigDlg.cpp
|
||||||
|
- FORMS += RigDlg.ui
|
||||||
|
- }
|
||||||
|
- message("with hamlib")
|
||||||
|
-}
|
||||||
|
qwt {
|
||||||
|
DEFINES += QWT_NO_SVG
|
||||||
|
macx {
|
151
docker/files/js8call/js8call-hamlib.patch
Normal file
151
docker/files/js8call/js8call-hamlib.patch
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
diff -ur js8call-orig/CMake/Modules/Findhamlib.cmake js8call/CMake/Modules/Findhamlib.cmake
|
||||||
|
--- js8call-orig/CMake/Modules/Findhamlib.cmake 2020-07-22 18:14:18.014499840 +0200
|
||||||
|
+++ js8call/CMake/Modules/Findhamlib.cmake 2020-07-22 18:16:07.200375473 +0200
|
||||||
|
@@ -78,4 +78,4 @@
|
||||||
|
# Handle the QUIETLY and REQUIRED arguments and set HAMLIB_FOUND to
|
||||||
|
# TRUE if all listed variables are TRUE
|
||||||
|
include (FindPackageHandleStandardArgs)
|
||||||
|
-find_package_handle_standard_args (hamlib DEFAULT_MSG hamlib_INCLUDE_DIRS hamlib_LIBRARIES hamlib_LIBRARY_DIRS)
|
||||||
|
+find_package_handle_standard_args (hamlib DEFAULT_MSG hamlib_INCLUDE_DIRS hamlib_LIBRARIES)
|
||||||
|
diff -ur js8call-orig/CMakeLists.txt js8call/CMakeLists.txt
|
||||||
|
--- js8call-orig/CMakeLists.txt 2020-07-22 18:14:18.014499840 +0200
|
||||||
|
+++ js8call/CMakeLists.txt 2020-07-22 18:17:55.629633825 +0200
|
||||||
|
@@ -558,7 +558,7 @@
|
||||||
|
#
|
||||||
|
# libhamlib setup
|
||||||
|
#
|
||||||
|
-set (hamlib_STATIC 1)
|
||||||
|
+set (hamlib_STATIC 0)
|
||||||
|
find_package (hamlib 3 REQUIRED)
|
||||||
|
find_program (RIGCTL_EXE rigctl)
|
||||||
|
find_program (RIGCTLD_EXE rigctld)
|
||||||
|
@@ -911,56 +911,6 @@
|
||||||
|
target_link_libraries (js8 wsjt_fort wsjt_cxx Qt5::Core)
|
||||||
|
endif (${OPENMP_FOUND} OR APPLE)
|
||||||
|
|
||||||
|
-# build the main application
|
||||||
|
-add_executable (js8call MACOSX_BUNDLE
|
||||||
|
- ${sqlite3_CSRCS}
|
||||||
|
- ${wsjtx_CXXSRCS}
|
||||||
|
- ${wsjtx_GENUISRCS}
|
||||||
|
- wsjtx.rc
|
||||||
|
- ${WSJTX_ICON_FILE}
|
||||||
|
- ${wsjtx_RESOURCES_RCC}
|
||||||
|
- images.qrc
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-if (WSJT_CREATE_WINMAIN)
|
||||||
|
- set_target_properties (js8call PROPERTIES WIN32_EXECUTABLE ON)
|
||||||
|
-endif (WSJT_CREATE_WINMAIN)
|
||||||
|
-
|
||||||
|
-set_target_properties (js8call PROPERTIES
|
||||||
|
- MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Darwin/Info.plist.in"
|
||||||
|
- MACOSX_BUNDLE_INFO_STRING "${WSJTX_DESCRIPTION_SUMMARY}"
|
||||||
|
- MACOSX_BUNDLE_ICON_FILE "${WSJTX_ICON_FILE}"
|
||||||
|
- MACOSX_BUNDLE_BUNDLE_VERSION ${wsjtx_VERSION}
|
||||||
|
- MACOSX_BUNDLE_SHORT_VERSION_STRING "v${wsjtx_VERSION}"
|
||||||
|
- MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${wsjtx_VERSION}"
|
||||||
|
- MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}"
|
||||||
|
- MACOSX_BUNDLE_BUNDLE_EXECUTABLE_NAME "${PROJECT_NAME}"
|
||||||
|
- MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT}"
|
||||||
|
- MACOSX_BUNDLE_GUI_IDENTIFIER "org.kn4crd.js8call"
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-target_include_directories (js8call PRIVATE ${FFTW3_INCLUDE_DIRS})
|
||||||
|
-if (APPLE)
|
||||||
|
- target_link_libraries (js8call wsjt_fort wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
|
||||||
|
-else ()
|
||||||
|
- target_link_libraries (js8call wsjt_fort_omp wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
|
||||||
|
- if (OpenMP_C_FLAGS)
|
||||||
|
- set_target_properties (js8call PROPERTIES
|
||||||
|
- COMPILE_FLAGS "${OpenMP_C_FLAGS}"
|
||||||
|
- LINK_FLAGS "${OpenMP_C_FLAGS}"
|
||||||
|
- )
|
||||||
|
- endif ()
|
||||||
|
- set_target_properties (js8call PROPERTIES
|
||||||
|
- Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp
|
||||||
|
- )
|
||||||
|
- if (WIN32)
|
||||||
|
- set_target_properties (js8call PROPERTIES
|
||||||
|
- LINK_FLAGS -Wl,--stack,16777216
|
||||||
|
- )
|
||||||
|
- endif ()
|
||||||
|
-endif ()
|
||||||
|
-qt5_use_modules (js8call SerialPort) # not sure why the interface link library syntax above doesn't work
|
||||||
|
-
|
||||||
|
# if (UNIX)
|
||||||
|
# if (NOT WSJT_SKIP_MANPAGES)
|
||||||
|
# add_subdirectory (manpages)
|
||||||
|
@@ -976,38 +926,10 @@
|
||||||
|
#
|
||||||
|
# installation
|
||||||
|
#
|
||||||
|
-install (TARGETS js8call
|
||||||
|
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
- BUNDLE DESTINATION . COMPONENT runtime
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
install (TARGETS js8 RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
)
|
||||||
|
|
||||||
|
-install (PROGRAMS
|
||||||
|
- ${RIGCTL_EXE}
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- RENAME rigctl-local${CMAKE_EXECUTABLE_SUFFIX}
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-install (PROGRAMS
|
||||||
|
- ${RIGCTLD_EXE}
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- RENAME rigctld-local${CMAKE_EXECUTABLE_SUFFIX}
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-install (FILES
|
||||||
|
- README
|
||||||
|
- COPYING
|
||||||
|
- INSTALL
|
||||||
|
- INSTALL-WSJTX
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
install (FILES
|
||||||
|
contrib/Ephemeris/JPLEPH
|
||||||
|
DESTINATION ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}
|
||||||
|
@@ -1061,32 +983,6 @@
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/wsjtx_config.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
-
|
||||||
|
-if (NOT WIN32 AND NOT APPLE)
|
||||||
|
- # install a desktop file so js8call appears in the application start
|
||||||
|
- # menu with an icon
|
||||||
|
- install (
|
||||||
|
- FILES js8call.desktop
|
||||||
|
- DESTINATION /usr/share/applications
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
- install (
|
||||||
|
- FILES icons/Unix/js8call_icon.png
|
||||||
|
- DESTINATION /usr/share/pixmaps
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
- IF("${CMAKE_INSTALL_PREFIX}" STREQUAL "/opt/js8call")
|
||||||
|
- execute_process(COMMAND ln -s /opt/js8call/bin/js8call ljs8call)
|
||||||
|
-
|
||||||
|
- install(FILES
|
||||||
|
- ${CMAKE_BINARY_DIR}/ljs8call DESTINATION /usr/bin/ RENAME js8call
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
- endif()
|
||||||
|
-endif (NOT WIN32 AND NOT APPLE)
|
||||||
|
-
|
||||||
|
-
|
||||||
|
#
|
||||||
|
# bundle fixup only done in Release or MinSizeRel configurations
|
||||||
|
#
|
||||||
|
Only in js8call/: .idea
|
23
docker/files/sdrplay/install-lib.aarch64.patch
Normal file
23
docker/files/sdrplay/install-lib.aarch64.patch
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
diff -ur sdrplay-orig/install_lib.sh sdrplay/install_lib.sh
|
||||||
|
--- sdrplay-orig/install_lib.sh 2020-05-24 14:30:06.022483867 +0000
|
||||||
|
+++ sdrplay/install_lib.sh 2020-05-24 14:30:49.093435726 +0000
|
||||||
|
@@ -4,19 +4,6 @@
|
||||||
|
export MAJVERS="3"
|
||||||
|
|
||||||
|
echo "Installing SDRplay RSP API library ${VERS}..."
|
||||||
|
-read -p "Press RETURN to view the license agreement" ret
|
||||||
|
-
|
||||||
|
-more sdrplay_license.txt
|
||||||
|
-
|
||||||
|
-while true; do
|
||||||
|
- echo "Press y and RETURN to accept the license agreement and continue with"
|
||||||
|
- read -p "the installation, or press n and RETURN to exit the installer [y/n] " yn
|
||||||
|
- case $yn in
|
||||||
|
- [Yy]* ) break;;
|
||||||
|
- [Nn]* ) exit;;
|
||||||
|
- * ) echo "Please answer y or n";;
|
||||||
|
- esac
|
||||||
|
-done
|
||||||
|
|
||||||
|
export ARCH=`uname -m`
|
||||||
|
|
40
docker/files/sdrplay/install-lib.armv7l.patch
Normal file
40
docker/files/sdrplay/install-lib.armv7l.patch
Normal file
@ -0,0 +1,40 @@
|
|||||||
|
diff -ur sdrplay-orig/install_lib.sh sdrplay/install_lib.sh
|
||||||
|
--- sdrplay-orig/install_lib.sh 2020-05-24 14:13:04.561271707 +0000
|
||||||
|
+++ sdrplay/install_lib.sh 2020-05-24 14:16:20.068329040 +0000
|
||||||
|
@@ -4,19 +4,6 @@
|
||||||
|
MAJVERS="3"
|
||||||
|
|
||||||
|
echo "Installing SDRplay RSP API library ${VERS}..."
|
||||||
|
-read -p "Press RETURN to view the license agreement" ret
|
||||||
|
-
|
||||||
|
-more sdrplay_license.txt
|
||||||
|
-
|
||||||
|
-while true; do
|
||||||
|
- echo "Press y and RETURN to accept the license agreement and continue with"
|
||||||
|
- read -p "the installation, or press n and RETURN to exit the installer [y/n] " yn
|
||||||
|
- case $yn in
|
||||||
|
- [Yy]* ) break;;
|
||||||
|
- [Nn]* ) exit;;
|
||||||
|
- * ) echo "Please answer y or n";;
|
||||||
|
- esac
|
||||||
|
-done
|
||||||
|
|
||||||
|
ARCH=`uname -m`
|
||||||
|
|
||||||
|
@@ -141,16 +128,6 @@
|
||||||
|
echo "SDRplay API ${VERS} Installation Finished"
|
||||||
|
echo " "
|
||||||
|
|
||||||
|
-while true; do
|
||||||
|
- echo "Would you like to add SDRplay USB IDs to the local database for easier
|
||||||
|
-"
|
||||||
|
- read -p "identification in applications such as lsusb? [y/n] " yn
|
||||||
|
- case $yn in
|
||||||
|
- [Yy]* ) break;;
|
||||||
|
- [Nn]* ) exit;;
|
||||||
|
- * ) echo "Please answer y or n";;
|
||||||
|
- esac
|
||||||
|
-done
|
||||||
|
sudo cp scripts/sdrplay_usbids.sh ${INSTALLBINDIR}/.
|
||||||
|
sudo chmod 755 ${INSTALLBINDIR}/sdrplay_usbids.sh
|
||||||
|
sudo cp scripts/sdrplay_ids.txt ${INSTALLBINDIR}/.
|
39
docker/files/sdrplay/install-lib.x86_64.patch
Normal file
39
docker/files/sdrplay/install-lib.x86_64.patch
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
diff -ur sdrplay-orig/install_lib.sh sdrplay/install_lib.sh
|
||||||
|
--- sdrplay-orig/install_lib.sh 2020-05-24 13:56:56.622000041 +0000
|
||||||
|
+++ sdrplay/install_lib.sh 2020-05-24 13:58:51.837801559 +0000
|
||||||
|
@@ -4,19 +4,6 @@
|
||||||
|
MAJVERS="3"
|
||||||
|
|
||||||
|
echo "Installing SDRplay RSP API library ${VERS}..."
|
||||||
|
-read -p "Press RETURN to view the license agreement" ret
|
||||||
|
-
|
||||||
|
-more sdrplay_license.txt
|
||||||
|
-
|
||||||
|
-while true; do
|
||||||
|
- echo "Press y and RETURN to accept the license agreement and continue with"
|
||||||
|
- read -p "the installation, or press n and RETURN to exit the installer [y/n] " yn
|
||||||
|
- case $yn in
|
||||||
|
- [Yy]* ) break;;
|
||||||
|
- [Nn]* ) exit;;
|
||||||
|
- * ) echo "Please answer y or n";;
|
||||||
|
- esac
|
||||||
|
-done
|
||||||
|
|
||||||
|
ARCH=`uname -m`
|
||||||
|
OSDIST="Unknown"
|
||||||
|
@@ -157,15 +144,6 @@
|
||||||
|
echo " "
|
||||||
|
echo "SDRplay API ${VERS} Installation Finished"
|
||||||
|
echo " "
|
||||||
|
-while true; do
|
||||||
|
- echo "Would you like to add SDRplay USB IDs to the local database for easier"
|
||||||
|
- read -p "identification in applications such as lsusb? [y/n] " yn
|
||||||
|
- case $yn in
|
||||||
|
- [Yy]* ) break;;
|
||||||
|
- [Nn]* ) exit;;
|
||||||
|
- * ) echo "Please answer y or n";;
|
||||||
|
- esac
|
||||||
|
-done
|
||||||
|
sudo cp scripts/sdrplay_usbids.sh ${INSTALLBINDIR}/.
|
||||||
|
sudo chmod 755 ${INSTALLBINDIR}/sdrplay_usbids.sh
|
||||||
|
sudo cp scripts/sdrplay_ids.txt ${INSTALLBINDIR}/.
|
2
docker/files/services/codecserver/run
Executable file
2
docker/files/services/codecserver/run
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/execlineb -P
|
||||||
|
/usr/local/bin/codecserver
|
2
docker/files/services/sdrplay/run
Executable file
2
docker/files/services/sdrplay/run
Executable file
@ -0,0 +1,2 @@
|
|||||||
|
#!/usr/bin/execlineb -P
|
||||||
|
/usr/local/bin/sdrplay_apiService
|
50
docker/files/wsjtx/wsjtx-hamlib.patch
Normal file
50
docker/files/wsjtx/wsjtx-hamlib.patch
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
--- CMakeLists.txt.orig 2021-09-28 14:33:14.329598412 +0200
|
||||||
|
+++ CMakeLists.txt 2021-09-28 14:34:23.052345270 +0200
|
||||||
|
@@ -106,24 +106,6 @@
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
-# build and install hamlib locally so it can be referenced by the
|
||||||
|
-# WSJT-X build
|
||||||
|
-#
|
||||||
|
-ExternalProject_Add (hamlib
|
||||||
|
- GIT_REPOSITORY ${hamlib_repo}
|
||||||
|
- GIT_TAG ${hamlib_TAG}
|
||||||
|
- GIT_SHALLOW False
|
||||||
|
- URL ${CMAKE_CURRENT_SOURCE_DIR}/src/${__hamlib_upstream}.tar.gz
|
||||||
|
- URL_HASH MD5=${hamlib_md5sum}
|
||||||
|
- #UPDATE_COMMAND ${CMAKE_COMMAND} -E env "[ -f ./bootstrap ] && ./bootstrap"
|
||||||
|
- PATCH_COMMAND ${PATCH_EXECUTABLE} -p1 -N < ${CMAKE_CURRENT_SOURCE_DIR}/hamlib.patch
|
||||||
|
- CONFIGURE_COMMAND <SOURCE_DIR>/configure --prefix=<INSTALL_DIR> --disable-shared --enable-static --without-cxx-binding ${EXTRA_FLAGS} # LIBUSB_LIBS=${USB_LIBRARY}
|
||||||
|
- BUILD_COMMAND $(MAKE) all V=1 # $(MAKE) is ExternalProject_Add() magic to do recursive make
|
||||||
|
- INSTALL_COMMAND $(MAKE) install-strip V=1 DESTDIR=""
|
||||||
|
- STEP_TARGETS update install
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-#
|
||||||
|
# custom target to make a hamlib source tarball
|
||||||
|
#
|
||||||
|
add_custom_target (hamlib_sources
|
||||||
|
@@ -161,7 +143,6 @@
|
||||||
|
# build and optionally install WSJT-X using the hamlib package built
|
||||||
|
# above
|
||||||
|
#
|
||||||
|
-ExternalProject_Get_Property (hamlib INSTALL_DIR)
|
||||||
|
ExternalProject_Add (wsjtx
|
||||||
|
GIT_REPOSITORY ${wsjtx_repo}
|
||||||
|
GIT_TAG ${WSJTX_TAG}
|
||||||
|
@@ -186,14 +167,8 @@
|
||||||
|
DEPENDEES build
|
||||||
|
)
|
||||||
|
|
||||||
|
-set_target_properties (hamlib PROPERTIES EXCLUDE_FROM_ALL 1)
|
||||||
|
set_target_properties (wsjtx PROPERTIES EXCLUDE_FROM_ALL 1)
|
||||||
|
|
||||||
|
-add_dependencies (wsjtx-configure hamlib-install)
|
||||||
|
-add_dependencies (wsjtx-build hamlib-install)
|
||||||
|
-add_dependencies (wsjtx-install hamlib-install)
|
||||||
|
-add_dependencies (wsjtx-package hamlib-install)
|
||||||
|
-
|
||||||
|
# export traditional targets
|
||||||
|
add_custom_target (build ALL DEPENDS wsjtx-build)
|
||||||
|
add_custom_target (install DEPENDS wsjtx-install)
|
310
docker/files/wsjtx/wsjtx.patch
Normal file
310
docker/files/wsjtx/wsjtx.patch
Normal file
@ -0,0 +1,310 @@
|
|||||||
|
diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt
|
||||||
|
--- wsjtx-orig/CMakeLists.txt 2021-11-02 16:34:09.361811689 +0100
|
||||||
|
+++ wsjtx/CMakeLists.txt 2021-11-02 16:38:36.696088115 +0100
|
||||||
|
@@ -122,7 +122,7 @@
|
||||||
|
option (WSJT_QDEBUG_TO_FILE "Redirect Qt debuging messages to a trace file.")
|
||||||
|
option (WSJT_SOFT_KEYING "Apply a ramp to CW keying envelope to reduce transients." ON)
|
||||||
|
option (WSJT_SKIP_MANPAGES "Skip *nix manpage generation.")
|
||||||
|
-option (WSJT_GENERATE_DOCS "Generate documentation files." ON)
|
||||||
|
+option (WSJT_GENERATE_DOCS "Generate documentation files.")
|
||||||
|
option (WSJT_RIG_NONE_CAN_SPLIT "Allow split operation with \"None\" as rig.")
|
||||||
|
option (WSJT_TRACE_UDP "Debugging option that turns on UDP message protocol diagnostics.")
|
||||||
|
option (WSJT_BUILD_UTILS "Build simulators and code demonstrators." ON)
|
||||||
|
@@ -169,76 +169,7 @@
|
||||||
|
)
|
||||||
|
|
||||||
|
set (wsjt_qt_CXXSRCS
|
||||||
|
- helper_functions.cpp
|
||||||
|
- qt_helpers.cpp
|
||||||
|
- widgets/MessageBox.cpp
|
||||||
|
- MetaDataRegistry.cpp
|
||||||
|
- Network/NetworkServerLookup.cpp
|
||||||
|
revision_utils.cpp
|
||||||
|
- L10nLoader.cpp
|
||||||
|
- WFPalette.cpp
|
||||||
|
- Radio.cpp
|
||||||
|
- RadioMetaType.cpp
|
||||||
|
- NonInheritingProcess.cpp
|
||||||
|
- models/IARURegions.cpp
|
||||||
|
- models/Bands.cpp
|
||||||
|
- models/Modes.cpp
|
||||||
|
- models/FrequencyList.cpp
|
||||||
|
- models/StationList.cpp
|
||||||
|
- widgets/FrequencyLineEdit.cpp
|
||||||
|
- widgets/FrequencyDeltaLineEdit.cpp
|
||||||
|
- item_delegates/CandidateKeyFilter.cpp
|
||||||
|
- item_delegates/ForeignKeyDelegate.cpp
|
||||||
|
- validators/LiveFrequencyValidator.cpp
|
||||||
|
- GetUserId.cpp
|
||||||
|
- Audio/AudioDevice.cpp
|
||||||
|
- Transceiver/Transceiver.cpp
|
||||||
|
- Transceiver/TransceiverBase.cpp
|
||||||
|
- Transceiver/EmulateSplitTransceiver.cpp
|
||||||
|
- Transceiver/TransceiverFactory.cpp
|
||||||
|
- Transceiver/PollingTransceiver.cpp
|
||||||
|
- Transceiver/HamlibTransceiver.cpp
|
||||||
|
- Transceiver/HRDTransceiver.cpp
|
||||||
|
- Transceiver/DXLabSuiteCommanderTransceiver.cpp
|
||||||
|
- Network/NetworkMessage.cpp
|
||||||
|
- Network/MessageClient.cpp
|
||||||
|
- widgets/LettersSpinBox.cpp
|
||||||
|
- widgets/HintedSpinBox.cpp
|
||||||
|
- widgets/RestrictedSpinBox.cpp
|
||||||
|
- widgets/HelpTextWindow.cpp
|
||||||
|
- SampleDownloader.cpp
|
||||||
|
- SampleDownloader/DirectoryDelegate.cpp
|
||||||
|
- SampleDownloader/Directory.cpp
|
||||||
|
- SampleDownloader/FileNode.cpp
|
||||||
|
- SampleDownloader/RemoteFile.cpp
|
||||||
|
- DisplayManual.cpp
|
||||||
|
- MultiSettings.cpp
|
||||||
|
- validators/MaidenheadLocatorValidator.cpp
|
||||||
|
- validators/CallsignValidator.cpp
|
||||||
|
- widgets/SplashScreen.cpp
|
||||||
|
- EqualizationToolsDialog.cpp
|
||||||
|
- widgets/DoubleClickablePushButton.cpp
|
||||||
|
- widgets/DoubleClickableRadioButton.cpp
|
||||||
|
- Network/LotWUsers.cpp
|
||||||
|
- models/DecodeHighlightingModel.cpp
|
||||||
|
- widgets/DecodeHighlightingListView.cpp
|
||||||
|
- models/FoxLog.cpp
|
||||||
|
- widgets/AbstractLogWindow.cpp
|
||||||
|
- widgets/FoxLogWindow.cpp
|
||||||
|
- widgets/CabrilloLogWindow.cpp
|
||||||
|
- item_delegates/CallsignDelegate.cpp
|
||||||
|
- item_delegates/MaidenheadLocatorDelegate.cpp
|
||||||
|
- item_delegates/FrequencyDelegate.cpp
|
||||||
|
- item_delegates/FrequencyDeltaDelegate.cpp
|
||||||
|
- item_delegates/SQLiteDateTimeDelegate.cpp
|
||||||
|
- models/CabrilloLog.cpp
|
||||||
|
- logbook/AD1CCty.cpp
|
||||||
|
- logbook/WorkedBefore.cpp
|
||||||
|
- logbook/Multiplier.cpp
|
||||||
|
- Network/NetworkAccessManager.cpp
|
||||||
|
- widgets/LazyFillComboBox.cpp
|
||||||
|
- widgets/CheckableItemComboBox.cpp
|
||||||
|
- widgets/BandComboBox.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set (wsjt_qtmm_CXXSRCS
|
||||||
|
@@ -1079,9 +1010,6 @@
|
||||||
|
if (WSJT_GENERATE_DOCS)
|
||||||
|
add_subdirectory (doc)
|
||||||
|
endif (WSJT_GENERATE_DOCS)
|
||||||
|
-if (EXISTS ${CMAKE_SOURCE_DIR}/tests AND IS_DIRECTORY ${CMAKE_SOURCE_DIR}/tests)
|
||||||
|
- add_subdirectory (tests)
|
||||||
|
-endif ()
|
||||||
|
|
||||||
|
# build a library of package functionality (without and optionally with OpenMP support)
|
||||||
|
add_library (wsjt_cxx STATIC ${wsjt_CSRCS} ${wsjt_CXXSRCS})
|
||||||
|
@@ -1340,10 +1268,7 @@
|
||||||
|
add_library (wsjt_qt STATIC ${wsjt_qt_CXXSRCS} ${wsjt_qt_GENUISRCS} ${GENAXSRCS})
|
||||||
|
# set wsjtx_udp exports to static variants
|
||||||
|
target_compile_definitions (wsjt_qt PUBLIC UDP_STATIC_DEFINE)
|
||||||
|
-target_link_libraries (wsjt_qt Hamlib::Hamlib Boost::log qcp Qt5::Widgets Qt5::Network Qt5::Sql)
|
||||||
|
-if (WIN32)
|
||||||
|
- target_link_libraries (wsjt_qt Qt5::AxContainer Qt5::AxBase)
|
||||||
|
-endif (WIN32)
|
||||||
|
+target_link_libraries (wsjt_qt Qt5::Core)
|
||||||
|
|
||||||
|
# build a library of package Qt functionality used in Fortran utilities
|
||||||
|
add_library (fort_qt STATIC ${fort_qt_CXXSRCS})
|
||||||
|
@@ -1408,60 +1333,6 @@
|
||||||
|
add_subdirectory (map65)
|
||||||
|
endif ()
|
||||||
|
|
||||||
|
-# build the main application
|
||||||
|
-generate_version_info (wsjtx_VERSION_RESOURCES
|
||||||
|
- NAME wsjtx
|
||||||
|
- BUNDLE ${PROJECT_BUNDLE_NAME}
|
||||||
|
- ICON ${WSJTX_ICON_FILE}
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-add_executable (wsjtx MACOSX_BUNDLE
|
||||||
|
- ${wsjtx_CXXSRCS}
|
||||||
|
- ${wsjtx_GENUISRCS}
|
||||||
|
- ${WSJTX_ICON_FILE}
|
||||||
|
- ${wsjtx_RESOURCES_RCC}
|
||||||
|
- ${wsjtx_VERSION_RESOURCES}
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-if (WSJT_CREATE_WINMAIN)
|
||||||
|
- set_target_properties (wsjtx PROPERTIES WIN32_EXECUTABLE ON)
|
||||||
|
-endif (WSJT_CREATE_WINMAIN)
|
||||||
|
-
|
||||||
|
-set_target_properties (wsjtx PROPERTIES
|
||||||
|
- MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Darwin/Info.plist.in"
|
||||||
|
- MACOSX_BUNDLE_INFO_STRING "${PROJECT_DESCRIPTION}"
|
||||||
|
- MACOSX_BUNDLE_ICON_FILE "${WSJTX_ICON_FILE}"
|
||||||
|
- MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
|
||||||
|
- MACOSX_BUNDLE_SHORT_VERSION_STRING "v${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}"
|
||||||
|
- MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${SCS_VERSION_STR}"
|
||||||
|
- MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_BUNDLE_NAME}"
|
||||||
|
- MACOSX_BUNDLE_BUNDLE_EXECUTABLE_NAME "${PROJECT_NAME}"
|
||||||
|
- MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT}"
|
||||||
|
- MACOSX_BUNDLE_GUI_IDENTIFIER "org.k1jt.wsjtx"
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
|
||||||
|
-if (APPLE)
|
||||||
|
- target_link_libraries (wsjtx wsjt_fort)
|
||||||
|
-else ()
|
||||||
|
- target_link_libraries (wsjtx wsjt_fort_omp)
|
||||||
|
- if (OpenMP_C_FLAGS)
|
||||||
|
- set_target_properties (wsjtx PROPERTIES
|
||||||
|
- COMPILE_FLAGS "${OpenMP_C_FLAGS}"
|
||||||
|
- LINK_FLAGS "${OpenMP_C_FLAGS}"
|
||||||
|
- )
|
||||||
|
- endif ()
|
||||||
|
- set_target_properties (wsjtx PROPERTIES
|
||||||
|
- Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp
|
||||||
|
- )
|
||||||
|
- if (WIN32)
|
||||||
|
- set_target_properties (wsjtx PROPERTIES
|
||||||
|
- LINK_FLAGS -Wl,--stack,0x1000000,--heap,0x20000000
|
||||||
|
- )
|
||||||
|
- endif ()
|
||||||
|
-endif ()
|
||||||
|
-target_link_libraries (wsjtx Qt5::SerialPort wsjt_cxx wsjt_qt wsjt_qtmm ${FFTW3_LIBRARIES} ${LIBM_LIBRARIES})
|
||||||
|
-
|
||||||
|
# make a library for WSJT-X UDP servers
|
||||||
|
# add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS})
|
||||||
|
add_library (wsjtx_udp-static STATIC ${UDP_library_CXXSRCS})
|
||||||
|
@@ -1501,47 +1372,9 @@
|
||||||
|
add_executable (wsjtx_app_version AppVersion/AppVersion.cpp ${wsjtx_app_version_VERSION_RESOURCES})
|
||||||
|
target_link_libraries (wsjtx_app_version wsjt_qt)
|
||||||
|
|
||||||
|
-generate_version_info (message_aggregator_VERSION_RESOURCES
|
||||||
|
- NAME message_aggregator
|
||||||
|
- BUNDLE ${PROJECT_BUNDLE_NAME}
|
||||||
|
- ICON ${WSJTX_ICON_FILE}
|
||||||
|
- FILE_DESCRIPTION "Example WSJT-X UDP Message Protocol application"
|
||||||
|
- )
|
||||||
|
-add_resources (message_aggregator_RESOURCES /qss ${message_aggregator_STYLESHEETS})
|
||||||
|
-configure_file (UDPExamples/message_aggregator.qrc.in message_aggregator.qrc @ONLY)
|
||||||
|
-qt5_add_resources (message_aggregator_RESOURCES_RCC
|
||||||
|
- ${CMAKE_CURRENT_BINARY_DIR}/message_aggregator.qrc
|
||||||
|
- contrib/QDarkStyleSheet/qdarkstyle/style.qrc
|
||||||
|
- )
|
||||||
|
-add_executable (message_aggregator
|
||||||
|
- ${message_aggregator_CXXSRCS}
|
||||||
|
- ${message_aggregator_RESOURCES_RCC}
|
||||||
|
- ${message_aggregator_VERSION_RESOURCES}
|
||||||
|
- )
|
||||||
|
-target_link_libraries (message_aggregator wsjt_qt Qt5::Widgets wsjtx_udp-static)
|
||||||
|
-
|
||||||
|
-if (WSJT_CREATE_WINMAIN)
|
||||||
|
- set_target_properties (message_aggregator PROPERTIES WIN32_EXECUTABLE ON)
|
||||||
|
-endif (WSJT_CREATE_WINMAIN)
|
||||||
|
-
|
||||||
|
-if (UNIX)
|
||||||
|
- if (NOT WSJT_SKIP_MANPAGES)
|
||||||
|
- add_subdirectory (manpages)
|
||||||
|
- add_dependencies (wsjtx manpages)
|
||||||
|
- endif (NOT WSJT_SKIP_MANPAGES)
|
||||||
|
- if (NOT APPLE)
|
||||||
|
- add_subdirectory (debian)
|
||||||
|
- add_dependencies (wsjtx debian)
|
||||||
|
- endif (NOT APPLE)
|
||||||
|
-endif (UNIX)
|
||||||
|
-
|
||||||
|
#
|
||||||
|
# installation
|
||||||
|
#
|
||||||
|
-install (TARGETS wsjtx
|
||||||
|
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
- BUNDLE DESTINATION . COMPONENT runtime
|
||||||
|
- )
|
||||||
|
|
||||||
|
# install (TARGETS wsjtx_udp EXPORT udp
|
||||||
|
# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
@@ -1560,12 +1393,7 @@
|
||||||
|
# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wsjtx
|
||||||
|
# )
|
||||||
|
|
||||||
|
-install (TARGETS udp_daemon message_aggregator wsjtx_app_version
|
||||||
|
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
- BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-install (TARGETS jt9 wsprd fmtave fcal fmeasure
|
||||||
|
+install (TARGETS wsjtx_app_version jt9 wsprd
|
||||||
|
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
|
||||||
|
)
|
||||||
|
@@ -1578,38 +1406,6 @@
|
||||||
|
)
|
||||||
|
endif(WSJT_BUILD_UTILS)
|
||||||
|
|
||||||
|
-install (PROGRAMS
|
||||||
|
- ${RIGCTL_EXE}
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- RENAME rigctl-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-install (PROGRAMS
|
||||||
|
- ${RIGCTLD_EXE}
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- RENAME rigctld-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-install (PROGRAMS
|
||||||
|
- ${RIGCTLCOM_EXE}
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_BINDIR}
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- RENAME rigctlcom-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
-install (FILES
|
||||||
|
- README
|
||||||
|
- COPYING
|
||||||
|
- AUTHORS
|
||||||
|
- THANKS
|
||||||
|
- NEWS
|
||||||
|
- BUGS
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
install (FILES
|
||||||
|
cty.dat
|
||||||
|
cty.dat_copyright.txt
|
||||||
|
@@ -1618,13 +1414,6 @@
|
||||||
|
#COMPONENT runtime
|
||||||
|
)
|
||||||
|
|
||||||
|
-install (DIRECTORY
|
||||||
|
- example_log_configurations
|
||||||
|
- DESTINATION ${CMAKE_INSTALL_DOCDIR}
|
||||||
|
- FILES_MATCHING REGEX "^.*[^~]$"
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
-
|
||||||
|
#
|
||||||
|
# Mac installer files
|
||||||
|
#
|
||||||
|
@@ -1676,22 +1465,6 @@
|
||||||
|
"${CMAKE_CURRENT_BINARY_DIR}/wsjtx_config.h"
|
||||||
|
)
|
||||||
|
|
||||||
|
-
|
||||||
|
-if (NOT WIN32 AND NOT APPLE)
|
||||||
|
- # install a desktop file so wsjtx appears in the application start
|
||||||
|
- # menu with an icon
|
||||||
|
- install (
|
||||||
|
- FILES wsjtx.desktop message_aggregator.desktop
|
||||||
|
- DESTINATION share/applications
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
- install (
|
||||||
|
- FILES icons/Unix/wsjtx_icon.png
|
||||||
|
- DESTINATION share/pixmaps
|
||||||
|
- #COMPONENT runtime
|
||||||
|
- )
|
||||||
|
-endif (NOT WIN32 AND NOT APPLE)
|
||||||
|
-
|
||||||
|
if (APPLE)
|
||||||
|
set (CMAKE_POSTFLIGHT_SCRIPT
|
||||||
|
"${wsjtx_BINARY_DIR}/postflight.sh")
|
31
docker/scripts/install-connectors.sh
Executable file
31
docker/scripts/install-connectors.sh
Executable file
@ -0,0 +1,31 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
BUILD_PACKAGES="git cmake make gcc g++ libsamplerate-dev libfftw3-dev"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/owrx_connector.git
|
||||||
|
cmakebuild owrx_connector 0.6.0
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
44
docker/scripts/install-dependencies-airspy.sh
Executable file
44
docker/scripts/install-dependencies-airspy.sh
Executable file
@ -0,0 +1,44 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0"
|
||||||
|
BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++ pkg-config"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/airspy/airspyone_host.git
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild airspyone_host 652fd7f1a8f85687641e0bd91f739694d7258ecc
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyAirspy.git
|
||||||
|
cmakebuild SoapyAirspy 10d697b209e7f1acc8b2c8d24851d46170ef77e3
|
||||||
|
|
||||||
|
git clone https://github.com/airspy/airspyhf.git
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild airspyhf 8891387edddcd185e2949e9814e9ef35f46f0722
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyAirspyHF.git
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild SoapyAirspyHF 5488dac5b44f1432ce67b40b915f7e61d3bd4853
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
36
docker/scripts/install-dependencies-bladerf.sh
Executable file
36
docker/scripts/install-dependencies-bladerf.sh
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0"
|
||||||
|
BUILD_PACKAGES="git cmake make gcc g++ libusb-1.0-0-dev"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/Nuand/bladeRF.git
|
||||||
|
cmakebuild bladeRF 2021.10
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyBladeRF.git
|
||||||
|
# latest from master as of 2022-01-12
|
||||||
|
cmakebuild SoapyBladeRF 70505a5cdf8c9deabc4af3eb3384aa82a7b6f021
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
32
docker/scripts/install-dependencies-fcdpp.sh
Executable file
32
docker/scripts/install-dependencies-fcdpp.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libhidapi-hidraw0 libhidapi-libusb0 libasound2"
|
||||||
|
BUILD_PACKAGES="git cmake make gcc g++ libhidapi-dev libasound2-dev"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyFCDPP.git
|
||||||
|
cmakebuild SoapyFCDPP soapy-fcdpp-0.1.1
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
41
docker/scripts/install-dependencies-hackrf.sh
Executable file
41
docker/scripts/install-dependencies-hackrf.sh
Executable file
@ -0,0 +1,41 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0 libfftw3-3 udev"
|
||||||
|
BUILD_PACKAGES="git cmake make patch wget sudo gcc g++ libusb-1.0-0-dev libfftw3-dev pkg-config"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/mossmann/hackrf.git
|
||||||
|
cd hackrf
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
git checkout 6e5cbda2945c3bab0e6e1510eae418eda60c358e
|
||||||
|
cmakebuild host
|
||||||
|
cd ..
|
||||||
|
rm -rf hackrf
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyHackRF.git
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild SoapyHackRF 7d530872f96c1cbe0ed62617c32c48ce7e103e1d
|
||||||
|
|
||||||
|
SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
46
docker/scripts/install-dependencies-hpsdr.sh
Executable file
46
docker/scripts/install-dependencies-hpsdr.sh
Executable file
@ -0,0 +1,46 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
BUILD_PACKAGES="git wget gcc libc6-dev"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $BUILD_PACKAGES
|
||||||
|
|
||||||
|
pushd /tmp
|
||||||
|
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
GOVERSION=1.15.5
|
||||||
|
|
||||||
|
case ${ARCH} in
|
||||||
|
x86_64)
|
||||||
|
PACKAGE=go${GOVERSION}.linux-amd64.tar.gz
|
||||||
|
;;
|
||||||
|
armv*)
|
||||||
|
PACKAGE=go${GOVERSION}.linux-armv6l.tar.gz
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
PACKAGE=go${GOVERSION}.linux-arm64.tar.gz
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
wget https://golang.org/dl/${PACKAGE}
|
||||||
|
tar xfz $PACKAGE
|
||||||
|
|
||||||
|
git clone https://github.com/jancona/hpsdrconnector.git
|
||||||
|
pushd hpsdrconnector
|
||||||
|
git checkout v0.6.0
|
||||||
|
/tmp/go/bin/go build
|
||||||
|
install -m 0755 hpsdrconnector /usr/local/bin
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
rm -rf hpsdrconnector
|
||||||
|
rm -rf go
|
||||||
|
rm $PACKAGE
|
||||||
|
|
||||||
|
popd
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
32
docker/scripts/install-dependencies-limesdr.sh
Executable file
32
docker/scripts/install-dependencies-limesdr.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0 libatomic1"
|
||||||
|
BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
SIMD_FLAGS=""
|
||||||
|
if [[ 'x86_64' == `uname -m` ]] ; then
|
||||||
|
SIMD_FLAGS="-DDEFAULT_SIMD_FLAGS=SSE3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
git clone https://github.com/myriadrf/LimeSuite.git
|
||||||
|
cd LimeSuite
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
git checkout 9526621f8b4c9e2a7f638b5ef50c45560dcad22a
|
||||||
|
mkdir builddir
|
||||||
|
cd builddir
|
||||||
|
cmake .. -DENABLE_EXAMPLES=OFF -DENABLE_DESKTOP=OFF -DENABLE_LIME_UTIL=OFF -DENABLE_QUICKTEST=OFF -DENABLE_OCTAVE=OFF -DENABLE_GUI=OFF -DCMAKE_CXX_STANDARD_LIBRARIES="-latomic" ${SIMD_FLAGS}
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf LimeSuite
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
27
docker/scripts/install-dependencies-perseus.sh
Executable file
27
docker/scripts/install-dependencies-perseus.sh
Executable file
@ -0,0 +1,27 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0 libudev1"
|
||||||
|
BUILD_PACKAGES="git make gcc autoconf automake libtool libusb-1.0-0-dev xxd"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/Microtelecom/libperseus-sdr.git
|
||||||
|
cd libperseus-sdr
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
git checkout c2c95daeaa08bf0daed0e8ada970ab17cc264e1b
|
||||||
|
./bootstrap.sh
|
||||||
|
./configure
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
ldconfig /etc/ld.so.conf.d
|
||||||
|
cd ..
|
||||||
|
rm -rf libperseus-sdr
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
39
docker/scripts/install-dependencies-plutosdr.sh
Executable file
39
docker/scripts/install-dependencies-plutosdr.sh
Executable file
@ -0,0 +1,39 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake .. ${3:-}
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0 libxml2"
|
||||||
|
BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++ libxml2-dev flex bison pkg-config"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/analogdevicesinc/libiio.git
|
||||||
|
cmakebuild libiio v0.21 -DCMAKE_INSTALL_PREFIX=/usr/local
|
||||||
|
|
||||||
|
git clone https://github.com/analogdevicesinc/libad9361-iio.git
|
||||||
|
cmakebuild libad9361-iio v0.2
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyPlutoSDR.git
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild SoapyPlutoSDR 93717b32ef052e0dfa717aa2c1a4eb27af16111f
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
37
docker/scripts/install-dependencies-radioberry.sh
Executable file
37
docker/scripts/install-dependencies-radioberry.sh
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0 libfftw3-3 udev"
|
||||||
|
BUILD_PACKAGES="git cmake make patch wget sudo gcc g++ libusb-1.0-0-dev libfftw3-dev pkg-config"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/pa3gsb/Radioberry-2.x
|
||||||
|
cd Radioberry-2.x/SBC/rpi-4
|
||||||
|
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild SoapyRadioberrySDR 8d17de6b4dc076e628900a82f05c7cf0b16cbe24
|
||||||
|
cd ../../..
|
||||||
|
rm -rf Radioberry-2.x
|
||||||
|
|
||||||
|
SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
36
docker/scripts/install-dependencies-rtlsdr-soapy.sh
Executable file
36
docker/scripts/install-dependencies-rtlsdr-soapy.sh
Executable file
@ -0,0 +1,36 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0-0"
|
||||||
|
BUILD_PACKAGES="git libusb-1.0-0-dev cmake make gcc g++ pkg-config"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/osmocom/rtl-sdr.git
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild rtl-sdr ed0317e6a58c098874ac58b769cf2e609c18d9a5
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyRTLSDR.git
|
||||||
|
cmakebuild SoapyRTLSDR soapy-rtl-sdr-0.3.1
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
33
docker/scripts/install-dependencies-rtlsdr.sh
Executable file
33
docker/scripts/install-dependencies-rtlsdr.sh
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0.0"
|
||||||
|
BUILD_PACKAGES="git libusb-1.0.0-dev cmake make gcc g++ pkg-config"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/osmocom/rtl-sdr.git
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild rtl-sdr ed0317e6a58c098874ac58b769cf2e609c18d9a5
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
32
docker/scripts/install-dependencies-runds.sh
Executable file
32
docker/scripts/install-dependencies-runds.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES=""
|
||||||
|
BUILD_PACKAGES="git cmake make gcc g++ pkg-config"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/runds_connector.git
|
||||||
|
cmakebuild runds_connector 0.2.1
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
57
docker/scripts/install-dependencies-sdrplay.sh
Executable file
57
docker/scripts/install-dependencies-sdrplay.sh
Executable file
@ -0,0 +1,57 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0.0 udev"
|
||||||
|
BUILD_PACKAGES="git cmake make patch wget sudo gcc g++ libusb-1.0-0-dev"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
ARCH=$(uname -m)
|
||||||
|
|
||||||
|
case $ARCH in
|
||||||
|
x86_64)
|
||||||
|
BINARY=SDRplay_RSP_API-Linux-3.07.1.run
|
||||||
|
;;
|
||||||
|
armv*)
|
||||||
|
BINARY=SDRplay_RSP_API-ARM32-3.07.2.run
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
BINARY=SDRplay_RSP_API-ARM64-3.07.1.run
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
wget https://www.sdrplay.com/software/$BINARY
|
||||||
|
sh $BINARY --noexec --target sdrplay
|
||||||
|
patch --verbose -Np0 < /install-lib.$ARCH.patch
|
||||||
|
|
||||||
|
cd sdrplay
|
||||||
|
./install_lib.sh
|
||||||
|
cd ..
|
||||||
|
rm -rf sdrplay
|
||||||
|
rm $BINARY
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapySDRPlay3.git
|
||||||
|
# latest from master as of 2021-06-19 (reliability fixes)
|
||||||
|
cmakebuild SoapySDRPlay3 a869f25364a1f0d5b16169ff908aa21a2ace475d
|
||||||
|
|
||||||
|
SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
32
docker/scripts/install-dependencies-soapyremote.sh
Executable file
32
docker/scripts/install-dependencies-soapyremote.sh
Executable file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
set -euo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="avahi-daemon libavahi-client3"
|
||||||
|
BUILD_PACKAGES="git cmake make gcc g++ libavahi-client-dev"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyRemote.git
|
||||||
|
cmakebuild SoapyRemote soapy-remote-0.5.2
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
33
docker/scripts/install-dependencies-soapysdr.sh
Executable file
33
docker/scripts/install-dependencies-soapysdr.sh
Executable file
@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libudev1"
|
||||||
|
BUILD_PACKAGES="git cmake make patch wget sudo gcc g++"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapySDR
|
||||||
|
# latest from master as of 2020-09-04
|
||||||
|
cmakebuild SoapySDR 580b94f3dad46899f34ec0a060dbb4534e844e57
|
||||||
|
|
||||||
|
SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
59
docker/scripts/install-dependencies-uhd.sh
Executable file
59
docker/scripts/install-dependencies-uhd.sh
Executable file
@ -0,0 +1,59 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libusb-1.0.0 libboost-chrono1.74.0 libboost-date-time1.74.0 libboost-filesystem1.74.0 libboost-program-options1.74.0 libboost-regex1.74.0 libboost-test1.74.0 libboost-serialization1.74.0 libboost-thread1.74.0 libboost-system1.74.0 python3-numpy python3-mako"
|
||||||
|
BUILD_PACKAGES="git cmake make gcc g++ libusb-1.0-0-dev libboost-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-program-options-dev libboost-regex-dev libboost-test-dev libboost-serialization-dev libboost-thread-dev libboost-system-dev"
|
||||||
|
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/EttusResearch/uhd.git
|
||||||
|
mkdir -p uhd/host/build
|
||||||
|
cd uhd/host/build
|
||||||
|
git checkout v4.1.0.4
|
||||||
|
# see https://github.com/EttusResearch/uhd/issues/350
|
||||||
|
case `uname -m` in
|
||||||
|
arm*)
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_UTILS=OFF -DENABLE_PYTHON_API=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TESTS=OFF -DENABLE_OCTOCLOCK=OFF -DENABLE_MAN_PAGES=OFF -DSTRIP_BINARIES=ON \
|
||||||
|
-DCMAKE_CXX_FLAGS:STRING="-march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 -Wno-psabi" \
|
||||||
|
-DCMAKE_C_FLAGS:STRING="-march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 -Wno-psabi" \
|
||||||
|
-DCMAKE_ASM_FLAGS:STRING="-march=armv7-a -mfloat-abi=hard -mfpu=neon -mtune=cortex-a8 -g" ..
|
||||||
|
;;
|
||||||
|
aarch64*)
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_UTILS=OFF -DENABLE_PYTHON_API=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TESTS=OFF -DENABLE_OCTOCLOCK=OFF -DENABLE_MAN_PAGES=OFF -DSTRIP_BINARIES=ON \
|
||||||
|
-DCMAKE_CXX_FLAGS:STRING="-march=armv8-a -mtune=cortex-a72 -Wno-psabi" \
|
||||||
|
-DCMAKE_C_FLAGS:STRING="-march=armv8-a -mtune=cortex-a72 -Wno-psabi" \
|
||||||
|
-DCMAKE_ASM_FLAGS:STRING="-march=armv8-a -mtune=cortex-a72 -g" ..
|
||||||
|
;;
|
||||||
|
x86_64)
|
||||||
|
cmake -DCMAKE_BUILD_TYPE=Release -DENABLE_UTILS=OFF -DENABLE_PYTHON_API=OFF -DENABLE_EXAMPLES=OFF -DENABLE_TESTS=OFF -DENABLE_OCTOCLOCK=OFF -DENABLE_MAN_PAGES=OFF -DSTRIP_BINARIES=ON ..
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../../..
|
||||||
|
rm -rf uhd
|
||||||
|
|
||||||
|
git clone https://github.com/pothosware/SoapyUHD.git
|
||||||
|
cmakebuild SoapyUHD soapy-uhd-0.4.1
|
||||||
|
|
||||||
|
SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
116
docker/scripts/install-dependencies.sh
Executable file
116
docker/scripts/install-dependencies.sh
Executable file
@ -0,0 +1,116 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ${CMAKE_ARGS:-} ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libfftw3-bin python3 python3-setuptools netcat-openbsd libsndfile1 liblapack3 libusb-1.0-0 libqt5core5a libreadline8 libgfortran5 libgomp1 libasound2 libudev1 ca-certificates libpulse0 libfaad2 libopus0 libboost-program-options1.74.0 libboost-log1.74.0"
|
||||||
|
BUILD_PACKAGES="wget git libsndfile1-dev libfftw3-dev cmake make gcc g++ liblapack-dev texinfo gfortran libusb-1.0-0-dev qtbase5-dev qtmultimedia5-dev qttools5-dev libqt5serialport5-dev qttools5-dev-tools asciidoctor asciidoc libasound2-dev libudev-dev libhamlib-dev patch xsltproc qt5-qmake libfaad-dev libopus-dev libboost-dev libboost-program-options-dev libboost-log-dev libboost-regex-dev libpulse-dev"
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install auto-apt-proxy
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
case `uname -m` in
|
||||||
|
arm*)
|
||||||
|
PLATFORM=armhf
|
||||||
|
;;
|
||||||
|
aarch64*)
|
||||||
|
PLATFORM=aarch64
|
||||||
|
;;
|
||||||
|
x86_64*)
|
||||||
|
PLATFORM=amd64
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
wget https://github.com/just-containers/s6-overlay/releases/download/v1.21.8.0/s6-overlay-${PLATFORM}.tar.gz
|
||||||
|
tar xzf s6-overlay-${PLATFORM}.tar.gz -C /
|
||||||
|
rm s6-overlay-${PLATFORM}.tar.gz
|
||||||
|
|
||||||
|
JS8CALL_VERSION=2.2.0
|
||||||
|
JS8CALL_DIR=js8call
|
||||||
|
JS8CALL_TGZ=js8call-${JS8CALL_VERSION}.tgz
|
||||||
|
wget http://files.js8call.com/${JS8CALL_VERSION}/${JS8CALL_TGZ}
|
||||||
|
tar xfz ${JS8CALL_TGZ}
|
||||||
|
# patch allows us to build against the packaged hamlib
|
||||||
|
patch -Np1 -d ${JS8CALL_DIR} < /js8call-hamlib.patch
|
||||||
|
rm /js8call-hamlib.patch
|
||||||
|
cmakebuild ${JS8CALL_DIR}
|
||||||
|
rm ${JS8CALL_TGZ}
|
||||||
|
|
||||||
|
WSJT_DIR=wsjtx-2.5.4
|
||||||
|
WSJT_TGZ=${WSJT_DIR}.tgz
|
||||||
|
wget http://physics.princeton.edu/pulsar/k1jt/${WSJT_TGZ}
|
||||||
|
tar xfz ${WSJT_TGZ}
|
||||||
|
patch -Np0 -d ${WSJT_DIR} < /wsjtx-hamlib.patch
|
||||||
|
mv /wsjtx.patch ${WSJT_DIR}
|
||||||
|
cmakebuild ${WSJT_DIR}
|
||||||
|
rm ${WSJT_TGZ}
|
||||||
|
|
||||||
|
git clone --depth 1 -b 1.6 https://github.com/wb2osz/direwolf.git
|
||||||
|
cd direwolf
|
||||||
|
# hamlib is present (necessary for the wsjt-x and js8call builds) and would be used, but there's no real need.
|
||||||
|
# this patch prevents direwolf from linking to it, and it can be stripped at the end of the script.
|
||||||
|
patch -Np1 < /direwolf-hamlib.patch
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf direwolf
|
||||||
|
# strip lots of generic documentation that will never be read inside a docker container
|
||||||
|
rm /usr/local/share/doc/direwolf/*.pdf
|
||||||
|
# examples are pointless, too
|
||||||
|
rm -rf /usr/local/share/doc/direwolf/examples/
|
||||||
|
|
||||||
|
git clone https://github.com/drowe67/codec2.git
|
||||||
|
cd codec2
|
||||||
|
# latest commit from master as of 2020-10-04
|
||||||
|
git checkout 55d7bb8d1bddf881bdbfcb971a718b83e6344598
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
install -m 0755 src/freedv_rx /usr/local/bin
|
||||||
|
cd ../..
|
||||||
|
rm -rf codec2
|
||||||
|
|
||||||
|
wget https://downloads.sourceforge.net/project/drm/dream/2.1.1/dream-2.1.1-svn808.tar.gz
|
||||||
|
tar xvfz dream-2.1.1-svn808.tar.gz
|
||||||
|
pushd dream
|
||||||
|
patch -Np0 < /dream.patch
|
||||||
|
qmake CONFIG+=console
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
popd
|
||||||
|
rm -rf dream
|
||||||
|
rm dream-2.1.1-svn808.tar.gz
|
||||||
|
|
||||||
|
git clone https://github.com/mobilinkd/m17-cxx-demod.git
|
||||||
|
cmakebuild m17-cxx-demod v2.3
|
||||||
|
|
||||||
|
git clone https://github.com/hessu/aprs-symbols /usr/share/aprs-symbols
|
||||||
|
pushd /usr/share/aprs-symbols
|
||||||
|
git checkout 5c2abe2658ee4d2563f3c73b90c6f59124839802
|
||||||
|
# remove unused files (including git meta information)
|
||||||
|
rm -rf .git aprs-symbols.ai aprs-sym-export.js
|
||||||
|
popd
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
60
docker/scripts/install-owrx-tools.sh
Executable file
60
docker/scripts/install-owrx-tools.sh
Executable file
@ -0,0 +1,60 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euxo pipefail
|
||||||
|
export MAKEFLAGS="-j4"
|
||||||
|
|
||||||
|
function cmakebuild() {
|
||||||
|
cd $1
|
||||||
|
if [[ ! -z "${2:-}" ]]; then
|
||||||
|
git checkout $2
|
||||||
|
fi
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
cmake ${CMAKE_ARGS:-} ..
|
||||||
|
make
|
||||||
|
make install
|
||||||
|
cd ../..
|
||||||
|
rm -rf $1
|
||||||
|
}
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
|
||||||
|
STATIC_PACKAGES="libfftw3-bin libprotobuf23 libsamplerate0 libicu67 libudev1"
|
||||||
|
BUILD_PACKAGES="git autoconf automake libtool libfftw3-dev pkg-config cmake make gcc g++ libprotobuf-dev protobuf-compiler libsamplerate-dev libicu-dev libpython3-dev libudev-dev"
|
||||||
|
apt-get update
|
||||||
|
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/js8py.git
|
||||||
|
pushd js8py
|
||||||
|
git checkout 0.1.2
|
||||||
|
python3 setup.py install
|
||||||
|
popd
|
||||||
|
rm -rf js8py
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/csdr.git
|
||||||
|
cmakebuild csdr 0.18.0
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/pycsdr.git
|
||||||
|
cd pycsdr
|
||||||
|
git checkout 0.18.0
|
||||||
|
./setup.py install install_headers
|
||||||
|
cd ..
|
||||||
|
rm -rf pycsdr
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/codecserver.git
|
||||||
|
mkdir -p /usr/local/etc/codecserver
|
||||||
|
cp codecserver/conf/codecserver.conf /usr/local/etc/codecserver
|
||||||
|
cmakebuild codecserver 0.2.0
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/digiham.git
|
||||||
|
cmakebuild digiham 0.6.0
|
||||||
|
|
||||||
|
git clone https://github.com/jketterl/pydigiham.git
|
||||||
|
cd pydigiham
|
||||||
|
git checkout 0.6.0
|
||||||
|
./setup.py install
|
||||||
|
cd ..
|
||||||
|
rm -rf pydigiham
|
||||||
|
|
||||||
|
apt-get -y purge --autoremove $BUILD_PACKAGES
|
||||||
|
apt-get clean
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
37
docker/scripts/run.sh
Executable file
37
docker/scripts/run.sh
Executable file
@ -0,0 +1,37 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
set -euo pipefail
|
||||||
|
|
||||||
|
mkdir -p /etc/openwebrx/openwebrx.conf.d
|
||||||
|
mkdir -p /var/lib/openwebrx
|
||||||
|
mkdir -p /tmp/openwebrx/
|
||||||
|
if [[ ! -f /etc/openwebrx/openwebrx.conf.d/20-temporary-directory.conf ]] ; then
|
||||||
|
cat << EOF > /etc/openwebrx/openwebrx.conf.d/20-temporary-directory.conf
|
||||||
|
[core]
|
||||||
|
temporary_directory = /tmp/openwebrx
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
if [[ ! -f /etc/openwebrx/bands.json ]] ; then
|
||||||
|
cp bands.json /etc/openwebrx/
|
||||||
|
fi
|
||||||
|
if [[ ! -f /etc/openwebrx/openwebrx.conf ]] ; then
|
||||||
|
cp openwebrx.conf /etc/openwebrx/
|
||||||
|
fi
|
||||||
|
if [[ ! -z "${OPENWEBRX_ADMIN_USER:-}" ]] && [[ ! -z "${OPENWEBRX_ADMIN_PASSWORD:-}" ]] ; then
|
||||||
|
if ! python3 openwebrx.py admin --silent hasuser "${OPENWEBRX_ADMIN_USER}" ; then
|
||||||
|
OWRX_PASSWORD="${OPENWEBRX_ADMIN_PASSWORD}" python3 openwebrx.py admin --noninteractive adduser "${OPENWEBRX_ADMIN_USER}"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
_term() {
|
||||||
|
echo "Caught signal!"
|
||||||
|
kill -TERM "$child" 2>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
trap _term SIGTERM SIGINT
|
||||||
|
|
||||||
|
python3 openwebrx.py $@ &
|
||||||
|
|
||||||
|
child=$!
|
||||||
|
wait "$child"
|
||||||
|
|
0
htdocs/__init__.py
Normal file
0
htdocs/__init__.py
Normal file
BIN
htdocs/apple-touch-icon.png
Normal file
BIN
htdocs/apple-touch-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
162
htdocs/css/admin.css
Normal file
162
htdocs/css/admin.css
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
@import url("openwebrx-header.css");
|
||||||
|
@import url("openwebrx-globals.css");
|
||||||
|
|
||||||
|
html, body {
|
||||||
|
height: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin-bottom: 5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
background: #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.buttons {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #222;
|
||||||
|
z-index: 2;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: right;
|
||||||
|
border-top: 1px solid #444;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row .map-input {
|
||||||
|
margin: 15px 15px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-section h3 {
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 1em 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.matrix {
|
||||||
|
display: grid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.q65-matrix {
|
||||||
|
grid-template-columns: repeat(5, auto);
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageupload .image-container {
|
||||||
|
max-width: 100%;
|
||||||
|
padding: 7px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageupload img.webrx-top-photo {
|
||||||
|
max-height: 350px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-grid > div {
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.settings-grid .btn {
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
padding: 20px;
|
||||||
|
font-size: 1.2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-body {
|
||||||
|
overflow: auto;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-top: none;
|
||||||
|
border-bottom-left-radius: 0.25rem;
|
||||||
|
border-bottom-right-radius: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tab-body .form-group {
|
||||||
|
padding-right: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmarks table .frequency, .bookmark-list table .frequency {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmarks table input, .bookmarks table select {
|
||||||
|
width: initial;
|
||||||
|
text-align: inherit;
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.bookmark-list table .form-check-input {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions {
|
||||||
|
margin: 1rem 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.actions .btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsjt-decoding-depths-table {
|
||||||
|
width: auto;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.wsjt-decoding-depths-table td:first-child {
|
||||||
|
padding-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sdr-device-list .list-group-item,
|
||||||
|
.sdr-profile-list .list-group-item {
|
||||||
|
background: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sdr-device-list .sdr-profile-list {
|
||||||
|
max-height: 20rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.removable-group.removable, .add-group {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.removable-group.removable .removable-item, .add-group .add-group-select {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
margin-right: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.removable-group.removable .option-remove-button, .add-group .option-add-button {
|
||||||
|
flex: 0 0 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.option-add-button, .option-remove-button {
|
||||||
|
width: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheduler-static-time-inputs {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheduler-static-time-inputs > * {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
width: unset;
|
||||||
|
}
|
||||||
|
|
||||||
|
.scheduler-static-time-inputs > select {
|
||||||
|
flex: 1 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.breadcrumb {
|
||||||
|
margin-top: .5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.imageupload.is-invalid ~ .invalid-feedback {
|
||||||
|
display: block;
|
||||||
|
}
|
12
htdocs/css/bootstrap.min.css
vendored
Normal file
12
htdocs/css/bootstrap.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
34
htdocs/css/login.css
Normal file
34
htdocs/css/login.css
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
@import url("openwebrx-header.css");
|
||||||
|
@import url("openwebrx-globals.css");
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login-container {
|
||||||
|
flex: 1;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login {
|
||||||
|
position: absolute;
|
||||||
|
left: 50%;
|
||||||
|
top: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
|
|
||||||
|
width: 500px;
|
||||||
|
|
||||||
|
padding: 20px;
|
||||||
|
border-radius: 10px;
|
||||||
|
border: 1px solid #575757;
|
||||||
|
box-shadow: 0 0 20px #000;
|
||||||
|
}
|
||||||
|
|
||||||
|
.login .btn {
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn-login {
|
||||||
|
height: 50px;
|
||||||
|
}
|
65
htdocs/css/map.css
Normal file
65
htdocs/css/map.css
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
@import url("openwebrx-header.css");
|
||||||
|
@import url("openwebrx-globals.css");
|
||||||
|
|
||||||
|
body {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-map {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 10px 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
margin-block-start: 5px;
|
||||||
|
margin-block-end: 5px;
|
||||||
|
padding-inline-start: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* don't show the filter in it's initial position */
|
||||||
|
.openwebrx-map-legend {
|
||||||
|
display: none;
|
||||||
|
background-color: #fff;
|
||||||
|
padding: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
user-select: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* show it as soon as google maps has moved it to its container */
|
||||||
|
.openwebrx-map .openwebrx-map-legend {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-map-legend ul {
|
||||||
|
list-style-type: none;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-map-legend ul li {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-map-legend ul li.disabled {
|
||||||
|
opacity: .3;
|
||||||
|
filter: grayscale(70%);
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-map-legend li.square .illustration {
|
||||||
|
display: inline-block;
|
||||||
|
width: 30px;
|
||||||
|
height: 20px;
|
||||||
|
margin-right: 10px;
|
||||||
|
border-width: 2px;
|
||||||
|
border-style: solid;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-map-legend select {
|
||||||
|
background-color: #FFF;
|
||||||
|
border-color: #DDD;
|
||||||
|
padding: 5px;
|
||||||
|
}
|
7
htdocs/css/openwebrx-globals.css
Normal file
7
htdocs/css/openwebrx-globals.css
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
html, body
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 100%;
|
||||||
|
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
|
||||||
|
}
|
227
htdocs/css/openwebrx-header.css
Normal file
227
htdocs/css/openwebrx-header.css
Normal file
@ -0,0 +1,227 @@
|
|||||||
|
.webrx-top-container {
|
||||||
|
position: relative;
|
||||||
|
z-index:1000;
|
||||||
|
background-color: #575757;
|
||||||
|
|
||||||
|
background-image: url(../gfx/openwebrx-top-photo.jpg);
|
||||||
|
background-position-x: center;
|
||||||
|
background-position-y: top;
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-size: cover;
|
||||||
|
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-description-container {
|
||||||
|
transition-property: height, opacity;
|
||||||
|
transition-duration: 1s;
|
||||||
|
transition-timing-function: ease-out;
|
||||||
|
opacity: 0;
|
||||||
|
height: 0;
|
||||||
|
/* originally, top-bar + description was 350px */
|
||||||
|
max-height: 283px;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-description-container.expanded {
|
||||||
|
opacity: 1;
|
||||||
|
height: 283px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-top-bar {
|
||||||
|
height:67px;
|
||||||
|
|
||||||
|
background: rgba(128, 128, 128, 0.15);
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
user-select: none;
|
||||||
|
-webkit-touch-callout: none;
|
||||||
|
-webkit-user-select: none;
|
||||||
|
-khtml-user-select: none;
|
||||||
|
-moz-user-select: none;
|
||||||
|
-ms-user-select: none;
|
||||||
|
overflow: hidden;
|
||||||
|
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-top-bar > * {
|
||||||
|
flex: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-top-container, .webrx-top-container * {
|
||||||
|
line-height: initial;
|
||||||
|
box-sizing: initial;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-top-logo {
|
||||||
|
width: 261px;
|
||||||
|
padding: 12px;
|
||||||
|
filter: drop-shadow(0 0 2.5px rgba(0, 0, 0, .9));
|
||||||
|
/* overwritten by media queries */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-avatar {
|
||||||
|
background-color: rgba(154, 154, 154, .5);
|
||||||
|
margin: 7px;
|
||||||
|
|
||||||
|
width: 46px;
|
||||||
|
height: 46px;
|
||||||
|
padding: 4px;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-sizing: content-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-texts {
|
||||||
|
/* minimum layout width */
|
||||||
|
width: 0;
|
||||||
|
/* will be getting wider with flex */
|
||||||
|
flex: 1;
|
||||||
|
overflow: hidden;
|
||||||
|
margin: auto 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-texts div, .webrx-rx-texts h1 {
|
||||||
|
margin: 0 10px;
|
||||||
|
padding: 3px;
|
||||||
|
white-space:nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
color: #909090;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-title {
|
||||||
|
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
|
||||||
|
font-size: 11pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-desc {
|
||||||
|
font-size: 10pt;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-main-buttons .button {
|
||||||
|
display: block;
|
||||||
|
width: 55px;
|
||||||
|
cursor:pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-main-buttons .button[data-toggle-panel] {
|
||||||
|
/* will be enabled by javascript if the panel is present in the DOM */
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-main-buttons .button img,
|
||||||
|
.openwebrx-main-buttons .button svg {
|
||||||
|
height: 38px;
|
||||||
|
filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5));
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-main-buttons a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-main-buttons .button:hover {
|
||||||
|
background-color: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-main-buttons .button:active {
|
||||||
|
background-color: rgba(255, 255, 255, 0.55);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.openwebrx-main-buttons {
|
||||||
|
padding: 5px 15px;
|
||||||
|
display: flex;
|
||||||
|
list-style: none;
|
||||||
|
margin:0;
|
||||||
|
color: white;
|
||||||
|
text-shadow: 0px 0px 4px #000000;
|
||||||
|
text-align: center;
|
||||||
|
font-size: 9pt;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-photo-title {
|
||||||
|
margin: 10px 15px;
|
||||||
|
color: white;
|
||||||
|
font-size: 16pt;
|
||||||
|
text-shadow: 1px 1px 4px #444;
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-photo-desc {
|
||||||
|
margin: 10px 15px;
|
||||||
|
color: white;
|
||||||
|
font-size: 10pt;
|
||||||
|
font-weight: bold;
|
||||||
|
text-shadow: 0px 0px 6px #444;
|
||||||
|
opacity: 1;
|
||||||
|
line-height: 1.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.webrx-rx-photo-desc a {
|
||||||
|
color: #5ca8ff;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-photo-trigger {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Responsive stuff
|
||||||
|
*/
|
||||||
|
|
||||||
|
@media (min-width: 576px) {
|
||||||
|
.webrx-rx-texts {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 768px) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 992px) {
|
||||||
|
.webrx-top-logo {
|
||||||
|
display: initial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (min-width: 1200px) {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* RX details arrow up/down switching
|
||||||
|
*/
|
||||||
|
|
||||||
|
.openwebrx-rx-details-arrow {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
left: 50%;
|
||||||
|
transform: translate(-50%, 0);
|
||||||
|
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 0;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-rx-details-arrow svg {
|
||||||
|
height: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-rx-details-arrow .up {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-rx-details-arrow--up .down {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.openwebrx-rx-details-arrow--up .up {
|
||||||
|
display: initial;
|
||||||
|
}
|
1346
htdocs/css/openwebrx.css
Normal file
1346
htdocs/css/openwebrx.css
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user