Compare commits

..

1036 Commits

Author SHA1 Message Date
Jakob Ketterl
57f55bbdd5
Merge pull request #342 from bd5rv/develop
Add --no-http-keep-alive to wget's arguments
2023-03-10 21:11:31 +01:00
Michael Chen
e8ba61bb81
Add --no-http-keep-alive to wget's arguments
When downloading SDRPlay API from sdrplay.com'server, it reports 403 forbidden error when the environment variable https_proxy is set. Adding --no-http-keep-live argument to wget will make the download working.
2023-03-11 00:31:19 +08:00
Jakob Ketterl
cb5b2e64af change chunking to work with actual byte-sizes 2023-02-22 17:23:11 +01:00
Jakob Ketterl
685b9970d2 switch frequency field to 5 bytes to support QO-100 2023-02-22 16:19:18 +01:00
Jakob Ketterl
c385a8f6b1 update changelogs 2023-02-22 14:13:01 +01:00
Jakob Ketterl
aa60b9d4a7 add msk144decoder to docker build 2023-02-21 19:50:44 +01:00
Jakob Ketterl
bff09e3363 add msk144decoder to recommended packages 2023-02-21 17:42:33 +01:00
Jakob Ketterl
774f8bd91a remove debugging messages 2023-02-21 17:41:55 +01:00
Jakob Ketterl
b1684908a4 remove todo 2023-02-19 16:18:49 +01:00
Jakob Ketterl
ed76fd7606 add MSK144 service demodulator 2023-02-19 16:18:08 +01:00
Jakob Ketterl
7b3f212ccb improve error handling during service initialization 2023-02-19 16:14:08 +01:00
Jakob Ketterl
216a3db45d add MSK144 to list of pskreporter modes 2023-02-16 19:47:46 +01:00
Jakob Ketterl
c16de474c6 route msk144 data to the wsjt message panel 2023-02-14 18:45:51 +01:00
Jakob Ketterl
afcd8277d1 add MSK144 parsing 2023-02-14 18:36:17 +01:00
Jakob Ketterl
525b70d495 add msk144 frequencies 2023-02-14 15:40:20 +01:00
Jakob Ketterl
f58023f3e5 add msk144demodulator chain 2023-02-14 15:39:59 +01:00
Jakob Ketterl
252edb7a5a add feature detection 2023-02-14 15:38:33 +01:00
Jakob Ketterl
2993cc4279 update wsjt-x homepage url 2023-02-14 15:37:37 +01:00
Jakob Ketterl
cc4f3c6c1d correctly commit patch? 2023-01-28 19:23:46 +01:00
Jakob Ketterl
0de597481c update to wsjt-x 2.6.1 2023-01-28 19:13:10 +01:00
Jakob Ketterl
2342bb5d29 update WSJT-X download location 2023-01-28 17:36:45 +01:00
Jakob Ketterl
b1ac8caf9b replace with a more robust state engine implementation 2023-01-28 16:37:32 +01:00
Jakob Ketterl
d79a1396a6 change name for sdrplay device in default config 2022-12-11 23:54:35 +01:00
Jakob Ketterl
1e6e7528b5 add a pseudo-input to display the sdr device type 2022-12-11 23:48:56 +01:00
Jakob Ketterl
f6326f8631 use a more generic include instead of manually updating the list 2022-12-11 22:41:10 +01:00
Jakob Ketterl
c61986dbcc add log module to the list 2022-12-11 21:06:22 +01:00
Jakob Ketterl
bbc9d9e7a8 log names instead of ids for improved transparency 2022-12-11 20:41:35 +01:00
Jakob Ketterl
a309af40e9 update dependencies 2022-12-11 20:29:45 +01:00
Jakob Ketterl
f3a3b9243c update connectors 2022-12-11 00:58:58 +01:00
Jakob Ketterl
edc9009359 fix svg include path 2022-12-10 19:50:47 +01:00
Jakob Ketterl
13e323cdd2 show sdr device log messages in the web configuration 2022-12-10 19:50:26 +01:00
Jakob Ketterl
ab40a2934f remove old config (no longer used) 2022-12-10 19:44:35 +01:00
Jakob Ketterl
322b6a0d52 set loglevels sooner 2022-11-30 18:53:09 +01:00
Jakob Ketterl
bba900d8f8 fix config default 2022-11-30 18:51:01 +01:00
Jakob Ketterl
64f0510da0 use a dropdown for callsign database setting; add aprs.fi 2022-11-30 16:54:22 +01:00
Jakob Ketterl
4050bd7f96 update version in feature check 2022-11-30 01:16:12 +01:00
Jakob Ketterl
35abd711ca update dependencies 2022-11-30 01:15:28 +01:00
Jakob Ketterl
258e41669e structured callsign data 2022-11-30 01:07:16 +01:00
Jakob Ketterl
975f5ffdf0 make loglevel adjustable in config or on CLI 2022-11-29 20:23:39 +01:00
Jakob Ketterl
90ed47a115 move pocsag demodulator to digiham to fix import problems 2022-11-10 22:43:08 +01:00
Jakob Ketterl
271bd723bc
Merge pull request #318 from luarvique/map_distance
Adding distance display to the info windows.
2022-10-04 16:32:09 +02:00
Jakob Ketterl
8a7e91be38 update all docker dependencies 2022-09-30 18:51:47 +02:00
Jakob Ketterl
9416db5f42 Merge branch 'master' into develop 2022-09-30 18:49:45 +02:00
Marat Fayzullin
0127e32ea1 Removing dash from APRS callsigns and showing distance to them. 2022-09-26 15:24:59 -04:00
Jakob Ketterl
e20d94e241 update dependencies for docker 2022-09-20 18:51:09 +02:00
Jakob Ketterl
6c01d48493 update version 2022-09-20 18:06:03 +02:00
Jakob Ketterl
94269e211e fix changelog timestamp 2022-09-20 18:01:43 +02:00
Jakob Ketterl
811d95c7bc fifisdr fixes 2022-09-20 18:01:08 +02:00
Jakob Ketterl
c07e33d19d update csdr and pycsdr dependencies in docker 2022-09-19 19:07:23 +02:00
Jakob Ketterl
c150eca75c fifisdr fixes 2022-09-19 18:46:11 +02:00
Marat Fayzullin
7a61f991ad Removed parentheses, added a space before "km". 2022-09-16 00:02:17 -04:00
Marat Fayzullin
4423c7f13a Adding distance display to the info windows. 2022-09-15 19:34:39 -04:00
Jakob Ketterl
5cd0847362
Merge pull request #306 from luarvique/filter_width
Added filter boundaries display.
2022-07-31 22:44:07 +02:00
Jakob Ketterl
1635cbfa42
Merge pull request #307 from luarvique/callsign_lookup
Added an option to add callsign database URL for lookups on a map.
2022-07-31 22:35:19 +02:00
Marat Fayzullin
e92b6d657b Addressing comments from jketterl. 2022-07-31 16:10:33 -04:00
Jakob Ketterl
d5f7ce9508
Merge pull request #309 from luarvique/waterfall_colors
Now calculating waterfall colors based on what is on the screen (with…
2022-07-31 22:08:01 +02:00
Jakob Ketterl
bfd4d5657c
Merge pull request #308 from luarvique/zoom_reset
Now resetting zoom when changing to a different profile.
2022-07-31 21:59:15 +02:00
Marat Fayzullin
bb625a5f9f Added filter boundaries display. 2022-07-31 15:27:41 -04:00
Marat Fayzullin
2ccdc90cc5 Added an option to add callsign database URL for lookups on a map. 2022-07-31 15:25:52 -04:00
Marat Fayzullin
ff43555411 Now resetting zoom when changing to a different profile. 2022-07-31 15:16:52 -04:00
Marat Fayzullin
339864a572 Now calculating waterfall colors based on what is on the screen (with zoom). 2022-07-31 15:15:38 -04:00
Jakob Ketterl
6192978f2f Merge branch 'master' into develop 2022-07-10 03:18:54 +02:00
Jakob Ketterl
66d4d88156 update hpsdrconnector to 0.6.1 2022-07-09 18:34:28 +02:00
Jakob Ketterl
c87daaabbe fix scroll events on the frequency bar 2022-06-19 22:40:47 +02:00
Jakob Ketterl
6f0a209a38 fix deprecation warning 2022-06-18 20:42:11 +02:00
Jakob Ketterl
26440d4e24 make waterfall zoom continuous 2022-06-18 15:57:06 +02:00
Jakob Ketterl
08188527ce high-res scroll events for the waterfall zoom 2022-06-17 19:42:40 +02:00
Jakob Ketterl
8532d9048e process high-resolution scroll events for the frequency display 2022-06-17 19:42:05 +02:00
Jakob Ketterl
1771fd55e1 move develop to the next minor version 2022-06-16 23:53:56 +02:00
Jakob Ketterl
0145cf5668 update release versions for docker 2022-06-16 22:48:57 +02:00
Jakob Ketterl
921fb23c8d prepare release of version 1.2.0 2022-06-15 18:28:50 +02:00
Jakob Ketterl
eb3ec5dc36 update m17-cxx-demod to version 2.3 2022-06-15 18:25:26 +02:00
Jakob Ketterl
35ad4712bb disable PPM input for devices that don't support it 2022-06-09 20:25:29 +02:00
Jakob Ketterl
fe7f2317de add a quick note about HTML being supported 2022-06-09 19:22:45 +02:00
Jakob Ketterl
b5bbdae317 fix failed logins for path-routed environemnts 2022-06-09 18:43:54 +02:00
Jakob Ketterl
cec4e326c8 prevent "None" showing up in text inputs 2022-06-09 17:24:53 +02:00
Jakob Ketterl
eccbdc1655 update libraries in docker 2022-06-01 18:04:54 +02:00
Jakob Ketterl
08485f255a add return codes 2022-06-01 17:58:06 +02:00
Jakob Ketterl
be8e35cbcf output more descriptive output when dependencies fail 2022-06-01 17:11:45 +02:00
Jakob Ketterl
843dde1a68 check for csdr & digiham python bindings 2022-06-01 16:43:18 +02:00
Jakob Ketterl
f018ef1d81 turn off debug logging for now 2022-06-01 16:19:24 +02:00
Jakob Ketterl
6b43ddf920 add udev dependencies for codecserver 2022-01-24 11:38:06 +01:00
Jakob Ketterl
242ec5dfd0 update docker dependencies 2022-01-24 11:03:15 +01:00
Jakob Ketterl
b354f38bfb add js8call as a recommended package (available in bullseye now) 2022-01-18 16:55:19 +01:00
Jakob Ketterl
983aa8cebc add bladerf docker image build 2022-01-12 18:01:25 +01:00
Jakob Ketterl
619f1254fd update wsjt-x to version 2.5.4 2022-01-12 17:59:45 +01:00
Jakob Ketterl
b5b52770ee update changelogs 2022-01-12 16:00:16 +01:00
Jakob Ketterl
7fd98c8c5c add support for blade rf devices 2022-01-12 15:48:06 +01:00
Jakob Ketterl
39bfba673b catch error resulting from monitor race condition 2022-01-11 21:56:16 +01:00
Jakob Ketterl
5adb53d990 distinguish between error condition and normal socket close 2022-01-11 19:57:52 +01:00
Jakob Ketterl
f3dcf5c320 check closed condition after aquiring the lock to avoid deadlocks 2022-01-05 17:55:46 +01:00
Jakob Ketterl
2ce7d943fa fix a client counting bug by deferring client instantiation 2022-01-03 15:19:12 +01:00
Jakob Ketterl
60f57bf206 add codecserver to recommended packages 2021-12-29 14:26:30 +01:00
Jakob Ketterl
221e0f232b try to avoid "can only be started once" error 2021-12-27 16:37:10 +01:00
Jakob Ketterl
46c78f6463 avoid demodulator concurrency
* this frees up resources used by the current demodulator before
  starting a new one
* this addresses an issue where users of single-channel AMBE sticks
  could not seamlessly switch between digital modes
2021-12-23 16:32:51 +01:00
Jakob Ketterl
40c68933e1 add preliminary parsing and display of M17 metadata 2021-12-21 21:18:17 +01:00
Jakob Ketterl
81b8f183c2 update connector with bias_tee fixes 2021-12-20 16:11:51 +01:00
Jakob Ketterl
03f0faf378 update digiham / pydigiham dependencies 2021-12-18 17:54:27 +01:00
Jakob Ketterl
f316b2c8ca allow latitude and longitude to be 0 in location-picker 2021-12-14 12:46:25 +01:00
Jakob Ketterl
6c3ef7a6ed
Merge pull request #281 from chrismrutledge/patch-1
Update bands.json
2021-12-13 14:21:47 +01:00
Jakob Ketterl
4ce3816f48 show codecserver errors in the client 2021-12-13 13:26:47 +01:00
Jakob Ketterl
397155983d improve handling of failed devices 2021-12-06 15:50:03 +01:00
Jakob Ketterl
9c28143dfb add debugging to the feature detection system 2021-12-01 19:22:48 +01:00
chrismrutledge
ed354cfa6f
Update bands.json
80M WSPR frequency change and additional 60M frequency according to wsprnet.org.
2021-11-28 07:02:16 -06:00
Jakob Ketterl
dcdfe7969a fix sample rate updates for secondary demods 2021-11-08 17:52:37 +01:00
Jakob Ketterl
6d414698e8 update to wsjt-x 2.5.2 2021-11-05 02:20:49 +01:00
Jakob Ketterl
70cf4557f7 update to wsjt-x 2.5.1 2021-11-02 17:31:58 +01:00
Jakob Ketterl
b0e18286df update connector 2021-11-02 16:11:19 +01:00
Jakob Ketterl
85c7a05978 use ImportError for python 3.5 compatibility 2021-10-27 18:33:23 +02:00
Jakob Ketterl
33c8e34456 use the resume call before pumping data from a reader 2021-10-26 16:40:38 +02:00
Jakob Ketterl
4bc6608e87 update csdr in docker 2021-10-25 14:15:32 +02:00
Jakob Ketterl
f967a8d87a catch exceptions while parsing ax25 frames 2021-10-22 15:07:42 +02:00
Jakob Ketterl
d757b817b1 make digimodes work in start_mod again 2021-10-15 16:41:07 +02:00
Jakob Ketterl
9f89a21cfb remove psk31 character animation since it's killing the client 2021-10-15 15:57:27 +02:00
Jakob Ketterl
aaf696e8d7
Merge pull request #273 from doccodyblue/feature/266-normalize-prometheus-metric-names
Feature/266 normalize prometheus metric names
2021-10-04 16:00:34 +02:00
Andre Schinkel
efa305eeec normalize metric label to match prometheus data-model guide 2021-10-03 08:48:40 +02:00
Andre Schinkel
eb43e39a81 normalize metric label to match prometheus data-model guide 2021-10-03 08:39:57 +02:00
Jakob Ketterl
c4687816c1 update docker to debian bullseye 2021-10-01 16:23:47 +02:00
Jakob Ketterl
8cce5bd889 add metrics for pocsag 2021-10-01 00:52:32 +02:00
Jakob Ketterl
66dd4b4581 update list of supported modes for pskreporter 2021-10-01 00:09:20 +02:00
Jakob Ketterl
9689ce5202 catch invalid config values for enum dropdowns and reset to default 2021-09-30 23:32:46 +02:00
Jakob Ketterl
818b9d87b8 add a validator that prevents invalid locations 2021-09-30 23:26:26 +02:00
Jakob Ketterl
0f2aca62f3 code style 2021-09-30 23:09:22 +02:00
Jakob Ketterl
1e57fb4609 expect a broken pipe 2021-09-30 23:04:59 +02:00
Jakob Ketterl
0b64b4ac97 handle errors when gps coordinates are out of range 2021-09-30 23:03:21 +02:00
Jakob Ketterl
460bada88f update owrx libraries 2021-09-30 01:37:10 +02:00
Jakob Ketterl
330598ddf2 use check implemented in python 2021-09-29 17:23:23 +02:00
Jakob Ketterl
8f36355817 update changelog 2021-09-29 15:43:48 +02:00
Jakob Ketterl
ccf741da00 add nmux back to recommended packages 2021-09-29 15:42:49 +02:00
Jakob Ketterl
c3917c61d3 fix audio compression switching 2021-09-28 17:46:18 +02:00
Jakob Ketterl
d869c5ee2d restore live switching capability for fft compression 2021-09-28 16:55:17 +02:00
Jakob Ketterl
c89394822a Merge branch 'develop' into pycsdr 2021-09-28 16:44:50 +02:00
Jakob Ketterl
1836344fab update to wsjt-x 2.5.0 2021-09-28 16:42:52 +02:00
Jakob Ketterl
25e2a8013e parser typing 2021-09-28 00:27:01 +02:00
Jakob Ketterl
757ec01ea4 clientReader is not used any more 2021-09-28 00:14:53 +02:00
Jakob Ketterl
a07480fd9a remove old csdr code 2021-09-27 18:53:49 +02:00
Jakob Ketterl
e77b0f4a67 fix the secondary fft display 2021-09-27 18:18:31 +02:00
Jakob Ketterl
909a969e04 restore wfm deemphasis tau functionality 2021-09-27 17:46:19 +02:00
Jakob Ketterl
edace3d451 work on some todos 2021-09-27 17:29:51 +02:00
Jakob Ketterl
5b1000df87 Merge branch 'develop' into pycsdr 2021-09-24 23:08:37 +02:00
Jakob Ketterl
fae281a507 update codecserver in docker 2021-09-24 22:34:53 +02:00
Jakob Ketterl
cbcba5807f restore PSK decoding 2021-09-23 18:43:41 +02:00
Jakob Ketterl
3fa3aac766 introduce defaults layer to fix codecserver when empty 2021-09-23 15:17:46 +02:00
Jakob Ketterl
981948b708 update components in docker build 2021-09-22 18:15:47 +02:00
Jakob Ketterl
c41b303130 update dependencies 2021-09-22 17:22:00 +02:00
Jakob Ketterl
6589c9dbe1 add a feature check for js8py since it's optional now 2021-09-22 13:11:27 +02:00
Jakob Ketterl
acc70b6449 re-implement format conversion with pycsdr 2021-09-20 18:36:24 +02:00
Jakob Ketterl
81925986a6 update dependencies 2021-09-20 18:04:24 +02:00
Jakob Ketterl
83d01553e3 use "Optional" in typing 2021-09-20 17:24:10 +02:00
Jakob Ketterl
f2a97415b9 more localized imports 2021-09-20 16:55:17 +02:00
Jakob Ketterl
95b4510c3a more localized imports 2021-09-20 16:53:00 +02:00
Jakob Ketterl
81ed1a9ebb abstract chain features; use local imports to avoid hard dependencies 2021-09-20 16:14:23 +02:00
Jakob Ketterl
b2e15c559e refactor 2021-09-20 15:32:26 +02:00
Jakob Ketterl
c10fdd2a53 move 2021-09-20 15:16:06 +02:00
Jakob Ketterl
9efe41a2b1 move the pump mechanism, allowing the old output code to be removed 2021-09-20 15:09:26 +02:00
Jakob Ketterl
4b36aca6fc update wording to direct users to the feature report 2021-09-20 14:45:00 +02:00
Jakob Ketterl
cb29fc251c update dependencies 2021-09-17 18:58:48 +02:00
Jakob Ketterl
78dcdd5715 add support for DMR locations 2021-09-17 18:24:33 +02:00
Jakob Ketterl
6fbe6b4983 restore automatic config application for direwolf 2021-09-15 15:37:09 +02:00
Jakob Ketterl
284059a920 clean up direwolf config file after use 2021-09-15 15:04:12 +02:00
Jakob Ketterl
0403ebff5c improve handling of source processes 2021-09-15 15:03:11 +02:00
Jakob Ketterl
6129b92277 avoid duplicate method 2021-09-15 15:01:36 +02:00
Jakob Ketterl
1ff3c174c2 limit freedv to 4kHz since it's audio input is only 8kHz 2021-09-13 16:58:45 +02:00
Jakob Ketterl
e5b120311d get freedv back by modeling a corresponding module and chain 2021-09-13 16:58:02 +02:00
Jakob Ketterl
1c937e147e use a generic unpickler 2021-09-13 00:14:38 +02:00
Jakob Ketterl
1d2ee127e0 Merge branch 'develop' into pycsdr 2021-09-12 23:31:44 +02:00
Jakob Ketterl
ee9b602e4f catch http errors 2021-09-12 23:31:33 +02:00
Jakob Ketterl
72f925e537 receive pocsag messages in pickled form 2021-09-10 15:38:36 +02:00
Jakob Ketterl
bf37dee78b receive metadata in pickled form 2021-09-09 22:25:45 +02:00
Jakob Ketterl
72920135e9 fix initial setup of dial frequency 2021-09-09 22:24:41 +02:00
Jakob Ketterl
66cf940523 refactor the metaparser into a modules and use accordingly 2021-09-09 15:11:33 +02:00
Jakob Ketterl
ca0f7af1d0 use stereo downmix; disable squelch for DRM 2021-09-08 13:48:11 +02:00
Jakob Ketterl
d9db74e565 fix reading from process 2021-09-08 13:47:46 +02:00
Jakob Ketterl
3218e0b8aa update hpsdrconnector to 0.6.0 2021-09-08 12:54:34 +02:00
Jakob Ketterl
c8ebbb505a restore dmr filter 2021-09-07 17:37:32 +02:00
Jakob Ketterl
9ca5e0ebd6 restore DRM functionality 2021-09-07 17:31:32 +02:00
Jakob Ketterl
f3b05c6318 re-add m17 2021-09-07 14:45:52 +02:00
Jakob Ketterl
f9f0bdde12 restore js8 functionality 2021-09-06 22:50:57 +02:00
Jakob Ketterl
6014ce8921 restore pocsag functionality 2021-09-06 20:00:14 +02:00
Jakob Ketterl
b9f43654cd restore aprs functionality 2021-09-06 15:05:33 +02:00
Jakob Ketterl
7c43c78c4b refactor aprs stuff 2021-09-02 11:00:57 +02:00
Jakob Ketterl
efa7faaa2a correctly shutdown resampler 2021-09-02 10:53:05 +02:00
Jakob Ketterl
f9df35ffd4 rebuilt the resampler using pycsdr 2021-09-01 15:58:39 +02:00
Jakob Ketterl
01260d66c8 create a base class for python-implemented modules 2021-09-01 15:08:28 +02:00
Jakob Ketterl
51453662e2 fix dial frequencies 2021-08-31 22:46:11 +02:00
Jakob Ketterl
120328ce12 restore background services 2021-08-31 21:53:15 +02:00
Jakob Ketterl
869f971ced add the remaining modes 2021-08-31 17:01:52 +02:00
Jakob Ketterl
73d326037c restore audio chopper decoding 2021-08-31 16:54:37 +02:00
Jakob Ketterl
4a4901fa38 restore secondary fft 2021-08-28 00:10:46 +02:00
Jakob Ketterl
47e78579d4 handle unparseable utf meta data 2021-08-27 18:31:10 +02:00
Jakob Ketterl
54a1cae352 fix hd audio 2021-08-27 18:30:46 +02:00
Jakob Ketterl
4c1777dc19 refactor 2021-08-27 17:34:48 +02:00
Jakob Ketterl
42b315ef86 handle empty converter chain 2021-08-27 16:11:03 +02:00
Jakob Ketterl
3bb4f48faf fix errors on shutdown (duplicate calls) 2021-08-26 17:22:10 +02:00
Jakob Ketterl
ee3d934529 fix thread leak 2021-08-26 17:21:52 +02:00
Jakob Ketterl
aecb79a4d4 restore demodulation of digital voice modes 2021-08-26 15:58:02 +02:00
Jakob Ketterl
5032f4b66d first steps at rewiring the dsp stuff 2021-08-23 14:25:28 +02:00
Jakob Ketterl
0f1feb9d47 return to the simpler API 2021-08-16 16:41:18 +02:00
Jakob Ketterl
be6f533437 re-structure client audio conversion 2021-08-12 18:01:03 +02:00
Jakob Ketterl
c3d393252b parse metadata as UTF-8 2021-08-12 16:51:21 +02:00
Jakob Ketterl
bb56eb8db2 don't highlight for data 2021-08-11 14:10:52 +02:00
Jakob Ketterl
1e8527da68 add YSF chain; re-introduce RRC filters 2021-08-10 14:03:49 +02:00
Jakob Ketterl
2b3123c7cb dmr tdma slot filter control 2021-08-07 00:09:40 +02:00
Jakob Ketterl
8e945d4149 update metadata asynchronously when download finishes 2021-08-06 21:23:44 +02:00
Jakob Ketterl
3ccb4a11d2 add new DMR chain 2021-08-06 20:02:59 +02:00
Jakob Ketterl
dd7255a9d2 display talker alias (if no radioid data is available) 2021-08-06 20:02:30 +02:00
Jakob Ketterl
307e944911 split metadata into lines (if more than one was received) 2021-08-06 20:01:35 +02:00
Jakob Ketterl
175e140f86 Merge branch 'develop' into pycsdr 2021-08-04 00:01:11 +02:00
Jakob Ketterl
ad59b1b3b7 add codecserver help text 2021-08-03 19:52:49 +02:00
Jakob Ketterl
5256409ddf update m17-cxx-demod to 2.2 in docker 2021-08-03 19:51:03 +02:00
Jakob Ketterl
65950565b6 bump develop to next version (1.2.0) 2021-08-03 15:57:36 +02:00
Jakob Ketterl
66492ff40a make sure we send all the data 2021-08-03 15:03:20 +02:00
Jakob Ketterl
52df289230 update tools to release tags 2021-08-02 21:54:11 +02:00
Jakob Ketterl
1845fa3f39 prepare release 1.1.0 2021-08-02 18:26:16 +02:00
Jakob Ketterl
fa49e59200 increase required connector version to 0.5 (0.4 would work but cannot be
parsed)
2021-08-02 18:11:45 +02:00
Jakob Ketterl
d0d3e67174 add missing digiham components 2021-08-02 17:39:18 +02:00
Jakob Ketterl
c5a314810e read metadata from pipeline decoders 2021-08-01 00:49:20 +02:00
Jakob Ketterl
f8f2740c77 implement nxdn chain using new digiham components 2021-07-31 00:10:10 +02:00
Jakob Ketterl
1c91c6dcc1 start building digiham chains 2021-07-30 00:06:21 +02:00
Jakob Ketterl
11a3606070 use the new cutoff parameter to compensate the fractional decimator 2021-07-25 23:38:24 +02:00
Jakob Ketterl
75aac5969a implement WFM with the new chain elements 2021-07-25 22:44:53 +02:00
Jakob Ketterl
459a99cbf8 backport the sync implementation from the csdr++ branch 2021-07-25 20:06:14 +02:00
Jakob Ketterl
c07d9ecf92 use the right rates 2021-07-25 19:36:03 +02:00
Jakob Ketterl
99c7093a1a pack the client audio processing into its own chain 2021-07-25 19:31:56 +02:00
Jakob Ketterl
223c2d1709 BufferReader won't return bytes 2021-07-25 17:36:32 +02:00
Jakob Ketterl
6db80ec51a clarify s-meter interval calculations 2021-07-25 00:17:27 +02:00
Jakob Ketterl
207ada70fd restore s-meter display 2021-07-25 00:05:48 +02:00
Jakob Ketterl
c50da15bfd apply all decimation in comples to simplify the chain 2021-07-24 22:25:41 +02:00
Jakob Ketterl
ab99b8e476 don't wrap the module, it's not necessary 2021-07-24 22:11:41 +02:00
Jakob Ketterl
7d7cec1ec3 update to match pycsdr chaanges 2021-07-24 18:50:30 +02:00
Jakob Ketterl
de14fa4b93 don't compile the tests (they're optional by now) 2021-07-23 11:44:14 +02:00
Jakob Ketterl
355b47760c update m17 in docker to v2.0 2021-07-23 10:52:21 +02:00
Jakob Ketterl
aeca8265c3 fine-tune agc 2021-07-20 17:58:32 +02:00
Jakob Ketterl
b242f09d5d Merge branch 'develop' into pycsdr 2021-07-20 13:33:52 +02:00
Jakob Ketterl
ad396fa970 remove "unvoiced quality" setting 2021-07-20 13:33:26 +02:00
Jakob Ketterl
2bcb62e706 add ssb chain 2021-07-20 00:57:43 +02:00
Jakob Ketterl
be093b8b05 implement a method to replace chain members 2021-07-20 00:44:41 +02:00
Jakob Ketterl
eb76ec4a9f add am demodulator chain 2021-07-19 23:32:03 +02:00
Jakob Ketterl
f03a6c127e fix initial demodulator parameters 2021-07-19 19:48:18 +02:00
Jakob Ketterl
5bb14a8997 first working nfm chain using pycsdr 2021-07-19 19:04:14 +02:00
Jakob Ketterl
bb77d2ce0a fix subscription 2021-07-18 14:57:50 +02:00
Jakob Ketterl
8531d5e4ab properly shutdown and unblock the final buffer 2021-07-18 14:56:48 +02:00
Jakob Ketterl
320521a74a adopt to updated api 2021-07-16 16:12:16 +02:00
Jakob Ketterl
5e7a0a38aa Merge branch 'develop' into pycsdr 2021-07-15 18:09:39 +02:00
Jakob Ketterl
e6dd1e0fde disable squelch for DRM, too 2021-07-15 12:54:21 +02:00
Jakob Ketterl
0277ae8722 fix plutosdr soapy module url 2021-07-15 12:53:48 +02:00
Jakob Ketterl
12c032112b handle errors caused by values that don't fit into json 2021-07-09 13:52:59 +02:00
Jakob Ketterl
4e61ed3645 handle errors while parsing dprs data 2021-07-09 13:52:33 +02:00
Jakob Ketterl
6a59369c62 update remote device input field behaviour 2021-07-05 12:58:16 +02:00
Jakob Ketterl
0039d5fdcb update codecserver in docker 2021-07-04 16:13:45 +02:00
Jakob Ketterl
40075c1adb check if id contained in radioid data matches request 2021-06-28 13:04:47 +02:00
Jakob Ketterl
7a4ed3b383 update path accordingly 2021-06-19 20:23:26 +02:00
Jakob Ketterl
2479c2207a update soapysdrplay3 2021-06-19 20:16:21 +02:00
Jakob Ketterl
48eb754170 collapse empty meta lines 2021-06-18 09:31:02 +02:00
Jakob Ketterl
ddcdd550fd update dependencies 2021-06-17 15:01:10 +02:00
Jakob Ketterl
a48a5e366b improve variable usage 2021-06-17 14:58:16 +02:00
Jakob Ketterl
8b34e6c689 remove dsd 2021-06-17 14:57:59 +02:00
Jakob Ketterl
e71cd01522 always update to ensure removal of old state 2021-06-17 14:57:24 +02:00
Jakob Ketterl
2ecefcecd5 update dependency handling for nxdn 2021-06-17 14:13:17 +02:00
Jakob Ketterl
5d8fd9ae95 update codecserver and digiham in docker 2021-06-15 23:09:32 +02:00
Jakob Ketterl
f5c2525f22 switch NXDN to use digiham decoder; add meta panel 2021-06-15 22:50:30 +02:00
Jakob Ketterl
34065e455f parse NMEA coordinates from metadata 2021-06-14 23:39:18 +02:00
Jakob Ketterl
b142233d4e report as DPRS on the map 2021-06-11 16:43:28 +02:00
Jakob Ketterl
e9b2007863 fix DPRS parsing and display 2021-06-11 14:36:11 +02:00
Jakob Ketterl
455b2ce1f1 adapt D-Star terminology in the labels 2021-06-09 23:28:07 +02:00
Jakob Ketterl
d0ee6f7d3e update changelogs 2021-06-08 23:08:06 +02:00
Jakob Ketterl
5b0aa274eb increase required digiham version to 0.5 2021-06-08 23:06:25 +02:00
Jakob Ketterl
234cbf0fa8 update dependency system to use digiham for d-star 2021-06-08 23:01:49 +02:00
Jakob Ketterl
4fd5a62980 fix flexbox display of metadata panels 2021-06-08 23:01:03 +02:00
Jakob Ketterl
ba97f76737 add parsing of DPMR data 2021-06-08 18:38:53 +02:00
Jakob Ketterl
f3d1084b60 make the location icon less jumpy 2021-06-08 17:55:56 +02:00
Jakob Ketterl
6c2ba7bc1d only work with header field if sync is available 2021-06-08 14:05:17 +02:00
Jakob Ketterl
2be58503c6 adapt protocol / mode string 2021-06-08 14:04:54 +02:00
Jakob Ketterl
17a78ffa79 fix typo 2021-06-08 14:04:28 +02:00
Jakob Ketterl
322582d29b add dstar metadata panel 2021-06-08 13:37:13 +02:00
Jakob Ketterl
5fd303f4a2 replace dsd with dstar_decoder from the digiham package 2021-06-08 13:36:08 +02:00
Jakob Ketterl
46d7fa7347 improve error message 2021-06-03 15:23:28 +02:00
Jakob Ketterl
845f937fa3 make property deletions evaluate to false for convenience 2021-06-01 11:37:51 +02:00
Jakob Ketterl
85a58eefa9 update codecserver and digiham 2021-05-31 21:06:13 +02:00
Jakob Ketterl
8923b90b3e check if AMBE is available at codecserver 2021-05-31 20:41:37 +02:00
Jakob Ketterl
a9d9206d2e update WSJT-X to 2.4.0 2021-05-31 19:54:11 +02:00
Jakob Ketterl
a374e93ee8 replace mbelib with codecserver in docker 2021-05-31 18:40:45 +02:00
Jakob Ketterl
bcf05e00f7 actually, digiham should recommend the codecserver 2021-05-31 00:44:52 +02:00
Jakob Ketterl
b35d1908c7 fix user in postinst script 2021-05-31 00:44:28 +02:00
Jakob Ketterl
d824cc375e add codecserver as a recommended dependency 2021-05-30 23:38:58 +02:00
Jakob Ketterl
d04ab43977 add ability to configure codecserver 2021-05-29 18:50:17 +02:00
Jakob Ketterl
9cd730dc9a allow digiham binaries to return their own name 2021-05-28 00:02:20 +02:00
Jakob Ketterl
a16ad952c4 change digiham / ambe integration 2021-05-27 21:35:55 +02:00
Jakob Ketterl
3f7a93acfc drop the scheduler from the config if it's empty 2021-05-19 16:02:44 +02:00
Jakob Ketterl
bdf1ed4709 update changelogs 2021-05-19 15:41:04 +02:00
Jakob Ketterl
ebc935c1a9 improve message 2021-05-18 20:46:33 +02:00
Jakob Ketterl
5b92c317c1 improve connection timeout handling 2021-05-18 20:44:05 +02:00
Jakob Ketterl
48dc75c728 improve handshake handling 2021-05-18 16:00:15 +02:00
Jakob Ketterl
3e7eb09f3e introduce a websocket handler interface 2021-05-18 15:42:30 +02:00
Jakob Ketterl
9baebf444d update connectors in docker 2021-05-18 00:34:06 +02:00
Jakob Ketterl
83feb2c0e0 parse individual connector versions 2021-05-17 23:57:37 +02:00
Jakob Ketterl
33a942707c allow slots to be off in the daylight scheduler 2021-05-17 23:23:25 +02:00
Jakob Ketterl
e206b83e74 move the error overlay so it doesn't block the title menu buttons 2021-05-17 21:14:00 +02:00
Jakob Ketterl
970be58e9c invent a new icon for continuous auto waterfall mode 2021-05-17 20:25:25 +02:00
Jakob Ketterl
2e326573d0 sync favicons 2021-05-17 17:19:12 +02:00
Jakob Ketterl
49a069f0ee add more icon options for other weird browsers 2021-05-17 17:14:14 +02:00
Jakob Ketterl
a580989639 update favicon 2021-05-17 16:47:00 +02:00
Jakob Ketterl
c46b3275a9 allow negative frequencies in exponential display, closes #247 2021-05-17 15:08:44 +02:00
Jakob Ketterl
0258a75650 replace meta panel images with svg (inlining does not work due to
filters)
2021-05-16 22:47:35 +02:00
Jakob Ketterl
979f11f40a move play button to svg-defs 2021-05-16 17:47:02 +02:00
Jakob Ketterl
a04f198ade inline the google maps pin svg 2021-05-16 17:30:34 +02:00
Jakob Ketterl
8a54ef4cd0 clean up
* remove sprites and corresponding styles
* remove base pngs
* remove other unused images
2021-05-16 16:10:00 +02:00
Jakob Ketterl
7ec592ce3d replace up and down arrows with svgs 2021-05-16 15:59:21 +02:00
Jakob Ketterl
6e0e271294 replace bookmark button with svg 2021-05-16 01:06:57 +02:00
Jakob Ketterl
7427a65f18 replace edit icon with svg 2021-05-16 00:56:50 +02:00
Jakob Ketterl
39d49ca991 replace trashcan icon with svg 2021-05-16 00:39:53 +02:00
Jakob Ketterl
31a30532a7 replace waterfall default button with svg 2021-05-16 00:22:11 +02:00
Jakob Ketterl
2190fd7c5a modified inkscape, too 2021-05-16 00:08:21 +02:00
Jakob Ketterl
981053a7c7 correct opacity 2021-05-16 00:07:30 +02:00
Jakob Ketterl
2d8ae33542 replace squelch button with svg 2021-05-15 23:57:24 +02:00
Jakob Ketterl
ced6153aa7 replace waterfall auto button with svg 2021-05-15 23:40:53 +02:00
Jakob Ketterl
4a1676bb81 replace speaker icons with svg 2021-05-15 23:02:06 +02:00
Jakob Ketterl
6af115f4f0 replace top logo with svg 2021-05-15 21:42:04 +02:00
Jakob Ketterl
8550f10d88 allow svg to be gzipped 2021-05-14 23:10:17 +02:00
Jakob Ketterl
3b8961c8c6 replace zoom in / out total with svg 2021-05-14 23:01:27 +02:00
Jakob Ketterl
eb55167add remove the prefix 2021-05-14 22:31:23 +02:00
Jakob Ketterl
ae8061ee77 replace zoom in and out icons with svg 2021-05-14 20:00:07 +02:00
Jakob Ketterl
4f0d4983ca introduce http timeout; single router instance 2021-05-14 18:36:30 +02:00
Jakob Ketterl
d34ac58e73 use placeholder for device and profile in tabs as well 2021-05-14 16:00:29 +02:00
Jakob Ketterl
ee8688345e display a placeholder if device name is empty 2021-05-14 15:52:18 +02:00
Jakob Ketterl
4aba612760 replace settings icon with svg 2021-05-14 01:30:59 +02:00
Jakob Ketterl
e709ca0e77 replace map icon with svg 2021-05-13 18:38:02 +02:00
Jakob Ketterl
6bd3fdf6f4 replace receiver icon with svg 2021-05-13 15:46:55 +02:00
Jakob Ketterl
4b969fa3b2
Merge pull request #235 from jancona/hpsdr_config
Set proper config options for HPSDR connector
2021-05-12 21:13:37 +02:00
Jakob Ketterl
1020c9bac9 improve form validation
* don't ingore errors in optional fields
* don't attempt parsing if key is not present in upload
* force display of fields with errors
2021-05-12 16:22:45 +02:00
Jakob Ketterl
002827cbf4 move openwebrx-panel-status to svg 2021-05-12 00:43:01 +02:00
Jakob Ketterl
a676e203c7 first svg for openwebrx-panel-log 2021-05-11 23:36:30 +02:00
Jim Ancona
87b9a52fcb Don't filter inputs, add a validator for RF Gain 2021-05-11 11:21:52 -04:00
Jakob Ketterl
2d2f9bed40 add empty __init__.py (PEP420 doesn't always work...) 2021-05-11 14:28:35 +02:00
Jim Ancona
e37bc0573d Set proper config options for HPSDR connector 2021-05-10 20:35:49 -04:00
Jakob Ketterl
301b3b59a5 fix linter issues 2021-05-10 23:02:43 +02:00
Jakob Ketterl
40c78940ef don't close twice 2021-05-10 21:27:40 +02:00
Jakob Ketterl
a006d8c125 bumb develop to the next minor version 2021-05-09 16:06:03 +02:00
Jakob Ketterl
0c9d37e381 Merge branch 'develop' into release-1.0 2021-05-08 21:10:58 +02:00
Jakob Ketterl
dc848a7006 fix bandwidth calculation for single-service groups 2021-05-08 00:59:57 +02:00
Jakob Ketterl
093ad6cd0d improve oversampling for resampling 2021-05-08 00:38:00 +02:00
Jakob Ketterl
fd26acca68 don't resample when there's only one service 2021-05-08 00:37:30 +02:00
Jakob Ketterl
3daf005c81 Merge branch 'develop' into release-1.0 2021-05-07 17:53:51 +02:00
Jakob Ketterl
1b31c5fc90 keep the spinner visible while the image loads 2021-05-07 17:44:24 +02:00
Jakob Ketterl
0206a6f94c introduce spinner during file uploads 2021-05-07 17:33:10 +02:00
Jakob Ketterl
484b829b90 fix problem when switching image file types 2021-05-07 17:19:11 +02:00
Jakob Ketterl
ad8877f83c add webp support for uploadable images 2021-05-07 16:57:54 +02:00
Jakob Ketterl
e205953bfc short description should be a question (lintian) 2021-05-06 19:39:58 +02:00
Jakob Ketterl
8a7182f9d5 update docker build versions 2021-05-06 19:30:07 +02:00
Jakob Ketterl
f86487f459 prepare release 1.0.0 2021-05-06 19:27:43 +02:00
Jakob Ketterl
7fc7fe5e82 fix audio chopper mode timestamp problem 2021-05-05 22:55:20 +02:00
Jakob Ketterl
3057c3ffd7 make the circle a little bit smaller to improve rendering 2021-05-05 20:00:27 +02:00
Jakob Ketterl
282ba4d095 move play button overlay to javascript to avoid downloading the image 2021-05-05 19:56:14 +02:00
Jakob Ketterl
1b4b87b14e replace play button with an svg 2021-05-05 19:27:03 +02:00
Jakob Ketterl
55254b1c44 compress png images for performance 2021-05-05 18:43:24 +02:00
Jakob Ketterl
cd935c0dcb check for empty return 2021-05-04 16:05:44 +02:00
Jakob Ketterl
a17690dc91 clear session cookie if invalid 2021-05-03 23:22:28 +02:00
Jakob Ketterl
fe1a1207e6 implement session timeout 2021-05-03 23:07:27 +02:00
Jakob Ketterl
041e8930bf don't send native deletions 2021-05-03 19:28:03 +02:00
Jakob Ketterl
d9fe604171 improve error handling on file switches 2021-05-02 00:07:24 +02:00
Jakob Ketterl
290f67735d improve decoding file switchover 2021-05-02 00:06:50 +02:00
Jakob Ketterl
0fa8774493 increase bandwidth for digital modes to 12.5 2021-05-01 18:27:15 +02:00
Jakob Ketterl
53c5c0f045 add a latencyHint to improve audio playback 2021-05-01 16:55:08 +02:00
Jakob Ketterl
11568256ed remove unused imports 2021-05-01 16:51:02 +02:00
Jakob Ketterl
2152184bf9 fix compatibility issues with python 3.5 2021-05-01 16:49:53 +02:00
Jakob Ketterl
f8971ac704 protect against low-level errors during switching 2021-04-30 01:20:33 +02:00
Jakob Ketterl
540198b12a 96kHz is reported as working, too - refs #201 2021-04-29 20:15:51 +02:00
Jakob Ketterl
48d498941e fix url for image replacement, too 2021-04-29 19:53:43 +02:00
Jakob Ketterl
318cb728e1 fix imageupload path 2021-04-29 19:41:06 +02:00
Jakob Ketterl
f481c3f8e3 implement image upload error handling 2021-04-29 19:07:10 +02:00
Jakob Ketterl
af553c422d implement file size upload limit 2021-04-29 18:18:18 +02:00
Jakob Ketterl
7115d5c951 prefer native sample rate, if good - closes #201 2021-04-29 16:23:51 +02:00
Jakob Ketterl
7642341b2e fix checkbox labels when removing their optional fields 2021-04-29 15:34:46 +02:00
Jakob Ketterl
29bce9e07a refactor: move form stuff out of source code 2021-04-29 15:28:18 +02:00
Jakob Ketterl
35dcff90ea refactor owrx.form -> owrx.form.input 2021-04-29 15:17:21 +02:00
Jakob Ketterl
bc193c834c use a number display to avoid wrong input and support locales 2021-04-28 23:03:03 +02:00
Jakob Ketterl
3bc39a9ca3 fix "NaN" display problem 2021-04-28 22:44:33 +02:00
Jakob Ketterl
4a77d2cc38 fill error variable with an empty string for the device list 2021-04-27 23:19:48 +02:00
Jakob Ketterl
a7e2aae292 reset initial demodulator params on reconnects 2021-04-27 23:13:44 +02:00
Jakob Ketterl
c6e01eed1a implement top-level error handling 2021-04-27 18:23:59 +02:00
Jakob Ketterl
118335b2b6 lock on dsp to avoid race conditions 2021-04-27 16:58:23 +02:00
Jakob Ketterl
0c7b0d2eaa improve dsp control handling 2021-04-27 01:58:20 +02:00
Jakob Ketterl
cb8ec3c760 improve sdr device state handling 2021-04-27 01:44:30 +02:00
Jakob Ketterl
e408c66702 switch condition sequencing to get better error messages 2021-04-27 01:15:56 +02:00
Jakob Ketterl
d97d66c787 move logging config to the top again 2021-04-27 00:53:45 +02:00
Jakob Ketterl
96ada02e38 initialize logging first 2021-04-27 00:47:33 +02:00
Jakob Ketterl
ae729990ca let's see if we can override the loglevel this way 2021-04-27 00:45:14 +02:00
Jakob Ketterl
afc4fc2d00 improve logging configuration 2021-04-27 00:33:52 +02:00
Jakob Ketterl
25d04f4cbc exclude keys that have been moved to openwebrx.conf 2021-04-26 21:27:15 +02:00
Jakob Ketterl
5a60869f8e check for contents of bookmark files to improve migration 2021-04-26 21:05:33 +02:00
Jakob Ketterl
7962da9454 initialize settings 2021-04-26 20:10:44 +02:00
Jakob Ketterl
4691987cc4 fix config command 2021-04-26 19:34:50 +02:00
Jakob Ketterl
05985ff46a add command for explicit migration 2021-04-26 19:27:12 +02:00
Jakob Ketterl
159c231884 types don't play that much of a role any more 2021-04-25 21:46:00 +02:00
Jakob Ketterl
86e64225bd credit @jancona in the changelog 2021-04-25 21:45:29 +02:00
Jakob Ketterl
1156916631 setup S6 to accept openwebrx arguments on docker run 2021-04-25 19:25:54 +02:00
Jakob Ketterl
a6ed578a0f handle sdr device and profile name changes 2021-04-25 00:48:45 +02:00
Jakob Ketterl
8c5546ad90 remove debugging again 2021-04-24 20:17:55 +02:00
Jakob Ketterl
f3ed4a719a fix command 2021-04-24 20:14:25 +02:00
Jakob Ketterl
2da2a57e13 change password if user already exists 2021-04-24 20:12:39 +02:00
Jakob Ketterl
6de91c0c4e let's try this way 2021-04-24 20:07:08 +02:00
Jakob Ketterl
cc3e43c6cd enable reconfigure 2021-04-24 20:04:07 +02:00
Jakob Ketterl
d04cf5f5a1 add the necessary template 2021-04-24 19:52:20 +02:00
Jakob Ketterl
b7e38960c0 handle config key not set 2021-04-24 19:48:42 +02:00
Jakob Ketterl
1e684f9bf1 debug config script, too 2021-04-24 19:46:19 +02:00
Jakob Ketterl
259d036083 enable debugging to see what's wrong 2021-04-24 19:42:42 +02:00
Jakob Ketterl
71b0fa968b merge openwebrx-admin into openwebrx 2021-04-24 19:39:48 +02:00
Jakob Ketterl
6ad3a80fc6 update digiham dependency to 0.4 (improved dc blocker) 2021-04-23 18:51:39 +02:00
Jakob Ketterl
b1cfe79ddd both ubuntu and debian have js8call packages, so add it to recommended 2021-04-23 18:35:52 +02:00
Jakob Ketterl
5e6508cd47 update with JS8 frequency on 11m 2021-04-23 17:20:37 +02:00
Jakob Ketterl
5f5881cdfa update owrx_connector in docker 2021-04-21 23:21:47 +02:00
Jakob Ketterl
f6b0e37664 add the ability to set admin user and pass via env variables for docker 2021-04-21 14:29:36 +02:00
Jakob Ketterl
1bc5633b27 update digiham 2021-04-20 17:49:41 +02:00
Jakob Ketterl
1c23fdf3ff update m17-cxx-demod 2021-04-20 01:17:18 +02:00
Jakob Ketterl
bd29f9c572 dc_block is part of the digiham package 2021-04-20 01:07:06 +02:00
Jakob Ketterl
89cd17042a re-introduce (improved) dc blocker to allow slightly off-frequency
signals
2021-04-20 01:06:01 +02:00
Jakob Ketterl
8b5cf9983e display a hint if no bookmarks are in the system 2021-04-18 21:15:02 +02:00
Jakob Ketterl
04a5e6705f remove bookmarks from distribution 2021-04-18 19:30:49 +02:00
Jakob Ketterl
77de488521 mark last breadcrumb active 2021-04-18 19:25:29 +02:00
Jakob Ketterl
52b535c608 remove id input from new profile page 2021-04-18 19:17:27 +02:00
Jakob Ketterl
05ea11f5d1 introduce generated device ids 2021-04-18 19:04:43 +02:00
Jakob Ketterl
e8cf014903 introduce breadcrumbs in the web config 2021-04-18 17:49:13 +02:00
Jakob Ketterl
1968e15237 fix for submit for path routed environments 2021-04-18 16:30:02 +02:00
Jakob Ketterl
da698e7a3c fix login for path routed environment 2021-04-18 15:59:05 +02:00
Jakob Ketterl
b9db64d4f9 fix device links for path-route environments 2021-04-18 15:40:46 +02:00
Jakob Ketterl
51af299aa2 merge in updates from receiverbook 2021-04-18 01:41:13 +02:00
Jakob Ketterl
440b3a3822 remove config_webrx.py from docker images, too 2021-04-18 01:01:48 +02:00
Jakob Ketterl
5ec0005f81 remove digimodes_enable setting since it no longer works 2021-04-18 00:50:13 +02:00
Jakob Ketterl
11b0d2d90a add deprecation notice 2021-04-18 00:49:38 +02:00
Jakob Ketterl
322a52e854 remove config_webrx.py from debian package 2021-04-18 00:08:34 +02:00
Jakob Ketterl
1b8153c461 rename default profiles 2021-04-18 00:03:18 +02:00
Jakob Ketterl
dae32f2e95 return an empty layer if no config is available 2021-04-17 23:56:32 +02:00
Jakob Ketterl
b4c2923dd2 add some info text 2021-04-17 18:00:13 +02:00
Jakob Ketterl
68739724d4 make the sdr type dropdown show beautiful names 2021-04-17 17:42:08 +02:00
Jakob Ketterl
4993a56235 use a single connection to avoid the managing overhead 2021-04-11 21:04:13 +02:00
Jakob Ketterl
cb3cb50cbd fix chopper startup 2021-04-11 20:10:49 +02:00
Jakob Ketterl
7e4671afe4 Improve profile handling
* introduce profile sources
* subscriptions can handle config change events
* web config changes to profile changes will now take effect immediately
2021-04-11 18:46:21 +02:00
Jakob Ketterl
19c8432371 always perform shutdown tasks 2021-04-11 18:42:35 +02:00
Jakob Ketterl
9351e4793c merge AudioHandler and AudioChopper; split audio module 2021-04-11 14:40:28 +02:00
Jakob Ketterl
1f91908e06 maybe this will suit the unittest loader better 2021-04-10 02:12:18 +02:00
Jakob Ketterl
907359df82 fix js8 parser 2021-04-09 22:40:30 +02:00
Jakob Ketterl
e210c3a667 group audio writers by interval 2021-04-09 20:15:03 +02:00
Jakob Ketterl
9c4d7377d0 more type hints that don't work... circular imports... broken :( 2021-04-09 18:37:00 +02:00
Jakob Ketterl
8ce1192811 type hinting is invalid. this shouldn't work, but obviously type hinting
is broken. remove :(
2021-04-09 18:29:36 +02:00
Jakob Ketterl
d18a4c83ac don't send bookmarks if the parameters are not available 2021-04-09 18:29:08 +02:00
Jakob Ketterl
bbad34cec3 move wsjt/js8 decisions out of csdr 2021-04-09 18:16:25 +02:00
Jakob Ketterl
22ec80c8ea make decoding queue settings work from the web config 2021-04-07 18:57:42 +02:00
Jakob Ketterl
5487861da1 make wsprnet and pskreporter settings work from the web config 2021-04-07 17:54:14 +02:00
Jakob Ketterl
ebd4d93908 add note about background decoding 2021-04-07 16:23:13 +02:00
Jakob Ketterl
fcbaa4f22a implement aprs config changes 2021-04-07 16:20:10 +02:00
Jakob Ketterl
c0ca216e4d make "digimodes_fft_size" work from web config 2021-04-05 17:18:30 +02:00
Jakob Ketterl
a9990f1f41 remove redpitaya source (working with hpsdr_connector) 2021-04-05 15:48:03 +02:00
Jakob Ketterl
b877d8439a fix "remote" mappings for rtl_tcp and soapy_remote 2021-04-02 21:46:21 +02:00
Jakob Ketterl
6cca37a9df fix runds "remote" input mapping 2021-04-02 21:44:51 +02:00
Jakob Ketterl
7a2f62a307 fix name 2021-04-02 21:43:46 +02:00
Jakob Ketterl
1932890dd0 extended "blur" behavior (using body click events) 2021-03-31 02:01:13 +02:00
Jakob Ketterl
02e699c597 add pointer to frequency display to indicate clickability 2021-03-31 01:40:35 +02:00
Jakob Ketterl
46d742a12c add cursor to indicate scrollability 2021-03-31 01:38:53 +02:00
Jakob Ketterl
b3e99e0a3d prefix -> suffix; no tabstop 2021-03-31 01:36:02 +02:00
Jakob Ketterl
96cce831ef don't tab into the exponent selector input 2021-03-31 01:28:38 +02:00
Jakob Ketterl
3e00a4f390 remove map file declaration (not working) 2021-03-31 01:23:18 +02:00
Jakob Ketterl
0abd121fda inline location-picker 2021-03-31 01:22:39 +02:00
Jakob Ketterl
b605927207 update changelogs 2021-03-31 00:34:55 +02:00
Jakob Ketterl
3696272ef7 inline nmux_memory since i've never seen the need to change it 2021-03-31 00:23:36 +02:00
Jakob Ketterl
5a7c12dfac expose waterfall auto adjustment settings in web config 2021-03-31 00:18:06 +02:00
Jakob Ketterl
170b720e48 restructure config 2021-03-31 00:00:38 +02:00
Jakob Ketterl
c6962b4f42 change headline wording 2021-03-30 23:41:26 +02:00
Jakob Ketterl
8e7b758ef8 send personal bookmarks to the server 2021-03-30 18:50:30 +02:00
Jakob Ketterl
1b9e77982d make "new bookmark" api work with arrays 2021-03-30 18:30:08 +02:00
Jakob Ketterl
2d142e45ed implement dialog to import personal bookmarks 2021-03-30 18:19:23 +02:00
Jakob Ketterl
620ba11565 update wsjt-x patchset 2021-03-30 16:15:05 +02:00
Jakob Ketterl
e297cffbfe update to wsjt-x 2.3.1 2021-03-30 15:14:35 +02:00
Jakob Ketterl
af211739fb confirmation modal before deleting bookmarks 2021-03-28 16:51:34 +02:00
Jakob Ketterl
a86a2f31cd styling 2021-03-27 23:50:39 +01:00
Jakob Ketterl
6796699e35 don't redirect XHR calls to the login page, 403 instead 2021-03-27 23:45:21 +01:00
Jakob Ketterl
df72147b93 handle only successful results 2021-03-27 23:40:30 +01:00
Jakob Ketterl
65443eb0ba improve event handling 2021-03-27 23:40:10 +01:00
Jakob Ketterl
29c0f7148a re-work the bookmarks table to incorporate the improved frequency input 2021-03-27 23:08:43 +01:00
Jakob Ketterl
e1dd9d32f4 prevent javascript errors if frequency is NaN 2021-03-25 16:08:02 +01:00
Jakob Ketterl
287a04be94 send updated bookmarks to clients on the fly 2021-03-25 15:25:15 +01:00
Jakob Ketterl
20cd3f6efe more inputs that can display errors 2021-03-25 15:02:59 +01:00
Jakob Ketterl
69237c0bb4 make more inputs display errors 2021-03-25 14:48:09 +01:00
Jakob Ketterl
383c08ed48 implement tuning precision dropdown 2021-03-24 23:43:19 +01:00
Jakob Ketterl
19496d46a3 fix form evaluation for optional fields 2021-03-24 23:17:50 +01:00
Jakob Ketterl
6ddced4689 implement basic error handling and validation for forms 2021-03-24 22:46:51 +01:00
Jakob Ketterl
4cbce9c840 always remove device props on switch, fixes device failover 2021-03-24 20:47:04 +01:00
Jakob Ketterl
b01792c3d2 fix deletion of sdrs when there's no changes 2021-03-24 17:25:59 +01:00
Jakob Ketterl
5f7daba3b2 move the default sdrs to the new defaults file 2021-03-24 17:19:49 +01:00
Jakob Ketterl
a90f77e545 retain the redirect url on login failure 2021-03-24 16:53:01 +01:00
Jakob Ketterl
d50d08ad2c add a robots.txt to exclude certain routes for search engines 2021-03-24 16:08:13 +01:00
Jakob Ketterl
deeaccba12 profile as properties, live sync additions and removals with the client 2021-03-24 15:57:25 +01:00
Jakob Ketterl
62e67afc9c update config to version 6 2021-03-21 15:23:26 +01:00
Jakob Ketterl
c9d303c43e remove "configurable_keys" hack 2021-03-21 15:19:40 +01:00
Jakob Ketterl
5fc8672dd6 fix profile detection 2021-03-21 00:18:35 +01:00
Jakob Ketterl
acee318dae make the frontend resume when an sdr device becomes present 2021-03-21 00:14:18 +01:00
Jakob Ketterl
8fa1796037 re-start connection sdr if no sdr was available before 2021-03-20 23:30:09 +01:00
Jakob Ketterl
2a82f4e452 wire profile transmission into active sdr device hash 2021-03-20 23:14:29 +01:00
Jakob Ketterl
341e254640 fix shutdown iteration 2021-03-20 17:24:00 +01:00
Jakob Ketterl
d872152cc8 restore python 3.5 compatibility 2021-03-20 17:23:35 +01:00
Jakob Ketterl
3b9763eee5 fix device deletion 2021-03-20 02:16:08 +01:00
Jakob Ketterl
cfeab98620 hook up service handling to new device events 2021-03-20 01:56:07 +01:00
Jakob Ketterl
792f76f831 turn the dict of active sources into a living PropertyManager 2021-03-20 01:10:18 +01:00
Jakob Ketterl
c58ebfa657 readonly also prevents deletion 2021-03-20 00:54:45 +01:00
Jakob Ketterl
c50473fea5 implement device shutdown on deletion or lack of profiles 2021-03-18 22:59:46 +01:00
Jakob Ketterl
f1619b81fe use the right method 2021-03-18 22:24:53 +01:00
Jakob Ketterl
364c7eb505 show more information on the sdr settings page 2021-03-18 21:53:59 +01:00
Jakob Ketterl
9dcf342b13 fix scheduler behavior on enable / disable 2021-03-18 21:17:23 +01:00
Jakob Ketterl
d573561c67 activate enable / disable cycle 2021-03-18 19:59:10 +01:00
Jakob Ketterl
37e7331627 fix device failover (concurrent modification problem) 2021-03-18 19:47:11 +01:00
Jakob Ketterl
b25a673829 refactor state handling: uncouple failed and enabled flags 2021-03-18 19:34:53 +01:00
Jakob Ketterl
916f19ac60 mapping sdr device layer 2021-03-18 18:59:38 +01:00
Jakob Ketterl
620771eaf2 use a property layer right from the start 2021-03-18 18:58:29 +01:00
Jakob Ketterl
161408dbf4 handle deletions correctly 2021-03-06 23:48:31 +01:00
Jakob Ketterl
e0985c3802 fix status page 2021-03-06 23:34:27 +01:00
Jakob Ketterl
3d20e3ed80 simplify api by abstracting layer changes 2021-03-06 22:20:47 +01:00
Jakob Ketterl
6af0ad0262 fix frequency unit dropdown for firefox 2021-03-05 20:31:23 +01:00
Jakob Ketterl
b4460f4f70 fix receiver appearance in firefox 2021-03-05 20:20:22 +01:00
Jakob Ketterl
ff9f771e1b handle the resampler 2021-03-05 19:44:45 +01:00
Jakob Ketterl
4c5ec23ba7 remove profile list from sdr device index 2021-03-05 19:44:25 +01:00
Jakob Ketterl
1b44229ec3 clean up profile handling 2021-03-05 19:28:54 +01:00
Jakob Ketterl
2e28694b49 implement profile removal behaviour 2021-03-05 19:09:51 +01:00
Jakob Ketterl
2ba2ec38e0 new profile carousel implementation reacts to new profiles 2021-03-05 18:57:09 +01:00
Jakob Ketterl
a3cfde02c4 re-wire profile add & delete 2021-03-05 18:32:16 +01:00
Jakob Ketterl
a14f247859 make the add button look more like the remove button 2021-03-05 18:07:19 +01:00
Jakob Ketterl
45e9bd12a5 hightlight "new profile" link 2021-03-05 17:51:19 +01:00
Jakob Ketterl
190c90ccdf tab styling 2021-03-05 17:43:15 +01:00
Jakob Ketterl
60df3afe26 add tab navigation to profile and device pages 2021-03-04 22:14:10 +01:00
Jakob Ketterl
4e14b29537 apply type="button" on all buttons to make submit on enter work 2021-03-03 23:25:00 +01:00
Jakob Ketterl
3814200452 implement device and profile deletion 2021-03-03 23:07:41 +01:00
Jakob Ketterl
a9dbedee6d consistent wording 2021-03-03 22:35:57 +01:00
Jakob Ketterl
8671f98c14 implement "add profile" sequence 2021-03-03 22:33:37 +01:00
Jakob Ketterl
400ed3541d update "new sdr" routing too to avoid conflicts 2021-03-03 22:10:19 +01:00
Jakob Ketterl
03315d7960 switch url scheme to avoid conflicts 2021-03-03 21:55:49 +01:00
Jakob Ketterl
d123232f28 implement device and profile delete modals 2021-03-03 21:51:33 +01:00
Jakob Ketterl
eab1c6ce80 remove profile list from device page; make links work 2021-03-03 15:38:15 +01:00
Jakob Ketterl
fdbb76bca1 add working redirect after device add completes 2021-03-03 15:30:33 +01:00
Jakob Ketterl
c0b7cf5f8d resolve the ugly assets_prefix hack 2021-03-03 15:24:18 +01:00
Jakob Ketterl
37d89c074b implement "new device" page (redirects not working yet) 2021-03-03 00:16:28 +01:00
Jakob Ketterl
2b1dc76e48 add profile list to the device page 2021-03-02 20:28:49 +01:00
Jakob Ketterl
e0b289b6a5 remove debugging message 2021-03-02 20:19:48 +01:00
Jakob Ketterl
d81f0ae96c change display precision behavior to reference Hertz 2021-03-01 01:19:06 +01:00
Jakob Ketterl
6bd47cf914 implement property carousel for profile switching 2021-03-01 00:26:56 +01:00
Jakob Ketterl
c7db144f7b add name input for profiles 2021-02-28 21:26:55 +01:00
Jakob Ketterl
d0ddf72b10 fix typo 2021-02-28 21:04:43 +01:00
Jakob Ketterl
92cce78320 fix panel switching 2021-02-28 18:23:35 +01:00
Jakob Ketterl
1871fc359a apply some styling 2021-02-28 18:07:25 +01:00
Jakob Ketterl
a92ead3261 implement exponential frequency input on the receiver, too 2021-02-28 17:28:22 +01:00
Jakob Ketterl
094f470ebb automatically switch SI prefixes based on frequency 2021-02-28 15:51:07 +01:00
Jakob Ketterl
06b6054071 improve floating point handling 2021-02-27 23:21:14 +01:00
Jakob Ketterl
0537e23e38 make a more generic ExponentialInput and use that for the sample_rate input 2021-02-27 23:14:41 +01:00
Jakob Ketterl
7a0c934af5 use frequency input for the other inputs, too 2021-02-27 22:44:48 +01:00
Jakob Ketterl
e787336fc4 fix empty input 2021-02-27 22:43:18 +01:00
Jakob Ketterl
71acad3b4f add keyboard shortcuts for quicker input 2021-02-27 22:30:48 +01:00
Jakob Ketterl
c389d3b619 implement a frequency input with switchable exponent 2021-02-27 22:15:19 +01:00
Jakob Ketterl
ccdb010e9d more information on the sdr list 2021-02-27 20:48:37 +01:00
Jakob Ketterl
6a9bbf7bc9 wording change 2021-02-27 20:17:58 +01:00
Jakob Ketterl
ccba3e8597 fix positioning (still absolute, but not moving any more) 2021-02-27 17:23:03 +01:00
Jakob Ketterl
beb3d696c9 use transform / will-change properties for waterfall
* prevents expensive layout events in the browser
* allows the browser to optimize rendering
2021-02-27 17:06:53 +01:00
Jakob Ketterl
54142f4f15 allow squelch_auto_margin = 0 2021-02-27 01:23:59 +01:00
Jakob Ketterl
b6ed06dff4 use the new bottom bar for the bookmarks, too 2021-02-27 01:18:08 +01:00
Jakob Ketterl
36c4a16fb5 move to settings module 2021-02-27 01:16:03 +01:00
Jakob Ketterl
1b44c31a89 more space at the bottom 2021-02-27 01:13:57 +01:00
Jakob Ketterl
45d4d868d7 clear waterfall on fft_size change so that a setting change becomes visible immediately 2021-02-27 01:09:51 +01:00
Jakob Ketterl
e9cb5d54be send changed keys over websocket connection for the map 2021-02-27 01:00:38 +01:00
Jakob Ketterl
7dcafab2c1 restart on fft_compression changes, too 2021-02-27 00:29:04 +01:00
Jakob Ketterl
baef88bd94 restart demodulator on compression changes 2021-02-27 00:17:37 +01:00
Jakob Ketterl
ad3ed1e626 disconnect clients if the max_clients setting is lowered 2021-02-27 00:01:21 +01:00
Jakob Ketterl
0a76801a03 activate "service_decoder" setting 2021-02-26 23:50:58 +01:00
Jakob Ketterl
3164683e74 handle device shudown when schedule is off 2021-02-26 22:36:15 +01:00
Jakob Ketterl
4e7f02fc2c activate more scheduler and service settings 2021-02-26 21:27:42 +01:00
Jakob Ketterl
0231d98ab8 wire "services_enabled" setting 2021-02-26 17:53:32 +01:00
Jakob Ketterl
6822475674 exclude template inputs when moving to the visible section 2021-02-26 01:12:48 +01:00
Jakob Ketterl
412e0a51c7 implement property deletion handling; activate scheduler deletion 2021-02-26 01:12:03 +01:00
Jakob Ketterl
91c4d6f568 make scheduler respond to config changes 2021-02-25 22:19:05 +01:00
Jakob Ketterl
d8b3974728 use floats; explicit conversion 2021-02-25 20:50:40 +01:00
Jakob Ketterl
5cd9d386a6 combine waterfall_[min|max]_level into a single config 2021-02-25 15:13:39 +01:00
Jakob Ketterl
f6f0a87002 this todo is resolved 2021-02-25 00:38:23 +01:00
Jakob Ketterl
8c767be53a add inputs for perseus 2021-02-24 23:54:46 +01:00
Jakob Ketterl
bccb87e660 handle deletions in the top layer 2021-02-24 23:04:57 +01:00
Jakob Ketterl
0c1dc70217 Make the apply button always visible 2021-02-24 23:04:23 +01:00
Jakob Ketterl
388d9d46fe prevent runtime properties in the config 2021-02-24 22:30:28 +01:00
Jakob Ketterl
2785f43c6a implement adding and removing scheduler slots 2021-02-24 21:09:19 +01:00
Jakob Ketterl
45a70a1079 parse values from form 2021-02-24 20:17:43 +01:00
Jakob Ketterl
2d823b2945 render scheduler profile inputs 2021-02-24 19:56:07 +01:00
Jakob Ketterl
65758a0098 start implementing scheduler input (daylight works) 2021-02-24 17:12:23 +01:00
Jakob Ketterl
ea96038201 remove unused imports 2021-02-24 12:31:53 +01:00
Jakob Ketterl
ed3d84b974 use the container instead of a (potentially missing) canvas 2021-02-24 00:59:31 +01:00
Jakob Ketterl
710a18aae3 initialize canvas on demand to avoid overlap when changing parameters 2021-02-24 00:58:50 +01:00
Jakob Ketterl
f69d78926e create filtering that prevents overwriting the device name 2021-02-24 00:09:57 +01:00
Jakob Ketterl
4199a583f8 fix agc parameter 2021-02-23 23:24:30 +01:00
Jakob Ketterl
dfaecdb357 use hierarchical property layers to make config changes effective
immediately
2021-02-23 23:23:37 +01:00
Jakob Ketterl
631232fe7c make AGC optional 2021-02-23 20:02:38 +01:00
Jakob Ketterl
f9772faa6f add separator before the optional inputs dropdown 2021-02-23 19:23:54 +01:00
Jakob Ketterl
4e32d724c4 fix storing profiles 2021-02-23 18:41:49 +01:00
Jakob Ketterl
c5df6a1527 implement profile editing page 2021-02-23 18:32:23 +01:00
Jakob Ketterl
ed258cc9a0 fill in gain stages for hackrf 2021-02-23 17:40:06 +01:00
Jakob Ketterl
437943c26c fill in airspy gain stages 2021-02-23 17:36:16 +01:00
Jakob Ketterl
d15d9d8c76 remove implicit optional handling for optional fields 2021-02-23 00:27:29 +01:00
Jakob Ketterl
436010ffe3 implement explicit removal of non-present keys 2021-02-23 00:12:22 +01:00
Jakob Ketterl
679f99d701 change checkbox handling to detect presence 2021-02-23 00:11:51 +01:00
Jakob Ketterl
1eff7a3b69 fix typo 2021-02-22 23:52:57 +01:00
Jakob Ketterl
54a34b2084 implement optional device fields 2021-02-22 23:49:28 +01:00
Jakob Ketterl
f8beae5f46 fix javascript errors 2021-02-22 23:47:19 +01:00
Jakob Ketterl
9beb3b9168 remove the label attribute from the checkboxes 2021-02-22 00:57:02 +01:00
Jakob Ketterl
770fd749cd introduce the basic concept of optional keys 2021-02-22 00:35:47 +01:00
Jakob Ketterl
683a711b49 fix bias_tee for hackrf 2021-02-21 18:11:28 +01:00
Jakob Ketterl
bd31fa5149 add the ability to disable devices 2021-02-21 18:11:08 +01:00
Jakob Ketterl
7f3d421b25 introduce profile list 2021-02-20 23:45:06 +01:00
Jakob Ketterl
44250f9719 add some device details on the list page 2021-02-20 22:57:17 +01:00
Jakob Ketterl
c2e8ac516c introduce enums for state management 2021-02-20 22:54:07 +01:00
Jakob Ketterl
dd5ab32b47 set always-on default to false 2021-02-20 19:43:04 +01:00
Jakob Ketterl
361ed55b93 add more device-specific options 2021-02-20 19:20:31 +01:00
Jakob Ketterl
8b24eff72e add sdrplay specific options 2021-02-20 19:00:28 +01:00
Jakob Ketterl
18e8ca5e43 add bias_tee and direct_sampling options 2021-02-20 18:48:12 +01:00
Jakob Ketterl
0ab6729fcc create device descriptions for all 2021-02-20 18:09:24 +01:00
Jakob Ketterl
0e64f15e65 add more device inputs 2021-02-20 17:54:19 +01:00
Jakob Ketterl
058463a9b3 fix display and parsing issues 2021-02-20 00:36:18 +01:00
Jakob Ketterl
bd7e5b7166 implement individual gain stages option 2021-02-20 00:16:32 +01:00
Jakob Ketterl
d0d946e09f implement gain dialog with AGC option 2021-02-19 21:07:13 +01:00
Jakob Ketterl
86278ff44d wire data parsing and storage 2021-02-19 18:45:29 +01:00
Jakob Ketterl
039b57d28b add more inputs, bind to actual data 2021-02-19 18:18:25 +01:00
Jakob Ketterl
27c16c3720 add more inputs 2021-02-19 16:29:30 +01:00
Jakob Ketterl
3aa238727e start building device forms 2021-02-19 15:29:17 +01:00
Jakob Ketterl
4316832b95 input merging mechanism 2021-02-19 14:53:30 +01:00
Jakob Ketterl
bec61465c9 move device descriptions to owrx.source 2021-02-19 14:44:16 +01:00
Jakob Ketterl
012952f6f3 implement some basic infrastructure to present device forms 2021-02-19 00:46:52 +01:00
Jakob Ketterl
872c7a4bfd setup device list and routing for device pages 2021-02-19 00:03:25 +01:00
Jakob Ketterl
d65743f2ea rename template variable 2021-02-18 23:05:43 +01:00
Jakob Ketterl
c5585e290a undo javascript device configuration 2021-02-18 22:24:31 +01:00
Jakob Ketterl
54fde2c1c0 reuse existing template 2021-02-18 22:12:13 +01:00
Jakob Ketterl
d612792593 update permissions on write 2021-02-18 21:07:45 +01:00
Jakob Ketterl
0d77aaff26 restrict access to openwebrx users file 2021-02-18 20:57:41 +01:00
Jakob Ketterl
b06a629ffb fix variable substitution 2021-02-18 18:41:39 +01:00
Jakob Ketterl
a29d72d67f more details in the password dialog 2021-02-18 18:38:37 +01:00
Jakob Ketterl
1a6f738c97 fix permission problems on initial install 2021-02-18 18:28:12 +01:00
Jakob Ketterl
50e19085b0 don't use full path (lintian) 2021-02-18 17:28:00 +01:00
Jakob Ketterl
e70ff075ca fix pasword prompt (lintian) 2021-02-18 17:25:33 +01:00
Jakob Ketterl
34b369b200 restore unconditional confmodule 2021-02-18 17:09:08 +01:00
Jakob Ketterl
fc5d560345 don't need to check for command, if it's not there the result will be
the same
2021-02-18 17:04:45 +01:00
Jakob Ketterl
e8ad4588ce add debhelper token to postrm script (lintian) 2021-02-18 17:02:14 +01:00
Jakob Ketterl
74aea63b9b always remove password, no matter what the value 2021-02-18 16:14:45 +01:00
Jakob Ketterl
a750726459 new mechanism doesn't require any dummy values in the db 2021-02-18 16:14:15 +01:00
Jakob Ketterl
eb8b8c4a5a include confmodule only when needed, avoiding potential warnings 2021-02-18 16:08:22 +01:00
Jakob Ketterl
1956907d6d suppress errors during check 2021-02-18 16:04:56 +01:00
Jakob Ketterl
8f49337b81 don't use expansion to test 2021-02-18 16:01:13 +01:00
Jakob Ketterl
5e37b75cfb test for existence of admin user before asking questions 2021-02-18 15:55:55 +01:00
Jakob Ketterl
c09f17579c implement a command to test for a user's existence 2021-02-18 15:42:12 +01:00
Jakob Ketterl
06d4b24b09 handle config key not set 2021-02-18 15:27:05 +01:00
Jakob Ketterl
9492bbebbb un-silence 2021-02-18 01:42:06 +01:00
Jakob Ketterl
ad5166cf9e allow reconfigure in postinst 2021-02-18 01:36:04 +01:00
Jakob Ketterl
0714ce5703 parse password from env if available 2021-02-18 01:32:27 +01:00
Jakob Ketterl
2eec29db05 change debconf priority to high 2021-02-18 01:28:40 +01:00
Jakob Ketterl
3122077603 fix debconf password questions 2021-02-18 01:12:26 +01:00
Jakob Ketterl
518588885c make postrm executable 2021-02-18 01:00:47 +01:00
Jakob Ketterl
8271eddefb rename templates file 2021-02-18 00:26:52 +01:00
Jakob Ketterl
404f995e39 confmodule doesn't work with our bash parameters 2021-02-18 00:22:37 +01:00
Jakob Ketterl
8fcfa689ae add postinst/postrm integration 2021-02-18 00:13:58 +01:00
Jakob Ketterl
f488a01c78 linitian also finds spelling errors?!? 2021-02-17 23:45:22 +01:00
Jakob Ketterl
06361754b3 add config script 2021-02-17 23:39:16 +01:00
Jakob Ketterl
b7688c3c97 add infotext for custom html colors 2021-02-16 18:39:42 +01:00
Jakob Ketterl
691d88f841 waterfall config fine-adjustments
* hide the waterfall colors input when pre-defined color scheme is
  selected
* skip unparseable lines on custom color input
* fallback to black and white if custom color config is unusable
* always use the waterfall classes when sending changes to the client
2021-02-16 18:35:18 +01:00
Jakob Ketterl
9aebeb51f8 remove waterfall_colors unless scheme is custom 2021-02-16 18:12:10 +01:00
Jakob Ketterl
8d2763930b implement input for custom waterfall colors 2021-02-16 18:07:13 +01:00
Jakob Ketterl
409370aba2 implement custom waterfall option 2021-02-16 17:48:12 +01:00
Jakob Ketterl
9175629838 send waterfall colors to the client 2021-02-16 17:34:04 +01:00
Jakob Ketterl
3c0a26eaa8 prevent file corruption during json.dump 2021-02-16 17:17:09 +01:00
Jakob Ketterl
496e771e17 implement new waterfall color selection 2021-02-16 17:12:57 +01:00
Jakob Ketterl
c8496a2547 remove unused import 2021-02-16 15:59:31 +01:00
Jakob Ketterl
d3ba866800 comment config since it is now supported in the web config 2021-02-15 22:58:02 +01:00
Jakob Ketterl
8267aa8d9d implement removal 2021-02-15 22:57:21 +01:00
Jakob Ketterl
c2617fcfaf use a converter -> parsing done 2021-02-15 22:22:07 +01:00
Jakob Ketterl
1112334ea8 render inputs, mode dropdown 2021-02-15 22:14:56 +01:00
Jakob Ketterl
578f165bdc wording change 2021-02-15 20:20:53 +01:00
Jakob Ketterl
a664770881 change link targets to _blank 2021-02-15 20:20:32 +01:00
Jakob Ketterl
c0193e677c add an input for wsjt_decoding_depths 2021-02-15 20:19:43 +01:00
Jakob Ketterl
819790cbc8 prevent an endless loop when client has problematic audio 2021-02-15 18:03:16 +01:00
Jakob Ketterl
b2d4046d8a apply z-index layering to status bars to make them render correctly 2021-02-15 18:00:46 +01:00
Jakob Ketterl
28b1abfa40 fix missing unit 2021-02-15 17:33:47 +01:00
Jakob Ketterl
a72a11d3c7 fix old unsubscription todo 2021-02-15 17:25:46 +01:00
Jakob Ketterl
2d37f63f2c title should be a header for SEO 2021-02-15 17:16:55 +01:00
Jakob Ketterl
48a9c76c18 inline header variables 2021-02-15 17:12:17 +01:00
Jakob Ketterl
7f9c0539bb break out demodulation and decoding settings 2021-02-15 16:06:14 +01:00
Jakob Ketterl
e61dde7d0e separate background decoding 2021-02-15 15:56:17 +01:00
Jakob Ketterl
d998ab5c61 break out reporting into its own settings page 2021-02-15 15:49:44 +01:00
Jakob Ketterl
49640b5e33 generalize settings controller 2021-02-15 15:40:37 +01:00
Jakob Ketterl
391069653a split settings controller module (preparation to split general settings) 2021-02-15 15:29:02 +01:00
Jakob Ketterl
830d7ae656 fix ios 14.2 bug 2021-02-15 00:04:43 +01:00
Jakob Ketterl
48c594fdae implement bookmark deletion 2021-02-14 16:51:16 +01:00
Jakob Ketterl
29a161b7b7 add the "add bookmarks" function 2021-02-14 16:21:09 +01:00
Jakob Ketterl
9b1659d3dd remove index (unused) 2021-02-14 14:48:32 +01:00
Jakob Ketterl
dbf23baa45 wait for successful ajax call 2021-02-14 00:44:36 +01:00
Jakob Ketterl
3d97d362b5 implement bookmark storage 2021-02-14 00:41:03 +01:00
Jakob Ketterl
8ea4d11e9c make the bookmarks table editable 2021-02-13 23:53:16 +01:00
Jakob Ketterl
48f26d00d6 add action column 2021-02-13 18:41:42 +01:00
Jakob Ketterl
3b60e0b737 display existing bookmarks in table 2021-02-13 18:35:15 +01:00
Jakob Ketterl
3e4ba42aab style settings page; add bookmark editor page 2021-02-13 17:08:56 +01:00
Jakob Ketterl
cda43b5c5c re-route settings urls 2021-02-13 16:44:14 +01:00
Jakob Ketterl
ae76470612 auto-reload bookmarks from file 2021-02-13 01:29:21 +01:00
Jakob Ketterl
5e51beac46 implement auto-reloading for bookmarks 2021-02-13 01:10:36 +01:00
Jakob Ketterl
8acfb8c1cf add configuration for max_client limit 2021-02-13 00:52:08 +01:00
Jakob Ketterl
ad0ca114f5 switch to subparsers 2021-02-12 18:34:28 +01:00
Jakob Ketterl
3f3f5eacfe no need to be verbose here 2021-02-12 17:45:10 +01:00
Jakob Ketterl
dd2fda54d1 add logging setup for owrxadmin 2021-02-12 17:00:51 +01:00
Jakob Ketterl
7d88d83c36 handle empty file 2021-02-12 17:00:35 +01:00
Jakob Ketterl
5068bcd347 run black 2021-02-11 23:08:19 +01:00
Jakob Ketterl
024a6684ce fix undefined variable 2021-02-11 23:07:45 +01:00
Jakob Ketterl
aad757df36 remove experimental csdr settings 2021-02-11 22:51:50 +01:00
Jakob Ketterl
690eed5d58 update changelog 2021-02-11 22:44:55 +01:00
Jakob Ketterl
c3d459558a prevent accidental text selection 2021-02-11 21:59:30 +01:00
Jakob Ketterl
fb457ce9f1 comment all config keys that are now in the web config 2021-02-11 19:42:23 +01:00
Jakob Ketterl
a8c93fd8d1 enable web config 2021-02-11 19:37:45 +01:00
Jakob Ketterl
f23fa59ac3 implement config layering 2021-02-11 19:31:44 +01:00
Jakob Ketterl
e926611307 break config module apart 2021-02-11 13:55:06 +01:00
Jakob Ketterl
1cc4b13ba6 add newline (lintian) 2021-02-11 00:29:31 +01:00
Jakob Ketterl
fdfaed005b add data directory volume definition (for whatever it's worth) 2021-02-11 00:25:31 +01:00
Jakob Ketterl
0cf67d5e2c don't use recursive (lintian) 2021-02-11 00:24:02 +01:00
Jakob Ketterl
0fd172edc3 check file contents; work with file extensions 2021-02-11 00:20:17 +01:00
Jakob Ketterl
64f827d235 loopify 2021-02-10 22:25:43 +01:00
Jakob Ketterl
1e72485425 implement temporary file cleanup 2021-02-10 22:24:43 +01:00
Jakob Ketterl
7097dc1cd8 ability to restore original image 2021-02-10 21:29:46 +01:00
Jakob Ketterl
8cf9b509c1 apply authorization to image upload 2021-02-10 20:32:07 +01:00
Jakob Ketterl
17c20d12e0 refactor authentication / authorization into a mixin 2021-02-10 20:21:45 +01:00
Jakob Ketterl
8422a33081 add information note about caching 2021-02-09 18:06:32 +01:00
Jakob Ketterl
75418baf06 apply cachebuster for form 2021-02-09 18:00:56 +01:00
Jakob Ketterl
9f17c941d1 generalize image upload form element 2021-02-09 17:54:02 +01:00
Jakob Ketterl
779aa33a4a add and resolve todos 2021-02-09 00:47:09 +01:00
Jakob Ketterl
7aa0f8b35d improve image handling 2021-02-09 00:38:59 +01:00
Jakob Ketterl
3b670016be implement uploading of top panorama, too 2021-02-09 00:12:53 +01:00
Jakob Ketterl
ad5daaae95 add exception for uploaded images 2021-02-08 23:44:10 +01:00
Jakob Ketterl
16d0e1a0d7 implement handling of uploaded files on save 2021-02-08 23:36:46 +01:00
Jakob Ketterl
4df5f19bd6 add todos 2021-02-08 23:30:44 +01:00
Jakob Ketterl
a1c024bfe2 implement dynamic file upload 2021-02-08 23:29:24 +01:00
Jakob Ketterl
2d72055070 organize 2021-02-08 20:30:12 +01:00
Jakob Ketterl
331e9627d6 implement forced password change for generated passwords 2021-02-08 18:30:54 +01:00
Jakob Ketterl
ed6594401c monitor user file modifications & reload if necessary 2021-02-08 17:24:59 +01:00
Jakob Ketterl
d9578cc5f4 thoroughly validate user 2021-02-08 17:09:22 +01:00
Jakob Ketterl
2c6b0e3d30 implement user list, enable, disable 2021-02-08 17:04:55 +01:00
Jakob Ketterl
b0c7abe362 implement form result parsing for q65 matrix 2021-02-08 16:32:00 +01:00
Jakob Ketterl
346f2af2fb update matrix generation with new abilities 2021-02-08 16:22:23 +01:00
Jakob Ketterl
902fc666c2 stricter q65 mode parsing and availability check 2021-02-08 15:58:37 +01:00
Jakob Ketterl
3a1e5ee73c avoid using tuples, they don't work in json (future config system) 2021-02-08 15:34:55 +01:00
Jakob Ketterl
a083042002 implement display of Q65 mode matrix 2021-02-08 15:16:04 +01:00
Jakob Ketterl
ce48892173 make dropdowns work with enums directly 2021-02-08 01:16:02 +01:00
Jakob Ketterl
5cfacac6c0 add aprs_igate_dir option 2021-02-08 01:00:00 +01:00
Jakob Ketterl
4758672c94 add aprs_igate_symbol 2021-02-08 00:43:39 +01:00
Jakob Ketterl
23fceb2998 add optional aprs fields and todos 2021-02-07 23:15:57 +01:00
Jakob Ketterl
e5bd78fd0c add fst4 and fst4w interval settings 2021-02-07 22:49:11 +01:00
Jakob Ketterl
8c4b9dd08a add settings for frequency_display_resolution and squelch_auto_margin 2021-02-07 22:40:03 +01:00
Jakob Ketterl
0517a59308 fix login page layout 2021-02-07 22:36:03 +01:00
Jakob Ketterl
ba3a68c3fa a bit of styling for the settings 2021-02-07 22:09:06 +01:00
Jakob Ketterl
d920540021 fix receiver_keys textarea 2021-02-07 21:45:02 +01:00
Jakob Ketterl
47ecc26f28 add a wfm tau dropdown to the web settings 2021-02-07 21:36:08 +01:00
Jakob Ketterl
689cd49694 drop "experimental pipe settings" (will become unavailable in the
future)
2021-02-07 18:23:17 +01:00
Jakob Ketterl
b60a8a1af0 add the ability to put append a unit to inputs 2021-02-07 18:21:57 +01:00
Jakob Ketterl
8de70cd523 add receiver_keys to the settings page 2021-02-07 18:04:46 +01:00
Jakob Ketterl
25db7c716d change heading 2021-02-07 17:36:44 +01:00
Jakob Ketterl
88020b894e move aprs_symbols_path to new config 2021-02-07 00:21:57 +01:00
Jakob Ketterl
ee687d4e27 fix copy&paste fail 2021-02-06 23:17:43 +01:00
Jakob Ketterl
b318b5e88a remove temporary directory from old config 2021-02-06 22:53:12 +01:00
Jakob Ketterl
8a25718d29 create config overrides directory 2021-02-06 22:31:02 +01:00
Jakob Ketterl
617bed91c4 fix config verification 2021-02-06 22:08:27 +01:00
Jakob Ketterl
9357d57a28 move temporary_directyr to core config; implement override logic 2021-02-06 21:55:47 +01:00
Jakob Ketterl
5d291b5b36 add pskreporter settings mappings 2021-02-06 21:01:59 +01:00
Jakob Ketterl
01c58327aa implement password reset command 2021-02-06 19:12:44 +01:00
Jakob Ketterl
635bf55465 format 2021-02-06 19:03:28 +01:00
Jakob Ketterl
732985c529 add help 2021-02-06 19:02:50 +01:00
Jakob Ketterl
9c5858e1e5 change wording 2021-02-06 19:01:14 +01:00
Jakob Ketterl
1fed499b7f create initial user in postinst script 2021-02-06 18:59:01 +01:00
Jakob Ketterl
d99669b3aa add "silent" flag to openwebrx-admin 2021-02-06 18:57:51 +01:00
Jakob Ketterl
e548d6a5de random salt for passwords 2021-02-06 18:43:37 +01:00
Jakob Ketterl
8806dc538e implement hashed passwords 2021-02-06 18:38:49 +01:00
Jakob Ketterl
f6f01ebee5 default password implementation 2021-02-06 18:22:13 +01:00
Jakob Ketterl
1d9ab1494f remove web_port from config 2021-02-06 18:17:37 +01:00
Jakob Ketterl
7054ec5d59 remove old users file from distribution 2021-02-06 18:15:55 +01:00
Jakob Ketterl
d72027e630 implement user deletion 2021-02-06 18:15:02 +01:00
Jakob Ketterl
99fe232a21 include command to create a user 2021-02-06 18:04:32 +01:00
Jakob Ketterl
dd2f0629d3 rename 2021-02-06 16:44:40 +01:00
Jakob Ketterl
ffcf5c0c27 create owrxadmin 2021-02-06 16:43:54 +01:00
Jakob Ketterl
3226c01f60 introduce core config file (settings that cannot be edited from the web) 2021-02-06 16:38:03 +01:00
Jakob Ketterl
54fb58755d add openwebrx data directory for persistent files 2021-02-06 15:50:50 +01:00
Jakob Ketterl
d9b662106c rename class 2021-02-05 17:58:27 +01:00
Jakob Ketterl
53faca64c0 clean up header styles 2021-02-05 17:56:02 +01:00
Jakob Ketterl
c23acc1513 automatically align 2021-02-05 17:22:43 +01:00
Jakob Ketterl
8e4716f241 drop empty Q65 decodes 2021-02-05 01:07:09 +01:00
Jakob Ketterl
e8fca853df unsubscribe on close; self-referencing prevents unsubscription 2021-02-04 18:00:03 +01:00
Jakob Ketterl
d6d6d97a13 add Q65 mode integration 2021-02-03 20:11:07 +01:00
Jakob Ketterl
e66be7c12d add feature definition for wsjt-x 2.4 2021-02-03 19:33:02 +01:00
Jakob Ketterl
56a42498a5 add frequencies for Q65 on available bands 2021-02-03 19:26:41 +01:00
Jakob Ketterl
bda718cbee update runds_connector 2021-02-03 17:09:51 +01:00
Jakob Ketterl
13eaee5ee9 replace eb200 with runds 2021-02-03 03:21:09 +01:00
Jakob Ketterl
44270af88f remove unused files to save space 2021-02-01 23:56:47 +01:00
Jakob Ketterl
bb680293a1 update m17 2021-02-01 23:56:35 +01:00
Jakob Ketterl
1ee75295e5 update to wsjtx 2.3.0 2021-02-01 23:56:09 +01:00
Jakob Ketterl
5e1c4391c6 include prometheus metrics, refs #200 2021-02-01 18:43:14 +01:00
Jakob Ketterl
998092f377 reroute /metrics to /metrics.json 2021-02-01 18:26:26 +01:00
Jakob Ketterl
dea07cd49b update connectors again 2021-02-01 13:37:01 +01:00
Jakob Ketterl
e3f99d6985 update eb200_connector, too 2021-01-31 23:35:05 +01:00
Jakob Ketterl
081b63def3 update connector with 32bit fixes 2021-01-31 23:05:36 +01:00
Jakob Ketterl
3c91f3cc2f add a timeout to wspr uploads 2021-01-31 20:31:54 +01:00
Jakob Ketterl
61a5250792 fix typos 2021-01-30 16:18:30 +01:00
Jakob Ketterl
881637811f switch when profile OR sdr has changed 2021-01-30 16:17:05 +01:00
Jakob Ketterl
142ca578ec truncate waterfall only when profile has changed 2021-01-30 16:04:29 +01:00
Jakob Ketterl
ad8ff1c2f7 send "sdr_id" to be able to detect changes 2021-01-30 16:04:13 +01:00
Jakob Ketterl
8372f198db add the ability to make a layer readonly 2021-01-30 16:03:35 +01:00
Jakob Ketterl
2a5448f5c1 update dsd feature detection to avoid start-up hangs 2021-01-30 15:03:52 +01:00
Jakob Ketterl
c8695a8e62 Merge branch 'master' into develop 2021-01-26 17:34:41 +01:00
Jakob Ketterl
9b2947827a Merge branch 'release-0.20' into develop 2021-01-25 19:40:28 +01:00
Jakob Ketterl
bee0f67efd Merge branch 'release-0.20' into develop 2021-01-25 19:37:57 +01:00
Jakob Ketterl
612345f0b2 Merge branch 'master' into develop 2021-01-25 14:34:03 +01:00
Jakob Ketterl
4a86af69d1 Fix merging error 2021-01-24 23:20:17 +01:00
Jakob Ketterl
bf31a27dca Merge branch 'fix_arbitrary_code_execution' into develop 2021-01-24 22:55:11 +01:00
Jakob Ketterl
a5bdf6c3ac Merge branch 'fix_arbitrary_code_execution' into develop 2021-01-24 22:47:08 +01:00
Jakob Ketterl
faad38f72d Merge branch 'develop' into pycsdr 2021-01-24 00:37:58 +01:00
Jakob Ketterl
9258e76468 fix typo 2021-01-24 00:37:49 +01:00
Jakob Ketterl
e11bbbf494 remove fft stuff from csdr 2021-01-23 19:40:05 +01:00
Jakob Ketterl
4b94126dc3 use the fft chain directly without csdr dsp classes 2021-01-23 19:27:01 +01:00
Jakob Ketterl
4e429d047d Merge branch 'develop' into pycsdr 2021-01-23 17:17:44 +01:00
Jakob Ketterl
1d9b2729ef add server version to log information 2021-01-23 16:43:51 +01:00
Jakob Ketterl
999d32fd8a
Merge pull request #210 from legacycode/add-documentation
Added documentation to APRS section
2021-01-23 15:11:37 +01:00
legacycode
642552cc08
Added documentation to APRS 2021-01-23 08:47:39 +01:00
Jakob Ketterl
a0d219d120 protect against parser errors to prevent queue backlogging 2021-01-22 19:48:31 +01:00
Jakob Ketterl
68a1abd37e keep intermediate sample rate down to a minimum 2021-01-22 18:47:34 +01:00
Jakob Ketterl
bcab2b2288 update copyright notices 2021-01-22 18:10:51 +01:00
Jakob Ketterl
b8868cb55a move overlays to separate z-index to fix locator grid colors 2021-01-22 18:07:02 +01:00
Jakob Ketterl
f29f7b20e3 change shutdown handling to be able to join() 2021-01-22 17:34:35 +01:00
Jakob Ketterl
ae1287b8a2 remove faulty dependency 2021-01-22 17:34:09 +01:00
Jakob Ketterl
185fdb67cb handle SIGTERM 2021-01-22 17:33:53 +01:00
Jakob Ketterl
0ed69ef2f7 add viewport declaration 2021-01-20 23:09:56 +01:00
Jakob Ketterl
655b6849b7 prevent labels from being selected 2021-01-20 22:26:19 +01:00
Jakob Ketterl
39757b00b2 update changelog 2021-01-20 22:24:16 +01:00
Jakob Ketterl
64b7b485b3 run the code formatter over all 2021-01-20 17:01:46 +01:00
Jakob Ketterl
f0dc2f8ebe format code 2021-01-20 16:46:55 +01:00
Jakob Ketterl
55e1aa5857 use the property stack the way it's intended for better consistency 2021-01-20 16:46:29 +01:00
Jakob Ketterl
fe45d139ad fix an unset property error 2021-01-20 16:41:53 +01:00
Jakob Ketterl
181855e7a4 add filtering capability to the map 2021-01-20 00:39:34 +01:00
Jakob Ketterl
5d3d6423ed fix ysf images; remove obsolete code 2021-01-19 22:04:33 +01:00
Jakob Ketterl
6e60247026 apply CSS magic to DMR, too 2021-01-19 20:54:35 +01:00
Jakob Ketterl
6e416d0839 set prefixes using CSS 2021-01-19 00:36:55 +01:00
Jakob Ketterl
ee8d896d60 implement output buffer shutdown 2021-01-17 21:01:54 +01:00
Jakob Ketterl
db83256bcf Merge branch 'develop' into pycsdr 2021-01-17 20:58:02 +01:00
Jakob Ketterl
23bf1df72a update list of features with recent development 2021-01-17 19:51:04 +01:00
Jakob Ketterl
413c02f272 add discord to readme 2021-01-17 19:45:39 +01:00
Jakob Ketterl
502d324cd4 fix dmr mute overlay 2021-01-17 19:41:17 +01:00
Jakob Ketterl
3246e5ab3a move ysf metadata parsing to server; improve map pin behavior 2021-01-17 19:21:13 +01:00
Jakob Ketterl
c59c5b76d8 fix callsign highlight on map for mobile / portable calls 2021-01-17 18:50:55 +01:00
Jakob Ketterl
297d6b540d Merge branch 'develop' into pycsdr 2021-01-17 18:16:32 +01:00
Jakob Ketterl
e917b920c8 remove failing stop() implementation on destructor 2021-01-17 18:11:10 +01:00
Jakob Ketterl
a0eeea8fe3 improve queue shutdown to avoid stale files 2021-01-17 17:49:03 +01:00
Jakob Ketterl
0f81964598 reserve one line of space to stop the icons from jumping 2021-01-17 01:49:10 +01:00
Jakob Ketterl
9c52219ca3 use gap instead of margins 2021-01-16 22:32:48 +01:00
Jakob Ketterl
8a73f2c9df rewrite DMR panel, too 2021-01-16 22:07:55 +01:00
Jakob Ketterl
98da3a6d99 delegate, don't duplicate. better this way 2021-01-16 21:20:21 +01:00
Jakob Ketterl
667fe596dc ysf does not need autoclear any more 2021-01-16 21:19:00 +01:00
Jakob Ketterl
f3444a4edb setup autoclear 2021-01-16 21:17:12 +01:00
Jakob Ketterl
946866319c improve location handling & clearing 2021-01-16 21:16:49 +01:00
Jakob Ketterl
8be0092f61 rewrite ysf panel update to make it less jumpy 2021-01-16 21:07:58 +01:00
Jakob Ketterl
3f94832d00 use flex layout 2021-01-16 19:46:39 +01:00
Jakob Ketterl
41f9407024 re-package code for meta panels into classes 2021-01-16 19:40:22 +01:00
Jakob Ketterl
13215960c4 show header buttons conditionally 2021-01-16 18:06:37 +01:00
Jakob Ketterl
9f702f5d14 let's try to make the header somewhat responsive 2021-01-16 17:34:17 +01:00
Jakob Ketterl
992a5c33a2 check for keys' existence 2021-01-16 15:45:33 +01:00
Jakob Ketterl
ae217f9ded specify flex-direction explicitly 2021-01-15 19:55:37 +01:00
Jakob Ketterl
00631d7349 hide map overlay until map is loaded 2021-01-15 19:43:16 +01:00
Jakob Ketterl
163ebcd327 actually position text in the center 2021-01-15 19:33:55 +01:00
Jakob Ketterl
a31b246924 restructure header 2021-01-15 19:06:00 +01:00
Jakob Ketterl
a8ef3a0e6a get rid of the e() function 2021-01-15 18:09:18 +01:00
Jakob Ketterl
b9f0c91ced update changelog 2021-01-15 16:28:38 +01:00
Jakob Ketterl
966a404700 don't spot FST4W on pskreporter (same as WSPR?) 2021-01-15 16:27:15 +01:00
Jakob Ketterl
885e361bab implement reporting of FST4W spots (in theory) 2021-01-15 16:19:45 +01:00
Jakob Ketterl
a65f15869b add wsprnet metrics 2021-01-15 00:11:20 +01:00
Jakob Ketterl
1b36baad88 extend default WFM bandwidth to 150kHz, allowing up to 200kHz 2021-01-14 23:47:12 +01:00
Jakob Ketterl
3273716706 add some info to the config 2021-01-14 23:02:34 +01:00
Jakob Ketterl
2c3586a92a add changelog 2021-01-14 22:58:40 +01:00
Jakob Ketterl
74a4f5b272 add wsprnet config variables 2021-01-14 22:56:52 +01:00
Jakob Ketterl
747a5ce7ef fix reporting system shutdown 2021-01-14 22:55:35 +01:00
Jakob Ketterl
e3aa3fa4c6 implement wsprnet reporting, refs #62 2021-01-14 22:54:59 +01:00
Jakob Ketterl
132bd2b445 create reporting engine to distribute spots 2021-01-14 20:52:56 +01:00
Jakob Ketterl
2334ad1d5b try a list of sample rates; prefer 48kHz 2021-01-14 17:07:43 +01:00
dl9rdz
57efdff43e try enforcing 44100 samples/s for audio to avoid problems with odd defautl sampling rates 2021-01-14 16:51:00 +01:00
Jakob Ketterl
c5323f8d54 validate start_freq, use center_freq if invalid 2021-01-14 00:12:53 +01:00
Jakob Ketterl
7f3071336b check if new value is undefined 2021-01-13 23:50:36 +01:00
Jakob Ketterl
db98590985 implement profile validation 2021-01-13 23:44:00 +01:00
Jakob Ketterl
a90ef4efec add m17-demod as recommended package 2021-01-10 02:15:23 +01:00
Jakob Ketterl
b27c03c1c4 restore autostart to avoid unused thread 2021-01-09 20:08:40 +01:00
Jakob Ketterl
502546f9d3 improve cpu usage thread instance protection 2021-01-09 20:01:39 +01:00
Jakob Ketterl
113c06fae4 introduce separate wsjt-x version check based on wsjtx_app_version 2021-01-09 19:19:53 +01:00
Jakob Ketterl
73b75edc14 remove duplicate import 2021-01-09 19:10:08 +01:00
Jakob Ketterl
5337c20744 remove duplicate 2021-01-09 19:01:39 +01:00
Jakob Ketterl
f4629804ff explicitly unset chain since automatic garbage collection is broken 2021-01-04 00:24:06 +01:00
Jakob Ketterl
2783091cea unset buffer since it can't be reused 2021-01-04 00:23:29 +01:00
Jakob Ketterl
91be89e44e Merge branch 'develop' into pycsdr 2021-01-03 15:59:27 +01:00
Jakob Ketterl
57e5923a4d apply performance optimizations to s-meter, too 2021-01-02 18:16:25 +01:00
Jakob Ketterl
9d89cbceed use transform for better performance 2021-01-02 17:53:54 +01:00
Jakob Ketterl
a2d731503f update api 2021-01-02 03:12:21 +01:00
Jakob Ketterl
3e69c71ed5 Merge branch 'develop' into pycsdr 2021-01-02 03:11:41 +01:00
Jakob Ketterl
44f4532452 add debug logging 2021-01-02 02:25:07 +01:00
Jakob Ketterl
c1245308bd make this more robust 2021-01-01 23:37:10 +01:00
Jakob Ketterl
a1cbc45b88 prevent multiple creation of cpu usage thread 2020-12-31 23:18:01 +01:00
Jakob Ketterl
90f319ebda split config into global and device config
* less config properties sent to the client
2020-12-31 23:03:36 +01:00
Jakob Ketterl
9674af10ce
Merge pull request #202 from ewsandor/develop
User Customization of APRS IGate Beacon Details
2020-12-30 21:44:40 +01:00
Jakob Ketterl
5a77b6a8e5 show bandplan bookmarks only when mode is available 2020-12-30 21:37:25 +01:00
Jakob Ketterl
53553fcce2 fix subscription handling 2020-12-30 21:33:02 +01:00
Ed Sandor
1730ef27da Remove POWER from pbeacon string 2020-12-30 12:21:07 -07:00
Ed Sandor
57a6db5df2 Removing inapplicable fields 2020-12-30 12:16:12 -07:00
Ed Sandor
32fe01f128 Round instead of floor height conversion 2020-12-30 11:03:59 -07:00
Jakob Ketterl
b85d801121 create separate subscription for bookmarks 2020-12-30 18:45:13 +01:00
Ed Sandor
daa499ab93 PR comments edits 2020-12-30 10:33:21 -07:00
Jakob Ketterl
68fcb8522e fix typo 2020-12-30 18:05:10 +01:00
Jakob Ketterl
341b94b9ff prevent KeyError by checking for key existence 2020-12-30 17:46:13 +01:00
Jakob Ketterl
f4b9decd23 more animation performance optimizations 2020-12-30 17:45:32 +01:00
Jakob Ketterl
cf0c6e7f9d adapt to config event api changes 2020-12-30 17:18:46 +01:00
Jakob Ketterl
29703d10b2 server side: send only changed config keys 2020-12-30 17:17:14 +01:00
Jakob Ketterl
abb0813948 send only necessary config changes 2020-12-30 17:15:48 +01:00
Jakob Ketterl
2c3146314b send property changes in bulk to global subscribers 2020-12-30 17:14:06 +01:00
Jakob Ketterl
eb34c45145 apply transform trick to get GPU optimized animations 2020-12-28 21:16:54 +01:00
Jakob Ketterl
993aa87776 use css animations for the progressbar (better performance?) 2020-12-28 20:55:02 +01:00
Jakob Ketterl
ca183c7c5a Merge branch 'develop' into pycsdr 2020-12-27 20:22:42 +01:00
Jakob Ketterl
71043d4305 update m17-cxx-demod in docker 2020-12-27 20:10:41 +01:00
Jakob Ketterl
eb981c04e9 Merge branch 'm17' into develop 2020-12-27 19:51:32 +01:00
Jakob Ketterl
ecf934864a move dc_block to individual chains since it interferes with m17 demod 2020-12-27 19:49:59 +01:00
Jakob Ketterl
686eeb706b add external reference control 2020-12-27 13:52:49 +01:00
Jakob Ketterl
fa3b5cd7e6 implement new buffer input / output api 2020-12-25 20:27:30 +01:00
Jakob Ketterl
94575d2212 update m17-cxx-demod 2020-12-22 12:51:36 +01:00
Jakob Ketterl
ca9e9601ab update m17-cxx-demod and dependencies 2020-12-21 19:42:15 +01:00
Jakob Ketterl
06f3499b6d Merge branch 'develop' into m17 2020-12-21 17:04:09 +01:00
Jakob Ketterl
2df527ed20 wrap averager (prepare to make it switchable) 2020-12-21 00:33:48 +01:00
Jakob Ketterl
2c7c41cded move fft calculations into fft chain 2020-12-20 22:55:10 +01:00
Jakob Ketterl
1083d51e18 update fft parameters without restarting 2020-12-19 17:13:36 +01:00
Jakob Ketterl
40c07ebb57 move fft calculations to dsp class 2020-12-19 16:41:48 +01:00
Jakob Ketterl
efe80a75f5 put the socketclient on the source so it can be shared 2020-12-19 16:28:18 +01:00
Jakob Ketterl
1bd6aa73f3 encapsulate fft chain in its own class 2020-12-16 18:52:00 +01:00
Jakob Ketterl
4b61192b36 add a feature flag 2020-12-16 10:18:47 +01:00
Jakob Ketterl
664c6e049f pycsdr based ffd (baby steps) 2020-12-15 23:02:12 +01:00
Jakob Ketterl
db3d662dae fix typo 2020-12-13 16:31:19 +01:00
Ed Sandor
dee050f338 Fix comment 2020-12-12 11:38:50 -07:00
Ed Sandor
ae00a14a35 Fix comment formatting 2020-12-12 11:38:15 -07:00
Ed Sandor
86fdbe45e9 Add examples and comments to default config 2020-12-12 11:23:35 -07:00
Ed Sandor
b04dcc18d0 This is Python not C 2020-12-12 11:10:15 -07:00
Ed Sandor
1cc88ff362 if check fix 2020-12-12 11:09:12 -07:00
Ed Sandor
3435052e27 sanitize empty comment 2020-12-12 11:08:47 -07:00
Ed Sandor
4c3d037e58 Cleanup debug logging 2020-12-12 11:07:50 -07:00
Ed Sandor
f83790a5be debug comment length 2020-12-12 10:15:26 -07:00
Ed Sandor
11bb04419b fix parenthesis 2020-12-12 10:13:46 -07:00
Ed Sandor
519b02da79 improve quotes check 2020-12-12 10:12:43 -07:00
Ed Sandor
fdbbbcb64c Sanitize comment closing quote 2020-12-12 10:04:42 -07:00
Ed Sandor
0fb4ae4fc0 sanitize comment for opening quote 2020-12-12 09:59:34 -07:00
Jakob Ketterl
181511bc8e remove maps link from header 2020-12-11 17:53:31 +01:00
Jakob Ketterl
e062412e60 show receiver location pin on the map 2020-12-11 17:47:17 +01:00
Jakob Ketterl
bdb6d75f83 better sorting for the legend 2020-12-10 22:22:08 +01:00
Jakob Ketterl
433111124f reset default to 4 2020-12-10 20:59:40 +01:00
Jakob Ketterl
23080dbe22 allow frequency display precision to be set via configuration 2020-12-10 20:58:07 +01:00
Jakob Ketterl
05096c2a16 fully initialize sdr devices
* makes always-on work as expected
* prevents race conditions when multiple clients connect at the same
  time
2020-12-10 18:28:10 +01:00
Ed Sandor
5559cded85 Add quotes around default pbeacon comment 2020-12-09 23:17:42 -07:00
Ed Sandor
9f45e8880a formating pbeacon string 2020-12-09 23:09:37 -07:00
Ed Sandor
dc128662da log pbeacon string 2020-12-09 23:05:04 -07:00
Ed Sandor
dc3fd24903 Correcting key check 2020-12-09 22:59:16 -07:00
Ed Sandor
b2efa81b0d Formatting additional PBEACON details 2020-12-09 22:54:06 -07:00
Jakob Ketterl
2c04d40c53 allow antenna information to be sent to pskreporter 2020-12-10 01:36:09 +01:00
Jakob Ketterl
fcff9d16ff filter out problematic spots instead of breaking completely 2020-12-09 23:38:27 +01:00
Jakob Ketterl
eef61f9d1e break the pskreporter loop if there's nothing to upload 2020-12-09 22:59:45 +01:00
Jakob Ketterl
8f9f9e8397
Merge pull request #197 from acfnews/develop
correct typo, and prevent warning during postinstall
2020-12-09 21:53:13 +01:00
acfnews
d0e7747c7f correct typo, and prevent warning during postinstall 2020-12-09 21:38:59 +01:00
Jakob Ketterl
9e45cfd02a implement clear function for js8, too - refs #187 2020-12-09 21:19:22 +01:00
Jakob Ketterl
aa66e69c15 implement clear button for packet, pocsag, wsjt-x, refs #187 2020-12-09 20:08:50 +01:00
Jakob Ketterl
9bf4b149aa move pocsag message panel 2020-12-09 19:53:37 +01:00
Jakob Ketterl
5474973752 move aprs message panel 2020-12-09 19:42:46 +01:00
Jakob Ketterl
3e30ab57a6 move wsjt message panel logic to own class 2020-12-09 19:26:34 +01:00
Jakob Ketterl
9d6099b6d8 FST4[W] frontend work 2020-12-09 17:38:37 +01:00
Jakob Ketterl
a7f667779a allow roaming / portable / mobile calls in wsjt-x message 2020-12-09 12:47:08 +01:00
Jakob Ketterl
f71240c9a6 handle exception when output is missing 2020-12-09 12:31:01 +01:00
Jakob Ketterl
f8fc61e9bd streamline datetime parsing 2020-12-09 12:02:40 +01:00
Jakob Ketterl
a8011e3a1a use profiles instead of parsing to detect mode 2020-12-09 11:38:46 +01:00
Jakob Ketterl
e8fcf05775 add m17-demod to docker builds (preliminary) 2020-12-08 19:43:50 +01:00
Jakob Ketterl
cfb6fb5b30 add changelog message 2020-12-08 17:01:04 +01:00
Jakob Ketterl
fb68ca3c66 add documentation 2020-12-08 16:59:49 +01:00
Jakob Ketterl
6af19f44e8 Merge branch 'develop' into m17 2020-12-08 16:57:00 +01:00
Jakob Ketterl
3291dbe8d2 fix fst4w profile 2020-12-08 01:06:21 +01:00
Jakob Ketterl
efac5b0449 change job decoder error handling so errors reflect in metrics 2020-12-08 00:28:34 +01:00
Jakob Ketterl
519155a12f fix "R" callsign problem 2020-12-08 00:01:00 +01:00
Jakob Ketterl
603c3df1b6 fix fst4(w) filenames 2020-12-08 00:00:21 +01:00
Jakob Ketterl
05ca541a8e fix jt9 parameters 2020-12-07 20:29:22 +01:00
Jakob Ketterl
917884b5f5 add changelog message 2020-12-07 11:59:43 +01:00
Jakob Ketterl
22a2bd1de1 default config for FST4/FST4W intervals 2020-12-07 11:57:34 +01:00
Jakob Ketterl
af4923c741 enable reporting of FST4/FST4W to pskreporter 2020-12-07 11:56:21 +01:00
Jakob Ketterl
ac4401175f add FST4 and FST4W modes 2020-12-07 11:56:01 +01:00
Jakob Ketterl
71c649b016 add and definitions for VLF bands including frequencies for FST4/FST4W 2020-12-07 11:52:46 +01:00
Jakob Ketterl
cbdb143966 allow 25kHz packet when manually adjusting 2020-12-06 23:24:57 +01:00
Jakob Ketterl
8c105b0c40 fix direwolf build (uses cmake now) 2020-12-06 01:44:14 +01:00
Jakob Ketterl
8e760a0fcc use new direwolf 1.6 2020-12-06 00:43:45 +01:00
Jakob Ketterl
6f46e4d376 remove debugging 2020-12-06 00:42:48 +01:00
Jakob Ketterl
bee6ddc843 use information from the mode registry to set up services 2020-12-06 00:36:20 +01:00
Jakob Ketterl
a3fd931931 demodulate digimodes starting at 0 Hz 2020-12-06 00:21:46 +01:00
Jakob Ketterl
e2fa293c74 fix paths 2020-12-04 00:39:05 +01:00
Jakob Ketterl
c4ed481ce2 update aprs-symbols location for docker 2020-12-04 00:12:51 +01:00
Jakob Ketterl
e6ea3832fc add aprs-symbols debian package 2020-12-04 00:11:47 +01:00
Jakob Ketterl
9a8c0ce442 update list of device types in config 2020-12-02 23:36:30 +01:00
Jakob Ketterl
49ec66e27c add hpsdr change log notice 2020-12-02 23:35:37 +01:00
Jakob Ketterl
2b6456168e add libc6-dev for header files 2020-12-02 17:59:24 +01:00
Jakob Ketterl
e6cbe6ffc8 add hpsdr build 2020-12-02 16:51:52 +01:00
Jakob Ketterl
00d496086e add gcc as it seems to be required on arm (?) 2020-12-02 16:50:14 +01:00
Jakob Ketterl
1894ed50d1 add hpsdrconnector docker build 2020-12-01 23:33:05 +01:00
Jakob Ketterl
7ad5ca03b0 add eb200 to full build 2020-12-01 21:42:20 +01:00
Jakob Ketterl
b380187453 add docker build for eb200 devices 2020-12-01 21:39:22 +01:00
Jakob Ketterl
2022c53fad make soapysdr-tools a hard dependency; recommend eb200_connector 2020-12-01 17:41:17 +01:00
Jakob Ketterl
46b7660e2d add long flag mapping for eb200 2020-12-01 14:14:52 +01:00
Jakob Ketterl
e90b10abfd Merge branch 'master' into develop 2020-11-30 20:30:30 +01:00
Jakob Ketterl
a8bd13f7e6 increase bandwidth for packet to 12.5kHz 2020-11-30 17:13:03 +01:00
Jakob Ketterl
daf2848c4d increase package dependency version 2020-11-30 13:24:25 +01:00
Jakob Ketterl
0614637342 add eb200 support 2020-11-30 00:34:44 +01:00
Jakob Ketterl
865ffb28af Merge branch 'rf103' into develop 2020-11-29 16:01:56 +01:00
Jakob Ketterl
8b89d1e062 update changelog 2020-11-29 16:01:35 +01:00
Jakob Ketterl
e4cf95856e update connectors 2020-11-28 22:11:12 +01:00
Jakob Ketterl
74be25f656 rename all occurences to SDDC 2020-11-27 18:49:33 +01:00
Jakob Ketterl
b5d56eaec2 update to use new sddc_connector 2020-11-27 18:39:10 +01:00
Jakob Ketterl
8bb6e91597 Merge branch 'develop' into rf103 2020-11-23 18:42:17 +01:00
Jakob Ketterl
d72f2d9e5c update changelog 2020-11-23 15:34:44 +01:00
Jakob Ketterl
781b4383d6 remove port flag and turn rtltcp_compat into an option 2020-11-23 15:26:01 +01:00
Jakob Ketterl
017bbc3748 attempt to include m17-demod (untested due to lack of signals) 2020-11-23 01:00:25 +01:00
Jakob Ketterl
69a5e0bc5d Merge branch 'develop' into rf103 2020-11-12 23:45:39 +01:00
Jakob Ketterl
2579b9be26 remove specific instructions, complete list 2020-11-12 23:44:02 +01:00
Jakob Ketterl
9bfef01438
Merge pull request #188 from jancona/hpsdr_connector
Support for HPSDR radios (specifically, the Hermes-Lite 2)
2020-11-12 23:39:28 +01:00
Jim Ancona
c0d4b2f6a5 Remove debug option, mention in config_webrx.py 2020-11-12 17:36:36 -05:00
Jakob Ketterl
529e9c3c60 Merge branch 'develop' into rf103 2020-11-12 18:01:59 +01:00
Jakob Ketterl
504c256b3e make auto squelch level margin configurable 2020-11-12 18:00:24 +01:00
Jim Ancona
91572c56e2 Make hpsdrconnector into a true connector. 2020-11-09 19:24:13 -05:00
Jakob Ketterl
3b229b95b6 Merge branch 'develop' into rf103 2020-11-04 22:45:46 +01:00
Jakob Ketterl
0f4b8dc794 fill-in undeclared variable, refs #192 2020-11-04 22:38:24 +01:00
Jakob Ketterl
e700f0a9e4 replace nanoscroller with compressed version, drop map reference.
closes #191
2020-11-04 22:32:13 +01:00
Jim Ancona
c85400063c Initial HPSDR radio support 2020-11-02 07:11:54 -05:00
Jakob Ketterl
dc03639cad add source for rf103 (experimental) 2020-10-25 16:53:18 +01:00
Jakob Ketterl
e6a04aa5e9 use agc on wsjtx/js8 since the levels are too low on some sdrs 2020-10-25 14:41:53 +01:00
Jakob Ketterl
1bc3830e5e guard against the case where receiver_keys are missing in the
configuration
2020-10-16 22:53:57 +02:00
Jakob Ketterl
93f7195429
Merge pull request #173 from jwt27/jwt27/highlight-freq-digits
Highlight frequency digits on mouse hover
2020-10-16 20:29:52 +02:00
Jakob Ketterl
d04e0d2a2a link feature report to the wiki for DRM and FreeDV 2020-10-16 19:52:51 +02:00
Jakob Ketterl
259eef2e68 move develop to the next version 0.21 2020-10-11 23:16:59 +02:00
J.W. Jagersma
325eab35a9
highlight frequency digits on mouse hover 2020-08-30 23:13:26 +02:00
309 changed files with 20691 additions and 7085 deletions

View File

@ -1,3 +1,48 @@
**unreleased**
- SDR device log messages are now available in the web configuration to simplify troubleshooting
- Added support for the MSK144 digimode
**1.2.1**
- FifiSDR support fixed (pipeline formats now line up correctly)
- Added "Device" input for FifiSDR devices for sound card selection
**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

View File

@ -11,11 +11,16 @@ It has the following features:
- filter passband can be set from GUI
- it extensively uses HTML5 features like WebSocket, Web Audio API, and Canvas
- it works in Google Chrome, Chromium and Mozilla Firefox
- currently supports RTL-SDR, HackRF, SDRplay, AirSpy, LimeSDR, PlutoSDR
- supports a wide range of [SDR hardware](https://github.com/jketterl/openwebrx/wiki/Supported-Hardware#sdr-devices)
- Multiple SDR devices can be used simultaneously
- [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag)
- [dsd](https://github.com/f4exb/dsdcc) based demodulators (D-Star, NXDN)
- [wsjt-x](https://physics.princeton.edu/pulsar/k1jt/wsjtx.html) based demodulators (FT8, FT4, WSPR, JT65, JT9)
- [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag, D-Star, NXDN)
- [wsjt-x](https://wsjt.sourceforge.io/) based demodulators (FT8, FT4, WSPR, JT65, JT9, FST4,
FST4W)
- [direwolf](https://github.com/wb2osz/direwolf) based demodulation of APRS packets
- [JS8Call](http://js8call.com/) support
- [DRM](https://github.com/jketterl/openwebrx/wiki/DRM-demodulator-notes) support
- [FreeDV](https://github.com/jketterl/openwebrx/wiki/FreeDV-demodulator-notes) support
- M17 support based on [m17-cxx-demod](https://github.com/mobilinkd/m17-cxx-demod)
## Setup
@ -35,6 +40,9 @@ If you have trouble setting up or configuring your receiver, you have some great
you just generally want to have some OpenWebRX-related chat, come visit us over on
[our groups.io group](https://groups.io/g/openwebrx).
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).
## Usage tips
You can zoom the waterfall display by the mouse wheel. You can also drag the waterfall to pan across it.

View File

@ -1,4 +1,24 @@
[
{
"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,
@ -9,8 +29,11 @@
"wspr": 1836600,
"jt65": 1838000,
"jt9": 1839000,
"js8": 1842000
}
"js8": 1842000,
"fst4": 1839000,
"fst4w": 1836800
},
"tags": ["hamradio"]
},
{
"name": "80m",
@ -19,12 +42,13 @@
"frequencies": {
"bpsk31": 3580000,
"ft8": 3573000,
"wspr": 3592600,
"wspr": 3568600,
"jt65": 3570000,
"jt9": 3572000,
"ft4": [3568000, 3575000],
"js8": 3578000
}
},
"tags": ["hamradio"]
},
{
"name": "60m",
@ -32,8 +56,9 @@
"upper_bound": 5366500,
"frequencies": {
"ft8": 5357000,
"wspr": 5364700
}
"wspr": [5287200, 5364700]
},
"tags": ["hamradio"]
},
{
"name": "40m",
@ -47,7 +72,8 @@
"jt9": 7078000,
"ft4": 7047500,
"js8": 7078000
}
},
"tags": ["hamradio"]
},
{
"name": "30m",
@ -61,7 +87,8 @@
"jt9": 10140000,
"ft4": 10140000,
"js8": 10130000
}
},
"tags": ["hamradio"]
},
{
"name": "20m",
@ -75,7 +102,8 @@
"jt9": 14078000,
"ft4": 14080000,
"js8": 14078000
}
},
"tags": ["hamradio"]
},
{
"name": "17m",
@ -89,7 +117,8 @@
"jt9": 18104000,
"ft4": 18104000,
"js8": 18104000
}
},
"tags": ["hamradio"]
},
{
"name": "15m",
@ -103,7 +132,8 @@
"jt9": 21078000,
"ft4": 21140000,
"js8": 21078000
}
},
"tags": ["hamradio"]
},
{
"name": "12m",
@ -117,7 +147,8 @@
"jt9": 24919000,
"ft4": 24919000,
"js8": 24922000
}
},
"tags": ["hamradio"]
},
{
"name": "10m",
@ -131,7 +162,8 @@
"jt9": 28078000,
"ft4": 28180000,
"js8": 28078000
}
},
"tags": ["hamradio"]
},
{
"name": "6m",
@ -144,16 +176,21 @@
"jt65": 50310000,
"jt9": 50312000,
"ft4": 50318000,
"js8": 50318000
}
"js8": 50318000,
"q65": [50211000, 50275000],
"msk144": 50260000
},
"tags": ["hamradio"]
},
{
"name": "4m",
"lower_bound": 70150000,
"upper_bound": 70200000,
"frequencies": {
"wspr": 70091000
}
"wspr": 70091000,
"msk144": 70230000
},
"tags": ["hamradio"]
},
{
"name": "2m",
@ -164,110 +201,171 @@
"ft8": 144174000,
"ft4": 144170000,
"jt65": 144120000,
"packet": 144800000
}
"packet": 144800000,
"q65": 144116000,
"msk144": 144360000
},
"tags": ["hamradio"]
},
{
"name": "70cm",
"lower_bound": 430000000,
"upper_bound": 440000000,
"frequencies": {
"pocsag": 439987500
}
"pocsag": 439987500,
"q65": 432065000,
"msk144": 432360000
},
"tags": ["hamradio"]
},
{
"name": "23cm",
"lower_bound": 1240000000,
"upper_bound": 1300000000
"upper_bound": 1300000000,
"frequencies": {
"q65": 1296065000
},
"tags": ["hamradio"]
},
{
"name": "13cm",
"lower_bound": 2320000000,
"upper_bound": 2450000000
"upper_bound": 2450000000,
"frequencies": {
"q65": [2301065000, 2304065000, 2320065000]
},
"tags": ["hamradio"]
},
{
"name": "9cm",
"lower_bound": 3400000000,
"upper_bound": 3475000000
"upper_bound": 3475000000,
"frequencies": {
"q65": 3400065000
},
"tags": ["hamradio"]
},
{
"name": "6cm",
"lower_bound": 5650000000,
"upper_bound": 5850000000
"upper_bound": 5850000000,
"frequencies": {
"q65": 5760200000
},
"tags": ["hamradio"]
},
{
"name": "3cm",
"lower_bound": 10000000000,
"upper_bound": 10500000000
"upper_bound": 10500000000,
"frequencies": {
"q65": 10368200000
},
"tags": ["hamradio"]
},
{
"name": "120m Broadcast",
"lower_bound": 2300000,
"upper_bound": 2495000
"upper_bound": 2495000,
"tags": ["broadcast"]
},
{
"name": "90m Broadcast",
"lower_bound": 3200000,
"upper_bound": 3400000
"upper_bound": 3400000,
"tags": ["broadcast"]
},
{
"name": "75m Broadcast",
"lower_bound": 3900000,
"upper_bound": 4000000
"upper_bound": 4000000,
"tags": ["broadcast"]
},
{
"name": "60m Broadcast",
"lower_bound": 4750000,
"upper_bound": 4995000
"upper_bound": 4995000,
"tags": ["broadcast"]
},
{
"name": "49m Broadcast",
"lower_bound": 5900000,
"upper_bound": 6200000
"upper_bound": 6200000,
"tags": ["broadcast"]
},
{
"name": "41m Broadcast",
"lower_bound": 7200000,
"upper_bound": 7450000
"upper_bound": 7450000,
"tags": ["broadcast"]
},
{
"name": "31m Broadcast",
"lower_bound": 9400000,
"upper_bound": 9900000
"upper_bound": 9900000,
"tags": ["broadcast"]
},
{
"name": "25m Broadcast",
"lower_bound": 11600000,
"upper_bound": 12100000
"upper_bound": 12100000,
"tags": ["broadcast"]
},
{
"name": "22m Broadcast",
"lower_bound": 13570000,
"upper_bound": 13870000
"upper_bound": 13870000,
"tags": ["broadcast"]
},
{
"name": "19m Broadcast",
"lower_bound": 15100000,
"upper_bound": 15830000
"upper_bound": 15830000,
"tags": ["broadcast"]
},
{
"name": "16m Broadcast",
"lower_bound": 17480000,
"upper_bound": 17900000
"upper_bound": 17900000,
"tags": ["broadcast"]
},
{
"name": "15m Broadcast",
"lower_bound": 18900000,
"upper_bound": 19020000
"upper_bound": 19020000,
"tags": ["broadcast"]
},
{
"name": "13m Broadcast",
"lower_bound": 21450000,
"upper_bound": 21850000
"upper_bound": 21850000,
"tags": ["broadcast"]
},
{
"name": "11m Broadcast",
"lower_bound": 25670000,
"upper_bound": 26100000
"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"]
}
]

View File

@ -1,217 +0,0 @@
[
{
"name": "DB0ZU",
"frequency": 145725000,
"modulation": "nfm"
},
{
"name": "DB0ZM",
"frequency": 145750000,
"modulation": "nfm"
},
{
"name": "DM0ULR",
"frequency": 145787500,
"modulation": "nfm"
},
{
"name": "DB0EL",
"frequency": 439275000,
"modulation": "nfm"
},
{
"name": "DB0NJ",
"frequency": 438775000,
"modulation": "nfm"
},
{
"name": "DB0NJ",
"frequency": 439437500,
"modulation": "dmr"
},
{
"name": "DB0UFO",
"frequency": 438312500,
"modulation": "dmr"
},
{
"name": "DB0PV",
"frequency": 438525000,
"modulation": "ysf"
},
{
"name": "DB0BZA",
"frequency": 438412500,
"modulation": "ysf"
},
{
"name": "DB0OSH",
"frequency": 438250000,
"modulation": "ysf"
},
{
"name": "DB0ULR",
"frequency": 439325000,
"modulation": "nfm"
},
{
"name": "DB0ZU",
"frequency": 438850000,
"modulation": "nfm"
},
{
"name": "DB0ISW",
"frequency": 438650000,
"modulation": "nfm"
},
{
"name": "Radio DARC",
"frequency": 6070000,
"modulation": "am"
},
{
"name": "DB0TVM",
"frequency": 439575000,
"modulation": "dstar"
},
{
"name": "DB0TVM",
"frequency": 439800000,
"modulation": "dmr"
},
{
"name": "DB0TR",
"frequency": 438700000,
"modulation": "nfm"
},
{
"name": "DB0PME",
"frequency": 439825000,
"modulation": "dmr"
},
{
"name": "DB0HKN",
"frequency": 438300000,
"modulation": "dmr"
},
{
"name": "OE2XHM",
"frequency": 438825000,
"modulation": "nfm"
},
{
"name": "DM0WW",
"frequency": 438962500,
"modulation": "dmr"
},
{
"name": "OE7XXR",
"frequency": 438200000,
"modulation": "dstar"
},
{
"name": "OE2XZR",
"frequency": 439000000,
"modulation": "dstar"
},
{
"name": "DB0OAL",
"frequency": 439912500,
"modulation": "dmr"
},
{
"name": "DB0AAT",
"frequency": 439550000,
"modulation": "dmr"
},
{
"name": "DB0FSG",
"frequency": 439937500,
"modulation": "dmr"
},
{
"name": "DB0ULR",
"frequency": 145575000,
"modulation": "nfm"
},
{
"name": "DB0RDH",
"frequency": 145737500,
"modulation": "dstar"
},
{
"name": "DM0GAP",
"frequency": 145612500,
"modulation": "nfm"
},
{
"name": "DB0XF",
"frequency": 145600000,
"modulation": "nfm"
},
{
"name": "DB0TOL",
"frequency": 145712500,
"modulation": "nfm"
},
{
"name": "DB0TTB",
"frequency": 439587500,
"modulation": "dmr"
},
{
"name": "DB0TRS",
"frequency": 439125000,
"modulation": "nfm"
},
{
"name": "DB0OAL",
"frequency": 438937500,
"modulation": "nfm"
},
{
"name": "DM0ULR",
"frequency": 439337500,
"modulation": "nxdn"
},
{
"name": "DB0MIR",
"frequency": 439300000,
"modulation": "nfm"
},
{
"name": "DB0PM",
"frequency": 439075000,
"modulation": "nfm"
},
{
"name": "DB0CP",
"frequency": 439025000,
"modulation": "nfm"
},
{
"name": "OE7XGR",
"frequency": 438925000,
"modulation": "dmr"
},
{
"name": "DB0TOL",
"frequency": 438725000,
"modulation": "nfm"
},
{
"name": "DB0OAL",
"frequency": 438325000,
"modulation": "dstar"
},
{
"name": "DB0ROL",
"frequency": 439237500,
"modulation": "nfm"
},
{
"name": "DB0ABX",
"frequency": 439137500,
"modulation": "nfm"
}
]

View File

@ -1,345 +0,0 @@
# -*- coding: utf-8 -*-
"""
config_webrx: configuration options for OpenWebRX
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>
Copyright (c) 2019-2020 by Jakob Ketterl <dd5jfk@darc.de>
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/>.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
In addition, as a special exception, the copyright holders
state that config_rtl.py and config_webrx.py are not part of the
Corresponding Source defined in GNU AGPL version 3 section 1.
(It means that you do not have to redistribute config_rtl.py and
config_webrx.py if you make any changes to these two configuration files,
and use them for running your web service with OpenWebRX.)
"""
# configuration version. please only modify if you're able to perform the associated migration steps.
version = 3
# NOTE: you can find additional information about configuring OpenWebRX in the Wiki:
# https://github.com/jketterl/openwebrx/wiki/Configuration-guide
# ==== Server settings ====
web_port = 8073
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 ====
fft_fps = 9
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.
)
audio_compression = "adpcm" # valid values: "adpcm", "none"
fft_compression = "adpcm" # valid values: "adpcm", "none"
# Tau setting for WFM (broadcast FM) deemphasis\
# 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
# determines the quality, and thus the cpu usage, for the ambe codec used by digital voice modes
# if you're running on a Raspi (up to 3B+) you'll want to leave this on 1
digital_voice_unvoiced_quality = 1
# 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:
- decrease `samp_rate`,
- set `fft_voverlap_factor` to 0,
- decrease `fft_fps` and `fft_size`,
- limit the number of users by decreasing `max_clients`.
"""
# ==== I/Q sources ====
# (Uncomment the appropriate by removing # characters at the beginning of the corresponding lines.)
###############################################################################
# Is my SDR hardware supported? #
# Check here: https://github.com/jketterl/openwebrx/wiki/Supported-Hardware #
###############################################################################
# Currently supported types of sdr receivers:
# "rtl_sdr", "rtl_sdr_soapy", "sdrplay", "hackrf", "airspy", "airspyhf", "fifi_sdr",
# "perseussdr", "lime_sdr", "pluto_sdr", "soapy_remote"
#
# In order to use rtl_sdr, you will need to install librtlsdr-dev and the connector.
# In order to use sdrplay, airspy or airspyhf, you will need to install soapysdr, the corresponding driver, and the
# connector.
#
# https://github.com/jketterl/owrx_connector
#
# In order to use Perseus HF you need to install the libperseus-sdr
#
# https://github.com/Microtelecom/libperseus-sdr
#
# and do the proper changes to the sdrs object below
# (see also Wiki in https://github.com/jketterl/openwebrx/wiki/Sample-configuration-for-Perseus-HF-receiver).
#
sdrs = {
"rtlsdr": {
"name": "RTL-SDR USB Stick",
"type": "rtl_sdr",
"ppm": 0,
# you can change this if you use an upconverter. formula is:
# center_freq + lfo_offset = actual frequency on the sdr
# "lfo_offset": 0,
"profiles": {
"70cm": {
"name": "70cm Relais",
"center_freq": 438800000,
"rf_gain": 29,
"samp_rate": 2400000,
"start_freq": 439275000,
"start_mod": "nfm",
},
"2m": {
"name": "2m komplett",
"center_freq": 145000000,
"rf_gain": 29,
"samp_rate": 2048000,
"start_freq": 145725000,
"start_mod": "nfm",
},
},
},
"airspy": {
"name": "Airspy HF+",
"type": "airspyhf",
"ppm": 0,
"rf_gain": "auto",
"profiles": {
"20m": {
"name": "20m",
"center_freq": 14150000,
"samp_rate": 384000,
"start_freq": 14070000,
"start_mod": "usb",
},
"30m": {
"name": "30m",
"center_freq": 10125000,
"samp_rate": 192000,
"start_freq": 10142000,
"start_mod": "usb",
},
"40m": {
"name": "40m",
"center_freq": 7100000,
"samp_rate": 256000,
"start_freq": 7070000,
"start_mod": "lsb",
},
"80m": {
"name": "80m",
"center_freq": 3650000,
"samp_rate": 384000,
"start_freq": 3570000,
"start_mod": "lsb",
},
"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 ====
### google turbo colormap (see: https://ai.googleblog.com/2019/08/turbo-improved-rainbow-colormap-for.html)
waterfall_colors = [0x30123b, 0x311542, 0x33184a, 0x341b51, 0x351e58, 0x36215f, 0x372466, 0x38266c, 0x392973, 0x3a2c79, 0x3b2f80, 0x3c3286, 0x3d358b, 0x3e3891, 0x3e3a97, 0x3f3d9c, 0x4040a2, 0x4043a7, 0x4146ac, 0x4248b1, 0x424bb6, 0x434eba, 0x4351bf, 0x4453c3, 0x4456c7, 0x4559cb, 0x455bcf, 0x455ed3, 0x4561d7, 0x4663da, 0x4666dd, 0x4669e1, 0x466be4, 0x466ee7, 0x4671e9, 0x4673ec, 0x4676ee, 0x4678f1, 0x467bf3, 0x467df5, 0x4680f7, 0x4682f9, 0x4685fa, 0x4587fc, 0x458afd, 0x448cfe, 0x448ffe, 0x4391ff, 0x4294ff, 0x4196ff, 0x3f99ff, 0x3e9bff, 0x3d9efe, 0x3ba1fd, 0x3aa3fd, 0x38a6fb, 0x36a8fa, 0x35abf9, 0x33adf7, 0x31b0f6, 0x2fb2f4, 0x2db5f2, 0x2cb7f0, 0x2ab9ee, 0x28bcec, 0x26beea, 0x25c0e7, 0x23c3e5, 0x21c5e2, 0x20c7e0, 0x1fc9dd, 0x1dccdb, 0x1cced8, 0x1bd0d5, 0x1ad2d3, 0x19d4d0, 0x18d6cd, 0x18d8cb, 0x18dac8, 0x17dbc5, 0x17ddc3, 0x17dfc0, 0x18e0be, 0x18e2bb, 0x19e3b9, 0x1ae5b7, 0x1be6b4, 0x1de8b2, 0x1ee9af, 0x20eaad, 0x22ecaa, 0x24eda7, 0x27eea4, 0x29efa1, 0x2cf09e, 0x2ff19b, 0x32f298, 0x35f394, 0x38f491, 0x3cf58e, 0x3ff68b, 0x43f787, 0x46f884, 0x4af980, 0x4efa7d, 0x51fa79, 0x55fb76, 0x59fc73, 0x5dfc6f, 0x61fd6c, 0x65fd69, 0x69fe65, 0x6dfe62, 0x71fe5f, 0x75ff5c, 0x79ff59, 0x7dff56, 0x80ff53, 0x84ff50, 0x88ff4e, 0x8bff4b, 0x8fff49, 0x92ff46, 0x96ff44, 0x99ff42, 0x9cfe40, 0x9ffe3e, 0xa2fd3d, 0xa4fd3b, 0xa7fc3a, 0xaafc39, 0xacfb38, 0xaffa37, 0xb1f936, 0xb4f835, 0xb7f835, 0xb9f634, 0xbcf534, 0xbff434, 0xc1f334, 0xc4f233, 0xc6f033, 0xc9ef34, 0xcbee34, 0xceec34, 0xd0eb34, 0xd2e934, 0xd5e835, 0xd7e635, 0xd9e435, 0xdbe236, 0xdde136, 0xe0df37, 0xe2dd37, 0xe4db38, 0xe6d938, 0xe7d738, 0xe9d539, 0xebd339, 0xedd139, 0xeecf3a, 0xf0cd3a, 0xf1cb3a, 0xf3c93a, 0xf4c73a, 0xf5c53a, 0xf7c33a, 0xf8c13a, 0xf9bf39, 0xfabd39, 0xfaba38, 0xfbb838, 0xfcb637, 0xfcb436, 0xfdb135, 0xfdaf35, 0xfeac34, 0xfea933, 0xfea732, 0xfea431, 0xffa12f, 0xff9e2e, 0xff9c2d, 0xff992c, 0xfe962b, 0xfe932a, 0xfe9028, 0xfe8d27, 0xfd8a26, 0xfd8724, 0xfc8423, 0xfc8122, 0xfb7e20, 0xfb7b1f, 0xfa781e, 0xf9751c, 0xf8721b, 0xf86f1a, 0xf76c19, 0xf66917, 0xf56616, 0xf46315, 0xf36014, 0xf25d13, 0xf05b11, 0xef5810, 0xee550f, 0xed530e, 0xeb500e, 0xea4e0d, 0xe94b0c, 0xe7490b, 0xe6470a, 0xe4450a, 0xe34209, 0xe14009, 0xdf3e08, 0xde3c07, 0xdc3a07, 0xda3806, 0xd83606, 0xd63405, 0xd43205, 0xd23105, 0xd02f04, 0xce2d04, 0xcc2b03, 0xca2903, 0xc82803, 0xc62602, 0xc32402, 0xc12302, 0xbf2102, 0xbc1f01, 0xba1e01, 0xb71c01, 0xb41b01, 0xb21901, 0xaf1801, 0xac1601, 0xaa1501, 0xa71401, 0xa41201, 0xa11101, 0x9e1001, 0x9b0f01, 0x980d01, 0x950c01, 0x920b01, 0x8e0a01, 0x8b0901, 0x880801, 0x850701, 0x810602, 0x7e0502, 0x7a0402]
### original theme by teejez:
#waterfall_colors = [0x000000, 0x0000FF, 0x00FFFF, 0x00FF00, 0xFFFF00, 0xFF0000, 0xFF00FF, 0xFFFFFF]
### old theme by HA7ILM:
#waterfall_colors = [0x000000, 0x2e6893, 0x69a5d0, 0x214b69, 0x9dc4e0, 0xfff775, 0xff8a8a, 0xb20000]
# waterfall_min_level = -115 #in dB
# waterfall_max_level = 0
# waterfall_auto_level_margin = {"min": 20, "max": 30}
##For the old colors, you might also want to set [fft_voverlap_factor] to 0.
waterfall_min_level = -88 # in dB
waterfall_max_level = -20
waterfall_auto_level_margin = {"min": 3, "max": 10, "min_range": 50}
# Note: When the auto waterfall level button is clicked, the following happens:
# [waterfall_min_level] = [current_min_power_level] - [waterfall_auto_level_margin["min"]]
# [waterfall_max_level] = [current_max_power_level] + [waterfall_auto_level_margin["max"]]
#
# ___|________________________________________|____________________________________|________________________________________|___> signal power
# \_waterfall_auto_level_margin["min"]_/ |__ current_min_power_level | \_waterfall_auto_level_margin["max"]_/
# current_max_power_level __|
# === Experimental settings ===
# Warning! The settings below are very experimental.
csdr_dynamic_bufsize = False # This allows you to change the buffering mode of csdr.
csdr_print_bufsizes = False # This prints the buffer sizes used for csdr processes.
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 = ""
# how long should positions be visible on the map?
# they will start fading out after half of that
# in seconds; default: 2 hours
map_position_retention_time = 2 * 60 * 60
# 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}
# 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
temporary_directory = "/tmp"
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
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
# path to the aprs symbols repository (get it here: https://github.com/hessu/aprs-symbols)
aprs_symbols_path = "/opt/aprs-symbols/png"
# === PSK Reporter setting ===
# 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"
# === Web admin settings ===
# this feature is experimental at the moment. it should not be enabled on shared receivers since it allows remote
# changes to the receiver settings. enable for testing in controlled environment only.
# webadmin_enabled = False

0
csdr/__init__.py Normal file
View File

142
csdr/chain/__init__.py Normal file
View 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
View 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
View 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
View 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

133
csdr/chain/digiham.py Normal file
View File

@ -0,0 +1,133 @@
from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain, DialFrequencyReceiver, MetaProvider, SlotFilterChain, DemodulatorError, ServiceDemodulator
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, PocsagDecoder
from digiham.ambe import Modes, ServerError
from owrx.meta import MetaParser
from owrx.pocsag import PocsagParser
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
)
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)

86
csdr/chain/digimodes.py Normal file
View File

@ -0,0 +1,86 @@
from csdr.chain.demodulator import ServiceDemodulator, SecondaryDemodulator, DialFrequencyReceiver, SecondarySelectorChain
from csdr.module.msk144 import Msk144Module, ParserAdapter
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
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 Msk144Demodulator(ServiceDemodulator, DialFrequencyReceiver):
def __init__(self):
self.parser = ParserAdapter()
workers = [
Convert(Format.FLOAT, Format.SHORT),
Msk144Module(),
self.parser,
]
super().__init__(workers)
def getFixedAudioRate(self) -> int:
return 12000
def setDialFrequency(self, frequency: int) -> None:
self.parser.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 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
View 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
View 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
View 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
View 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
View 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
View 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)

View File

@ -1,874 +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>
Copyright (c) 2019-2020 by Jakob Ketterl <dd5jfk@darc.de>
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 os
import signal
import threading
import math
from functools import partial
from owrx.kiss import KissClient, DirewolfConfig
from owrx.wsjt import Ft8Profile, WsprProfile, Jt9Profile, Jt65Profile, Ft4Profile
from owrx.js8 import Js8Profiles
from owrx.audio import AudioChopper
from csdr.pipe import Pipe
import logging
logger = logging.getLogger(__name__)
class output(object):
def send_output(self, t, read_fn):
if not self.supports_type(t):
# TODO rewrite the output mechanism in a way that avoids producing unnecessary data
logger.warning("dumping output of type %s since it is not supported.", t)
threading.Thread(target=self.pump(read_fn, lambda x: None), name="csdr_pump_thread").start()
return
self.receive_output(t, read_fn)
def receive_output(self, t, read_fn):
pass
def pump(self, read, write):
def copy():
run = True
while run:
data = None
try:
data = read()
except ValueError:
pass
if data is None or (isinstance(data, bytes) and len(data) == 0):
run = False
else:
write(data)
return copy
def supports_type(self, t):
return True
class dsp(object):
def __init__(self, output):
self.samp_rate = 250000
self.output_rate = 11025
self.hd_output_rate = 44100
self.fft_size = 1024
self.fft_fps = 5
self.center_freq = 0
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.base_bufsize = 512
self.decimation = None
self.last_decimation = None
self.nc_port = None
self.csdr_dynamic_bufsize = False
self.csdr_print_bufsizes = False
self.csdr_through = False
self.squelch_level = -150
self.fft_averages = 50
self.wfm_deemphasis_tau = 50e-6
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": Pipe.WRITE,
"shift_pipe": Pipe.WRITE,
"squelch_pipe": Pipe.WRITE,
"smeter_pipe": Pipe.READ,
"meta_pipe": Pipe.READ,
"iqtee_pipe": Pipe.NONE,
"iqtee2_pipe": Pipe.NONE,
"dmr_control_pipe": Pipe.WRITE,
}
self.pipes = {}
self.secondary_pipe_names = {"secondary_shift_pipe": Pipe.WRITE}
self.secondary_offset_freq = 1000
self.unvoiced_quality = 1
self.modification_lock = threading.Lock()
self.output = output
self.temporary_directory = None
self.pipe_base_path = None
self.set_temporary_directory("/tmp")
self.is_service = False
self.direwolf_config = None
self.direwolf_port = None
self.process = None
def set_service(self, flag=True):
self.is_service = flag
def set_temporary_directory(self, what):
self.temporary_directory = what
self.pipe_base_path = "{tmp_dir}/openwebrx_pipe_".format(tmp_dir=self.temporary_directory)
def chain(self, which):
chain = ["nc -v 127.0.0.1 {nc_port}"]
if self.csdr_dynamic_bufsize:
chain += ["csdr setbuf {start_bufsize}"]
if self.csdr_through:
chain += ["csdr through"]
if which == "fft":
chain += [
"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":
chain += ["csdr compress_fft_adpcm_f_u8 {fft_size}"]
return chain
chain += ["csdr shift_addfast_cc --fifo {shift_pipe}"]
if self.decimation > 1:
chain += ["csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING"]
chain += ["csdr bandpass_fir_fft_cc --fifo {bpf_pipe} {bpf_transition_bw} HAMMING"]
if self.output.supports_type("smeter"):
chain += [
"csdr squelch_and_smeter_cc --fifo {squelch_pipe} --outfifo {smeter_pipe} 5 {smeter_report_every}"
]
if self.secondary_demodulator:
if self.output.supports_type("secondary_fft"):
chain += ["csdr tee {iqtee_pipe}"]
chain += ["csdr tee {iqtee2_pipe}"]
# early exit if we don't want audio
if not self.output.supports_type("audio"):
return chain
# safe some cpu cycles... no need to decimate if decimation factor is 1
last_decimation_block = []
if self.last_decimation >= 2.0:
# activate prefilter if signal has been oversampled, e.g. WFM
last_decimation_block = ["csdr fractional_decimator_ff {last_decimation} 12 --prefilter"]
elif self.last_decimation != 1.0:
last_decimation_block = ["csdr fractional_decimator_ff {last_decimation}"]
if which == "nfm":
chain += ["csdr fmdemod_quadri_cf", "csdr limit_ff"]
chain += last_decimation_block
chain += [
"csdr deemphasis_nfm_ff {audio_rate}",
"csdr agc_ff --profile slow --max 3",
]
if self.get_audio_rate() != self.get_output_rate():
chain += [
"sox -t raw -r {audio_rate} -e floating-point -b 32 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - "
]
else:
chain += ["csdr convert_f_s16"]
elif which == "wfm":
chain += [
"csdr fmdemod_quadri_cf",
"csdr limit_ff",
]
chain += last_decimation_block
chain += [
"csdr deemphasis_wfm_ff {audio_rate} {wfm_deemphasis_tau}",
"csdr convert_f_s16"
]
elif self.isDigitalVoice(which):
chain += ["csdr fmdemod_quadri_cf", "dc_block "]
chain += last_decimation_block
# dsd modes
if which in ["dstar", "nxdn"]:
chain += ["csdr limit_ff", "csdr convert_f_s16"]
if which == "dstar":
chain += ["dsd -fd -i - -o - -u {unvoiced_quality} -g -1 "]
elif which == "nxdn":
chain += ["dsd -fi -i - -o - -u {unvoiced_quality} -g -1 "]
chain += [
"digitalvoice_filter",
"CSDR_FIXED_BUFSIZE=32 csdr agc_s16 --max 30 --initial 3",
"sox -t raw -r 8000 -e signed-integer -b 16 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
]
# digiham modes
else:
chain += ["rrc_filter", "gfsk_demodulator"]
if which == "dmr":
chain += [
"dmr_decoder --fifo {meta_pipe} --control-fifo {dmr_control_pipe}",
"mbe_synthesizer -f -u {unvoiced_quality}",
]
elif which == "ysf":
chain += ["ysf_decoder --fifo {meta_pipe}", "mbe_synthesizer -y -f -u {unvoiced_quality}"]
max_gain = 0.005
chain += [
"digitalvoice_filter -f",
"CSDR_FIXED_BUFSIZE=32 csdr agc_ff --max 0.005 --initial 0.0005",
"sox -t raw -r 8000 -e floating-point -b 32 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
]
elif which == "am":
chain += ["csdr amdemod_cf", "csdr fastdcblock_ff"]
chain += last_decimation_block
chain += [
"csdr agc_ff --profile slow --initial 200",
"csdr convert_f_s16",
]
elif self.isFreeDV(which):
chain += ["csdr realpart_cf"]
chain += last_decimation_block
chain += [
"csdr agc_ff",
"csdr convert_f_s16",
"freedv_rx 1600 - -",
"csdr agc_s16 --max 30 --initial 3",
"sox -t raw -r 8000 -e signed-integer -b 16 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
]
elif self.isDrm(which):
if self.last_decimation != 1.0:
# we are still dealing with complex samples here, so the regular last_decimation_block doesn't fit
chain += ["csdr fractional_decimator_cc {last_decimation}"]
chain += [
"csdr convert_f_s16",
"dream -c 6 --sigsrate 48000 --audsrate 48000 -I - -O -",
"sox -t raw -r 48000 -e signed-integer -b 16 -c 2 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - ",
]
elif which == "ssb":
chain += ["csdr realpart_cf"]
chain += last_decimation_block
chain += ["csdr agc_ff"]
# fixed sample rate necessary for the wsjt-x tools. fix with sox...
if self.get_audio_rate() != self.get_output_rate():
chain += [
"sox -t raw -r {audio_rate} -e floating-point -b 32 -c 1 --buffer 32 - -t raw -r {output_rate} -e signed-integer -b 16 -c 1 - "
]
else:
chain += ["csdr convert_f_s16"]
if self.audio_compression == "adpcm":
chain += ["csdr encode_ima_adpcm_i16_u8"]
return chain
def secondary_chain(self, which):
chain = ["cat {input_pipe}"]
if which == "fft":
chain += [
"csdr fft_cc {secondary_fft_input_size} {secondary_fft_block_size}",
"csdr logpower_cf -70"
if self.fft_averages == 0
else "csdr logaveragepower_cf -70 {secondary_fft_size} {fft_averages}",
"csdr fft_exchange_sides_ff {secondary_fft_input_size}",
]
if self.fft_compression == "adpcm":
chain += ["csdr compress_fft_adpcm_f_u8 {secondary_fft_size}"]
return chain
elif which == "bpsk31" or which == "bpsk63":
return chain + [
"csdr shift_addfast_cc --fifo {secondary_shift_pipe}",
"csdr bandpass_fir_fft_cc -{secondary_bpf_cutoff} {secondary_bpf_cutoff} {secondary_bpf_cutoff}",
"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",
]
elif self.isWsjtMode(which) or self.isJs8(which):
chain += ["csdr realpart_cf"]
if self.last_decimation != 1.0:
chain += ["csdr fractional_decimator_ff {last_decimation}"]
return chain + ["csdr limit_ff", "csdr convert_f_s16"]
elif which == "packet":
chain += ["csdr fmdemod_quadri_cf"]
if self.last_decimation != 1.0:
chain += ["csdr fractional_decimator_ff {last_decimation}"]
return chain + ["csdr convert_f_s16", "direwolf -c {direwolf_config} -r {audio_rate} -t 0 -q d -q h 1>&2"]
elif which == "pocsag":
chain += ["csdr fmdemod_quadri_cf"]
if self.last_decimation != 1.0:
chain += ["csdr fractional_decimator_ff {last_decimation}"]
return chain + ["fsk_demodulator -i", "pocsag_decoder"]
def set_secondary_demodulator(self, what):
if self.get_secondary_demodulator() == what:
return
self.secondary_demodulator = what
self.calculate_decimation()
self.restart()
def secondary_fft_block_size(self):
base = (self.samp_rate / self.decimation) / (self.fft_fps * 2)
if self.fft_averages == 0:
return base
return base / self.fft_averages
def secondary_decimation(self):
return 1 # currently unused
def secondary_bpf_cutoff(self):
if self.secondary_demodulator == "bpsk31":
return 31.25 / self.if_samp_rate()
elif self.secondary_demodulator == "bpsk63":
return 62.5 / self.if_samp_rate()
return 0
def secondary_bpf_transition_bw(self):
if self.secondary_demodulator == "bpsk31":
return 31.25 / self.if_samp_rate()
elif self.secondary_demodulator == "bpsk63":
return 62.5 / 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
elif self.secondary_demodulator == "bpsk63":
return int(round(self.if_samp_rate() / 62.5)) & ~3
return 0
def secondary_bw(self):
if self.secondary_demodulator == "bpsk31":
return 31.25
elif self.secondary_demodulator == "bpsk63":
return 62.5
def start_secondary_demodulator(self):
if not self.secondary_demodulator:
return
logger.debug("starting secondary demodulator from IF input sampled at %d" % self.if_samp_rate())
secondary_command_demod = " | ".join(self.secondary_chain(self.secondary_demodulator))
self.try_create_pipes(self.secondary_pipe_names, secondary_command_demod)
self.try_create_configs(secondary_command_demod)
secondary_command_demod = secondary_command_demod.format(
input_pipe=self.pipes["iqtee2_pipe"],
secondary_shift_pipe=self.pipes["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(),
last_decimation=self.last_decimation,
audio_rate=self.get_audio_rate(),
direwolf_config=self.direwolf_config,
)
logger.debug("secondary command (demod) = %s", secondary_command_demod)
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"
if self.output.supports_type("secondary_fft"):
secondary_command_fft = " | ".join(self.secondary_chain("fft"))
secondary_command_fft = secondary_command_fft.format(
input_pipe=self.pipes["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(),
fft_averages=self.fft_averages,
)
logger.debug("secondary command (fft) = %s", secondary_command_fft)
self.secondary_process_fft = subprocess.Popen(
secondary_command_fft, stdout=subprocess.PIPE, shell=True, start_new_session=True, env=my_env
)
self.output.send_output(
"secondary_fft",
partial(self.secondary_process_fft.stdout.read, int(self.get_secondary_fft_bytes_to_read())),
)
# direwolf does not provide any meaningful data on stdout
# more specifically, it doesn't provide any data. if however, for any strange reason, it would start to do so,
# it would block if not read. by piping it to devnull, we avoid a potential pitfall here.
secondary_output = subprocess.DEVNULL if self.isPacket() else subprocess.PIPE
self.secondary_process_demod = subprocess.Popen(
secondary_command_demod, stdout=secondary_output, shell=True, start_new_session=True, env=my_env
)
self.secondary_processes_running = True
if self.isWsjtMode():
smd = self.get_secondary_demodulator()
chopper_profile = None
if smd == "ft8":
chopper_profile = Ft8Profile()
elif smd == "wspr":
chopper_profile = WsprProfile()
elif smd == "jt65":
chopper_profile = Jt65Profile()
elif smd == "jt9":
chopper_profile = Jt9Profile()
elif smd == "ft4":
chopper_profile = Ft4Profile()
if chopper_profile is not None:
chopper = AudioChopper(self, self.secondary_process_demod.stdout, chopper_profile)
chopper.start()
self.output.send_output("wsjt_demod", chopper.read)
elif self.isJs8():
chopper = AudioChopper(self, self.secondary_process_demod.stdout, *Js8Profiles.getEnabledProfiles())
chopper.start()
self.output.send_output("js8_demod", chopper.read)
elif self.isPacket():
# we best get the ax25 packets from the kiss socket
kiss = KissClient(self.direwolf_port)
self.output.send_output("packet_demod", kiss.read)
elif self.isPocsag():
self.output.send_output("pocsag_demod", self.secondary_process_demod.stdout.readline)
else:
self.output.send_output("secondary_demod", partial(self.secondary_process_demod.stdout.read, 1))
# open control pipes for csdr and send initialization data
if self.has_pipe("secondary_shift_pipe"): # TODO digimodes
self.set_secondary_offset_freq(self.secondary_offset_freq) # TODO digimodes
def set_secondary_offset_freq(self, value):
self.secondary_offset_freq = value
if self.secondary_processes_running and self.has_pipe("secondary_shift_pipe"):
self.pipes["secondary_shift_pipe"].write("%g\n" % (-float(self.secondary_offset_freq) / self.if_samp_rate()))
def stop_secondary_demodulator(self):
if not self.secondary_processes_running:
return
self.try_delete_pipes(self.secondary_pipe_names)
self.try_delete_configs()
if self.secondary_process_fft:
try:
os.killpg(os.getpgid(self.secondary_process_fft.pid), signal.SIGTERM)
# drain any leftover data to free file descriptors
self.secondary_process_fft.communicate()
self.secondary_process_fft = None
except ProcessLookupError:
# been killed by something else, ignore
pass
if self.secondary_process_demod:
try:
os.killpg(os.getpgid(self.secondary_process_demod.pid), signal.SIGTERM)
# drain any leftover data to free file descriptors
self.secondary_process_demod.communicate()
self.secondary_process_demod = None
except ProcessLookupError:
# been killed by something else, ignore
pass
self.secondary_processes_running = False
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 get_audio_bytes_to_read(self):
# desired latency: 5ms
# uncompressed audio has 16 bits = 2 bytes per sample
base = self.output_rate * 0.005 * 2
# adpcm compresses the bitstream by 4
if self.audio_compression == "adpcm":
base = base / 4
return int(base)
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 int((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):
self.samp_rate = samp_rate
self.calculate_decimation()
if self.running:
self.restart()
def calculate_decimation(self):
(self.decimation, self.last_decimation, _) = self.get_decimation(self.samp_rate, self.get_audio_rate())
def get_decimation(self, input_rate, output_rate):
decimation = 1
correction = 1
# wideband fm has a much higher frequency deviation (75kHz).
# we cannot cover this if we immediately decimate to the sample rate the audio will have later on, so we need
# to compensate here.
# the factor of 5 is by experimentation only, with a minimum audio rate of 36kHz (enforced by the client)
# this allows us to cover at least +/- 80kHz of frequency spectrum (may be higher, but that's the worst case).
# the correction factor is automatically compensated for by the secondary decimation stage, which comes
# after the demodulator.
if self.get_demodulator() == "wfm":
correction = 5
while input_rate / (decimation + 1) >= output_rate * correction:
decimation += 1
fraction = float(input_rate / decimation) / output_rate
intermediate_rate = input_rate / decimation
return decimation, fraction, intermediate_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 get_hd_output_rate(self):
return self.hd_output_rate
def get_audio_rate(self):
if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isDrm():
return 48000
elif self.isWsjtMode() or self.isJs8():
return 12000
elif self.isFreeDV():
return 8000
elif self.isHdAudio():
return self.get_hd_output_rate()
return self.get_output_rate()
def isDigitalVoice(self, demodulator=None):
if demodulator is None:
demodulator = self.get_demodulator()
return demodulator in ["dmr", "dstar", "nxdn", "ysf"]
def isWsjtMode(self, demodulator=None):
if demodulator is None:
demodulator = self.get_secondary_demodulator()
return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4"]
def isJs8(self, demodulator = None):
if demodulator is None:
demodulator = self.get_secondary_demodulator()
return demodulator == "js8"
def isPacket(self, demodulator=None):
if demodulator is None:
demodulator = self.get_secondary_demodulator()
return demodulator == "packet"
def isPocsag(self, demodulator=None):
if demodulator is None:
demodulator = self.get_secondary_demodulator()
return demodulator == "pocsag"
def isFreeDV(self, demodulator=None):
if demodulator is None:
demodulator = self.get_demodulator()
return demodulator == "freedv"
def isHdAudio(self, demodulator=None):
if demodulator is None:
demodulator = self.get_demodulator()
return demodulator == "wfm"
def isDrm(self, demodulator=None):
if demodulator is None:
demodulator = self.get_demodulator()
return demodulator == "drm"
def set_output_rate(self, output_rate):
if self.output_rate == output_rate:
return
self.output_rate = output_rate
self.calculate_decimation()
self.restart()
def set_hd_output_rate(self, hd_output_rate):
if self.hd_output_rate == hd_output_rate:
return
self.hd_output_rate = hd_output_rate
self.calculate_decimation()
self.restart()
def set_demodulator(self, demodulator):
if demodulator in ["usb", "lsb", "cw"]:
demodulator = "ssb"
if self.demodulator == demodulator:
return
self.demodulator = demodulator
self.calculate_decimation()
self.restart()
def get_demodulator(self):
return self.demodulator
def set_fft_size(self, fft_size):
self.fft_size = fft_size
self.restart()
def set_fft_fps(self, fft_fps):
self.fft_fps = fft_fps
self.restart()
def set_fft_averages(self, fft_averages):
self.fft_averages = fft_averages
self.restart()
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_offset_freq(self, offset_freq):
if offset_freq is None:
return
self.offset_freq = offset_freq
if self.running:
self.pipes["shift_pipe"].write("%g\n" % (-float(self.offset_freq) / self.samp_rate))
def set_center_freq(self, center_freq):
# dsp only needs to know this to be able to pass it to decoders in the form of get_operating_freq()
self.center_freq = center_freq
def get_operating_freq(self):
return self.center_freq + self.offset_freq
def set_bpf(self, low_cut, high_cut):
self.low_cut = low_cut
self.high_cut = high_cut
if self.running:
self.pipes["bpf_pipe"].write(
"%g %g\n" % (float(self.low_cut) / self.if_samp_rate(), float(self.high_cut) / self.if_samp_rate())
)
def get_bpf(self):
return [self.low_cut, self.high_cut]
def convertToLinear(self, db):
return float(math.pow(10, db / 10))
def set_squelch_level(self, squelch_level):
self.squelch_level = squelch_level
# no squelch required on digital voice modes
actual_squelch = -150 if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV() else self.squelch_level
if self.running:
self.pipes["squelch_pipe"].write("%g\n" % (self.convertToLinear(actual_squelch)))
def set_unvoiced_quality(self, q):
self.unvoiced_quality = q
self.restart()
def get_unvoiced_quality(self):
return self.unvoiced_quality
def set_dmr_filter(self, filter):
if self.has_pipe("dmr_control_pipe"):
self.pipes["dmr_control_pipe"].write("{0}\n".format(filter))
def set_wfm_deemphasis_tau(self, tau):
if self.wfm_deemphasis_tau == tau:
return
self.wfm_deemphasis_tau = tau
self.restart()
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):
for pipe_name, pipe_type in pipe_names.items():
if self.has_pipe(pipe_name):
logger.warning("{pipe_name} is still in use", pipe_name=pipe_name)
self.pipes[pipe_name].close()
if "{" + pipe_name + "}" in command_base:
p = self.pipe_base_path + pipe_name
encoding = None
# TODO make digiham output unicode and then change this here
# the whole pipe enoding feature onlye exists because of this
if pipe_name == "meta_pipe":
encoding = "cp437"
self.pipes[pipe_name] = Pipe.create(p, pipe_type, encoding=encoding)
else:
self.pipes[pipe_name] = None
def has_pipe(self, name):
return name in self.pipes and self.pipes[name] is not None
def try_delete_pipes(self, pipe_names):
for pipe_name in pipe_names:
if self.has_pipe(pipe_name):
self.pipes[pipe_name].close()
self.pipes[pipe_name] = None
def try_create_configs(self, command):
if "{direwolf_config}" in command:
self.direwolf_config = "{tmp_dir}/openwebrx_direwolf_{myid}.conf".format(
tmp_dir=self.temporary_directory, myid=id(self)
)
self.direwolf_port = KissClient.getFreePort()
file = open(self.direwolf_config, "w")
file.write(DirewolfConfig().getConfig(self.direwolf_port, self.is_service))
file.close()
else:
self.direwolf_config = None
self.direwolf_port = None
def try_delete_configs(self):
if self.direwolf_config:
try:
os.unlink(self.direwolf_config)
except FileNotFoundError:
# result suits our expectations. fine :)
pass
except Exception:
logger.exception("try_delete_configs()")
self.direwolf_config = None
def start(self):
with self.modification_lock:
if self.running:
return
self.running = True
command_base = " | ".join(self.chain(self.demodulator))
# create control pipes for csdr
self.try_create_pipes(self.pipe_names, command_base)
# send initial config through the pipes
if self.has_pipe("bpf_pipe"):
self.set_bpf(self.low_cut, self.high_cut)
if self.has_pipe("shift_pipe"):
self.set_offset_freq(self.offset_freq)
if self.has_pipe("squelch_pipe"):
self.set_squelch_level(self.squelch_level)
if self.has_pipe("dmr_control_pipe"):
self.set_dmr_filter(3)
# run the command
command = command_base.format(
bpf_pipe=self.pipes["bpf_pipe"],
shift_pipe=self.pipes["shift_pipe"],
squelch_pipe=self.pipes["squelch_pipe"],
smeter_pipe=self.pipes["smeter_pipe"],
meta_pipe=self.pipes["meta_pipe"],
iqtee_pipe=self.pipes["iqtee_pipe"],
iqtee2_pipe=self.pipes["iqtee2_pipe"],
dmr_control_pipe=self.pipes["dmr_control_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,
output_rate=self.get_output_rate(),
smeter_report_every=int(self.if_samp_rate() / 6000),
unvoiced_quality=self.get_unvoiced_quality(),
audio_rate=self.get_audio_rate(),
wfm_deemphasis_tau=self.wfm_deemphasis_tau,
)
logger.debug("Command = %s", command)
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"
out = subprocess.PIPE if self.output.supports_type("audio") else subprocess.DEVNULL
self.process = subprocess.Popen(command, stdout=out, shell=True, start_new_session=True, env=my_env)
def watch_thread():
rc = self.process.wait()
logger.debug("dsp thread ended with rc=%d", rc)
if rc == 0 and self.running and not self.modification_lock.locked():
logger.debug("restarting since rc = 0, self.running = true, and no modification")
self.restart()
threading.Thread(target=watch_thread, name="csdr_watch_thread").start()
audio_type = "hd_audio" if self.isHdAudio() else "audio"
if self.output.supports_type(audio_type):
self.output.send_output(
audio_type,
partial(
self.process.stdout.read,
self.get_fft_bytes_to_read() if self.demodulator == "fft" else self.get_audio_bytes_to_read(),
),
)
self.start_secondary_demodulator()
if self.has_pipe("smeter_pipe"):
def read_smeter():
raw = self.pipes["smeter_pipe"].readline()
if len(raw) == 0:
return None
else:
return float(raw.rstrip("\n"))
self.output.send_output("smeter", read_smeter)
if self.has_pipe("meta_pipe"):
def read_meta():
raw = self.pipes["meta_pipe"].readline()
if len(raw) == 0:
return None
else:
return raw.rstrip("\n")
self.output.send_output("meta", read_meta)
if self.csdr_dynamic_bufsize:
self.process.stdout.read(8) # dummy read to skip bufsize & preamble
logger.debug("Note: CSDR_DYNAMIC_BUFSIZE_ON = 1")
def stop(self):
with self.modification_lock:
self.running = False
if self.process is not None:
try:
os.killpg(os.getpgid(self.process.pid), signal.SIGTERM)
# drain any leftover data to free file descriptors
self.process.communicate()
self.process = None
except ProcessLookupError:
# been killed by something else, ignore
pass
self.stop_secondary_demodulator()
self.try_delete_pipes(self.pipe_names)
def restart(self):
if not self.running:
return
self.stop()
self.start()
def __del__(self):
self.stop()

136
csdr/module/__init__.py Normal file
View 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.read1, 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
View 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
View 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
View 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

57
csdr/module/msk144.py Normal file
View File

@ -0,0 +1,57 @@
from pycsdr.types import Format
from csdr.module import PopenModule, ThreadModule
from owrx.wsjt import WsjtParser, Msk144Profile
import pickle
import logging
logger = logging.getLogger(__name__)
class Msk144Module(PopenModule):
def getCommand(self):
return ["msk144decoder"]
def getInputFormat(self) -> Format:
return Format.SHORT
def getOutputFormat(self) -> Format:
return Format.CHAR
class ParserAdapter(ThreadModule):
def __init__(self):
self.retained = bytes()
self.parser = WsjtParser()
self.dialFrequency = 0
super().__init__()
def run(self):
profile = Msk144Profile()
while self.doRun:
data = self.reader.read()
if data is None:
self.doRun = False
else:
self.retained += data
lines = self.retained.split(b"\n")
# keep the last line
# this should either be empty if the last char was \n
# or an incomplete line if the read returned early
self.retained = lines[-1]
# parse all completed lines
for line in lines[0:-1]:
# actual messages from msk144decoder should start with "*** "
if line[0:4] == b"*** ":
self.writer.write(pickle.dumps(self.parser.parse(profile, self.dialFrequency, line[4:])))
def getInputFormat(self) -> Format:
return Format.CHAR
def getOutputFormat(self) -> Format:
return Format.CHAR
def setDialFrequency(self, frequency: int) -> None:
self.dialFrequency = frequency

View File

@ -1,155 +0,0 @@
import os
import select
import time
import threading
import logging
logger = logging.getLogger(__name__)
class Pipe(object):
READ = "r"
WRITE = "w"
NONE = None
@staticmethod
def create(path, t, encoding=None):
if t == Pipe.READ:
return ReadingPipe(path, encoding=encoding)
elif t == Pipe.WRITE:
return WritingPipe(path, encoding=encoding)
elif t == Pipe.NONE:
return Pipe(path, None, encoding=encoding)
def __init__(self, path, direction, encoding=None):
self.doOpen = True
self.path = "{base}_{myid}".format(base=path, myid=id(self))
self.direction = direction
self.encoding = encoding
self.file = None
os.mkfifo(self.path)
def open(self):
"""
this method opens the file descriptor with an added O_NONBLOCK flag. This gives us a special behaviour for
FIFOS, when they are not opened by the opposing side:
- opening a pipe for writing will throw an OSError with errno = 6 (ENXIO). This is handled specially in the
WritingPipe class.
- opening a pipe for reading will pass through this method instantly, even if the opposing end has not been
opened yet, but the resulting file descriptor will behave as if O_NONBLOCK is set (even if we remove it
immediately here), resulting in empty reads until data is available. This is handled specially in the
ReadingPipe class.
"""
def opener(path, flags):
fd = os.open(path, flags | os.O_NONBLOCK)
os.set_blocking(fd, True)
return fd
self.file = open(self.path, self.direction, encoding=self.encoding, opener=opener)
def close(self):
self.doOpen = False
try:
if self.file is not None:
self.file.close()
os.unlink(self.path)
except FileNotFoundError:
# it seems like we keep calling this twice. no idea why, but we don't need the resulting error.
pass
except Exception:
logger.exception("Pipe.close()")
def __str__(self):
return self.path
class WritingPipe(Pipe):
def __init__(self, path, encoding=None):
self.queue = []
self.queueLock = threading.Lock()
super().__init__(path, "w", encoding=encoding)
self.open()
def open_and_dequeue(self):
"""
This method implements a retry loop that can be interrupted in case the Pipe gets shutdown before actually
being connected.
After the pipe is opened successfully, all data that has been queued is sent in the order it was passed into
write().
"""
retries = 0
while self.file is None and self.doOpen and retries < 10:
try:
super().open()
except OSError as error:
# ENXIO = FIFO has not been opened for reading
if error.errno == 6:
time.sleep(.1)
retries += 1
else:
raise
# if doOpen is false, opening has been canceled, so no warning in that case.
if self.file is None:
if self.doOpen:
logger.warning("could not open FIFO %s", self.path)
return
with self.queueLock:
for i in self.queue:
self.file.write(i)
self.file.flush()
self.queue = None
def open(self):
"""
This sends the opening operation off to a background thread. If we were to block the thread here, another pipe
may be waiting in the queue to be opened on the opposing side, resulting in a deadlock
"""
threading.Thread(target=self.open_and_dequeue, name="csdr_pipe_thread").start()
def write(self, data):
"""
This method queues all data to be written until the file is actually opened. As soon as a file is available,
it becomes a passthrough.
"""
if self.file is None:
with self.queueLock:
self.queue.append(data)
return
r = self.file.write(data)
self.file.flush()
return r
class ReadingPipe(Pipe):
def __init__(self, path, encoding=None):
super().__init__(path, "r", encoding=encoding)
def open(self):
"""
This method implements an interruptible loop that waits for the file descriptor to be opened and the first
batch of data coming in using repeated select() calls.
:return:
"""
if not self.doOpen:
return
super().open()
while self.doOpen:
(read, _, _) = select.select([self.file], [], [], 1)
if self.file in read:
break
def read(self):
if self.file is None:
self.open()
return self.file.read()
def readline(self):
if self.file is None:
self.open()
return self.file.readline()

68
debian/changelog vendored
View File

@ -1,3 +1,71 @@
openwebrx (1.3.0) UNRELEASED; urgency=low
* SDR device log messages are now available in the web configuration to
simplify troubleshooting
* Added support for the MSK144 digimode
-- Jakob Ketterl <jakob.ketterl@gmx.de> Fri, 30 Sep 2022 16:47:00 +0000
openwebrx (1.2.1) bullseye jammy; urgency=low
* FifiSDR support fixed (pipeline formats now line up correctly)
* Added "Device" input for FifiSDR devices for sound card selection
-- Jakob Ketterl <jakob.ketterl@gmx.de> Tue, 20 Sep 2022 16:01:00 +0000
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

4
debian/control vendored
View File

@ -10,7 +10,7 @@ Vcs-Git: https://github.com/jketterl/openwebrx.git
Package: openwebrx
Architecture: all
Depends: adduser, python3 (>= 3.5), python3-pkg-resources, csdr (>= 0.17), netcat, owrx-connector (>= 0.3), python3-js8py (>= 0.1), ${python3:Depends}, ${misc:Depends}
Recommends: digiham (>= 0.3), dsd (>= 1.7), sox, direwolf (>= 1.4), wsjtx, soapysdr-tools
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.2), nmux (>= 0.18), codecserver (>= 0.1), msk144decoder
Description: multi-user web sdr
Open source, multi-user SDR receiver with a web interface

8
debian/openwebrx.config vendored Executable file
View 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
View File

@ -0,0 +1 @@
/etc/openwebrx/openwebrx.conf.d

View File

@ -1,5 +1,3 @@
config_webrx.py etc/openwebrx/
bands.json etc/openwebrx/
bookmarks.json etc/openwebrx/
users.json etc/openwebrx/
openwebrx.conf etc/openwebrx/
systemd/openwebrx.service lib/systemd/system/

59
debian/openwebrx.postinst vendored Executable file
View 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
View 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
View 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.

7
debian/postinst vendored
View File

@ -1,7 +0,0 @@
#!/bin/bash
set -euxo pipefail
adduser --system --group --no-create-home --home /nonexistant openwebrx
usermod -aG plugdev openwebrx
#DEBHELPER#

View File

@ -2,10 +2,10 @@
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-redpitaya openwebrx-rtltcp openwebrx-full openwebrx"
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"
ARCHTAG="${TAG}-${ARCH}"
usage () {
echo "Usage: ${0} [command]"
@ -36,7 +36,7 @@ build () {
push () {
for image in ${IMAGES}; do
docker push jketterl/$image:$ARCHTAG
docker push jketterl/${image}:${ARCHTAG}
done
}
@ -45,11 +45,11 @@ manifest () {
# 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"
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
docker manifest create jketterl/${image}:${TAG} ${IMAGE_LIST}
docker manifest push --purge jketterl/${image}:${TAG}
done
}

View File

@ -1,9 +1,10 @@
FROM debian:buster-slim
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 && \
@ -12,12 +13,16 @@ 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
CMD [ "/opt/openwebrx/docker/scripts/run.sh" ]
ENV S6_CMD_ARG0="/opt/openwebrx/docker/scripts/run.sh"
CMD []
EXPOSE 8073

View 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

View File

@ -18,8 +18,10 @@ RUN /install-dependencies-rtlsdr.sh &&\
/install-dependencies-fcdpp.sh &&\
/install-dependencies-radioberry.sh &&\
/install-dependencies-uhd.sh &&\
/install-dependencies-redpitaya.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

View 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

View File

@ -1,8 +0,0 @@
ARG ARCHTAG
FROM openwebrx-soapysdr-base:$ARCHTAG
COPY docker/scripts/install-dependencies-redpitaya.sh /
RUN /install-dependencies-redpitaya.sh &&\
rm /install-dependencies-redpitaya.sh
COPY . /opt/openwebrx

View 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

View File

@ -1,5 +0,0 @@
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-redpitaya openwebrx-rtltcp openwebrx-full openwebrx"
ALL_ARCHS="x86_64 armv7l aarch64"
TAG=${TAG:-"latest"}
ARCHTAG="$TAG-$ARCH"

View 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)

View File

@ -0,0 +1,2 @@
#!/usr/bin/execlineb -P
/usr/local/bin/codecserver

View File

@ -1,18 +1,17 @@
--- CMakeLists.txt.orig 2020-07-21 20:59:55.982026645 +0200
+++ CMakeLists.txt 2020-07-21 21:01:25.444836112 +0200
@@ -80,24 +80,6 @@
--- 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 @@
include (ExternalProject)
-
-#
#
-# 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}
- URL ${CMAKE_CURRENT_SOURCE_DIR}/src/${__hamlib_upstream}
- 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
@ -22,10 +21,11 @@
- STEP_TARGETS update install
- )
-
#
-#
# custom target to make a hamlib source tarball
#
@@ -136,7 +118,6 @@
add_custom_target (hamlib_sources
@@ -161,7 +143,6 @@
# build and optionally install WSJT-X using the hamlib package built
# above
#
@ -33,11 +33,18 @@
ExternalProject_Add (wsjtx
GIT_REPOSITORY ${wsjtx_repo}
GIT_TAG ${WSJTX_TAG}
@@ -160,7 +141,6 @@
@@ -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-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)

View File

@ -1,59 +1,156 @@
diff -ur wsjtx-orig/CMake/Modules/Findhamlib.cmake wsjtx/CMake/Modules/Findhamlib.cmake
--- wsjtx-orig/CMake/Modules/Findhamlib.cmake 2020-07-21 21:10:43.124810140 +0200
+++ wsjtx/CMake/Modules/Findhamlib.cmake 2020-07-21 21:11:03.368019114 +0200
@@ -85,4 +85,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 wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt
--- wsjtx-orig/CMakeLists.txt 2020-07-21 21:10:43.124810140 +0200
+++ wsjtx/CMakeLists.txt 2020-07-21 22:14:04.454639589 +0200
@@ -871,7 +871,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)
@@ -1348,53 +1348,10 @@
--- wsjtx-orig/CMakeLists.txt 2023-01-28 17:43:05.586124507 +0100
+++ wsjtx/CMakeLists.txt 2023-01-28 17:56:07.108634912 +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)
@@ -170,77 +170,7 @@
)
endif(WSJT_BUILD_UTILS)
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
- item_delegates/MessageItemDelegate.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
@@ -1089,9 +1019,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})
@@ -1357,10 +1284,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})
@@ -1425,90 +1349,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.rc
- ${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)
-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 "${WSJTX_DESCRIPTION_SUMMARY}"
- MACOSX_BUNDLE_INFO_STRING "${PROJECT_DESCRIPTION}"
- 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_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 Qt5::SerialPort wsjt_fort wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
-if ((NOT ${OPENMP_FOUND}) OR APPLE)
- target_link_libraries (wsjtx wsjt_fort)
-else ()
- target_link_libraries (wsjtx Qt5::SerialPort wsjt_fort_omp wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
- target_link_libraries (wsjtx wsjt_fort_omp)
- if (OpenMP_C_FLAGS)
- set_target_properties (wsjtx PROPERTIES
- COMPILE_FLAGS "${OpenMP_C_FLAGS}"
@ -65,18 +162,72 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt
- )
- if (WIN32)
- set_target_properties (wsjtx PROPERTIES
- LINK_FLAGS -Wl,--stack,16777216
- 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})
@@ -1437,24 +1394,9 @@
set_target_properties (message_aggregator PROPERTIES WIN32_EXECUTABLE ON)
endif (WSJT_CREATE_WINMAIN)
-# 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})
-#target_include_directories (wsjtx_udp
-# INTERFACE
-# $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/wsjtx>
-# )
-target_include_directories (wsjtx_udp-static
- INTERFACE
- $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}/wsjtx>
- )
-#set_target_properties (wsjtx_udp PROPERTIES
-# PUBLIC_HEADER "${UDP_library_HEADERS}"
-# )
-set_target_properties (wsjtx_udp-static PROPERTIES
- OUTPUT_NAME wsjtx_udp
- )
-target_compile_definitions (wsjtx_udp-static PUBLIC UDP_STATIC_DEFINE)
-target_link_libraries (wsjtx_udp-static Qt5::Network Qt5::Gui)
-generate_export_header (wsjtx_udp-static BASE_NAME udp)
-
-generate_version_info (udp_daemon_VERSION_RESOURCES
- NAME udp_daemon
- BUNDLE ${PROJECT_BUNDLE_NAME}
- ICON ${WSJTX_ICON_FILE}
- FILE_DESCRIPTION "Example WSJT-X UDP Message Protocol daemon"
- )
-add_executable (udp_daemon UDPExamples/UDPDaemon.cpp ${udp_daemon_VERSION_RESOURCES})
-target_link_libraries (udp_daemon wsjtx_udp-static)
-
generate_version_info (wsjtx_app_version_VERSION_RESOURCES
NAME wsjtx_app_version
BUNDLE ${PROJECT_BUNDLE_NAME}
@@ -1518,47 +1358,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)
@ -98,21 +249,21 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt
# install (TARGETS wsjtx_udp EXPORT udp
# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -1473,12 +1415,7 @@
@@ -1577,12 +1379,7 @@
# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wsjtx
# )
-install (TARGETS udp_daemon message_aggregator
-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 jt9 wsprd
+install (TARGETS wsjtx_app_version jt9 wsprd
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
)
@@ -1491,39 +1428,6 @@
@@ -1595,38 +1392,6 @@
)
endif(WSJT_BUILD_UTILS)
@ -143,13 +294,48 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt
- AUTHORS
- THANKS
- NEWS
- INSTALL
- BUGS
- DESTINATION ${CMAKE_INSTALL_DOCDIR}
- #COMPONENT runtime
- )
-
install (FILES
contrib/Ephemeris/JPLEPH
DESTINATION ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}
Only in wsjtx: .idea
cty.dat
cty.dat_copyright.txt
@@ -1635,13 +1400,6 @@
#COMPONENT runtime
)
-install (DIRECTORY
- example_log_configurations
- DESTINATION ${CMAKE_INSTALL_DOCDIR}
- FILES_MATCHING REGEX "^.*[^~]$"
- #COMPONENT runtime
- )
-
#
# Mac installer files
#
@@ -1693,22 +1451,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")

View File

@ -18,13 +18,14 @@ function cmakebuild() {
cd /tmp
BUILD_PACKAGES="git cmake make gcc g++"
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.3.0
# latest develop as of 2022-12-11 (std::endl implicit flushing)
cmakebuild owrx_connector bca362707131289f91441c8080fd368fdc067b6d
apt-get -y purge --autoremove $BUILD_PACKAGES
apt-get clean

View 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/*

View 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.1
/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/*

View File

@ -1,5 +1,5 @@
#!/bin/bash
set -euo pipefail
set -euxo pipefail
export MAKEFLAGS="-j4"
function cmakebuild() {
@ -19,14 +19,15 @@ function cmakebuild() {
cd /tmp
STATIC_PACKAGES=""
BUILD_PACKAGES="git cmake make gcc g++"
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/pothosware/SoapyRedPitaya.git
cmakebuild SoapyRedPitaya soapy-redpitaya-0.1.1
git clone https://github.com/jketterl/runds_connector.git
# latest develop as of 2022-12-11 (std::endl implicit flushing)
cmakebuild runds_connector 06ca993a3c81ddb0a2581b1474895da07752a9e1
SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES
apt-get -y purge --autoremove $BUILD_PACKAGES
apt-get clean
rm -rf /var/lib/apt/lists/*

View File

@ -38,7 +38,7 @@ case $ARCH in
;;
esac
wget https://www.sdrplay.com/software/$BINARY
wget --no-http-keep-alive https://www.sdrplay.com/software/$BINARY
sh $BINARY --noexec --target sdrplay
patch --verbose -Np0 < /install-lib.$ARCH.patch
@ -48,9 +48,9 @@ cd ..
rm -rf sdrplay
rm $BINARY
git clone https://github.com/SDRplay/SoapySDRPlay.git
# latest from master as of 2020-09-04
cmakebuild SoapySDRPlay 105f8a6b3d449982d7ef860790c201aa066b8fa9
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

View File

@ -18,17 +18,16 @@ function cmakebuild() {
cd /tmp
STATIC_PACKAGES="libusb-1.0.0 libboost-chrono1.67.0 libboost-date-time1.67.0 libboost-filesystem1.67.0 libboost-program-options1.67.0 libboost-regex1.67.0 libboost-test1.67.0 libboost-serialization1.67.0 libboost-thread1.67.0 libboost-system1.67.0 python3-numpy python3-mako"
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
# 3.15.0.0 Release
mkdir -p uhd/host/build
cd uhd/host/build
git checkout v3.15.0.0
git checkout v4.1.0.4
# see https://github.com/EttusResearch/uhd/issues/350
case `uname -m` in
arm*)

View File

@ -7,6 +7,9 @@ function cmakebuild() {
if [[ ! -z "${2:-}" ]]; then
git checkout $2
fi
if [[ -f ".gitmodules" ]]; then
git submodule update --init
fi
mkdir build
cd build
cmake ${CMAKE_ARGS:-} ..
@ -18,8 +21,8 @@ function cmakebuild() {
cd /tmp
STATIC_PACKAGES="sox libfftw3-bin python3 python3-setuptools netcat-openbsd libsndfile1 liblapack3 libusb-1.0-0 libqt5core5a libreadline7 libgfortran4 libgomp1 libasound2 libudev1 ca-certificates libqt5gui5 libqt5sql5 libqt5printsupport5 libpulse0 libfaad2 libopus0"
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-default libfaad-dev libopus-dev"
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 libcurl4"
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 libcurl4-openssl-dev"
apt-get update
apt-get -y install auto-apt-proxy
apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES
@ -40,15 +43,6 @@ wget https://github.com/just-containers/s6-overlay/releases/download/v1.21.8.0/s
tar xzf s6-overlay-${PLATFORM}.tar.gz -C /
rm s6-overlay-${PLATFORM}.tar.gz
git clone https://git.code.sf.net/p/itpp/git itpp
cmakebuild itpp bb5c7e95f40e8fdb5c3f3d01a84bcbaf76f3676d
git clone https://github.com/szechyjs/mbelib.git
cmakebuild mbelib 9a04ed5c78176a9965f3d43f7aa1b1f5330e771f
git clone https://github.com/f4exb/dsd.git
cmakebuild dsd f6939f9edbbc6f66261833616391a4e59cb2b3d7
JS8CALL_VERSION=2.2.0
JS8CALL_DIR=js8call
JS8CALL_TGZ=js8call-${JS8CALL_VERSION}.tgz
@ -57,25 +51,33 @@ 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
CMAKE_ARGS="-D CMAKE_CXX_FLAGS=-DJS8_USE_HAMLIB_THREE" cmakebuild ${JS8CALL_DIR}
cmakebuild ${JS8CALL_DIR}
rm ${JS8CALL_TGZ}
WSJT_DIR=wsjtx-2.2.2
WSJT_DIR=wsjtx-2.6.1
WSJT_TGZ=${WSJT_DIR}.tgz
wget http://physics.princeton.edu/pulsar/k1jt/${WSJT_TGZ}
wget https://downloads.sourceforge.net/project/wsjt/${WSJT_DIR}/${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.5 https://github.com/wb2osz/direwolf.git
git clone https://github.com/alexander-sholohov/msk144decoder.git
# latest from main as of 2023-02-21
MAKEFLAGS="" cmakebuild msk144decoder fe2991681e455636e258e83c29fd4b2a72d16095
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.
# by setting enable_hamlib we prevent direwolf from linking to it, and it can be stripped at the end of the script.
make enable_hamlib=
# 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 ..
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
@ -106,9 +108,14 @@ popd
rm -rf dream
rm dream-2.1.1-svn808.tar.gz
git clone https://github.com/hessu/aprs-symbols /opt/aprs-symbols
pushd /opt/aprs-symbols
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

View File

@ -18,30 +18,43 @@ function cmakebuild() {
cd /tmp
STATIC_PACKAGES="libfftw3-bin"
BUILD_PACKAGES="git autoconf automake libtool libfftw3-dev pkg-config cmake make gcc g++"
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.0
# latest develop as of 2022-11-30 (structured callsign data)
git checkout f7e394b7892d26cbdcce5d43c0b4081a2a6a48f6
python3 setup.py install
popd
rm -rf js8py
git clone https://github.com/jketterl/csdr.git
cd csdr
git checkout 0.17.0
autoreconf -i
./configure
make
make install
cmakebuild csdr 0.18.1
git clone https://github.com/jketterl/pycsdr.git
cd pycsdr
git checkout 0.18.1
./setup.py install install_headers
cd ..
rm -rf csdr
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.3.0
cmakebuild digiham 0.6.1
git clone https://github.com/jketterl/pydigiham.git
cd pydigiham
git checkout 0.6.1
./setup.py install
cd ..
rm -rf pydigiham
apt-get -y purge --autoremove $BUILD_PACKAGES
apt-get clean

View File

@ -1,19 +1,25 @@
#!/bin/bash
set -euo pipefail
mkdir -p /etc/openwebrx/
mkdir -p /etc/openwebrx/openwebrx.conf.d
mkdir -p /var/lib/openwebrx
mkdir -p /tmp/openwebrx/
if [[ ! -f /etc/openwebrx/config_webrx.py ]] ; then
sed 's/temporary_directory = "\/tmp"/temporary_directory = "\/tmp\/openwebrx"/' < "/opt/openwebrx/config_webrx.py" > "/etc/openwebrx/config_webrx.py"
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/bookmarks.json ]] ; then
cp bookmarks.json /etc/openwebrx/
if [[ ! -f /etc/openwebrx/openwebrx.conf ]] ; then
cp openwebrx.conf /etc/openwebrx/
fi
if [[ ! -f /etc/openwebrx/users.json ]] ; then
cp users.json /etc/openwebrx/
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

BIN
htdocs/apple-touch-icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View File

@ -1,14 +1,166 @@
@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;
}
.device {
margin-top: 20px;
.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;
}
.device-log-messages {
max-height: 500px;
}

View File

@ -1,7 +0,0 @@
@import url("openwebrx-header.css");
@import url("openwebrx-globals.css");
h1 {
text-align: center;
margin: 50px 0;
}

View File

@ -1,6 +1,16 @@
@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%;

View File

@ -6,10 +6,6 @@ body {
flex-direction: column;
}
#webrx-top-container {
flex: none;
}
.openwebrx-map {
flex: 1 1 auto;
}
@ -25,10 +21,18 @@ ul {
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 {
@ -36,6 +40,15 @@ ul {
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;

View File

@ -5,21 +5,3 @@ html, body
height: 100%;
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
}
.sprite {
background-image: url(../gfx/openwebrx-sprites.png);
display: inline-block;
}
.openwebrx-button.highlighted .sprite {
background-image: linear-gradient(rgba(255,127,0,0.5), rgba(255,127,0,0.5)), url(../gfx/openwebrx-sprites.png);
background-blend-mode: overlay;
}
@media only screen and (-webkit-min-device-pixel-ratio: 2),
only screen and (min-device-pixel-ratio: 2) {
.sprite {
background-image: url(../gfx/openwebrx-sprites-2x.png);
background-size: 198px 77px;
}
}

View File

@ -1,32 +1,36 @@
#webrx-top-container
{
.webrx-top-container {
position: relative;
z-index:1000;
background-color: #575757;
}
#webrx-top-photo
{
width: 100%;
display: block;
}
background-image: url(../gfx/openwebrx-top-photo.jpg);
background-position-x: center;
background-position-y: top;
background-repeat: no-repeat;
background-size: cover;
#webrx-top-photo-clip
{
min-height: 67px;
max-height: 67px;
height: 350px;
overflow: hidden;
position: relative;
}
.webrx-top-bar-parts
{
.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;
}
#webrx-top-bar
{
background: rgba(128, 128, 128, 0.15);
margin:0;
padding:0;
@ -37,34 +41,32 @@
-moz-user-select: none;
-ms-user-select: none;
overflow: hidden;
position: absolute;
left: 0;
top: 0;
right: 0;
display: flex;
flex-direction: row;
}
#webrx-tob-container, #webrx-top-container * {
.webrx-top-bar > * {
flex: 0;
}
.webrx-top-container, .webrx-top-container * {
line-height: initial;
box-sizing: initial;
}
#webrx-top-container img {
vertical-align: initial;
}
#webrx-top-logo
{
.webrx-top-logo {
width: 261px;
padding: 12px;
float: left;
filter: drop-shadow(0 0 2.5px rgba(0, 0, 0, .9));
/* overwritten by media queries */
display: none;
}
#webrx-rx-avatar
{
.webrx-rx-avatar {
background-color: rgba(154, 154, 154, .5);
float: left;
margin: 7px;
cursor:pointer;
width: 46px;
height: 46px;
padding: 4px;
@ -72,88 +74,69 @@
box-sizing: content-box;
}
#webrx-rx-texts {
float: left;
padding: 10px;
.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 div, .webrx-rx-texts h1 {
margin: 0 10px;
padding: 3px;
}
#webrx-rx-title
{
white-space:nowrap;
overflow: hidden;
cursor:pointer;
font-family: "DejaVu Sans", Verdana, Geneva, sans-serif;
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
{
white-space:nowrap;
overflow: hidden;
cursor:pointer;
.webrx-rx-desc {
font-size: 10pt;
color: #909090;
}
#webrx-rx-desc a
{
color: #909090;
}
#openwebrx-rx-details-arrow
{
cursor:pointer;
position: absolute;
left: 470px;
top: 55px;
}
#openwebrx-rx-details-arrow a
{
margin: 0;
padding: 0;
line-height: 0;
display: block;
}
#openwebrx-main-buttons .button {
.openwebrx-main-buttons .button {
display: block;
width: 55px;
cursor:pointer;
}
#openwebrx-main-buttons .button img {
height: 38px;
.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 a {
.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
{
.openwebrx-main-buttons .button:hover {
background-color: rgba(255, 255, 255, 0.3);
}
#openwebrx-main-buttons .button:active
{
.openwebrx-main-buttons .button:active {
background-color: rgba(255, 255, 255, 0.55);
}
#openwebrx-main-buttons
{
.openwebrx-main-buttons {
padding: 5px 15px;
display: flex;
list-style: none;
float: right;
margin:0;
color: white;
text-shadow: 0px 0px 4px #000000;
@ -162,23 +145,17 @@
font-weight: bold;
}
#webrx-rx-photo-title
{
position: absolute;
left: 15px;
top: 78px;
color: White;
.webrx-rx-photo-title {
margin: 10px 15px;
color: white;
font-size: 16pt;
text-shadow: 1px 1px 4px #444;
opacity: 1;
}
#webrx-rx-photo-desc
{
position: absolute;
left: 15px;
top: 109px;
color: White;
.webrx-rx-photo-desc {
margin: 10px 15px;
color: white;
font-size: 10pt;
font-weight: bold;
text-shadow: 0px 0px 6px #444;
@ -186,50 +163,65 @@
line-height: 1.5em;
}
#webrx-rx-photo-desc a
{
.webrx-rx-photo-desc a {
color: #5ca8ff;
text-shadow: none;
}
.sprite-panel-status {
background-position: 0 0;
width: 44px;
height: 38px;
.openwebrx-photo-trigger {
cursor: pointer;
}
.sprite-panel-log {
background-position: -44px 0;
width: 38px;
height: 38px;
/*
* Responsive stuff
*/
@media (min-width: 576px) {
.webrx-rx-texts {
display: initial;
}
}
.sprite-panel-receiver {
background-position: -82px 0;
width: 40px;
height: 38px;
@media (min-width: 768px) {
}
.sprite-panel-map {
background-position: -122px 0;
width: 38px;
height: 38px;
@media (min-width: 992px) {
.webrx-top-logo {
display: initial;
}
}
.sprite-panel-settings {
background-position: -160px 0;
width: 38px;
height: 38px;
@media (min-width: 1200px) {
}
.sprite-rx-details-arrow-down {
background-position: 0 -65px;
width: 43px;
/*
* 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;
}
.sprite-rx-details-arrow-up {
background-position: -43px -65px;
width: 43px;
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;
}

View File

@ -3,7 +3,7 @@
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>
Copyright (c) 2019-2020 by Jakob Ketterl <dd5jfk@darc.de>
Copyright (c) 2019-2021 by Jakob Ketterl <dd5jfk@darc.de>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as
@ -36,15 +36,14 @@ input
vertical-align:middle;
}
input[type=range]
{
input[type=range] {
-webkit-appearance: none;
margin: 0 0;
background: transparent;
background: transparent !important;
--track-background: #B6B6B6;
}
input[type=range]:focus
{
input[type=range]:focus {
outline: none;
}
@ -297,11 +296,13 @@ input[type=range]:disabled {
#webrx-canvas-container canvas
{
position: absolute;
top: 0;
border-style: none;
image-rendering: crisp-edges;
image-rendering: -webkit-optimize-contrast;
width: 100%;
height: 200px;
will-change: transform;
}
#openwebrx-log-scroll
@ -336,12 +337,58 @@ input[type=range]:disabled {
margin: 0;
display: flex;
flex-direction: row;
cursor: pointer;
}
.webrx-actual-freq > * {
flex: 1;
}
.webrx-actual-freq .input-group {
display: flex;
flex-direction: row;
}
.webrx-actual-freq .input-group > * {
flex: 0 0 auto;
}
.webrx-actual-freq .input-group input {
flex: 1 0 auto;
margin-right: 0;
border-right: 1px solid #373737;
-moz-appearance: textfield;
}
.webrx-actual-freq .input-group input::-webkit-outer-spin-button,
.webrx-actual-freq .input-group input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
.input-group > :not(:last-child) {
border-top-right-radius: 0;
border-bottom-right-radius: 0;
}
.input-group > :not(:first-child) {
border-top-left-radius: 0;
border-bottom-left-radius: 0;
}
.input-group :first-child {
padding-left: 5px;
}
.input-group :last-child {
padding-right: 5px
}
.webrx-actual-freq .input-group input, .webrx-actual-freq .input-group select {
outline: none;
font-size: 16pt;
}
.webrx-actual-freq input {
font-family: 'roboto-mono';
width: 0;
@ -355,7 +402,17 @@ input[type=range]:disabled {
.webrx-actual-freq, .webrx-actual-freq input {
font-size: 16pt;
font-family: 'roboto-mono';
line-height: 22px;
}
.webrx-actual-freq .digit {
cursor: ns-resize;
}
.webrx-actual-freq .digit:hover {
color: #FFFF50;
border-radius: 5px;
background: -webkit-gradient( linear, left top, left bottom, color-stop(0.0 , #373737), color-stop(1, #4F4F4F) );
background: -moz-linear-gradient( center top, #373737 0%, #4F4F4F 100% );
}
.webrx-mouse-freq {
@ -544,21 +601,35 @@ img.openwebrx-mirror-img
-khtml-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
overflow: hidden;
z-index: 1
}
.openwebrx-progressbar-bar
{
.openwebrx-progressbar-bar {
background-color: #00aba6;
border-radius: 5px;
height: 100%;
width: 100%;
transition-property: transform, background-color;
transition-duration: 1s;
transition-timing-function: ease-in-out;
transform: translate(-100%) translateZ(0);
will-change: transform, background-color;
z-index: 0;
}
.openwebrx-progressbar--over .openwebrx-progressbar-bar {
background-color: #ff6262;
}
.openwebrx-progressbar-text
{
position: absolute;
left:0px;
top:4px;
width: inherit;
left:50%;
top:50%;
transform: translate(-50%, -50%);
white-space: nowrap;
z-index: 2;
}
#openwebrx-panel-status
@ -583,6 +654,7 @@ img.openwebrx-mirror-img
#openwebrx-panel-receiver .frequencies-container {
display: flex;
flex-direction: row;
gap: 5px;
}
#openwebrx-panel-receiver .frequencies {
@ -595,16 +667,6 @@ img.openwebrx-mirror-img
text-align: center;
}
#openwebrx-mute-on
{
color: lime;
}
#openwebrx-mute-off
{
color: white;
}
.openwebrx-panel-slider
{
position: relative;
@ -612,13 +674,6 @@ img.openwebrx-mirror-img
width: 95px;
}
.openwebrx-sliderbtn-img
{
width: 14px;
position:relative;
top: 1px;
}
.openwebrx-panel-line
{
padding-top: 5px;
@ -658,8 +713,7 @@ img.openwebrx-mirror-img
}
}
#openwebrx-smeter-outer
{
#openwebrx-smeter {
border-color: #888;
border-style: solid;
border-width: 0px;
@ -667,16 +721,20 @@ img.openwebrx-mirror-img
height: 7px;
background-color: #373737;
border-radius: 3px;
position: relative;
overflow: hidden;
}
#openwebrx-smeter-bar
{
transition: all 0.2s linear;
width: 0px;
height: 7px;
.openwebrx-smeter-bar {
transition-property: transform;
transition-duration: 0.2s;
transition-timing-function: linear;
will-change: transform;
transform: translate(-100%) translateZ(0);
width: 100%;
height: 100%;
background: linear-gradient(to top, #ff5939 , #961700);
position: absolute;
margin: 0; padding: 0; left: 0;
margin: 0;
padding: 0;
border-radius: 3px;
}
@ -692,19 +750,19 @@ img.openwebrx-mirror-img
}
.openwebrx-overlay {
position: fixed;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
opacity: 0.8;
background-color: #777;
left: 0;
top: 0;
z-index: 1001;
color: white;
font-weight: bold;
font-size: 20pt;
position: absolute;
width: 100%;
height: 100%;
margin: 0;
padding: 0;
opacity: 0.8;
background-color: #777;
left: 0;
top: 0;
z-index: 1001;
color: white;
font-weight: bold;
font-size: 20pt;
}
#openwebrx-autoplay-overlay
@ -713,8 +771,7 @@ img.openwebrx-mirror-img
transition: opacity 0.3s linear;
}
#openwebrx-autoplay-overlay img
{
#openwebrx-autoplay-overlay svg {
width: 150px;
}
@ -746,11 +803,14 @@ img.openwebrx-mirror-img
#openwebrx-digimode-canvas-container canvas
{
position: absolute;
top: 0;
pointer-events: none;
transition: width 500ms, left 500ms;
will-change: transform;
}
.openwebrx-panel select,
.openwebrx-panel input,
.openwebrx-dialog select,
.openwebrx-dialog input {
border-radius: 5px;
@ -759,11 +819,26 @@ img.openwebrx-mirror-img
font-weight: normal;
font-size: 13pt;
margin-right: 1px;
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.0 , #373737), color-stop(1, #4F4F4F) );
background:-moz-linear-gradient( center top, #373737 0%, #4F4F4F 100% );
background:linear-gradient(#373737, #4F4F4F);
border-color: transparent;
border-width: 0px;
-moz-appearance: none;
}
@supports(-moz-appearance: none) {
.openwebrx-panel select,
.openwebrx-dialog select {
-moz-appearance: none;
background-image: url('data:image/svg+xml;charset=US-ASCII,%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20width%3D%22292.4%22%20height%3D%22292.4%22%20%20xmlns%3Av%3D%22https%3A%2F%2Fvecta.io%2Fnano%22%3E%3Cpath%20d%3D%22M287%2069.4a17.6%2017.6%200%200%200-13-5.4H18.4c-5%200-9.3%201.8-12.9%205.4A17.6%2017.6%200%200%200%200%2082.2c0%205%201.8%209.3%205.4%2012.9l128%20127.9c3.6%203.6%207.8%205.4%2012.8%205.4s9.2-1.8%2012.8-5.4L287%2095c3.5-3.5%205.4-7.8%205.4-12.8s-1.9-9.2-5.5-12.8z%22%20fill%3D%22%23fff%22%2F%3E%3C%2Fsvg%3E'),
linear-gradient(#373737, #4F4F4F);
background-repeat: no-repeat, repeat;
background-position: right .3em top 50%, 0 0;
background-size: .65em auto, 100%;
}
.openwebrx-panel .input-group select,
.openwebrx-dialog .input-group select {
padding-right: 1em;
}
}
.openwebrx-panel select option,
@ -842,33 +917,6 @@ img.openwebrx-mirror-img
z-index: 10;
}
#openwebrx-digimode-content .part
{
perspective: 700px;
}
#openwebrx-digimode-content .part
{
animation: new-digimode-data-3d 100ms;
animation-timing-function: linear;
display: inline-block;
perspective-origin: 50% 50%;
transform-origin: 0% 50%;
}
@keyframes new-digimode-data
{
0%{ opacity: 0; }
100%{ opacity: 1; }
}
@keyframes new-digimode-data-3d
{
0%{ transform: rotateX(0deg) rotateY(-90deg) translateX(-5px) scale(1.3); }
100%{ transform: rotateX(0deg) rotateY(0deg) translateX(0) scale(1); }
}
#openwebrx-digimode-select-channel
{
transition: all 500ms;
@ -886,34 +934,44 @@ img.openwebrx-mirror-img
border-color: Red;
}
.openwebrx-meta-panel {
display: flex;
flex-direction: row;
gap: 10px;
/* compatibility with iOS 14.2 */
flex: 0 0 auto;
}
.openwebrx-meta-slot {
flex: 1;
width: 145px;
height: 196px;
float: left;
margin-right: 10px;
background-color: #676767;
padding: 2px 0;
color: #333;
text-align: center;
display: flex;
flex-direction: column;
position: relative;
overflow: hidden;
}
.openwebrx-meta-slot, .openwebrx-meta-slot.muted:before {
.openwebrx-meta-slot > * {
flex: 1 0 0;
line-height: 1.2em;
}
.openwebrx-meta-slot, .openwebrx-meta-slot .mute {
-webkit-border-radius: 5px;
-moz-border-radius: 5px;
border-radius: 5px;
}
.openwebrx-meta-slot.muted:before {
display: block;
content: "";
background-image: url("../gfx/openwebrx-mute.png");
width:100%;
height:133px;
background-position: center;
background-repeat: no-repeat;
.openwebrx-meta-slot .mute {
display: none;
cursor: pointer;
position: absolute;
@ -924,6 +982,17 @@ img.openwebrx-mirror-img
background-color: rgba(0,0,0,.3);
}
.openwebrx-meta-slot .mute svg {
position: absolute;
top: 50%;
left: 0;
transform: translate(0, -50%);
}
.openwebrx-meta-slot.muted .mute {
display: block;
}
.openwebrx-meta-slot.active {
background-color: #95bbdf;
}
@ -939,41 +1008,95 @@ img.openwebrx-mirror-img
box-shadow: rgba(0, 0, 0, 0.2) 0 -1px 7px 1px, inset #304701 0 -1px 9px, #89FF00 0 2px 12px;
}
.openwebrx-meta-slot:last-child {
margin-right: 0;
}
.openwebrx-meta-slot .openwebrx-meta-user-image {
width:100%;
height:133px;
flex: 0 1 100%;
background-position: center;
background-repeat: no-repeat;
line-height: 0;
overflow: hidden;
}
.openwebrx-meta-slot.active .openwebrx-meta-user-image {
background-image: url("../gfx/openwebrx-directcall.png");
.openwebrx-meta-slot .openwebrx-meta-user-image img {
max-width: 100%;
max-height: 100%;
display: none;
}
.openwebrx-meta-slot.active .openwebrx-meta-user-image.group {
background-image: url("../gfx/openwebrx-groupcall.png");
.openwebrx-meta-slot.active.direct .openwebrx-meta-user-image .directcall,
.openwebrx-meta-slot.active.individual .openwebrx-meta-user-image .directcall,
#openwebrx-panel-metadata-ysf .openwebrx-meta-slot.active .openwebrx-meta-user-image .directcall,
#openwebrx-panel-metadata-dstar .openwebrx-meta-slot.active .openwebrx-meta-user-image .directcall,
#openwebrx-panel-metadata-m17 .openwebrx-meta-slot.active .openwebrx-meta-user-image .directcall {
display: initial;
}
.openwebrx-meta-slot.active.group .openwebrx-meta-user-image .groupcall,
.openwebrx-meta-slot.active.conference .openwebrx-meta-user-image .groupcall {
display: initial;
}
.openwebrx-meta-slot.group .openwebrx-dmr-target:not(:empty):before {
content: "Talkgroup: ";
}
.openwebrx-meta-slot.direct .openwebrx-dmr-target:not(:empty):before {
content: "Direct: ";
}
.openwebrx-dmr-timeslot-panel * {
cursor: pointer;
user-select: none;
}
.openwebrx-maps-pin {
background-image: url("../gfx/google_maps_pin.svg");
background-position: center;
background-repeat: no-repeat;
.openwebrx-ysf-mode:not(:empty):before {
content: "Mode: ";
}
.openwebrx-ysf-up:not(:empty):before {
content: "Up: ";
}
.openwebrx-ysf-down:not(:empty):before {
content: "Down: ";
}
.openwebrx-m17-source:not(:empty):before {
content: "SRC: ";
}
.openwebrx-m17-destination:not(:empty):before {
content: "DEST: ";
}
.openwebrx-dstar-yourcall:not(:empty):before {
content: "UR: ";
}
.openwebrx-dstar-departure:not(:empty):before {
content: "RPT1: ";
}
.openwebrx-dstar-destination:not(:empty):before {
content: "RPT2: ";
}
.openwebrx-meta-slot.individual .openwebrx-nxdn-destination:not(:empty):before {
content: "Direct: ";
}
.openwebrx-meta-slot.conference .openwebrx-nxdn-destination:not(:empty):before {
content: "Conference: ";
}
.openwebrx-maps-pin svg {
width: 15px;
height: 15px;
background-size: contain;
display: inline-block;
vertical-align: middle;
}
.openwebrx-message-panel {
height: 180px;
position: relative;
}
.openwebrx-message-panel tbody {
@ -1139,6 +1262,10 @@ img.openwebrx-mirror-img
#openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="fst4"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-content-container,
#openwebrx-panel-digimodes[data-mode="ft8"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="wspr"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="jt65"] #openwebrx-digimode-select-channel,
@ -1146,7 +1273,11 @@ img.openwebrx-mirror-img
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-select-channel
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="fst4"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-select-channel,
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-select-channel
{
display: none;
}
@ -1158,81 +1289,61 @@ img.openwebrx-mirror-img
#openwebrx-panel-digimodes[data-mode="ft4"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="packet"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="pocsag"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-canvas-container
#openwebrx-panel-digimodes[data-mode="js8"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="fst4"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-canvas-container,
#openwebrx-panel-digimodes[data-mode="msk144"] #openwebrx-digimode-canvas-container
{
height: 200px;
margin: -10px;
}
.sprite-zoom-in {
background-position: 0 -38px;
width: 27px;
.openwebrx-zoom-button svg {
height: 27px;
}
.sprite-zoom-out {
background-position: -27px -38px;
width: 27px;
height: 27px;
}
.sprite-zoom-in-total {
background-position: -54px -38px;
width: 24px;
height: 27px;
}
.sprite-zoom-out-total {
background-position: -78px -38px;
width: 25px;
height: 27px;
}
.sprite-edit {
background-position: -131px -51px;
width: 14px;
.openwebrx-slider-button svg {
position:relative;
top: 1px;
height: 14px;
}
.sprite-trashcan {
background-position: -145px -38px;
width: 14px;
.openwebrx-mute-button svg.muted {
display: none;
}
.openwebrx-mute-button.muted svg.muted {
display: initial;
}
.openwebrx-mute-button.muted svg.unmuted {
display: none;
}
.bookmark .bookmark-actions .openwebrx-button svg {
height: 14px;
}
.sprite-speaker {
width: 14px;
height: 15px;
#openwebrx-waterfall-colors-auto .continuous {
display: none;
}
#openwebrx-mute-on .sprite-speaker {
background-position: -117px -38px;
#openwebrx-waterfall-colors-auto.highlighted .continuous {
display: initial;
}
#openwebrx-mute-off .sprite-speaker {
background-position: -103px -38px;
#openwebrx-waterfall-colors-auto.highlighted .auto {
display: none;
}
.sprite-squelch {
background-position: -131px -38px;
width: 14px;
height: 13px;
.openwebrx-waterfall-container {
flex-grow: 1;
display: flex;
flex-direction: column;
position: relative;
}
.sprite-waterfall-auto {
background-position: -103px -53px;
width: 14px;
height: 11px;
}
.sprite-waterfall-default {
background-position: -117px -53px;
width: 14px;
height: 12px;
}
.sprite-bookmark {
background-position: -159px -38px;
width: 21px;
height: 27px;
.openwebrx-waterfall-container > * {
flex: 0 0 auto;
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 318 B

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -3,7 +3,6 @@
<link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico" />
<link rel="stylesheet" href="static/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="static/css/admin.css" />
<link rel="stylesheet" href="static/css/features.css">
<script src="https://cdnjs.cloudflare.com/ajax/libs/showdown/1.9.0/showdown.min.js"></script>
<script src="static/lib/jquery-3.2.1.min.js"></script>
<script src="static/lib/Header.js"></script>
@ -11,6 +10,7 @@
</HEAD><BODY>
${header}
<div class="container">
${breadcrumb}
<h1>OpenWebRX Feature Report</h1>
<table class="features table">
<tr>
@ -20,5 +20,6 @@
<th>Available</th>
</tr>
</table>
${breadcrumb}
</div>
</BODY></HTML>

View File

@ -13,8 +13,7 @@ $(function(){
});
$table.append(
'<tr>' +
'<td colspan=2>' + name + '</td>' +
'<td>' + converter.makeHtml(details.description) + '</td>' +
'<td colspan=3>' + name + '</td>' +
'<td>' + (details.available ? 'YES' : 'NO') + '</td>' +
'</tr>' +
requirements.join("")

View File

@ -1,20 +0,0 @@
<!DOCTYPE HTML>
<html>
<head>
<title>OpenWebRX Settings</title>
<link rel="shortcut icon" type="image/x-icon" href="static/favicon.ico" />
<link rel="stylesheet" href="static/css/bootstrap.min.css" />
<link rel="stylesheet" type="text/css" href="static/css/admin.css" />
<script src="https://unpkg.com/location-picker/dist/location-picker.min.js"></script>
<script src="compiled/settings.js"></script>
<meta charset="utf-8">
</head>
<body>
${header}
<div class="container">
<div class="col-12">
<h1>General settings</h1>
</div>
${sections}
</div>
</body>

BIN
htdocs/gfx/favicon128.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

BIN
htdocs/gfx/favicon32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

BIN
htdocs/gfx/favicon44.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

BIN
htdocs/gfx/favicon64.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.4 KiB

BIN
htdocs/gfx/favicon96.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 90 KiB

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 970 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.3 KiB

View File

@ -0,0 +1 @@
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg"><defs><filter id="a" x="-.25" y="-.25" width="1.5" height="1.5" color-interpolation-filters="sRGB"><feFlood flood-color="#000" flood-opacity=".4" result="flood"/><feComposite in="flood" in2="SourceGraphic" operator="in" result="composite1"/><feGaussianBlur in="composite1" result="blur" stdDeviation="66.6"/><feOffset result="offset"/><feComposite in="SourceGraphic" in2="offset" result="composite2"/></filter></defs><path d="M550.98 541.91c-.99-28.904-4.377-57.939-9.421-86.393-6.111-34.469-13.889-85.002-43.983-107.46-17.404-12.988-39.941-17.249-59.865-25.081-9.697-3.81-18.384-7.594-26.537-11.901-27.518 30.176-63.4 45.962-105.19 45.964-41.774 0-77.652-15.786-105.17-45.964-8.153 4.308-16.84 8.093-26.537 11.901-19.924 7.832-42.461 12.092-59.863 25.081-30.096 22.463-37.873 72.996-43.983 107.46-5.045 28.454-8.433 57.489-9.422 86.393-.766 22.387 10.288 25.525 29.017 32.284 23.453 8.458 47.666 14.737 72.041 19.884 47.077 9.941 95.603 17.582 143.92 17.924 48.318-.343 96.844-7.983 143.92-17.924 24.375-5.145 48.59-11.424 72.041-19.884 18.736-6.757 29.789-9.895 29.023-32.284zM306 325.99c90.56-.01 123.15-90.68 131.68-165.17C448.19 69.06 404.8 0 306 0c-98.78 0-142.19 69.055-131.68 160.82C182.86 235.304 215.434 326 306 325.99z" filter="url(#a)" transform="matrix(.42446 0 0 .42484 70.12 69)" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.1 KiB

View File

@ -0,0 +1 @@
<svg width="400" height="400" xmlns="http://www.w3.org/2000/svg"><defs><filter id="a" x="-.25" y="-.25" width="1.5" height="1.5" color-interpolation-filters="sRGB"><feFlood flood-color="#000" flood-opacity=".4" result="flood"/><feComposite in="flood" in2="SourceGraphic" operator="in" result="composite1"/><feGaussianBlur in="composite1" result="blur" stdDeviation="66.6"/><feOffset result="offset"/><feComposite in="SourceGraphic" in2="offset" result="composite2"/></filter></defs><g fill="#fff"><g transform="matrix(.42446 0 0 .42484 129.12 42)" filter="url(#a)"><path d="M27.982.002c-98.778 0-142.188 69.056-131.678 160.823 8.54 74.484 41.112 165.183 131.678 165.173 90.558-.01 123.148-90.682 131.678-165.173C170.17 69.063 126.781.002 27.982.002zm277.996 0C207.2.002 163.79 69.058 174.3 160.825c8.54 74.484 41.113 165.183 131.678 165.173 90.559-.01 123.148-90.682 131.678-165.173C448.166 69.063 404.777.002 305.978.002zM-77.209 311.093c-8.153 4.308-16.84 8.09-26.537 11.898-19.924 7.833-42.463 12.095-59.863 25.084-30.095 22.463-37.871 72.996-43.98 107.46-5.045 28.454-8.435 57.492-9.424 86.395-.766 22.388 10.288 25.523 29.015 32.284 23.453 8.458 47.665 14.737 72.04 19.884 47.075 9.941 95.6 17.583 143.916 17.925 46.64-.33 93.461-7.487 138.998-16.923 45.538 9.437 92.359 16.593 138.999 16.923 48.317-.343 96.841-7.984 143.917-17.925 24.374-5.145 48.593-11.424 72.043-19.884 18.736-6.757 29.786-9.894 29.02-32.284h.01c-.99-28.903-4.38-57.941-9.424-86.395-6.111-34.47-13.886-85.002-43.98-107.46-17.404-12.989-39.94-17.252-59.863-25.084-9.697-3.81-18.384-7.59-26.537-11.898-27.517 30.177-63.398 45.962-105.186 45.965-41.773 0-77.65-15.787-105.17-45.965-8.153 4.308-16.84 8.09-26.537 11.898-2.394.941-4.828 1.826-7.284 2.685-2.456-.859-4.89-1.744-7.284-2.685-9.697-3.81-18.383-7.59-26.537-11.898-27.517 30.177-63.397 45.962-105.186 45.965-41.773 0-77.65-15.787-105.17-45.965z"/></g><g transform="matrix(.42446 0 0 .42484 70.12 102)" filter="url(#a)"><path d="M550.98 541.91c-.99-28.904-4.377-57.939-9.421-86.393-6.111-34.469-13.889-85.002-43.983-107.46-17.404-12.988-39.941-17.249-59.865-25.081-9.697-3.81-18.384-7.594-26.537-11.901-27.518 30.176-63.4 45.962-105.19 45.964-41.774 0-77.652-15.786-105.17-45.964-8.153 4.308-16.84 8.093-26.537 11.901-19.924 7.832-42.461 12.092-59.863 25.081-30.096 22.463-37.873 72.996-43.983 107.46-5.045 28.454-8.433 57.489-9.422 86.393-.766 22.387 10.288 25.525 29.017 32.284 23.453 8.458 47.666 14.737 72.041 19.884 47.077 9.941 95.603 17.582 143.92 17.924 48.318-.343 96.844-7.983 143.92-17.924 24.375-5.145 48.59-11.424 72.041-19.884 18.736-6.757 29.789-9.895 29.023-32.284zM306 325.99c90.56-.01 123.15-90.68 131.68-165.17C448.19 69.06 404.8 0 306 0c-98.78 0-142.19 69.055-131.68 160.82C182.86 235.304 215.434 326 306 325.99z"/></g></g></svg>

After

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 518 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 505 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 64 KiB

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 699 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 797 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

Some files were not shown because too many files have changed in this diff Show More