diff --git a/CHANGELOG.md b/CHANGELOG.md index e3fe16e6..83b7a22e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,14 +1,39 @@ -**unreleased** +**1.1.x - unreleased** +- 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 and FST4W (only available with WSJT-X 2.3) +- 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) + - HPSDR devices (Hermes Lite 2) thanks to @jancona - BBRF103 / RX666 / RX888 devices supported by libsddc - - Devices using the EB200 protocol + - R&S devices using the EB200 or Ammos protocols + +**0.20.3** +- Fix a compatibility issue with python versions <= 3.6 + +**0.20.2** +- Fix a security problem that allowed arbitrary commands to be executed on the receiver + ([See github issue #215](https://github.com/jketterl/openwebrx/issues/215)) **0.20.1** - Remove broken OSM map fallback diff --git a/README.md b/README.md index 9d6ccfa2..95171481 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,7 @@ It has the following features: - it works in Google Chrome, Chromium and Mozilla Firefox - 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) +- [digiham](https://github.com/jketterl/digiham) based demodularors (DMR, YSF, Pocsag, D-Star, NXDN) - [wsjt-x](https://physics.princeton.edu/pulsar/k1jt/wsjtx.html) based demodulators (FT8, FT4, WSPR, JT65, JT9, FST4, FST4W) - [direwolf](https://github.com/wb2osz/direwolf) based demodulation of APRS packets diff --git a/bands.json b/bands.json index ad7cc8c1..02bb7036 100644 --- a/bands.json +++ b/bands.json @@ -6,7 +6,8 @@ "frequencies": { "fst4": 136000, "fst4w": 136000 - } + }, + "tags": ["hamradio"] }, { "name": "630m", @@ -15,7 +16,8 @@ "frequencies": { "fst4": 474200, "fst4w": 474200 - } + }, + "tags": ["hamradio"] }, { "name": "160m", @@ -30,7 +32,8 @@ "js8": 1842000, "fst4": 1839000, "fst4w": 1836800 - } + }, + "tags": ["hamradio"] }, { "name": "80m", @@ -44,7 +47,8 @@ "jt9": 3572000, "ft4": [3568000, 3575000], "js8": 3578000 - } + }, + "tags": ["hamradio"] }, { "name": "60m", @@ -53,7 +57,8 @@ "frequencies": { "ft8": 5357000, "wspr": 5364700 - } + }, + "tags": ["hamradio"] }, { "name": "40m", @@ -67,7 +72,8 @@ "jt9": 7078000, "ft4": 7047500, "js8": 7078000 - } + }, + "tags": ["hamradio"] }, { "name": "30m", @@ -81,7 +87,8 @@ "jt9": 10140000, "ft4": 10140000, "js8": 10130000 - } + }, + "tags": ["hamradio"] }, { "name": "20m", @@ -95,7 +102,8 @@ "jt9": 14078000, "ft4": 14080000, "js8": 14078000 - } + }, + "tags": ["hamradio"] }, { "name": "17m", @@ -109,7 +117,8 @@ "jt9": 18104000, "ft4": 18104000, "js8": 18104000 - } + }, + "tags": ["hamradio"] }, { "name": "15m", @@ -123,7 +132,8 @@ "jt9": 21078000, "ft4": 21140000, "js8": 21078000 - } + }, + "tags": ["hamradio"] }, { "name": "12m", @@ -137,7 +147,8 @@ "jt9": 24919000, "ft4": 24919000, "js8": 24922000 - } + }, + "tags": ["hamradio"] }, { "name": "10m", @@ -151,7 +162,8 @@ "jt9": 28078000, "ft4": 28180000, "js8": 28078000 - } + }, + "tags": ["hamradio"] }, { "name": "6m", @@ -164,8 +176,10 @@ "jt65": 50310000, "jt9": 50312000, "ft4": 50318000, - "js8": 50318000 - } + "js8": 50318000, + "q65": [50211000, 50275000] + }, + "tags": ["hamradio"] }, { "name": "4m", @@ -173,7 +187,8 @@ "upper_bound": 70200000, "frequencies": { "wspr": 70091000 - } + }, + "tags": ["hamradio"] }, { "name": "2m", @@ -184,110 +199,169 @@ "ft8": 144174000, "ft4": 144170000, "jt65": 144120000, - "packet": 144800000 - } + "packet": 144800000, + "q65": 144116000 + }, + "tags": ["hamradio"] }, { "name": "70cm", "lower_bound": 430000000, "upper_bound": 440000000, "frequencies": { - "pocsag": 439987500 - } + "pocsag": 439987500, + "q65": 432065000 + }, + "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"] } ] \ No newline at end of file diff --git a/bookmarks.json b/bookmarks.json deleted file mode 100644 index dec818b2..00000000 --- a/bookmarks.json +++ /dev/null @@ -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" - } -] diff --git a/config_webrx.py b/config_webrx.py index b5f17026..4d61fbd4 100644 --- a/config_webrx.py +++ b/config_webrx.py @@ -32,32 +32,45 @@ config_webrx: configuration options for OpenWebRX and use them for running your web service with OpenWebRX.) """ +""" +DEPRECATION notice + +As of OpenWebRX 0.21, the configuration system has been completely overhauled. +The configuration of OpenWebRX should now be done in the new web-based +configuration interface exclusively. + +Existing configurations can still be used, but their values will be migrated +to the new storage infrastructure as soon as the web configuration is used to +edit them. + +The new configuration storage is not intended to be edited manually. +""" + # configuration version. please only modify if you're able to perform the associated migration steps. -version = 3 +version = 7 # 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 +#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" +#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.
-Receiver is operated by: Receiver Operator
-Device: Receiver Device
-Antenna: Receiver Antenna
-Website: http://localhost -""" +#photo_desc = """ +#You can add your own background photo and receiver information.
+#Receiver is operated by: Receiver Operator
+#Device: Receiver Device
+#Antenna: Receiver Antenna
+#Website: http://localhost +#""" # ==== Public receiver listings ==== # You can publish your receiver on online receiver directories, like https://www.receiverbook.de @@ -65,7 +78,7 @@ Website: http://localhost # 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 = [] +#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"] @@ -73,30 +86,29 @@ receiver_keys = [] # 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. -) +#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" +#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 +#wfm_deemphasis_tau = 50e-6 # for the rest of the world -digimodes_enable = True # Decoding digimodes come with higher CPU usage. -digimodes_fft_size = 2048 +#digimodes_fft_size = 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 +#digital_voice_unvoiced_quality = 1 # enables lookup of DMR ids using the radioid api -digital_voice_dmr_id_lookup = True +#digital_voice_dmr_id_lookup = True """ Note: if you experience audio underruns while CPU usage is 100%, you can: @@ -116,232 +128,230 @@ Note: if you experience audio underruns while CPU usage is 100%, you can: # Currently supported types of sdr receivers: # "rtl_sdr", "rtl_sdr_soapy", "sdrplay", "hackrf", "airspy", "airspyhf", "fifi_sdr", -# "perseussdr", "lime_sdr", "pluto_sdr", "soapy_remote", "hpsdr", "red_pitaya", "uhd", -# "radioberry", "fcdpp", "rtl_tcp", "sddc", "eb200" +# "perseussdr", "lime_sdr", "pluto_sdr", "soapy_remote", "hpsdr", "uhd", +# "radioberry", "fcdpp", "rtl_tcp", "sddc", "runds" # For more details on specific types, please checkout the wiki: # https://github.com/jketterl/openwebrx/wiki/Supported-Hardware#sdr-devices -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", - }, - }, - }, -} +#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] +#waterfall_scheme = "GoogleTurboWaterfall" ### original theme by teejez: -#waterfall_colors = [0x000000, 0x0000FF, 0x00FFFF, 0x00FF00, 0xFFFF00, 0xFF0000, 0xFF00FF, 0xFFFFFF] +#waterfall_scheme = "TeejeezWaterfall" ### 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} +#waterfall_scheme = "Ha7ilmWaterfall" ##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} +### custom waterfall schemes can be configured like this: +#waterfall_scheme = "CustomWaterfall" +#waterfall_colors = [0x0000FF, 0x00FF00, 0xFF0000] + +### Waterfall calibration +#waterfall_levels = {"min": -88, "max": -20} # in dB + +#waterfall_auto_levels = {"min": 3, "max": 10} +#waterfall_auto_min_range = 50 # Note: When the auto waterfall level button is clicked, the following happens: -# [waterfall_min_level] = [current_min_power_level] - [waterfall_auto_level_margin["min"]] -# [waterfall_max_level] = [current_max_power_level] + [waterfall_auto_level_margin["max"]] +# [waterfall_levels.min] = [current_min_power_level] - [waterfall_auto_levels["min"]] +# [waterfall_levels.max] = [current_max_power_level] + [waterfall_auto_levels["max"]] # -# ___|________________________________________|____________________________________|________________________________________|___> signal power -# \_waterfall_auto_level_margin["min"]_/ |__ current_min_power_level | \_waterfall_auto_level_margin["max"]_/ -# current_max_power_level __| +# ___|__________________________________|____________________________________|__________________________________|___> signal power +# \_waterfall_auto_levels["min"]_/ |__ current_min_power_level | \_waterfall_auto_levels["max"]_/ +# current_max_power_level __| # This setting allows you to modify the precision of the frequency displays in OpenWebRX. -# Set this to the number of digits you would like to see: -frequency_display_precision = 4 +# Set this to exponent of 10 to select the most precise digit in Hz you'd like to see +# examples: +# a value of 2 selects 10^2 = 100Hz tuning precision (default): +#tuning_precision = 2 +# a value of 1 selects 10^1 = 10Hz tuning precision: +#tuning_precision = 1 # This setting tells the auto-squelch the offset to add to the current signal level to use as the new squelch level. # Lowering this setting will give you a more sensitive squelch, but it may also cause unwanted squelch openings when # using the auto squelch. -squelch_auto_margin = 10 # in dB +#squelch_auto_margin = 10 # in dB -# === 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 = "" +#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 +#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 +#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 +#decoding_queue_length = 10 # wsjt decoding depth will allow more results, but will also consume more cpu -wsjt_decoding_depth = 3 +#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} +#wsjt_decoding_depths = {"jt65": 1} # FST4 can be transmitted in different intervals. This setting determines which intervals will be decoded. # available values (in seconds): 15, 30, 60, 120, 300, 900, 1800 -fst4_enabled_intervals = [15, 30] +#fst4_enabled_intervals = [15, 30] # FST4W can be transmitted in different intervals. This setting determines which intervals will be decoded. # available values (in seconds): 120, 300, 900, 1800 -fst4w_enabled_intervals = [120, 300] +#fst4w_enabled_intervals = [120, 300] + +# Q65 allows many combinations of intervals and submodes. This setting determines which combinations will be decoded. +# Please use the mode letter followed by the decode interval in seconds to specify the combinations. For example: +#q65_enabled_combinations = ["A30", "E120", "C60"] # JS8 comes in different speeds: normal, slow, fast, turbo. This setting controls which ones are enabled. -js8_enabled_profiles = ["normal", "slow"] +#js8_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" +#js8_decoding_depth = 3 # Enable background service for decoding digital data. You can find more information at: # https://github.com/jketterl/openwebrx/wiki/Background-decoding -services_enabled = False -services_decoders = ["ft8", "ft4", "wspr", "packet"] +#services_enabled = False +#services_decoders = ["ft8", "ft4", "wspr", "packet"] # === aprs igate settings === # If you want to share your APRS decodes with the aprs network, configure these settings accordingly. # Make sure that you have set services_enabled to true and customize services_decoders to your needs. -aprs_callsign = "N0CALL" -aprs_igate_enabled = False -aprs_igate_server = "euro.aprs2.net" -aprs_igate_password = "" +#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 = "/usr/share/aprs-symbols/png" +#aprs_igate_beacon = False # Uncomment the following to customize gateway beacon details reported to the aprs network # Plese see Dire Wolf's documentation on PBEACON configuration for complete details: @@ -367,18 +377,13 @@ aprs_symbols_path = "/usr/share/aprs-symbols/png" # === PSK Reporter settings === # enable this if you want to upload all ft8, ft4 etc spots to pskreporter.info # this also uses the receiver_gps setting from above, so make sure it contains a correct locator -pskreporter_enabled = False -pskreporter_callsign = "N0CALL" +#pskreporter_enabled = False +#pskreporter_callsign = "N0CALL" # optional antenna information, uncomment to enable #pskreporter_antenna_information = "Dipole" # === WSPRNet reporting settings # enable this if you want to upload WSPR spots to wsprnet.ort # in addition to these settings also make sure that receiver_gps contains your correct location -wsprnet_enabled = False -wsprnet_callsign = "N0CALL" - -# === 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 +#wsprnet_enabled = False +#wsprnet_callsign = "N0CALL" diff --git a/csdr/csdr.py b/csdr/__init__.py similarity index 83% rename from csdr/csdr.py rename to csdr/__init__.py index 25b4fc18..aeb67e32 100644 --- a/csdr/csdr.py +++ b/csdr/__init__.py @@ -28,10 +28,10 @@ import threading import math from functools import partial -from owrx.kiss import KissClient, DirewolfConfig -from owrx.wsjt import Ft8Profile, WsprProfile, Jt9Profile, Jt65Profile, Ft4Profile, Fst4Profile, Fst4wProfile -from owrx.js8 import Js8Profiles -from owrx.audio import AudioChopper +from csdr.output import Output + +from owrx.kiss import KissClient, DirewolfConfig, DirewolfConfigSubscriber +from owrx.audio.chopper import AudioChopper from csdr.pipe import Pipe @@ -40,40 +40,8 @@ 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): +class Dsp(DirewolfConfigSubscriber): + def __init__(self, output: Output): self.pycsdr_enabled = True self.pycsdr_chain = None self.buffer = None @@ -98,9 +66,6 @@ class dsp(object): 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 @@ -124,6 +89,7 @@ class dsp(object): self.secondary_pipe_names = {"secondary_shift_pipe": Pipe.WRITE} self.secondary_offset_freq = 1000 self.unvoiced_quality = 1 + self.codecserver = None self.modification_lock = threading.Lock() self.output = output @@ -133,7 +99,7 @@ class dsp(object): self.is_service = False self.direwolf_config = None - self.direwolf_port = None + self.direwolf_config_path = None self.process = None def setBuffer(self, buffer): @@ -150,10 +116,6 @@ class dsp(object): 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"] chain += ["csdr shift_addfast_cc --fifo {shift_pipe}"] if self.decimation > 1: chain += ["csdr fir_decimate_cc {decimation} {ddc_transition_bw} HAMMING"] @@ -199,43 +161,43 @@ class dsp(object): elif self.isDigitalVoice(which): chain += ["csdr fmdemod_quadri_cf"] chain += last_decimation_block - # dsd modes - if which in ["dstar", "nxdn"]: - chain += ["dc_block", "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 - ", - ] + chain += ["dc_block"] # m17 - elif which == "m17": + if which == "m17": chain += [ "csdr limit_ff", "csdr convert_f_s16", "m17-demod", - "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 += ["dc_block", "rrc_filter", "gfsk_demodulator"] - if which == "dmr": + # digiham modes + if which == "dstar": chain += [ - "dmr_decoder --fifo {meta_pipe} --control-fifo {dmr_control_pipe}", - "mbe_synthesizer -f -u {unvoiced_quality}", + "fsk_demodulator -s 10", + "dstar_decoder --fifo {meta_pipe}", + "mbe_synthesizer -d {codecserver_arg}", ] - 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 == "nxdn": + chain += [ + "rrc_filter --narrow", + "gfsk_demodulator --samples 20", + "nxdn_decoder --fifo {meta_pipe}", + "mbe_synthesizer {codecserver_arg}", + ] + else: + chain += ["rrc_filter", "gfsk_demodulator"] + if which == "dmr": + chain += [ + "dmr_decoder --fifo {meta_pipe} --control-fifo {dmr_control_pipe}", + "mbe_synthesizer {codecserver_arg}", + ] + elif which == "ysf": + chain += ["ysf_decoder --fifo {meta_pipe}", "mbe_synthesizer -y {codecserver_arg}"] + chain += ["digitalvoice_filter"] + chain += [ + "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 - ", + ] elif which == "am": chain += ["csdr amdemod_cf", "csdr fastdcblock_ff"] chain += last_decimation_block @@ -377,14 +339,10 @@ class dsp(object): if_samp_rate=self.if_samp_rate(), last_decimation=self.last_decimation, audio_rate=self.get_audio_rate(), - direwolf_config=self.direwolf_config, + direwolf_config=self.direwolf_config_path, ) 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( @@ -397,7 +355,7 @@ class dsp(object): 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 + secondary_command_fft, stdout=subprocess.PIPE, shell=True, start_new_session=True ) self.output.send_output( "secondary_fft", @@ -409,38 +367,18 @@ class dsp(object): # 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 + secondary_command_demod, stdout=secondary_output, shell=True, start_new_session=True ) self.secondary_processes_running = True - if self.isWsjtMode(): - smd = self.get_secondary_demodulator() - chopper_profiles = None - if smd == "ft8": - chopper_profiles = [Ft8Profile()] - elif smd == "wspr": - chopper_profiles = [WsprProfile()] - elif smd == "jt65": - chopper_profiles = [Jt65Profile()] - elif smd == "jt9": - chopper_profiles = [Jt9Profile()] - elif smd == "ft4": - chopper_profiles = [Ft4Profile()] - elif smd == "fst4": - chopper_profiles = Fst4Profile.getEnabledProfiles() - elif smd == "fst4w": - chopper_profiles = Fst4wProfile.getEnabledProfiles() - if chopper_profiles is not None and len(chopper_profiles): - chopper = AudioChopper(self, self.secondary_process_demod.stdout, *chopper_profiles) - 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) + if self.isWsjtMode() or self.isJs8(): + chopper = AudioChopper(self, self.get_secondary_demodulator()) + chopper.send_output("audio", self.secondary_process_demod.stdout.read) + output_type = "js8_demod" if self.isJs8() else "wsjt_demod" + self.output.send_output(output_type, chopper.read) elif self.isPacket(): # we best get the ax25 packets from the kiss socket - kiss = KissClient(self.direwolf_port) + kiss = KissClient(self.direwolf_config.getPort()) self.output.send_output("packet_demod", kiss.read) elif self.isPocsag(): self.output.send_output("pocsag_demod", self.secondary_process_demod.stdout.readline) @@ -487,11 +425,16 @@ class dsp(object): return self.secondary_demodulator def set_secondary_fft_size(self, secondary_fft_size): - # to change this, restart is required + if self.secondary_fft_size == secondary_fft_size: + return self.secondary_fft_size = secondary_fft_size + self.restart() def set_audio_compression(self, what): + if self.audio_compression == what: + return self.audio_compression = what + self.restart() def get_audio_bytes_to_read(self): # desired latency: 5ms @@ -506,6 +449,7 @@ class dsp(object): if self.fft_compression == what: return self.fft_compression = what + self.restart() def get_secondary_fft_bytes_to_read(self): if self.fft_compression == "none": @@ -528,6 +472,8 @@ class dsp(object): (self.decimation, self.last_decimation) = self.get_decimation(self.samp_rate, self.get_audio_rate()) def get_decimation(self, input_rate, output_rate): + if output_rate <= 0: + raise ValueError("invalid output rate: {rate}".format(rate=output_rate)) decimation = 1 target_rate = output_rate # wideband fm has a much higher frequency deviation (75kHz). @@ -571,7 +517,7 @@ class dsp(object): def isWsjtMode(self, demodulator=None): if demodulator is None: demodulator = self.get_secondary_demodulator() - return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w"] + return demodulator in ["ft8", "wspr", "jt65", "jt9", "ft4", "fst4", "fst4w", "q65"] def isJs8(self, demodulator=None): if demodulator is None: @@ -665,7 +611,7 @@ class dsp(object): # no squelch required on digital voice modes actual_squelch = ( -150 - if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV() + if self.isDigitalVoice() or self.isPacket() or self.isPocsag() or self.isFreeDV() or self.isDrm() else self.squelch_level ) if self.running: @@ -678,6 +624,15 @@ class dsp(object): def get_unvoiced_quality(self): return self.unvoiced_quality + def set_codecserver(self, s): + if self.codecserver == s: + return + self.codecserver = s + self.restart() + + def get_codecserver_arg(self): + return "-s {}".format(self.codecserver) if self.codecserver else "" + def set_dmr_filter(self, filter): if self.has_pipe("dmr_control_pipe"): self.pipes["dmr_control_pipe"].write("{0}\n".format(filter)) @@ -718,27 +673,34 @@ class dsp(object): def try_create_configs(self, command): if "{direwolf_config}" in command: - self.direwolf_config = "{tmp_dir}/openwebrx_direwolf_{myid}.conf".format( + self.direwolf_config_path = "{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)) + self.direwolf_config = DirewolfConfig() + self.direwolf_config.wire(self) + file = open(self.direwolf_config_path, "w") + file.write(self.direwolf_config.getConfig(self.is_service)) file.close() else: self.direwolf_config = None - self.direwolf_port = None + self.direwolf_config_path = None def try_delete_configs(self): - if self.direwolf_config: + if self.direwolf_config is not None: + self.direwolf_config.unwire(self) + self.direwolf_config = None + if self.direwolf_config_path is not None: try: - os.unlink(self.direwolf_config) + os.unlink(self.direwolf_config_path) except FileNotFoundError: # result suits our expectations. fine :) pass except Exception: logger.exception("try_delete_configs()") - self.direwolf_config = None + self.direwolf_config_path = None + + def onConfigChanged(self): + self.restart() def start(self): with self.modification_lock: @@ -781,19 +743,15 @@ class dsp(object): output_rate=self.get_output_rate(), smeter_report_every=int(self.if_samp_rate() / 6000), unvoiced_quality=self.get_unvoiced_quality(), + codecserver_arg=self.get_codecserver_arg(), 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) + self.process = subprocess.Popen(command, stdout=out, shell=True, start_new_session=True) def watch_thread(): rc = self.process.wait() @@ -837,10 +795,6 @@ class dsp(object): 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 @@ -859,6 +813,7 @@ class dsp(object): self.stop_secondary_demodulator() self.try_delete_pipes(self.pipe_names) + self.try_delete_configs() def restart(self): if not self.running: diff --git a/csdr/output.py b/csdr/output.py new file mode 100644 index 00000000..5fef242d --- /dev/null +++ b/csdr/output.py @@ -0,0 +1,36 @@ +import threading +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 diff --git a/debian/changelog b/debian/changelog index e1972360..f5684bc9 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,21 +1,60 @@ -openwebrx (0.21.0) UNRELEASED; urgency=low +openwebrx (1.1.0) UNRELEASED; 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 Sun, 09 May 2021 14:05: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 and FST4W (only available with - WSJT-X 2.3) + * 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) (`"type": "hpsdr"`) - - BBRF103 / RX666 / RX888 devices supported by libsddc (`"type": "sddc"`) - - Devices using the EB200 protocol (`"type": "eb200"`) + - 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 Sun, 11 Oct 2020 21:12:00 +0000 + -- Jakob Ketterl 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 Tue, 26 Jan 2021 15:28:00 +0000 + +openwebrx (0.20.2) buster focal; urgency=high + + * Fix a security problem that allowed arbitrary commands to be executed on + the receiver (See github issue #215: + https://github.com/jketterl/openwebrx/issues/215) + + -- Jakob Ketterl Sun, 24 Jan 2021 22:50:00 +0000 openwebrx (0.20.1) buster focal; urgency=low diff --git a/debian/control b/debian/control index 6654e6af..6b274bac 100644 --- a/debian/control +++ b/debian/control @@ -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.4), soapysdr-tools, python3-js8py (>= 0.1), ${python3:Depends}, ${misc:Depends} -Recommends: digiham (>= 0.3), dsd (>= 1.7), sox, direwolf (>= 1.4), wsjtx, eb200-connector, hpsdrconnector, aprs-symbols, m17-demod +Depends: adduser, python3 (>= 3.5), python3-pkg-resources, csdr (>= 0.17), netcat, owrx-connector (>= 0.5), soapysdr-tools, python3-js8py (>= 0.1), ${python3:Depends}, ${misc:Depends} +Recommends: digiham (>= 0.5), sox, direwolf (>= 1.4), wsjtx, runds-connector (>= 0.2), hpsdrconnector, aprs-symbols, m17-demod, js8call Description: multi-user web sdr - Open source, multi-user SDR receiver with a web interface \ No newline at end of file + Open source, multi-user SDR receiver with a web interface diff --git a/debian/openwebrx.config b/debian/openwebrx.config new file mode 100755 index 00000000..9a193930 --- /dev/null +++ b/debian/openwebrx.config @@ -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 diff --git a/debian/openwebrx.dirs b/debian/openwebrx.dirs new file mode 100644 index 00000000..c87b1b22 --- /dev/null +++ b/debian/openwebrx.dirs @@ -0,0 +1 @@ +/etc/openwebrx/openwebrx.conf.d \ No newline at end of file diff --git a/debian/openwebrx.install b/debian/openwebrx.install index 84b1f9ce..8db93442 100644 --- a/debian/openwebrx.install +++ b/debian/openwebrx.install @@ -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/ \ No newline at end of file diff --git a/debian/openwebrx.postinst b/debian/openwebrx.postinst new file mode 100755 index 00000000..935a0fe6 --- /dev/null +++ b/debian/openwebrx.postinst @@ -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# diff --git a/debian/openwebrx.postrm b/debian/openwebrx.postrm new file mode 100755 index 00000000..9260b8ec --- /dev/null +++ b/debian/openwebrx.postrm @@ -0,0 +1,8 @@ +#!/bin/sh -e + +if [ "$1" = purge ] && [ -e /usr/share/debconf/confmodule ]; then + . /usr/share/debconf/confmodule + db_purge +fi + +#DEBHELPER# diff --git a/debian/openwebrx.templates b/debian/openwebrx.templates new file mode 100644 index 00000000..8ef7e846 --- /dev/null +++ b/debian/openwebrx.templates @@ -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. \ No newline at end of file diff --git a/debian/postinst b/debian/postinst deleted file mode 100755 index 423db2c8..00000000 --- a/debian/postinst +++ /dev/null @@ -1,7 +0,0 @@ -#!/bin/bash -set -euxo pipefail - -adduser --system --group --no-create-home --home /nonexistent --quiet openwebrx -usermod -aG plugdev openwebrx - -#DEBHELPER# diff --git a/docker.sh b/docker.sh index 1583af69..c2bfe7f1 100755 --- a/docker.sh +++ b/docker.sh @@ -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-eb200 openwebrx-hpsdr 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-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 } diff --git a/docker/Dockerfiles/Dockerfile-base b/docker/Dockerfiles/Dockerfile-base index c338dc0f..6fd184f5 100644 --- a/docker/Dockerfiles/Dockerfile-base +++ b/docker/Dockerfiles/Dockerfile-base @@ -13,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 diff --git a/docker/Dockerfiles/Dockerfile-full b/docker/Dockerfiles/Dockerfile-full index b68d18ac..cecf45a4 100644 --- a/docker/Dockerfiles/Dockerfile-full +++ b/docker/Dockerfiles/Dockerfile-full @@ -18,10 +18,9 @@ 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-connectors.sh &&\ - /install-dependencies-eb200.sh &&\ + /install-dependencies-runds.sh &&\ rm /install-dependencies-*.sh &&\ rm /install-lib.*.patch && \ rm /install-connectors.sh diff --git a/docker/Dockerfiles/Dockerfile-redpitaya b/docker/Dockerfiles/Dockerfile-redpitaya deleted file mode 100644 index 7d389aaa..00000000 --- a/docker/Dockerfiles/Dockerfile-redpitaya +++ /dev/null @@ -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 diff --git a/docker/Dockerfiles/Dockerfile-eb200 b/docker/Dockerfiles/Dockerfile-runds similarity index 57% rename from docker/Dockerfiles/Dockerfile-eb200 rename to docker/Dockerfiles/Dockerfile-runds index f2f5181f..2a087e1f 100644 --- a/docker/Dockerfiles/Dockerfile-eb200 +++ b/docker/Dockerfiles/Dockerfile-runds @@ -2,11 +2,11 @@ ARG ARCHTAG FROM openwebrx-base:$ARCHTAG COPY docker/scripts/install-connectors.sh \ - docker/scripts/install-dependencies-eb200.sh / + docker/scripts/install-dependencies-runds.sh / RUN /install-connectors.sh &&\ rm /install-connectors.sh && \ - /install-dependencies-eb200.sh && \ - rm /install-dependencies-eb200.sh + /install-dependencies-runds.sh && \ + rm /install-dependencies-runds.sh COPY . /opt/openwebrx diff --git a/docker/env b/docker/env deleted file mode 100644 index f38dacdb..00000000 --- a/docker/env +++ /dev/null @@ -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" diff --git a/docker/files/services/codecserver/run b/docker/files/services/codecserver/run new file mode 100755 index 00000000..43c8212c --- /dev/null +++ b/docker/files/services/codecserver/run @@ -0,0 +1,2 @@ +#!/usr/bin/execlineb -P +/usr/local/bin/codecserver \ No newline at end of file diff --git a/docker/files/wsjtx/wsjtx-hamlib.patch b/docker/files/wsjtx/wsjtx-hamlib.patch index 09a8a882..47f37d93 100644 --- a/docker/files/wsjtx/wsjtx-hamlib.patch +++ b/docker/files/wsjtx/wsjtx-hamlib.patch @@ -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-03-30 15:28:36.956587995 +0200 ++++ CMakeLists.txt 2021-03-30 15:29:45.719326832 +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) diff --git a/docker/files/wsjtx/wsjtx.patch b/docker/files/wsjtx/wsjtx.patch index 59ac6b71..61ef53e3 100644 --- a/docker/files/wsjtx/wsjtx.patch +++ b/docker/files/wsjtx/wsjtx.patch @@ -1,6 +1,6 @@ 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 +--- wsjtx-orig/CMake/Modules/Findhamlib.cmake 2021-05-31 18:56:20.657682124 +0200 ++++ wsjtx/CMake/Modules/Findhamlib.cmake 2021-05-31 18:57:03.963994898 +0200 @@ -85,4 +85,4 @@ # Handle the QUIETLY and REQUIRED arguments and set HAMLIB_FOUND to # TRUE if all listed variables are TRUE @@ -8,9 +8,93 @@ diff -ur wsjtx-orig/CMake/Modules/Findhamlib.cmake wsjtx/CMake/Modules/Findhamli -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 @@ +--- wsjtx-orig/CMakeLists.txt 2021-05-31 18:56:20.657682124 +0200 ++++ wsjtx/CMakeLists.txt 2021-05-31 19:08:02.768474060 +0200 +@@ -122,7 +122,7 @@ + option (WSJT_QDEBUG_TO_FILE "Redirect Qt debuging messages to a trace file.") + option (WSJT_SOFT_KEYING "Apply a ramp to CW keying envelope to reduce transients." ON) + option (WSJT_SKIP_MANPAGES "Skip *nix manpage generation.") +-option (WSJT_GENERATE_DOCS "Generate documentation files." ON) ++option (WSJT_GENERATE_DOCS "Generate documentation files.") + option (WSJT_RIG_NONE_CAN_SPLIT "Allow split operation with \"None\" as rig.") + option (WSJT_TRACE_UDP "Debugging option that turns on UDP message protocol diagnostics.") + option (WSJT_BUILD_UTILS "Build simulators and code demonstrators." ON) +@@ -169,74 +169,7 @@ + ) + + set (wsjt_qt_CXXSRCS +- qt_helpers.cpp +- widgets/MessageBox.cpp +- MetaDataRegistry.cpp +- Network/NetworkServerLookup.cpp + revision_utils.cpp +- L10nLoader.cpp +- WFPalette.cpp +- Radio.cpp +- RadioMetaType.cpp +- NonInheritingProcess.cpp +- models/IARURegions.cpp +- models/Bands.cpp +- models/Modes.cpp +- models/FrequencyList.cpp +- models/StationList.cpp +- widgets/FrequencyLineEdit.cpp +- widgets/FrequencyDeltaLineEdit.cpp +- item_delegates/CandidateKeyFilter.cpp +- item_delegates/ForeignKeyDelegate.cpp +- validators/LiveFrequencyValidator.cpp +- GetUserId.cpp +- Audio/AudioDevice.cpp +- Transceiver/Transceiver.cpp +- Transceiver/TransceiverBase.cpp +- Transceiver/EmulateSplitTransceiver.cpp +- Transceiver/TransceiverFactory.cpp +- Transceiver/PollingTransceiver.cpp +- Transceiver/HamlibTransceiver.cpp +- Transceiver/HRDTransceiver.cpp +- Transceiver/DXLabSuiteCommanderTransceiver.cpp +- Network/NetworkMessage.cpp +- Network/MessageClient.cpp +- widgets/LettersSpinBox.cpp +- widgets/HintedSpinBox.cpp +- widgets/RestrictedSpinBox.cpp +- widgets/HelpTextWindow.cpp +- SampleDownloader.cpp +- SampleDownloader/DirectoryDelegate.cpp +- SampleDownloader/Directory.cpp +- SampleDownloader/FileNode.cpp +- SampleDownloader/RemoteFile.cpp +- DisplayManual.cpp +- MultiSettings.cpp +- validators/MaidenheadLocatorValidator.cpp +- validators/CallsignValidator.cpp +- widgets/SplashScreen.cpp +- EqualizationToolsDialog.cpp +- widgets/DoubleClickablePushButton.cpp +- widgets/DoubleClickableRadioButton.cpp +- Network/LotWUsers.cpp +- models/DecodeHighlightingModel.cpp +- widgets/DecodeHighlightingListView.cpp +- models/FoxLog.cpp +- widgets/AbstractLogWindow.cpp +- widgets/FoxLogWindow.cpp +- widgets/CabrilloLogWindow.cpp +- item_delegates/CallsignDelegate.cpp +- item_delegates/MaidenheadLocatorDelegate.cpp +- item_delegates/FrequencyDelegate.cpp +- item_delegates/FrequencyDeltaDelegate.cpp +- item_delegates/SQLiteDateTimeDelegate.cpp +- models/CabrilloLog.cpp +- logbook/AD1CCty.cpp +- logbook/WorkedBefore.cpp +- logbook/Multiplier.cpp +- Network/NetworkAccessManager.cpp +- widgets/LazyFillComboBox.cpp +- widgets/CheckableItemComboBox.cpp + ) + + set (wsjt_qtmm_CXXSRCS +@@ -857,7 +790,7 @@ # # libhamlib setup # @@ -19,31 +103,47 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt find_package (hamlib 3 REQUIRED) find_program (RIGCTL_EXE rigctl) find_program (RIGCTLD_EXE rigctld) -@@ -1348,53 +1348,10 @@ +@@ -895,9 +828,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 () - endif(WSJT_BUILD_UTILS) + # + # Library building setup +@@ -1380,60 +1310,6 @@ + target_link_libraries (jt9 wsjt_fort wsjt_cxx fort_qt) + endif (${OPENMP_FOUND} OR APPLE) -# build the main application +-generate_version_info (wsjtx_VERSION_RESOURCES +- NAME wsjtx +- BUNDLE ${PROJECT_BUNDLE_NAME} +- ICON ${WSJTX_ICON_FILE} +- ) +- -add_executable (wsjtx MACOSX_BUNDLE - ${wsjtx_CXXSRCS} - ${wsjtx_GENUISRCS} -- wsjtx.rc - ${WSJTX_ICON_FILE} - ${wsjtx_RESOURCES_RCC} +- ${wsjtx_VERSION_RESOURCES} - ) - - if (WSJT_CREATE_WINMAIN) - set_target_properties (wsjtx PROPERTIES WIN32_EXECUTABLE ON) - endif (WSJT_CREATE_WINMAIN) - +-if (WSJT_CREATE_WINMAIN) +- set_target_properties (wsjtx PROPERTIES WIN32_EXECUTABLE ON) +-endif (WSJT_CREATE_WINMAIN) +- -set_target_properties (wsjtx PROPERTIES - MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Darwin/Info.plist.in" -- MACOSX_BUNDLE_INFO_STRING "${WSJTX_DESCRIPTION_SUMMARY}" +- MACOSX_BUNDLE_INFO_STRING "${PROJECT_DESCRIPTION}" - MACOSX_BUNDLE_ICON_FILE "${WSJTX_ICON_FILE}" -- MACOSX_BUNDLE_BUNDLE_VERSION ${wsjtx_VERSION} -- MACOSX_BUNDLE_SHORT_VERSION_STRING "v${wsjtx_VERSION}" -- MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${wsjtx_VERSION}" -- MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_NAME}" +- MACOSX_BUNDLE_BUNDLE_VERSION ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH} +- MACOSX_BUNDLE_SHORT_VERSION_STRING "v${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" +- MACOSX_BUNDLE_LONG_VERSION_STRING "Version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}${SCS_VERSION_STR}" +- MACOSX_BUNDLE_BUNDLE_NAME "${PROJECT_BUNDLE_NAME}" - MACOSX_BUNDLE_BUNDLE_EXECUTABLE_NAME "${PROJECT_NAME}" - MACOSX_BUNDLE_COPYRIGHT "${PROJECT_COPYRIGHT}" - MACOSX_BUNDLE_GUI_IDENTIFIER "org.k1jt.wsjtx" @@ -51,9 +151,9 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt - -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}) +- target_link_libraries (wsjtx wsjt_fort) -else () -- target_link_libraries (wsjtx Qt5::SerialPort wsjt_fort_omp wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES}) +- target_link_libraries (wsjtx wsjt_fort_omp) - if (OpenMP_C_FLAGS) - set_target_properties (wsjtx PROPERTIES - COMPILE_FLAGS "${OpenMP_C_FLAGS}" @@ -65,18 +165,42 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt - ) - if (WIN32) - set_target_properties (wsjtx PROPERTIES -- LINK_FLAGS -Wl,--stack,16777216 +- LINK_FLAGS -Wl,--stack,0x1000000,--heap,0x20000000 - ) - endif () -endif () +-target_link_libraries (wsjtx Qt5::SerialPort wsjt_cxx wsjt_qt wsjt_qtmm ${hamlib_LIBRARIES} ${FFTW3_LIBRARIES} ${LIBM_LIBRARIES}) - # make a library for WSJT-X UDP servers # add_library (wsjtx_udp SHARED ${UDP_library_CXXSRCS}) add_library (wsjtx_udp-static STATIC ${UDP_library_CXXSRCS}) -@@ -1437,24 +1394,9 @@ - set_target_properties (message_aggregator PROPERTIES WIN32_EXECUTABLE ON) - endif (WSJT_CREATE_WINMAIN) +@@ -1473,47 +1349,9 @@ + add_executable (wsjtx_app_version AppVersion/AppVersion.cpp ${wsjtx_app_version_VERSION_RESOURCES}) + target_link_libraries (wsjtx_app_version wsjt_qt) +-generate_version_info (message_aggregator_VERSION_RESOURCES +- NAME message_aggregator +- BUNDLE ${PROJECT_BUNDLE_NAME} +- ICON ${WSJTX_ICON_FILE} +- FILE_DESCRIPTION "Example WSJT-X UDP Message Protocol application" +- ) +-add_resources (message_aggregator_RESOURCES /qss ${message_aggregator_STYLESHEETS}) +-configure_file (UDPExamples/message_aggregator.qrc.in message_aggregator.qrc @ONLY) +-qt5_add_resources (message_aggregator_RESOURCES_RCC +- ${CMAKE_CURRENT_BINARY_DIR}/message_aggregator.qrc +- contrib/QDarkStyleSheet/qdarkstyle/style.qrc +- ) +-add_executable (message_aggregator +- ${message_aggregator_CXXSRCS} +- ${message_aggregator_RESOURCES_RCC} +- ${message_aggregator_VERSION_RESOURCES} +- ) +-target_link_libraries (message_aggregator wsjt_qt Qt5::Widgets wsjtx_udp-static) +- +-if (WSJT_CREATE_WINMAIN) +- set_target_properties (message_aggregator PROPERTIES WIN32_EXECUTABLE ON) +-endif (WSJT_CREATE_WINMAIN) +- -if (UNIX) - if (NOT WSJT_SKIP_MANPAGES) - add_subdirectory (manpages) @@ -98,21 +222,21 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt # install (TARGETS wsjtx_udp EXPORT udp # RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} -@@ -1473,12 +1415,7 @@ +@@ -1532,12 +1370,7 @@ # DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/wsjtx # ) --install (TARGETS udp_daemon message_aggregator +-install (TARGETS udp_daemon message_aggregator wsjtx_app_version - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime - BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime - ) - -install (TARGETS jt9 wsprd fmtave fcal fmeasure -+install (TARGETS jt9 wsprd ++install (TARGETS wsjtx_app_version jt9 wsprd RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT runtime ) -@@ -1491,39 +1428,6 @@ +@@ -1549,38 +1382,6 @@ ) endif(WSJT_BUILD_UTILS) @@ -143,13 +267,50 @@ diff -ur wsjtx-orig/CMakeLists.txt wsjtx/CMakeLists.txt - AUTHORS - THANKS - NEWS -- INSTALL - BUGS - DESTINATION ${CMAKE_INSTALL_DOCDIR} - #COMPONENT runtime - ) - install (FILES - contrib/Ephemeris/JPLEPH - DESTINATION ${CMAKE_INSTALL_DATADIR}/${CMAKE_PROJECT_NAME} -Only in wsjtx: .idea + cty.dat + cty.dat_copyright.txt +@@ -1589,13 +1390,6 @@ + #COMPONENT runtime + ) + +-install (DIRECTORY +- example_log_configurations +- DESTINATION ${CMAKE_INSTALL_DOCDIR} +- FILES_MATCHING REGEX "^.*[^~]$" +- #COMPONENT runtime +- ) +- + # + # Mac installer files + # +@@ -1648,22 +1442,6 @@ + ) + + +-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) +- +- + # + # bundle fixup only done in non-Debug configurations + # +Only in wsjtx/: CMakeLists.txt.orig +Only in wsjtx/: .idea diff --git a/docker/scripts/install-connectors.sh b/docker/scripts/install-connectors.sh index be76988b..570b5c10 100755 --- a/docker/scripts/install-connectors.sh +++ b/docker/scripts/install-connectors.sh @@ -24,8 +24,8 @@ apt-get update apt-get -y install --no-install-recommends $BUILD_PACKAGES git clone https://github.com/jketterl/owrx_connector.git -# latest develop as of 2020-11-28 (int32 samples; debhelper) -cmakebuild owrx_connector 87a2fcc54e221aad71ec0700737ca7f385c388de +# latest develop as of 2021-05-18 (individual connector versions) +cmakebuild owrx_connector 167324219813f61b2be8164eb4acb1237ba2c304 apt-get -y purge --autoremove $BUILD_PACKAGES apt-get clean diff --git a/docker/scripts/install-dependencies-redpitaya.sh b/docker/scripts/install-dependencies-redpitaya.sh deleted file mode 100755 index e88b5c8b..00000000 --- a/docker/scripts/install-dependencies-redpitaya.sh +++ /dev/null @@ -1,32 +0,0 @@ -#!/bin/bash -set -euo pipefail -export MAKEFLAGS="-j4" - -function cmakebuild() { - cd $1 - if [[ ! -z "${2:-}" ]]; then - git checkout $2 - fi - mkdir build - cd build - cmake .. - make - make install - cd ../.. - rm -rf $1 -} - -cd /tmp - -STATIC_PACKAGES="" -BUILD_PACKAGES="git cmake make gcc g++" - -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 - -SUDO_FORCE_REMOVE=yes apt-get -y purge --autoremove $BUILD_PACKAGES -apt-get clean -rm -rf /var/lib/apt/lists/* diff --git a/docker/scripts/install-dependencies-eb200.sh b/docker/scripts/install-dependencies-runds.sh similarity index 71% rename from docker/scripts/install-dependencies-eb200.sh rename to docker/scripts/install-dependencies-runds.sh index ce0aba16..711a4372 100755 --- a/docker/scripts/install-dependencies-eb200.sh +++ b/docker/scripts/install-dependencies-runds.sh @@ -24,9 +24,9 @@ BUILD_PACKAGES="git cmake make gcc g++ pkg-config" apt-get update apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES -git clone https://github.com/jketterl/eb200_connector.git -# latest from develop as of 2020-12-01 -cmakebuild eb200_connector 9c8313770c1072df72d2fdb85307ca206c29c60a +git clone https://github.com/jketterl/runds_connector.git +# latest develop as of 2021-05-18 (individual connector versions) +cmakebuild runds_connector adfa04bee4ee36852feb07e7b845be2c3d3f97c7 apt-get -y purge --autoremove $BUILD_PACKAGES apt-get clean diff --git a/docker/scripts/install-dependencies-sdrplay.sh b/docker/scripts/install-dependencies-sdrplay.sh index 23241f37..d91ec6ce 100755 --- a/docker/scripts/install-dependencies-sdrplay.sh +++ b/docker/scripts/install-dependencies-sdrplay.sh @@ -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 diff --git a/docker/scripts/install-dependencies.sh b/docker/scripts/install-dependencies.sh index 55a95e7c..bae8d910 100755 --- a/docker/scripts/install-dependencies.sh +++ b/docker/scripts/install-dependencies.sh @@ -18,8 +18,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 libboost-program-options1.67.0" -BUILD_PACKAGES="wget git libsndfile1-dev libfftw3-dev cmake make gcc g++ liblapack-dev texinfo gfortran libusb-1.0-0-dev qtbase5-dev qtmultimedia5-dev qttools5-dev libqt5serialport5-dev qttools5-dev-tools asciidoctor asciidoc libasound2-dev libudev-dev libhamlib-dev patch xsltproc qt5-default libfaad-dev libopus-dev libgtest-dev libboost-dev libboost-program-options-dev" +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 libboost-program-options1.67.0 libboost-log1.67.0" +BUILD_PACKAGES="wget git libsndfile1-dev libfftw3-dev cmake make gcc g++ liblapack-dev texinfo gfortran libusb-1.0-0-dev qtbase5-dev qtmultimedia5-dev qttools5-dev libqt5serialport5-dev qttools5-dev-tools asciidoctor asciidoc libasound2-dev libudev-dev libhamlib-dev patch xsltproc qt5-default libfaad-dev libopus-dev libgtest-dev libboost-dev libboost-program-options-dev libboost-log-dev libboost-regex-dev" apt-get update apt-get -y install auto-apt-proxy apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES @@ -40,15 +40,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 @@ -60,7 +51,7 @@ rm /js8call-hamlib.patch CMAKE_ARGS="-D CMAKE_CXX_FLAGS=-DJS8_USE_HAMLIB_THREE" cmakebuild ${JS8CALL_DIR} rm ${JS8CALL_TGZ} -WSJT_DIR=wsjtx-2.2.2 +WSJT_DIR=wsjtx-2.4.0 WSJT_TGZ=${WSJT_DIR}.tgz wget http://physics.princeton.edu/pulsar/k1jt/${WSJT_TGZ} tar xfz ${WSJT_TGZ} @@ -111,12 +102,14 @@ rm -rf dream rm dream-2.1.1-svn808.tar.gz git clone https://github.com/mobilinkd/m17-cxx-demod.git -# latest master as of 2020-12-27 (new sync words) -cmakebuild m17-cxx-demod 2b84657676efb3b07b33de3ab3d0a6218e9d88b5 +# latest master as of 2021-04-20 +cmakebuild m17-cxx-demod c1d954fd5e5c53d28a2524e99484f832f9dcb826 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 diff --git a/docker/scripts/install-owrx-tools.sh b/docker/scripts/install-owrx-tools.sh index 9018c373..3ae5afc8 100755 --- a/docker/scripts/install-owrx-tools.sh +++ b/docker/scripts/install-owrx-tools.sh @@ -18,8 +18,8 @@ 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 libprotobuf17" +BUILD_PACKAGES="git autoconf automake libtool libfftw3-dev pkg-config cmake make gcc g++ libprotobuf-dev protobuf-compiler" apt-get update apt-get -y install --no-install-recommends $STATIC_PACKAGES $BUILD_PACKAGES @@ -40,8 +40,15 @@ make install cd .. rm -rf csdr +git clone https://github.com/jketterl/codecserver.git +mkdir -p /usr/local/etc/codecserver +cp codecserver/conf/codecserver.conf /usr/local/etc/codecserver +#latest develop as of 2021-07-04 (optional checksum fix) +cmakebuild codecserver d73c9a56a773355679bc2d4a10f199b62223d7a0 + git clone https://github.com/jketterl/digiham.git -cmakebuild digiham 0.3.0 +#latest develop as of 2021-06-15 (DMR LCSS overflow fix; D-Star alternate terminator) +cmakebuild digiham 418145d74b528596a39198a537ab56207d932595 apt-get -y purge --autoremove $BUILD_PACKAGES apt-get clean diff --git a/docker/scripts/run.sh b/docker/scripts/run.sh index 0f8bd322..cde6fdf8 100755 --- a/docker/scripts/run.sh +++ b/docker/scripts/run.sh @@ -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 diff --git a/htdocs/apple-touch-icon.png b/htdocs/apple-touch-icon.png new file mode 100644 index 00000000..5bc3c155 Binary files /dev/null and b/htdocs/apple-touch-icon.png differ diff --git a/htdocs/css/admin.css b/htdocs/css/admin.css index b6ebcea8..b956e9e3 100644 --- a/htdocs/css/admin.css +++ b/htdocs/css/admin.css @@ -1,14 +1,162 @@ @import url("openwebrx-header.css"); @import url("openwebrx-globals.css"); +html, body { + height: unset; +} + +body { + margin-bottom: 5rem; +} + +hr { + background: #444; +} + .buttons { + position: fixed; + bottom: 0; + left: 0; + right: 0; + background-color: #222; + z-index: 2; + padding: 10px; text-align: right; + border-top: 1px solid #444; } .row .map-input { margin: 15px 15px 0; } -.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; +} \ No newline at end of file diff --git a/htdocs/css/features.css b/htdocs/css/features.css deleted file mode 100644 index be41fef8..00000000 --- a/htdocs/css/features.css +++ /dev/null @@ -1,7 +0,0 @@ -@import url("openwebrx-header.css"); -@import url("openwebrx-globals.css"); - -h1 { - text-align: center; - margin: 50px 0; -} diff --git a/htdocs/css/login.css b/htdocs/css/login.css index 5e51dc9c..ccd6c026 100644 --- a/htdocs/css/login.css +++ b/htdocs/css/login.css @@ -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%; diff --git a/htdocs/css/map.css b/htdocs/css/map.css index 796f4422..70702b96 100644 --- a/htdocs/css/map.css +++ b/htdocs/css/map.css @@ -6,10 +6,6 @@ body { flex-direction: column; } -#webrx-top-container { - flex: none; -} - .openwebrx-map { flex: 1 1 auto; } diff --git a/htdocs/css/openwebrx-globals.css b/htdocs/css/openwebrx-globals.css index 8417ffd3..57598477 100644 --- a/htdocs/css/openwebrx-globals.css +++ b/htdocs/css/openwebrx-globals.css @@ -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; - } -} \ No newline at end of file diff --git a/htdocs/css/openwebrx-header.css b/htdocs/css/openwebrx-header.css index 83061f39..4e8601b7 100644 --- a/htdocs/css/openwebrx-header.css +++ b/htdocs/css/openwebrx-header.css @@ -1,4 +1,4 @@ -#webrx-top-container { +.webrx-top-container { position: relative; z-index:1000; background-color: #575757; @@ -12,7 +12,7 @@ overflow: hidden; } -#openwebrx-description-container { +.openwebrx-description-container { transition-property: height, opacity; transition-duration: 1s; transition-timing-function: ease-out; @@ -23,12 +23,12 @@ overflow: hidden; } -#openwebrx-description-container.expanded { +.openwebrx-description-container.expanded { opacity: 1; height: 283px; } -.webrx-top-bar-parts { +.webrx-top-bar { height:67px; background: rgba(128, 128, 128, 0.15); @@ -46,26 +46,27 @@ flex-direction: row; } -.webrx-top-bar-parts > * { +.webrx-top-bar > * { flex: 0; } -#webrx-top-container, #webrx-top-container * { +.webrx-top-container, .webrx-top-container * { line-height: initial; box-sizing: initial; } -#webrx-top-logo { +.webrx-top-logo { + width: 261px; padding: 12px; + filter: drop-shadow(0 0 2.5px rgba(0, 0, 0, .9)); /* overwritten by media queries */ display: none; } -#webrx-rx-avatar { +.webrx-rx-avatar { background-color: rgba(154, 154, 154, .5); margin: 7px; - cursor:pointer; width: 46px; height: 46px; padding: 4px; @@ -73,82 +74,66 @@ box-sizing: content-box; } -#webrx-rx-texts { +.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; white-space:nowrap; overflow: hidden; - cursor:pointer; color: #909090; + text-align: left; } -#webrx-rx-texts div:first-child { - margin-top: 10px; -} - -#webrx-rx-title { +.webrx-rx-title { font-family: "DejaVu Sans", Verdana, Geneva, sans-serif; font-size: 11pt; font-weight: bold; } -#webrx-rx-desc { +.webrx-rx-desc { font-size: 10pt; } -#openwebrx-rx-details-arrow { - cursor:pointer; - position: absolute; - bottom: 0; - left: 50%; - transform: translate(-50%, 0); -} - -#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[data-toggle-panel] { +.openwebrx-main-buttons .button[data-toggle-panel] { /* will be enabled by javascript if the panel is present in the DOM */ display: none; } -#openwebrx-main-buttons .button img { +.openwebrx-main-buttons .button img, +.openwebrx-main-buttons .button svg { height: 38px; + filter: drop-shadow(0 0 4px rgba(0, 0, 0, 0.5)); } -#openwebrx-main-buttons a { +.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; @@ -160,7 +145,7 @@ font-weight: bold; } -#webrx-rx-photo-title { +.webrx-rx-photo-title { margin: 10px 15px; color: white; font-size: 16pt; @@ -168,7 +153,7 @@ opacity: 1; } -#webrx-rx-photo-desc { +.webrx-rx-photo-desc { margin: 10px 15px; color: white; font-size: 10pt; @@ -178,17 +163,21 @@ line-height: 1.5em; } -#webrx-rx-photo-desc a { +.webrx-rx-photo-desc a { color: #5ca8ff; text-shadow: none; } +.openwebrx-photo-trigger { + cursor: pointer; +} + /* * Responsive stuff */ @media (min-width: 576px) { - #webrx-rx-texts { + .webrx-rx-texts { display: initial; } } @@ -197,7 +186,7 @@ } @media (min-width: 992px) { - #webrx-top-logo { + .webrx-top-logo { display: initial; } } @@ -206,47 +195,33 @@ } /* - * Sprites (images) + * RX details arrow up/down switching */ -.sprite-panel-status { - background-position: 0 0; - width: 44px; - height: 38px; +.openwebrx-rx-details-arrow { + position: absolute; + bottom: 0; + left: 50%; + transform: translate(-50%, 0); + + margin: 0; + padding: 0; + line-height: 0; + display: block; } -.sprite-panel-log { - background-position: -44px 0; - width: 38px; - height: 38px; -} - -.sprite-panel-receiver { - background-position: -82px 0; - width: 40px; - height: 38px; -} - -.sprite-panel-map { - background-position: -122px 0; - width: 38px; - height: 38px; -} - -.sprite-panel-settings { - background-position: -160px 0; - width: 38px; - height: 38px; -} - -.sprite-rx-details-arrow-down { - background-position: 0 -65px; - width: 43px; +.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; } \ No newline at end of file diff --git a/htdocs/css/openwebrx.css b/htdocs/css/openwebrx.css index bb0bb396..cb1e9549 100644 --- a/htdocs/css/openwebrx.css +++ b/htdocs/css/openwebrx.css @@ -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,10 @@ 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 { @@ -552,6 +602,7 @@ img.openwebrx-mirror-img -moz-user-select: none; -ms-user-select: none; overflow: hidden; + z-index: 1 } .openwebrx-progressbar-bar { @@ -564,6 +615,7 @@ img.openwebrx-mirror-img 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 { @@ -573,11 +625,11 @@ img.openwebrx-mirror-img .openwebrx-progressbar-text { position: absolute; - left:50; + left:50%; top:50%; transform: translate(-50%, -50%); white-space: nowrap; - z-index: 1; + z-index: 2; } #openwebrx-panel-status @@ -602,6 +654,7 @@ img.openwebrx-mirror-img #openwebrx-panel-receiver .frequencies-container { display: flex; flex-direction: row; + gap: 5px; } #openwebrx-panel-receiver .frequencies { @@ -614,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; @@ -631,13 +674,6 @@ img.openwebrx-mirror-img width: 95px; } -.openwebrx-sliderbtn-img -{ - width: 14px; - position:relative; - top: 1px; -} - .openwebrx-panel-line { padding-top: 5px; @@ -714,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 @@ -735,8 +771,7 @@ img.openwebrx-mirror-img transition: opacity 0.3s linear; } -#openwebrx-autoplay-overlay img -{ +#openwebrx-autoplay-overlay svg { width: 150px; } @@ -768,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; @@ -781,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, @@ -912,6 +965,8 @@ img.openwebrx-mirror-img display: flex; flex-direction: row; gap: 10px; + /* compatibility with iOS 14.2 */ + flex: 0 0 auto; } .openwebrx-meta-slot { @@ -928,26 +983,22 @@ img.openwebrx-mirror-img display: flex; flex-direction: column; position: relative; + overflow: hidden; } .openwebrx-meta-slot > * { - flex: 0; - flex-basis: 1.2em; + flex: 1 0 0; line-height: 1.2em; } -.openwebrx-meta-slot, .openwebrx-meta-slot.muted:before { +.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"); - background-position: center; - background-repeat: no-repeat; +.openwebrx-meta-slot .mute { + display: none; cursor: pointer; position: absolute; @@ -958,6 +1009,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; } @@ -974,18 +1036,29 @@ img.openwebrx-mirror-img } .openwebrx-meta-slot .openwebrx-meta-user-image { - flex: 1; + flex: 0 1 100%; background-position: center; background-repeat: no-repeat; + line-height: 0; + overflow: hidden; } -.openwebrx-meta-slot.active.direct .openwebrx-meta-user-image, -#openwebrx-panel-metadata-ysf .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.group .openwebrx-meta-user-image { - 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 { + 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 { @@ -998,6 +1071,7 @@ img.openwebrx-mirror-img .openwebrx-dmr-timeslot-panel * { cursor: pointer; + user-select: none; } .openwebrx-ysf-mode:not(:empty):before { @@ -1012,14 +1086,30 @@ img.openwebrx-mirror-img content: "Down: "; } -.openwebrx-maps-pin { - background-image: url("../gfx/google_maps_pin.svg"); - background-position: center; - background-repeat: no-repeat; +.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 { @@ -1192,6 +1282,7 @@ img.openwebrx-mirror-img #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="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, @@ -1201,7 +1292,8 @@ img.openwebrx-mirror-img #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="fst4"] #openwebrx-digimode-select-channel, -#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-select-channel +#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-select-channel, +#openwebrx-panel-digimodes[data-mode="q65"] #openwebrx-digimode-select-channel { display: none; } @@ -1215,81 +1307,58 @@ img.openwebrx-mirror-img #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="fst4"] #openwebrx-digimode-canvas-container, -#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-canvas-container +#openwebrx-panel-digimodes[data-mode="fst4w"] #openwebrx-digimode-canvas-container, +#openwebrx-panel-digimodes[data-mode="q65"] #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-button .sprite-speaker { - background-position: -103px -38px; +#openwebrx-waterfall-colors-auto.highlighted .continuous { + display: initial; } -.openwebrx-mute-button.muted .sprite-speaker { - background-position: -117px -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; } \ No newline at end of file diff --git a/htdocs/favicon.ico b/htdocs/favicon.ico index f8c9a2ae..6a07f1b1 100644 Binary files a/htdocs/favicon.ico and b/htdocs/favicon.ico differ diff --git a/htdocs/features.html b/htdocs/features.html index 90d156ea..53099b6d 100644 --- a/htdocs/features.html +++ b/htdocs/features.html @@ -3,7 +3,6 @@ - @@ -11,6 +10,7 @@ ${header}
+ ${breadcrumb}

OpenWebRX Feature Report

@@ -20,5 +20,6 @@
Available
+ ${breadcrumb}
\ No newline at end of file diff --git a/htdocs/features.js b/htdocs/features.js index 5ab0972d..fef2817e 100644 --- a/htdocs/features.js +++ b/htdocs/features.js @@ -13,8 +13,7 @@ $(function(){ }); $table.append( '' + - '' + name + '' + - '' + converter.makeHtml(details.description) + '' + + '' + name + '' + '' + (details.available ? 'YES' : 'NO') + '' + '' + requirements.join("") diff --git a/htdocs/generalsettings.html b/htdocs/generalsettings.html deleted file mode 100644 index 4731a028..00000000 --- a/htdocs/generalsettings.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - OpenWebRX Settings - - - - - - - - -${header} -
-
-

General settings

-
- ${sections} -
- \ No newline at end of file diff --git a/htdocs/gfx/favicon128.png b/htdocs/gfx/favicon128.png new file mode 100644 index 00000000..ad42441f Binary files /dev/null and b/htdocs/gfx/favicon128.png differ diff --git a/htdocs/gfx/favicon32.png b/htdocs/gfx/favicon32.png new file mode 100644 index 00000000..2c534af5 Binary files /dev/null and b/htdocs/gfx/favicon32.png differ diff --git a/htdocs/gfx/favicon44.png b/htdocs/gfx/favicon44.png new file mode 100644 index 00000000..d21f326e Binary files /dev/null and b/htdocs/gfx/favicon44.png differ diff --git a/htdocs/gfx/favicon64.png b/htdocs/gfx/favicon64.png new file mode 100644 index 00000000..b08e03fc Binary files /dev/null and b/htdocs/gfx/favicon64.png differ diff --git a/htdocs/gfx/favicon96.png b/htdocs/gfx/favicon96.png new file mode 100644 index 00000000..ee941298 Binary files /dev/null and b/htdocs/gfx/favicon96.png differ diff --git a/htdocs/gfx/openwebrx-background-cool-blue.png b/htdocs/gfx/openwebrx-background-cool-blue.png index 7430bd8a..236b366b 100644 Binary files a/htdocs/gfx/openwebrx-background-cool-blue.png and b/htdocs/gfx/openwebrx-background-cool-blue.png differ diff --git a/htdocs/gfx/openwebrx-background-lingrad.png b/htdocs/gfx/openwebrx-background-lingrad.png deleted file mode 100644 index 48537f7a..00000000 Binary files a/htdocs/gfx/openwebrx-background-lingrad.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-bookmark.png b/htdocs/gfx/openwebrx-bookmark.png deleted file mode 100644 index bf1164bf..00000000 Binary files a/htdocs/gfx/openwebrx-bookmark.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-directcall.png b/htdocs/gfx/openwebrx-directcall.png deleted file mode 100644 index 2d74713b..00000000 Binary files a/htdocs/gfx/openwebrx-directcall.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-directcall.svg b/htdocs/gfx/openwebrx-directcall.svg new file mode 100644 index 00000000..34401121 --- /dev/null +++ b/htdocs/gfx/openwebrx-directcall.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/htdocs/gfx/openwebrx-edit.png b/htdocs/gfx/openwebrx-edit.png deleted file mode 100644 index ab403a53..00000000 Binary files a/htdocs/gfx/openwebrx-edit.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-groupcall.png b/htdocs/gfx/openwebrx-groupcall.png deleted file mode 100644 index 5d61a4c7..00000000 Binary files a/htdocs/gfx/openwebrx-groupcall.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-groupcall.svg b/htdocs/gfx/openwebrx-groupcall.svg new file mode 100644 index 00000000..5083a576 --- /dev/null +++ b/htdocs/gfx/openwebrx-groupcall.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/htdocs/gfx/openwebrx-logo-big.png b/htdocs/gfx/openwebrx-logo-big.png deleted file mode 100644 index dcafb2ee..00000000 Binary files a/htdocs/gfx/openwebrx-logo-big.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-mute.png b/htdocs/gfx/openwebrx-mute.png deleted file mode 100644 index 23da7bbf..00000000 Binary files a/htdocs/gfx/openwebrx-mute.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-panel-log.png b/htdocs/gfx/openwebrx-panel-log.png deleted file mode 100644 index 58e6fd5f..00000000 Binary files a/htdocs/gfx/openwebrx-panel-log.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-panel-map.png b/htdocs/gfx/openwebrx-panel-map.png deleted file mode 100644 index 81ec9e2f..00000000 Binary files a/htdocs/gfx/openwebrx-panel-map.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-panel-receiver.png b/htdocs/gfx/openwebrx-panel-receiver.png deleted file mode 100644 index 5c80c3b6..00000000 Binary files a/htdocs/gfx/openwebrx-panel-receiver.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-panel-settings.png b/htdocs/gfx/openwebrx-panel-settings.png deleted file mode 100644 index 02a7a03a..00000000 Binary files a/htdocs/gfx/openwebrx-panel-settings.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-panel-status.png b/htdocs/gfx/openwebrx-panel-status.png deleted file mode 100644 index 064b54f7..00000000 Binary files a/htdocs/gfx/openwebrx-panel-status.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-play-button.png b/htdocs/gfx/openwebrx-play-button.png deleted file mode 100644 index 4a065217..00000000 Binary files a/htdocs/gfx/openwebrx-play-button.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-rx-details-arrow-up.png b/htdocs/gfx/openwebrx-rx-details-arrow-up.png deleted file mode 100644 index 0baccd04..00000000 Binary files a/htdocs/gfx/openwebrx-rx-details-arrow-up.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-rx-details-arrow.png b/htdocs/gfx/openwebrx-rx-details-arrow.png deleted file mode 100644 index 9995118f..00000000 Binary files a/htdocs/gfx/openwebrx-rx-details-arrow.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-scale-background.png b/htdocs/gfx/openwebrx-scale-background.png index 7fbb4d24..91453c58 100644 Binary files a/htdocs/gfx/openwebrx-scale-background.png and b/htdocs/gfx/openwebrx-scale-background.png differ diff --git a/htdocs/gfx/openwebrx-speaker-muted.png b/htdocs/gfx/openwebrx-speaker-muted.png deleted file mode 100644 index 0d545703..00000000 Binary files a/htdocs/gfx/openwebrx-speaker-muted.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-speaker.png b/htdocs/gfx/openwebrx-speaker.png deleted file mode 100644 index 6c88e23c..00000000 Binary files a/htdocs/gfx/openwebrx-speaker.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-sprites-2x.png b/htdocs/gfx/openwebrx-sprites-2x.png deleted file mode 100644 index 662d481f..00000000 Binary files a/htdocs/gfx/openwebrx-sprites-2x.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-sprites.png b/htdocs/gfx/openwebrx-sprites.png deleted file mode 100644 index fd2b3e72..00000000 Binary files a/htdocs/gfx/openwebrx-sprites.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-squelch-button.png b/htdocs/gfx/openwebrx-squelch-button.png deleted file mode 100644 index f67177c5..00000000 Binary files a/htdocs/gfx/openwebrx-squelch-button.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-top-logo.png b/htdocs/gfx/openwebrx-top-logo.png deleted file mode 100644 index 47724252..00000000 Binary files a/htdocs/gfx/openwebrx-top-logo.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-trashcan.png b/htdocs/gfx/openwebrx-trashcan.png deleted file mode 100644 index c47dd488..00000000 Binary files a/htdocs/gfx/openwebrx-trashcan.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-waterfall-auto.png b/htdocs/gfx/openwebrx-waterfall-auto.png deleted file mode 100644 index 7e41302a..00000000 Binary files a/htdocs/gfx/openwebrx-waterfall-auto.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-waterfall-default.png b/htdocs/gfx/openwebrx-waterfall-default.png deleted file mode 100644 index 1cd39fa5..00000000 Binary files a/htdocs/gfx/openwebrx-waterfall-default.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-zoom-in-total.png b/htdocs/gfx/openwebrx-zoom-in-total.png deleted file mode 100644 index 3646a377..00000000 Binary files a/htdocs/gfx/openwebrx-zoom-in-total.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-zoom-in.png b/htdocs/gfx/openwebrx-zoom-in.png deleted file mode 100644 index c8df0c8a..00000000 Binary files a/htdocs/gfx/openwebrx-zoom-in.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-zoom-out-total.png b/htdocs/gfx/openwebrx-zoom-out-total.png deleted file mode 100644 index d83b61df..00000000 Binary files a/htdocs/gfx/openwebrx-zoom-out-total.png and /dev/null differ diff --git a/htdocs/gfx/openwebrx-zoom-out.png b/htdocs/gfx/openwebrx-zoom-out.png deleted file mode 100644 index 60cd9120..00000000 Binary files a/htdocs/gfx/openwebrx-zoom-out.png and /dev/null differ diff --git a/htdocs/gfx/svg-defs.svg b/htdocs/gfx/svg-defs.svg new file mode 100644 index 00000000..251b0517 --- /dev/null +++ b/htdocs/gfx/svg-defs.svg @@ -0,0 +1,28 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/htdocs/include/header.include.html b/htdocs/include/header.include.html index ec316196..8ae0811f 100644 --- a/htdocs/include/header.include.html +++ b/htdocs/include/header.include.html @@ -1,25 +1,25 @@ -
-
- - Receiver avatar -
-
-
+
+
+ + Receiver avatar +
+

${receiver_name}

+
${receiver_location} | Loc: ${locator}, ASL: ${receiver_asl} m
-
-

Status
-

Log
-

Receiver
-
Map
- ${settingslink} +
+

Status
+

Log
+

Receiver
+
Map
+
Settings
-
-
-
-
-
- - +
+
${photo_title}
+
${photo_desc}
+ + + +
diff --git a/htdocs/index.html b/htdocs/index.html index 8b3af5af..300a7772 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -23,7 +23,14 @@ OpenWebRX | Open Source SDR Web App for Everyone! - + + + + + + + + @@ -34,142 +41,191 @@
${header} -
-
-
- -
-
-
-
- -
-
-
-
-
- Under construction -
We're working on the code right now, so the application might fail. +
+
+
+
+
-