From c77d3c24a43804bceb4b8b206a2a0cdfcb1a87e3 Mon Sep 17 00:00:00 2001 From: Marat Fayzullin Date: Sat, 20 May 2023 15:43:56 -0400 Subject: [PATCH 1/6] Added ability to jump center_frequency by right-clicking arrow buttons. --- htdocs/index.html | 4 ++-- htdocs/openwebrx.js | 11 +++++++++++ owrx/connection.py | 4 ++++ owrx/source/__init__.py | 5 +++++ 4 files changed, 22 insertions(+), 2 deletions(-) diff --git a/htdocs/index.html b/htdocs/index.html index 7659734e..83f689a7 100644 --- a/htdocs/index.html +++ b/htdocs/index.html @@ -45,10 +45,10 @@
-
+
-
+
diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 7c2133b4..0d3ef411 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -151,6 +151,17 @@ function tuneBySteps(steps) { } } +function jumpBySteps(steps) { + steps = Math.round(steps); + if (steps != 0) { + var f = center_freq + steps * bandwidth / 4; + ws.send(JSON.stringify({ + "type": "setfrequency", + "params": { "frequency": f } + })); + } +} + var waterfall_min_level; var waterfall_max_level; var waterfall_min_level_default; diff --git a/owrx/connection.py b/owrx/connection.py index 13e66696..19aac2e4 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -295,6 +295,10 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): profile = message["params"]["profile"].split("|") self.setSdr(profile[0]) self.sdr.activateProfile(profile[1]) + elif message["type"] == "setfrequency": + if "params" in message and "frequency" in message["params"]: + frequency = message["params"]["frequency"] + self.sdr.setCenterFreq(frequency) elif message["type"] == "connectionproperties": if "params" in message: self.connectionProperties = message["params"] diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index e3e79d9a..0239c7b9 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -231,6 +231,11 @@ class SdrSource(ABC): except KeyError: logger.warning("invalid profile %s for sdr %s. ignoring", profile_id, self.getId()) + def setCenterFreq(self, frequency): + if "center_freq" in self.sdrProps: + self.sdrProps["center_freq"] = frequency + self.wireEvents() + def getId(self): return self.id From 59380bd3f57a0a9befbc6f22178cb18a849b28cb Mon Sep 17 00:00:00 2001 From: Marat Fayzullin Date: Sat, 20 May 2023 17:28:54 -0400 Subject: [PATCH 2/6] No longer modifying current profile on center_freq jump. --- owrx/source/__init__.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index 0239c7b9..87c0ff44 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -116,21 +116,27 @@ class SdrSource(ABC): self.buffer = None self.props = PropertyStack() - - # layer 0 reserved for profile properties self.profileCarousel = SdrProfileCarousel(props) + + # layer 0 contains center_freq so that it can be changed + # independently of the profile + self.props.addLayer(0, PropertyLayer( + center_freq=self.profileCarousel["center_freq"] + )) + + # layer 1 reserved for profile properties # prevent profile names from overriding the device name - self.props.addLayer(0, PropertyFilter(self.profileCarousel, ByLambda(lambda x: x != "name"))) + self.props.addLayer(1, PropertyFilter(self.profileCarousel, ByLambda(lambda x: x != "name"))) # props from our device config - self.props.addLayer(1, props) + self.props.addLayer(2, props) # the sdr_id is constant, so we put it in a separate layer # this is used to detect device changes, that are then sent to the client - self.props.addLayer(2, PropertyLayer(sdr_id=id).readonly()) + self.props.addLayer(3, PropertyLayer(sdr_id=id).readonly()) # finally, accept global config properties from the top-level config - self.props.addLayer(3, Config.get()) + self.props.addLayer(4, Config.get()) self.sdrProps = self.props.filter(*self.getEventNames()) @@ -228,13 +234,13 @@ class SdrSource(ABC): logger.debug("activating profile {0} for {1}".format(profile_id, self.getId())) try: self.profileCarousel.switch(profile_id) + self.setCenterFreq(self.profileCarousel["center_freq"]) except KeyError: logger.warning("invalid profile %s for sdr %s. ignoring", profile_id, self.getId()) def setCenterFreq(self, frequency): - if "center_freq" in self.sdrProps: - self.sdrProps["center_freq"] = frequency - self.wireEvents() + if "center_freq" in self.props: + self.props["center_freq"] = frequency def getId(self): return self.id From 15bcd0d3fbfd85e042a201176a6797dc2ef1b40c Mon Sep 17 00:00:00 2001 From: Marat Fayzullin Date: Sat, 20 May 2023 18:04:48 -0400 Subject: [PATCH 3/6] Settings to disable side-stepping center frequency and audio recording. --- owrx/config/defaults.py | 2 ++ owrx/connection.py | 7 +++++-- owrx/controllers/settings/general.py | 8 ++++++++ 3 files changed, 15 insertions(+), 2 deletions(-) diff --git a/owrx/config/defaults.py b/owrx/config/defaults.py index 8b01bfde..0b1d380f 100644 --- a/owrx/config/defaults.py +++ b/owrx/config/defaults.py @@ -157,6 +157,8 @@ defaultConfig = PropertyLayer( waterfall_auto_min_range=50, ui_opacity=100, ui_frame=False, + allow_center_freq_changes=False, + allow_audio_recording=True, tuning_precision=2, squelch_auto_margin=10, google_maps_api_key="", diff --git a/owrx/connection.py b/owrx/connection.py index 19aac2e4..a81bb630 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -139,6 +139,8 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): "tuning_precision", "ui_opacity", "ui_frame", + "allow_center_freq_changes", + "allow_audio_recording", ] def __init__(self, conn): @@ -297,8 +299,9 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): self.sdr.activateProfile(profile[1]) elif message["type"] == "setfrequency": if "params" in message and "frequency" in message["params"]: - frequency = message["params"]["frequency"] - self.sdr.setCenterFreq(frequency) + if self.stack["allow_center_freq_changes"]: + frequency = message["params"]["frequency"] + self.sdr.setCenterFreq(frequency) elif message["type"] == "connectionproperties": if "params" in message: self.connectionProperties = message["params"] diff --git a/owrx/controllers/settings/general.py b/owrx/controllers/settings/general.py index 574ecefb..50bc11eb 100644 --- a/owrx/controllers/settings/general.py +++ b/owrx/controllers/settings/general.py @@ -91,6 +91,14 @@ class GeneralSettingsController(SettingsFormController): infotext="Specifies web page describing receiver usage policy " + "and shown when a client session times out.", ), + CheckboxInput( + "allow_center_freq_changes", + "Allow users to change center frequency", + ), + CheckboxInput( + "allow_audio_recording", + "Allow users to record received audio", + ), ), Section( "Receiver listings", From 640eb9ad455e3c28dc2db11d6c3af1ad55f6f478 Mon Sep 17 00:00:00 2001 From: Marat Fayzullin Date: Sat, 20 May 2023 22:26:42 -0400 Subject: [PATCH 4/6] Fixing some errors. --- owrx/source/__init__.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index 87c0ff44..acc8bf92 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -120,9 +120,7 @@ class SdrSource(ABC): # layer 0 contains center_freq so that it can be changed # independently of the profile - self.props.addLayer(0, PropertyLayer( - center_freq=self.profileCarousel["center_freq"] - )) + self.props.addLayer(0, PropertyLayer()) # layer 1 reserved for profile properties # prevent profile names from overriding the device name @@ -239,8 +237,7 @@ class SdrSource(ABC): logger.warning("invalid profile %s for sdr %s. ignoring", profile_id, self.getId()) def setCenterFreq(self, frequency): - if "center_freq" in self.props: - self.props["center_freq"] = frequency + self.props["center_freq"] = frequency def getId(self): return self.id From 9a0906695fb7f2c1e81662bbe39df2e1c5157284 Mon Sep 17 00:00:00 2001 From: Marat Fayzullin Date: Sat, 20 May 2023 23:08:21 -0400 Subject: [PATCH 5/6] Added magic key option for changing center frequency. --- htdocs/lib/DemodulatorPanel.js | 4 +++- htdocs/openwebrx.js | 8 +++++++- owrx/config/defaults.py | 1 + owrx/connection.py | 14 ++++++++++---- owrx/controllers/settings/general.py | 12 +++++++++--- 5 files changed, 30 insertions(+), 9 deletions(-) diff --git a/htdocs/lib/DemodulatorPanel.js b/htdocs/lib/DemodulatorPanel.js index 35cea9c6..738cac2e 100644 --- a/htdocs/lib/DemodulatorPanel.js +++ b/htdocs/lib/DemodulatorPanel.js @@ -238,6 +238,7 @@ DemodulatorPanel.prototype.transformHashParams = function(params) { if (typeof(params.secondary_mod) !== 'undefined') ret.secondary_mod = params.secondary_mod; if (typeof(params.offset_frequency) !== 'undefined') ret.offset_frequency = params.offset_frequency; if (typeof(params.sql) !== 'undefined') ret.squelch_level = parseInt(params.sql); + if (typeof(params.key) !== 'undefined') ret.magic_key = params.key; return ret; }; @@ -340,7 +341,8 @@ DemodulatorPanel.prototype.updateHash = function() { freq: demod.get_offset_frequency() + self.center_freq, mod: demod.get_modulation(), secondary_mod: demod.get_secondary_demod(), - sql: demod.getSquelch() + sql: demod.getSquelch(), + key: self.magic_key }, function(value, key){ if (typeof(value) === 'undefined' || value === false) return undefined; return key + '=' + value; diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 0d3ef411..230ae1fc 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -36,6 +36,7 @@ var tuning_step_default = 1; var tuning_step = 1; var nr_enabled = false; var nr_threshold = 0; +var magic_key = ""; function updateVolume() { audioEngine.setVolume(parseFloat($("#openwebrx-panel-volume").val()) / 100); @@ -157,7 +158,7 @@ function jumpBySteps(steps) { var f = center_freq + steps * bandwidth / 4; ws.send(JSON.stringify({ "type": "setfrequency", - "params": { "frequency": f } + "params": { "frequency": f, "key": magic_key } })); } } @@ -1091,6 +1092,11 @@ function on_ws_recv(evt) { $('#openwebrx-panel-receiver').css('border', x? '2px solid':''); } + if ('allow_audio_recording' in config) { + var x = config['allow_audio_recording']; + $('.openwebrx-record-button').css('display', x? '':'none'); + } + break; case "secondary_config": var s = json['value']; diff --git a/owrx/config/defaults.py b/owrx/config/defaults.py index 0b1d380f..6b71ce02 100644 --- a/owrx/config/defaults.py +++ b/owrx/config/defaults.py @@ -157,6 +157,7 @@ defaultConfig = PropertyLayer( waterfall_auto_min_range=50, ui_opacity=100, ui_frame=False, + magic_key="memagic", allow_center_freq_changes=False, allow_audio_recording=True, tuning_precision=2, diff --git a/owrx/connection.py b/owrx/connection.py index a81bb630..d05a6efb 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -141,6 +141,7 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): "ui_frame", "allow_center_freq_changes", "allow_audio_recording", + "magic_key", ] def __init__(self, conn): @@ -298,10 +299,15 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): self.setSdr(profile[0]) self.sdr.activateProfile(profile[1]) elif message["type"] == "setfrequency": - if "params" in message and "frequency" in message["params"]: - if self.stack["allow_center_freq_changes"]: - frequency = message["params"]["frequency"] - self.sdr.setCenterFreq(frequency) + # If the magic key is set in the settings, only allow + # center frequency changes if it matches the received + # key. + if "params" in message and self.stack["allow_center_freq_changes"]: + magic_key = self.stack["magic_key"] + params = message["params"] + if magic_key == "" or ("key" in params and params["key"] == magic_key): + if "frequency" in params: + self.sdr.setCenterFreq(params["frequency"]) elif message["type"] == "connectionproperties": if "params" in message: self.connectionProperties = message["params"] diff --git a/owrx/controllers/settings/general.py b/owrx/controllers/settings/general.py index 50bc11eb..c4e46e82 100644 --- a/owrx/controllers/settings/general.py +++ b/owrx/controllers/settings/general.py @@ -91,13 +91,19 @@ class GeneralSettingsController(SettingsFormController): infotext="Specifies web page describing receiver usage policy " + "and shown when a client session times out.", ), + CheckboxInput( + "allow_audio_recording", + "Allow users to record received audio", + ), CheckboxInput( "allow_center_freq_changes", "Allow users to change center frequency", ), - CheckboxInput( - "allow_audio_recording", - "Allow users to record received audio", + TextInput( + "magic_key", + "Magic key", + infotext="Enter a key the user has to supply to change center frequency." + + " Leave empty if you do not want to protect frequency changes with a key.", ), ), Section( From ddc756cad7bf07a8f6a786b7e947692d8d1e15a0 Mon Sep 17 00:00:00 2001 From: Marat Fayzullin Date: Sun, 21 May 2023 00:08:12 -0400 Subject: [PATCH 6/6] Magic key works at last! --- htdocs/lib/DemodulatorPanel.js | 15 +++++++++++++-- htdocs/openwebrx.js | 15 +++++++-------- owrx/connection.py | 3 +-- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/htdocs/lib/DemodulatorPanel.js b/htdocs/lib/DemodulatorPanel.js index 738cac2e..b6f460cc 100644 --- a/htdocs/lib/DemodulatorPanel.js +++ b/htdocs/lib/DemodulatorPanel.js @@ -217,6 +217,7 @@ DemodulatorPanel.prototype._apply = function(params) { this.getDemodulator().set_offset_frequency(params.offset_frequency); this.getDemodulator().setSquelch(params.squelch_level); this.updateButtons(); + this.setMagicKey(params.magic_key); }; DemodulatorPanel.prototype.setInitialParams = function(params) { @@ -227,6 +228,14 @@ DemodulatorPanel.prototype.resetInitialParams = function() { this.initialParams = {}; }; +DemodulatorPanel.prototype.setMagicKey = function(key) { + this.magic_key = key; +}; + +DemodulatorPanel.prototype.getMagicKey = function() { + return this.magic_key; +}; + DemodulatorPanel.prototype.onHashChange = function() { this._apply(this.transformHashParams(this.parseHash())); }; @@ -344,8 +353,10 @@ DemodulatorPanel.prototype.updateHash = function() { sql: demod.getSquelch(), key: self.magic_key }, function(value, key){ - if (typeof(value) === 'undefined' || value === false) return undefined; - return key + '=' + value; + if (typeof(value) === 'undefined' || value === false || value === '') + return undefined; + else + return key + '=' + value; }).filter(function(v) { return !!v; }).join(','); diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 230ae1fc..e5393032 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -36,7 +36,6 @@ var tuning_step_default = 1; var tuning_step = 1; var nr_enabled = false; var nr_threshold = 0; -var magic_key = ""; function updateVolume() { audioEngine.setVolume(parseFloat($("#openwebrx-panel-volume").val()) / 100); @@ -155,10 +154,10 @@ function tuneBySteps(steps) { function jumpBySteps(steps) { steps = Math.round(steps); if (steps != 0) { + var key = $('#openwebrx-panel-receiver').demodulatorPanel().getMagicKey(); var f = center_freq + steps * bandwidth / 4; ws.send(JSON.stringify({ - "type": "setfrequency", - "params": { "frequency": f, "key": magic_key } + "type": "setfrequency", "params": { "frequency": f, "key": key } })); } } @@ -1166,11 +1165,11 @@ function on_ws_recv(evt) { case 'secondary_demod': var value = json['value']; var panels = [ - $("#openwebrx-panel-wsjt-message").wsjtMessagePanel(), - $('#openwebrx-panel-packet-message').packetMessagePanel(), - $('#openwebrx-panel-pocsag-message').pocsagMessagePanel(), - $('#openwebrx-panel-sstv-message').sstvMessagePanel(), - $('#openwebrx-panel-fax-message').faxMessagePanel(), + $("#openwebrx-panel-wsjt-message").wsjtMessagePanel(), + $('#openwebrx-panel-packet-message').packetMessagePanel(), + $('#openwebrx-panel-pocsag-message').pocsagMessagePanel(), + $('#openwebrx-panel-sstv-message').sstvMessagePanel(), + $('#openwebrx-panel-fax-message').faxMessagePanel(), $("#openwebrx-panel-js8-message").js8() ]; if (!panels.some(function(panel) { diff --git a/owrx/connection.py b/owrx/connection.py index d05a6efb..27635e98 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -300,8 +300,7 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): self.sdr.activateProfile(profile[1]) elif message["type"] == "setfrequency": # If the magic key is set in the settings, only allow - # center frequency changes if it matches the received - # key. + # changes if it matches the received key if "params" in message and self.stack["allow_center_freq_changes"]: magic_key = self.stack["magic_key"] params = message["params"]