diff --git a/owrx/controllers/settings/sdr.py b/owrx/controllers/settings/sdr.py
index 926001e..90bb131 100644
--- a/owrx/controllers/settings/sdr.py
+++ b/owrx/controllers/settings/sdr.py
@@ -71,7 +71,7 @@ class SdrDeviceController(SettingsFormController):
def getSections(self):
try:
description = SdrDeviceDescription.getByType(self.device["type"])
- return [description.getSection()]
+ return [description.getSection(self.device)]
except SdrDeviceDescriptionMissing:
# TODO provide a generic interface that allows to switch the type
return []
diff --git a/owrx/source/__init__.py b/owrx/source/__init__.py
index 423a8b7..ecea90d 100644
--- a/owrx/source/__init__.py
+++ b/owrx/source/__init__.py
@@ -376,6 +376,9 @@ class SdrDeviceDescriptionMissing(Exception):
class SdrDeviceDescription(object):
+ def __init__(self):
+ self.indexedInputs = {input.id: input for input in self.getInputs()}
+
@staticmethod
def getByType(sdr_type: str) -> "SdrDeviceDescription":
try:
@@ -423,10 +426,14 @@ class SdrDeviceDescription(object):
# TODO `schedule`
]
- def mergeInputs(self, *args):
- # build a dictionary indexed by the input id to make sure every id only exists once
- inputs = {input.id: input for input_list in args for input in input_list}
- return inputs.values()
+ def getMandatoryKeys(self):
+ return ["name", "enabled"]
- def getSection(self):
- return Section("Device settings", *self.getInputs())
+ def getOptionalKeys(self):
+ return ["ppm", "always-on", "services", "rf_gain", "lfo_offset", "waterfall_min_level", "waterfall_max_level"]
+
+ def getSection(self, data):
+ visible_keys = set(self.getMandatoryKeys() + [k for k in self.getOptionalKeys() if k in data])
+ inputs = [input for k, input in self.indexedInputs.items() if k in visible_keys]
+ # TODO: render remaining keys in optional area
+ return Section("Device settings", *inputs)
diff --git a/owrx/source/airspy.py b/owrx/source/airspy.py
index 773d8b2..70005be 100644
--- a/owrx/source/airspy.py
+++ b/owrx/source/airspy.py
@@ -22,17 +22,21 @@ class AirspySource(SoapyConnectorSource):
class AirspyDeviceDescription(SoapyConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(
- super().getInputs(),
- [
- BiasTeeInput(),
- CheckboxInput(
- "bitpack",
- "",
- checkboxText="Enable bit-packing",
- infotext="Packs two 12-bit samples into 3 bytes."
- + " Lowers USB bandwidth consumption, increases CPU load",
- converter=OptionalConverter(defaultFormValue=False),
- ),
- ],
- )
+ return super().getInputs() + [
+ BiasTeeInput(),
+ CheckboxInput(
+ "bitpack",
+ "",
+ checkboxText="Enable bit-packing",
+ infotext="Packs two 12-bit samples into 3 bytes."
+ + " Lowers USB bandwidth consumption, increases CPU load",
+ converter=OptionalConverter(defaultFormValue=False),
+ ),
+ ]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["bias_tee", "bitpack"]
+
+ # TODO: find actual gain stages for airspay
+ # def getGainStages(self):
+ # return None
diff --git a/owrx/source/connector.py b/owrx/source/connector.py
index 40fd795..10d6bcb 100644
--- a/owrx/source/connector.py
+++ b/owrx/source/connector.py
@@ -76,23 +76,23 @@ class ConnectorSource(SdrSource):
class ConnectorDeviceDescription(SdrDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(
- super().getInputs(),
- [
- NumberInput(
- "rtltcp_compat",
- "Port for rtl_tcp compatible data",
- infotext="Activate an rtl_tcp compatible interface on the port number specified.
"
- + "Note: Port is only available on the local machine, not on the network.
"
- + "Note: IQ data may be degraded by the downsampling process to 8 bits.",
- converter=OptionalConverter(IntConverter()),
- ),
- CheckboxInput(
- "iqswap",
- "",
- checkboxText="Swap I and Q channels",
- infotext="Swapping inverts the spectrum, so this is useful in combination with an inverting mixer",
- converter=OptionalConverter(defaultFormValue=False),
- ),
- ],
- )
+ return super().getInputs() + [
+ NumberInput(
+ "rtltcp_compat",
+ "Port for rtl_tcp compatible data",
+ infotext="Activate an rtl_tcp compatible interface on the port number specified.
"
+ + "Note: Port is only available on the local machine, not on the network.
"
+ + "Note: IQ data may be degraded by the downsampling process to 8 bits.",
+ converter=OptionalConverter(IntConverter()),
+ ),
+ CheckboxInput(
+ "iqswap",
+ "",
+ checkboxText="Swap I and Q channels",
+ infotext="Swapping inverts the spectrum, so this is useful in combination with an inverting mixer",
+ converter=OptionalConverter(defaultFormValue=False),
+ ),
+ ]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["rtltcp_compat", "iqswap"]
diff --git a/owrx/source/hackrf.py b/owrx/source/hackrf.py
index f597168..978d152 100644
--- a/owrx/source/hackrf.py
+++ b/owrx/source/hackrf.py
@@ -16,4 +16,11 @@ class HackrfSource(SoapyConnectorSource):
class HackrfDeviceDescription(SoapyConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(super().getInputs(), [BiasTeeInput()])
+ return super().getInputs() + [BiasTeeInput()]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["bias_tee"]
+
+ # TODO: find actual gain stages for hackrf
+ # def getGainStages(self):
+ # return None
diff --git a/owrx/source/rtl_sdr.py b/owrx/source/rtl_sdr.py
index 91b97b5..a01e41d 100644
--- a/owrx/source/rtl_sdr.py
+++ b/owrx/source/rtl_sdr.py
@@ -18,16 +18,16 @@ class RtlSdrSource(ConnectorSource):
class RtlSdrDeviceDescription(ConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(
- super().getInputs(),
- [
- TextInput(
- "device",
- "Device identifier",
- infotext="Device serial number or index",
- converter=OptionalConverter(),
- ),
- BiasTeeInput(),
- DirectSamplingInput()
- ],
- )
+ return super().getInputs() + [
+ TextInput(
+ "device",
+ "Device identifier",
+ infotext="Device serial number or index",
+ converter=OptionalConverter(),
+ ),
+ BiasTeeInput(),
+ DirectSamplingInput()
+ ]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["device", "bias_tee", "direct_sampling"]
diff --git a/owrx/source/rtl_sdr_soapy.py b/owrx/source/rtl_sdr_soapy.py
index fec40bd..0257810 100644
--- a/owrx/source/rtl_sdr_soapy.py
+++ b/owrx/source/rtl_sdr_soapy.py
@@ -16,4 +16,7 @@ class RtlSdrSoapySource(SoapyConnectorSource):
class RtlSdrSoapyDeviceDescription(SoapyConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(super().getInputs(), [BiasTeeInput(), DirectSamplingInput()])
+ return super().getInputs() + [BiasTeeInput(), DirectSamplingInput()]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["bias_tee", "direct_sampling"]
diff --git a/owrx/source/rtl_tcp.py b/owrx/source/rtl_tcp.py
index ef80c38..5bf2712 100644
--- a/owrx/source/rtl_tcp.py
+++ b/owrx/source/rtl_tcp.py
@@ -23,4 +23,7 @@ class RtlTcpSource(ConnectorSource):
class RtlTcpDeviceDescription(ConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(super().getInputs(), [RemoteInput()])
+ return super().getInputs() + [RemoteInput()]
+
+ def getMandatoryKeys(self):
+ return super().getMandatoryKeys() + ["device"]
diff --git a/owrx/source/runds.py b/owrx/source/runds.py
index d820dfd..9b33da5 100644
--- a/owrx/source/runds.py
+++ b/owrx/source/runds.py
@@ -39,13 +39,13 @@ class ProtocolOptions(DropdownEnum):
class RundsDeviceDescription(ConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(
- super().getInputs(),
- [
- RemoteInput(),
- DropdownInput("protocol", "Protocol", ProtocolOptions),
- CheckboxInput(
- "long", "", "Use 32-bit sample size (LONG)", converter=OptionalConverter(defaultFormValue=False)
- ),
- ],
- )
+ return super().getInputs() + [
+ RemoteInput(),
+ DropdownInput("protocol", "Protocol", ProtocolOptions),
+ CheckboxInput(
+ "long", "", "Use 32-bit sample size (LONG)", converter=OptionalConverter(defaultFormValue=False)
+ ),
+ ]
+
+ def getMandatoryKeys(self):
+ return super().getMandatoryKeys() + ["device"]
diff --git a/owrx/source/sdrplay.py b/owrx/source/sdrplay.py
index 5cf5587..63b0cef 100644
--- a/owrx/source/sdrplay.py
+++ b/owrx/source/sdrplay.py
@@ -38,29 +38,29 @@ class SdrplayDeviceDescription(SoapyConnectorDeviceDescription):
return ["RFGR", "IFGR"]
def getInputs(self) -> List[Input]:
- return self.mergeInputs(
- super().getInputs(),
- [
- BiasTeeInput(),
- CheckboxInput(
- "rf_notch",
- "",
- checkboxText="Enable RF notch filter",
- converter=OptionalConverter(defaultFormValue=True),
+ return super().getInputs() + [
+ BiasTeeInput(),
+ CheckboxInput(
+ "rf_notch",
+ "",
+ checkboxText="Enable RF notch filter",
+ converter=OptionalConverter(defaultFormValue=True),
+ ),
+ CheckboxInput(
+ "dab_notch",
+ "",
+ checkboxText="Enable DAB notch filter",
+ converter=OptionalConverter(defaultFormValue=True),
+ ),
+ DropdownInput(
+ "if_mode",
+ "IF Mode",
+ IfModeOptions,
+ converter=OptionalConverter(
+ EnumConverter(IfModeOptions), defaultFormValue=IfModeOptions.IFMODE_ZERO_IF.name
),
- CheckboxInput(
- "dab_notch",
- "",
- checkboxText="Enable DAB notch filter",
- converter=OptionalConverter(defaultFormValue=True),
- ),
- DropdownInput(
- "if_mode",
- "IF Mode",
- IfModeOptions,
- converter=OptionalConverter(
- EnumConverter(IfModeOptions), defaultFormValue=IfModeOptions.IFMODE_ZERO_IF.name
- ),
- ),
- ],
- )
+ ),
+ ]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["bias_tee", "rf_notch", "dab_notch", "if_mode"]
diff --git a/owrx/source/soapy.py b/owrx/source/soapy.py
index 8e4778b..0db1c45 100644
--- a/owrx/source/soapy.py
+++ b/owrx/source/soapy.py
@@ -84,27 +84,27 @@ class SoapyConnectorSource(ConnectorSource, metaclass=ABCMeta):
class SoapyConnectorDeviceDescription(ConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(
- super().getInputs(),
- [
- TextInput(
- "device",
- "Device Identifier",
- infotext='SoapySDR device identifier string (example: "serial=123456789")',
- converter=OptionalConverter()
- ),
- GainInput(
- "rf_gain",
- "Device Gain",
- gain_stages=self.getGainStages(),
- ),
- TextInput(
- "antenna",
- "Antenna",
- converter=OptionalConverter(),
- ),
- ],
- )
+ return super().getInputs() + [
+ TextInput(
+ "device",
+ "Device Identifier",
+ infotext='SoapySDR device identifier string (example: "serial=123456789")',
+ converter=OptionalConverter()
+ ),
+ GainInput(
+ "rf_gain",
+ "Device Gain",
+ gain_stages=self.getGainStages(),
+ ),
+ TextInput(
+ "antenna",
+ "Antenna",
+ converter=OptionalConverter(),
+ ),
+ ]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["device", "rf_gain", "antenna"]
def getGainStages(self):
return None
diff --git a/owrx/source/soapy_remote.py b/owrx/source/soapy_remote.py
index 080ee7d..19be5a5 100644
--- a/owrx/source/soapy_remote.py
+++ b/owrx/source/soapy_remote.py
@@ -22,12 +22,12 @@ class SoapyRemoteSource(SoapyConnectorSource):
class SoapyRemoteDeviceDescription(SoapyConnectorDeviceDescription):
def getInputs(self) -> List[Input]:
- return self.mergeInputs(
- super().getInputs(),
- [
- RemoteInput(),
- TextInput(
- "remote_driver", "Remote driver", infotext="SoapySDR driver to be used on the remote SoapySDRServer"
- ),
- ],
- )
+ return super().getInputs() + [
+ RemoteInput(),
+ TextInput(
+ "remote_driver", "Remote driver", infotext="SoapySDR driver to be used on the remote SoapySDRServer"
+ ),
+ ]
+
+ def getOptionalKeys(self):
+ return super().getOptionalKeys() + ["remote_driver"]