diff --git a/csdr/chain/dablin.py b/csdr/chain/dablin.py
index d451a248..1e1c5667 100644
--- a/csdr/chain/dablin.py
+++ b/csdr/chain/dablin.py
@@ -1,4 +1,5 @@
-from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider
+from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, \
+ MetaProvider, DabServiceSelector
from csdr.module import PickleModule
from csdreti.modules import EtiDecoder
from owrx.dab.dablin import DablinModule
@@ -46,7 +47,7 @@ class MetaProcessor(PickleModule):
return result
-class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider):
+class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, MetaProvider, DabServiceSelector):
def __init__(self):
shift = Shift(0)
decoder = EtiDecoder()
@@ -59,10 +60,12 @@ class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain,
# will be replaced by setMetaWriter().
self.processor.setWriter(Buffer(Format.CHAR))
+ self.dablin = DablinModule()
+
workers = [
shift,
decoder,
- DablinModule(),
+ self.dablin,
Downmix(Format.FLOAT),
]
super().__init__(workers)
@@ -84,3 +87,6 @@ class Dablin(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain,
def setMetaWriter(self, writer: Writer) -> None:
self.processor.setWriter(writer)
+
+ def setDabServiceId(self, serviceId: int) -> None:
+ self.dablin.setDabServiceId(serviceId)
diff --git a/csdr/chain/demodulator.py b/csdr/chain/demodulator.py
index 99042d99..7b4506cc 100644
--- a/csdr/chain/demodulator.py
+++ b/csdr/chain/demodulator.py
@@ -55,6 +55,12 @@ class RdsChain(ABC):
pass
+class DabServiceSelector(ABC):
+ @abstractmethod
+ def setDabServiceId(self, serviceId: int) -> None:
+ pass
+
+
class BaseDemodulatorChain(Chain):
def supportsSquelch(self) -> bool:
return True
diff --git a/docker/scripts/install-owrx-tools.sh b/docker/scripts/install-owrx-tools.sh
index 231f5919..a4b64d01 100755
--- a/docker/scripts/install-owrx-tools.sh
+++ b/docker/scripts/install-owrx-tools.sh
@@ -32,13 +32,13 @@ popd
rm -rf js8py
git clone https://github.com/jketterl/csdr.git
-# latest develop as of 2024-01-22 (downmix format)
-cmakebuild csdr e6ae546a6a1d3fd052fe962eb5a04fd33e794214
+# latest develop as of 2024-01-25 (exemodule setargs)
+cmakebuild csdr 344179a616cdbadf501479ce9ed1b836543e657b
git clone https://github.com/jketterl/pycsdr.git
cd pycsdr
-# latest develop as of 2024-01-22 (downmix format)
-git checkout c7dafe83d08b74012e233502dff0bc6e6f17c01c
+# latest develop as of 2024-01-25 (execmodule setargs)
+git checkout 9063b8a119e366c31d089596641a24a427e3cbdc
./setup.py install install_headers
cd ..
rm -rf pycsdr
diff --git a/htdocs/lib/Demodulator.js b/htdocs/lib/Demodulator.js
index b55cbdcf..e729ebe7 100644
--- a/htdocs/lib/Demodulator.js
+++ b/htdocs/lib/Demodulator.js
@@ -205,6 +205,7 @@ function Demodulator(offset_frequency, modulation) {
this.filter = new Filter(this);
this.squelch_level = -150;
this.dmr_filter = 3;
+ this.dab_service_id = 0;
this.started = false;
this.state = {};
this.secondary_demod = false;
@@ -294,6 +295,7 @@ Demodulator.prototype.set = function () { //this function sends demodulator par
"offset_freq": this.offset_frequency,
"mod": this.modulation,
"dmr_filter": this.dmr_filter,
+ "dab_service_id": this.dab_service_id,
"squelch_level": this.squelch_level,
"secondary_mod": this.secondary_demod,
"secondary_offset_freq": this.secondary_offset_freq
@@ -331,6 +333,11 @@ Demodulator.prototype.setDmrFilter = function(dmr_filter) {
this.set();
};
+Demodulator.prototype.setDabServiceId = function(dab_service_id) {
+ this.dab_service_id = dab_service_id;
+ this.set();
+}
+
Demodulator.prototype.setBandpass = function(bandpass) {
this.bandpass = bandpass;
this.low_cut = bandpass.low_cut;
diff --git a/htdocs/lib/MetaPanel.js b/htdocs/lib/MetaPanel.js
index e84a29d3..d94a9d6b 100644
--- a/htdocs/lib/MetaPanel.js
+++ b/htdocs/lib/MetaPanel.js
@@ -553,9 +553,12 @@ WfmMetaPanel.prototype.clear = function() {
function DabMetaPanel(el) {
MetaPanel.call(this, el);
this.modes = ['DAB'];
- $(this.el).html(
- ''
- )
+ this.$select = $('');
+ $(this.el).append(this.$select);
+ this.$select.on("change", function() {
+ var service_id = parseInt($(this).val());
+ $('#openwebrx-panel-receiver').demodulatorPanel().getDemodulator().setDabServiceId(service_id);
+ });
this.clear();
}
@@ -573,7 +576,10 @@ DabMetaPanel.prototype.update = function(data) {
var options = Object.entries(data.programmes).map(function(e) {
return '';
});
- $(this.el).find('#dab-service-id').html(options.join(''));
+ $(this.el).find('#dab-service-id').html(
+ '' +
+ options.join('')
+ );
}
console.info(data);
diff --git a/owrx/dab/dablin.py b/owrx/dab/dablin.py
index ffb9bc68..ad7d2641 100644
--- a/owrx/dab/dablin.py
+++ b/owrx/dab/dablin.py
@@ -4,8 +4,17 @@ from pycsdr.types import Format
class DablinModule(ExecModule):
def __init__(self):
+ self.serviceId = 0
super().__init__(
Format.CHAR,
Format.FLOAT,
- ["dablin", "-1", "-p"]
+ self._buildArgs()
)
+
+ def _buildArgs(self):
+ return ["dablin", "-p", "-s", "{:#06x}".format(self.serviceId)]
+
+ def setDabServiceId(self, serviceId: int) -> None:
+ self.serviceId = serviceId
+ self.setArgs(self._buildArgs())
+ self.restart()
diff --git a/owrx/dsp.py b/owrx/dsp.py
index f9f8bb7f..84306d6a 100644
--- a/owrx/dsp.py
+++ b/owrx/dsp.py
@@ -3,7 +3,9 @@ from owrx.property import PropertyStack, PropertyLayer, PropertyValidator, Prope
from owrx.property.validators import OrValidator, RegexValidator, BoolValidator
from owrx.modes import Modes, DigitalMode
from csdr.chain import Chain
-from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain, SecondarySelectorChain, DeemphasisTauChain, DemodulatorError, RdsChain
+from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, \
+ SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain, SecondarySelectorChain, \
+ DeemphasisTauChain, DemodulatorError, RdsChain, DabServiceSelector
from csdr.chain.selector import Selector, SecondarySelector
from csdr.chain.clientaudio import ClientAudioChain
from csdr.chain.fft import FftChain
@@ -328,6 +330,11 @@ class ClientDemodulatorChain(Chain):
return
self.demodulator.setSlotFilter(filter)
+ def setDabServiceId(self, serviceId: int) -> None:
+ if not isinstance(self.demodulator, DabServiceSelector):
+ return
+ self.demodulator.setDabServiceId(serviceId)
+
def setSecondaryFftSize(self, size: int) -> None:
if size == self.secondaryFftSize:
return
@@ -422,6 +429,7 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
"mod": ModulationValidator(),
"secondary_offset_freq": "int",
"dmr_filter": "int",
+ "dab_service_id": "int",
}
self.localProps = PropertyValidator(PropertyLayer().filter(*validators.keys()), validators)
@@ -502,6 +510,7 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient)
self.props.wireProperty("high_cut", self.setHighCut),
self.props.wireProperty("mod", self.setDemodulator),
self.props.wireProperty("dmr_filter", self.chain.setSlotFilter),
+ self.props.wireProperty("dab_service_id", self.chain.setDabServiceId),
self.props.wireProperty("wfm_deemphasis_tau", self.chain.setWfmDeemphasisTau),
self.props.wireProperty("wfm_rds_rbds", self.chain.setRdsRbds),
self.props.wireProperty("secondary_mod", self.setSecondaryDemodulator),