diff --git a/htdocs/lib/DemodulatorPanel.js b/htdocs/lib/DemodulatorPanel.js index bbaffa52..e10388a2 100644 --- a/htdocs/lib/DemodulatorPanel.js +++ b/htdocs/lib/DemodulatorPanel.js @@ -197,9 +197,11 @@ DemodulatorPanel.prototype.collectParams = function() { }; DemodulatorPanel.prototype.startDemodulator = function() { - if (!Modes.initComplete() || !this.center_freq) return; var params = this.collectParams(); - this._apply(params); + this.setMagicKey(params.magic_key); + + if (Modes.initComplete() && this.center_freq) + this._apply(params); }; DemodulatorPanel.prototype.stopDemodulator = function() { @@ -212,7 +214,6 @@ DemodulatorPanel.prototype.stopDemodulator = function() { } DemodulatorPanel.prototype._apply = function(params) { - this.setMagicKey(params.magic_key); if (params.secondary_mod) { this.setMode(params.secondary_mod, params.mod) } else { diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 25304e48..9c2e27b1 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -1971,7 +1971,10 @@ function secondary_demod_waterfall_set_zoom(low_cut, high_cut) { function sdr_profile_changed() { var value = $('#openwebrx-sdr-profiles-listbox').val(); - ws.send(JSON.stringify({type: "selectprofile", params: {profile: value}})); + var key = $('#openwebrx-panel-receiver').demodulatorPanel().getMagicKey(); + ws.send(JSON.stringify({ + "type": "selectprofile", "params": { "profile": value, "key": key } + })); } function tuning_step_changed() { diff --git a/owrx/config/defaults.py b/owrx/config/defaults.py index b4b0260f..bc24c3eb 100644 --- a/owrx/config/defaults.py +++ b/owrx/config/defaults.py @@ -155,6 +155,7 @@ defaultConfig = PropertyLayer( waterfall_levels=PropertyLayer(min=-88, max=-20), waterfall_auto_levels=PropertyLayer(min=3, max=10), waterfall_auto_min_range=50, + key_locked=False, ui_opacity=100, ui_frame=False, ui_swap_wheel=False, diff --git a/owrx/connection.py b/owrx/connection.py index 8cbc2cf8..5d6e73c2 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -296,10 +296,15 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): if "params" in message and "sdr" in message["params"]: self.setSdr(message["params"]["sdr"]) elif message["type"] == "selectprofile": + # Locked source's profile can only be changed with a key if "params" in message and "profile" in message["params"]: - profile = message["params"]["profile"].split("|") + params = message["params"] + profile = params["profile"].split("|") + magic = self.stack["magic_key"] + key = params["key"] if "key" in params else None self.setSdr(profile[0]) - self.sdr.activateProfile(profile[1]) + if not self.sdr.isLocked() or magic == "" or key == magic: + self.sdr.activateProfile(profile[1]) elif message["type"] == "setfrequency": # If the magic key is set in the settings, only allow # changes if it matches the received key diff --git a/owrx/sdr.py b/owrx/sdr.py index d31417b5..79b216a2 100644 --- a/owrx/sdr.py +++ b/owrx/sdr.py @@ -233,6 +233,11 @@ class SdrService(object): if not sources: return None # TODO: configure default sdr in config? right now it will pick the first one off the list. + # For now, try returning the first unlocked source + for src in sources.keys(): + if not sources[src].isLocked(): + return sources[src] + # If no unlocked sources, just return the first one return sources[list(sources.keys())[0]] @staticmethod diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py index 0db26469..c84a0eff 100644 --- a/owrx/source/__init__.py +++ b/owrx/source/__init__.py @@ -383,6 +383,9 @@ class SdrSource(ABC): def isAvailable(self): return self.monitor is not None + def isLocked(self): + return "key_locked" in self.props and self.props["key_locked"] + def stop(self): with self.modificationLock: if self.process is not None: @@ -560,12 +563,6 @@ class SdrDeviceDescription(object): def getInputs(self) -> List[Input]: return [ CheckboxInput("enabled", "Enable this device", converter=OptionalConverter(defaultFormValue=True)), - GainInput("rf_gain", "Device gain", self.hasAgc()), - NumberInput( - "ppm", - "Frequency correction", - append="ppm", - ), CheckboxInput( "always-on", "Keep device running at all times", @@ -575,6 +572,16 @@ class SdrDeviceDescription(object): "services", "Run background services on this device", ), + CheckboxInput( + "key_locked", + "Protect access to this device with a magic key", + ), + GainInput("rf_gain", "Device gain", self.hasAgc()), + NumberInput( + "ppm", + "Frequency correction", + append="ppm", + ), ExponentialInput( "lfo_offset", "Oscillator offset", @@ -608,6 +615,7 @@ class SdrDeviceDescription(object): keys = [ "always-on", "services", + "key_locked", "rf_gain", "lfo_offset", "waterfall_levels",