diff --git a/csdr/chain/demodulator.py b/csdr/chain/demodulator.py index 034540c..c72658c 100644 --- a/csdr/chain/demodulator.py +++ b/csdr/chain/demodulator.py @@ -67,3 +67,7 @@ class SecondaryDemodulator(Chain): class ServiceDemodulator(SecondaryDemodulator, FixedAudioRateChain, metaclass=ABCMeta): pass + + +class DemodulatorError(Exception): + pass diff --git a/csdr/chain/digiham.py b/csdr/chain/digiham.py index f586358..7f65059 100644 --- a/csdr/chain/digiham.py +++ b/csdr/chain/digiham.py @@ -1,8 +1,8 @@ -from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain, DialFrequencyReceiver, MetaProvider, SlotFilterChain +from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain, DialFrequencyReceiver, MetaProvider, SlotFilterChain, DemodulatorError from pycsdr.modules import FmDemod, Agc, Writer, Buffer from pycsdr.types import Format from digiham.modules import DstarDecoder, DcBlock, FskDemodulator, GfskDemodulator, DigitalVoiceFilter, MbeSynthesizer, NarrowRrcFilter, NxdnDecoder, DmrDecoder, WideRrcFilter, YsfDecoder -from digiham.ambe import Modes +from digiham.ambe import Modes, ServerError from owrx.meta import MetaParser @@ -17,10 +17,16 @@ class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateC workers = [FmDemod(), DcBlock()] if filter is not None: workers += [filter] + try: + mbeSynthesizer = MbeSynthesizer(mbeMode, codecserver) + except ConnectionError as ce: + raise DemodulatorError("Connection to codecserver failed: {}".format(ce)) + except ServerError as se: + raise DemodulatorError("Codecserver error: {}".format(se)) workers += [ fskDemodulator, decoder, - MbeSynthesizer(mbeMode, codecserver), + mbeSynthesizer, DigitalVoiceFilter(), agc ] diff --git a/htdocs/openwebrx.js b/htdocs/openwebrx.js index 97ccc82..14bb039 100644 --- a/htdocs/openwebrx.js +++ b/htdocs/openwebrx.js @@ -838,6 +838,9 @@ function on_ws_recv(evt) { $overlay.show(); $("#openwebrx-panel-receiver").demodulatorPanel().stopDemodulator(); break; + case "demodulator_error": + divlog(json['value'], true); + break; case 'secondary_demod': var value = json['value']; var panels = [ diff --git a/owrx/connection.py b/owrx/connection.py index 9893529..b012f51 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -422,6 +422,9 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): def write_sdr_error(self, message): self.send({"type": "sdr_error", "value": message}) + def write_demodulator_error(self, message): + self.send({"type": "demodulator_error", "value": message}) + def write_backoff_message(self, reason): self.send({"type": "backoff", "reason": reason}) diff --git a/owrx/dsp.py b/owrx/dsp.py index 74b26ad..7793598 100644 --- a/owrx/dsp.py +++ b/owrx/dsp.py @@ -3,7 +3,7 @@ from owrx.property import PropertyStack, PropertyLayer, PropertyValidator 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 +from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver, MetaProvider, SlotFilterChain, SecondarySelectorChain, DeemphasisTauChain, DemodulatorError from csdr.chain.selector import Selector, SecondarySelector from csdr.chain.clientaudio import ClientAudioChain from csdr.chain.fft import FftChain @@ -544,19 +544,22 @@ class DspManager(SdrSourceEventClient, ClientDemodulatorSecondaryDspEventClient) return FreeDV() def setDemodulator(self, mod): - demodulator = self._getDemodulator(mod) - if demodulator is None: - raise ValueError("unsupported demodulator: {}".format(mod)) - self.chain.setDemodulator(demodulator) + try: + demodulator = self._getDemodulator(mod) + if demodulator is None: + raise ValueError("unsupported demodulator: {}".format(mod)) + self.chain.setDemodulator(demodulator) - output = "hd_audio" if isinstance(demodulator, HdAudio) else "audio" + output = "hd_audio" if isinstance(demodulator, HdAudio) else "audio" - if output != self.audioOutput: - self.audioOutput = output - # re-wire the audio to the correct client API - buffer = Buffer(self.chain.getOutputFormat()) - self.chain.setWriter(buffer) - self.wireOutput(self.audioOutput, buffer) + if output != self.audioOutput: + self.audioOutput = output + # re-wire the audio to the correct client API + buffer = Buffer(self.chain.getOutputFormat()) + self.chain.setWriter(buffer) + self.wireOutput(self.audioOutput, buffer) + except DemodulatorError as de: + self.handler.write_demodulator_error(str(de)) def _getSecondaryDemodulator(self, mod) -> Optional[SecondaryDemodulator]: if isinstance(mod, SecondaryDemodulator):