Compare commits

...

1040 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 477b457be9 update the version 2021-01-26 16:53:22 +01:00
Jakob Ketterl 58b35ec0f9 update changelogs for 0.20.3 2021-01-26 16:28:56 +01:00
Jakob Ketterl 9b2947827a Merge branch 'release-0.20' into develop 2021-01-25 19:40:28 +01:00
Jakob Ketterl ae0748952f remove unused import, too 2021-01-25 19:40:06 +01:00
Jakob Ketterl bee0f67efd Merge branch 'release-0.20' into develop 2021-01-25 19:37:57 +01:00
Jakob Ketterl f81cf3570a don't check the type since older python doesn't have re.Pattern 2021-01-25 19:36:55 +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
310 changed files with 20701 additions and 7087 deletions

View File

@ -1,3 +1,51 @@
**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
**0.20.2**
- Fix a security problem that allowed arbitrary commands to be executed on the receiver
([See github issue #215](https://github.com/jketterl/openwebrx/issues/215))

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

74
debian/changelog vendored
View File

@ -1,3 +1,77 @@
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
-- Jakob Ketterl <jakob.ketterl@gmx.de> Tue, 26 Jan 2021 15:28:00 +0000
openwebrx (0.20.2) buster focal; urgency=high
* Fix a security problem that allowed arbitrary commands to be executed on

6
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
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,155 +1,341 @@
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 @@
endif(WSJT_BUILD_UTILS)
-# build the main application
-add_executable (wsjtx MACOSX_BUNDLE
- ${wsjtx_CXXSRCS}
- ${wsjtx_GENUISRCS}
- wsjtx.rc
- ${WSJTX_ICON_FILE}
- ${wsjtx_RESOURCES_RCC}
- )
-
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_ICON_FILE "${WSJTX_ICON_FILE}"
- MACOSX_BUNDLE_BUNDLE_VERSION ${wsjtx_VERSION}
- MACOSX_BUNDLE_SHORT_VERSION_STRING "v${wsjtx_VERSION}"
- MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${wsjtx_VERSION}"
- MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}"
- MACOSX_BUNDLE_BUNDLE_EXECUTABLE_NAME "${PROJECT_NAME}"
- MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT}"
- MACOSX_BUNDLE_GUI_IDENTIFIER "org.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})
-else ()
- target_link_libraries (wsjtx Qt5::SerialPort wsjt_fort_omp wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES})
- if (OpenMP_C_FLAGS)
- set_target_properties (wsjtx PROPERTIES
- COMPILE_FLAGS "${OpenMP_C_FLAGS}"
- LINK_FLAGS "${OpenMP_C_FLAGS}"
- )
- endif ()
- set_target_properties (wsjtx PROPERTIES
- Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp
- )
- if (WIN32)
- set_target_properties (wsjtx PROPERTIES
- LINK_FLAGS -Wl,--stack,16777216
- )
- endif ()
-endif ()
-
# 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)
-if (UNIX)
- if (NOT WSJT_SKIP_MANPAGES)
- add_subdirectory (manpages)
- add_dependencies (wsjtx manpages)
- endif (NOT WSJT_SKIP_MANPAGES)
- if (NOT APPLE)
- add_subdirectory (debian)
- add_dependencies (wsjtx debian)
- endif (NOT APPLE)
-endif (UNIX)
-
#
# installation
#
-install (TARGETS wsjtx
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
- BUNDLE DESTINATION . COMPONENT runtime
- )
# install (TARGETS wsjtx_udp EXPORT udp
# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -1473,12 +1415,7 @@
# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wsjtx
# )
-install (TARGETS udp_daemon message_aggregator
- 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
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
)
@@ -1491,39 +1428,6 @@
)
endif(WSJT_BUILD_UTILS)
-install (PROGRAMS
- ${RIGCTL_EXE}
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- #COMPONENT runtime
- RENAME rigctl-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
- )
-
-install (PROGRAMS
- ${RIGCTLD_EXE}
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- #COMPONENT runtime
- RENAME rigctld-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
- )
-
-install (PROGRAMS
- ${RIGCTLCOM_EXE}
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- #COMPONENT runtime
- RENAME rigctlcom-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
- )
-
-install (FILES
- README
- COPYING
- AUTHORS
- THANKS
- NEWS
- INSTALL
- BUGS
- DESTINATION ${CMAKE_INSTALL_DOCDIR}
- #COMPONENT runtime
- )
-
install (FILES
contrib/Ephemeris/JPLEPH
DESTINATION ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME}
Only in wsjtx: .idea
--- 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 @@
)
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_ICON_FILE}
- ${wsjtx_RESOURCES_RCC}
- ${wsjtx_VERSION_RESOURCES}
- )
-
-if (WSJT_CREATE_WINMAIN)
- set_target_properties (wsjtx PROPERTIES WIN32_EXECUTABLE ON)
-endif (WSJT_CREATE_WINMAIN)
-
-set_target_properties (wsjtx PROPERTIES
- MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Darwin/Info.plist.in"
- MACOSX_BUNDLE_INFO_STRING "${PROJECT_DESCRIPTION}"
- MACOSX_BUNDLE_ICON_FILE "${WSJTX_ICON_FILE}"
- MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}
- MACOSX_BUNDLE_SHORT_VERSION_STRING "v${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}"
- MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${SCS_VERSION_STR}"
- MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_BUNDLE_NAME}"
- MACOSX_BUNDLE_BUNDLE_EXECUTABLE_NAME "${PROJECT_NAME}"
- MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT}"
- MACOSX_BUNDLE_GUI_IDENTIFIER "org.k1jt.wsjtx"
- )
-
-target_include_directories (wsjtx PRIVATE ${FFTW3_INCLUDE_DIRS})
-if ((NOT ${OPENMP_FOUND}) OR APPLE)
- target_link_libraries (wsjtx wsjt_fort)
-else ()
- target_link_libraries (wsjtx wsjt_fort_omp)
- if (OpenMP_C_FLAGS)
- set_target_properties (wsjtx PROPERTIES
- COMPILE_FLAGS "${OpenMP_C_FLAGS}"
- LINK_FLAGS "${OpenMP_C_FLAGS}"
- )
- endif ()
- set_target_properties (wsjtx PROPERTIES
- Fortran_MODULE_DIRECTORY ${CMAKE_BINARY_DIR}/fortran_modules_omp
- )
- if (WIN32)
- set_target_properties (wsjtx PROPERTIES
- LINK_FLAGS -Wl,--stack,0x1000000,--heap,0x20000000
- )
- endif ()
-endif ()
-target_link_libraries (wsjtx Qt5::SerialPort wsjt_cxx wsjt_qt wsjt_qtmm ${FFTW3_LIBRARIES} ${LIBM_LIBRARIES})
-
-# make a library for WSJT-X UDP servers
-# add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS})
-add_library (wsjtx_udp-static STATIC ${UDP_library_CXXSRCS})
-#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)
- add_dependencies (wsjtx manpages)
- endif (NOT WSJT_SKIP_MANPAGES)
- if (NOT APPLE)
- add_subdirectory (debian)
- add_dependencies (wsjtx debian)
- endif (NOT APPLE)
-endif (UNIX)
-
#
# installation
#
-install (TARGETS wsjtx
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
- BUNDLE DESTINATION . COMPONENT runtime
- )
# install (TARGETS wsjtx_udp EXPORT udp
# RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
@@ -1577,12 +1379,7 @@
# DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wsjtx
# )
-install (TARGETS udp_daemon message_aggregator wsjtx_app_version
- RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
- BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
- )
-
-install (TARGETS jt9 wsprd fmtave fcal fmeasure
+install (TARGETS wsjtx_app_version jt9 wsprd
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime
)
@@ -1595,38 +1392,6 @@
)
endif(WSJT_BUILD_UTILS)
-install (PROGRAMS
- ${RIGCTL_EXE}
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- #COMPONENT runtime
- RENAME rigctl-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
- )
-
-install (PROGRAMS
- ${RIGCTLD_EXE}
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- #COMPONENT runtime
- RENAME rigctld-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
- )
-
-install (PROGRAMS
- ${RIGCTLCOM_EXE}
- DESTINATION ${CMAKE_INSTALL_BINDIR}
- #COMPONENT runtime
- RENAME rigctlcom-wsjtx${CMAKE_EXECUTABLE_SUFFIX}
- )
-
-install (FILES
- README
- COPYING
- AUTHORS
- THANKS
- NEWS
- BUGS
- DESTINATION ${CMAKE_INSTALL_DOCDIR}
- #COMPONENT runtime
- )
-
install (FILES
cty.dat
cty.dat_copyright.txt
@@ -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