diff --git a/csdr/chain/digiham.py b/csdr/chain/digiham.py index fa52ead..5979529 100644 --- a/csdr/chain/digiham.py +++ b/csdr/chain/digiham.py @@ -1,11 +1,12 @@ -from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain -from pycsdr.modules import FmDemod, Agc, Writer +from csdr.chain.demodulator import BaseDemodulatorChain, FixedAudioRateChain, FixedIfSampleRateChain, DialFrequencyReceiver +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 owrx.meta import MetaParser -class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain): +class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, DialFrequencyReceiver): def __init__(self, fskDemodulator, decoder, mbeMode, filter=None, codecserver: str = ""): self.decoder = decoder if codecserver is None: @@ -23,6 +24,7 @@ class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateC DigitalVoiceFilter(), agc ] + self.metaParser = None super().__init__(workers) def getFixedIfSampleRate(self): @@ -32,11 +34,26 @@ class DigihamChain(BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateC return 8000 def setMetaWriter(self, writer: Writer): - self.decoder.setMetaWriter(writer) + if self.metaParser is None: + self.metaParser = MetaParser() + buffer = Buffer(Format.CHAR) + self.decoder.setMetaWriter(buffer) + self.metaParser.setReader(buffer.getReader()) + self.metaParser.setWriter(writer) def supportsSquelch(self): return False + def setDialFrequency(self, frequency: int) -> None: + if self.metaParser is None: + return + self.metaParser.setDialFrequency(frequency) + + def stop(self): + if self.metaParser is not None: + self.metaParser.stop() + super().stop() + class Dstar(DigihamChain): def __init__(self, codecserver: str = ""): diff --git a/owrx/connection.py b/owrx/connection.py index 62771e5..1a58ea6 100644 --- a/owrx/connection.py +++ b/owrx/connection.py @@ -420,7 +420,12 @@ class OpenWebRxReceiverClient(OpenWebRxClient, SdrSourceEventClient): self.send({"type": "features", "value": features}) def write_metadata(self, metadata): - self.send({"type": "metadata", "value": metadata}) + io = BytesIO(metadata.tobytes()) + try: + while True: + self.send({"type": "metadata", "value": pickle.load(io)}) + except EOFError: + pass def write_dial_frequencies(self, frequencies): self.send({"type": "dial_frequencies", "value": frequencies}) diff --git a/owrx/dsp.py b/owrx/dsp.py index 6b04a27..2afb012 100644 --- a/owrx/dsp.py +++ b/owrx/dsp.py @@ -1,4 +1,3 @@ -from owrx.meta import MetaParser from owrx.wsjt import WsjtParser from owrx.js8 import Js8Parser from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass @@ -192,6 +191,8 @@ class ClientDemodulatorChain(Chain): if self.centerFrequency is None or self.frequencyOffset is None: return dialFrequency = self.centerFrequency + self.frequencyOffset + if isinstance(self.demodulator, DialFrequencyReceiver): + self.demodulator.setDialFrequency(dialFrequency) if isinstance(self.secondaryDemodulator, DialFrequencyReceiver): self.secondaryDemodulator.setDialFrequency(dialFrequency) @@ -286,9 +287,6 @@ class DspManager(Output, SdrSourceEventClient): def __init__(self, handler, sdrSource): self.handler = handler self.sdrSource = sdrSource - self.parsers = { - "meta": MetaParser(self.handler), - } self.props = PropertyStack() @@ -527,9 +525,8 @@ class DspManager(Output, SdrSourceEventClient): "smeter": self.handler.write_s_meter_level, "secondary_fft": self.handler.write_secondary_fft, "secondary_demod": self.handler.write_secondary_demod, + "meta": self.handler.write_metadata, } - for demod, parser in self.parsers.items(): - writers[demod] = parser.parse write = writers[t] diff --git a/owrx/meta.py b/owrx/meta.py index b995910..121b4e3 100644 --- a/owrx/meta.py +++ b/owrx/meta.py @@ -1,12 +1,18 @@ -from owrx.config import Config -from urllib import request import json -from datetime import datetime, timedelta import logging import threading -from owrx.map import Map, LatLngLocation -from owrx.aprs import AprsParser, AprsLocation +import pickle from abc import ABC, abstractmethod +from datetime import datetime, timedelta +from urllib import request + +from pycsdr.types import Format + +from csdr.module import ThreadModule +from owrx.aprs import AprsParser, AprsLocation +from owrx.config import Config +from owrx.map import Map, LatLngLocation +from owrx.bands import Bandplan logger = logging.getLogger(__name__) @@ -158,9 +164,8 @@ class DStarEnricher(Enricher): return meta -class MetaParser: - def __init__(self, handler): - self.handler = handler +class MetaParser(ThreadModule): + def __init__(self): self.enrichers = { "DMR": RadioIDEnricher("dmr", self), "YSF": YsfMetaEnricher(self), @@ -168,6 +173,23 @@ class MetaParser: "NXDN": RadioIDEnricher("nxdn", self), } self.currentMetaData = None + self.band = None + super().__init__() + + def getInputFormat(self) -> Format: + return Format.CHAR + + def getOutputFormat(self) -> Format: + return Format.CHAR + + def run(self): + while self.doRun: + data = self.reader.read() + if data is None: + self.doRun = False + else: + for result in self.parse(data): + self.writer.write(pickle.dumps(result)) def parse(self, raw: memoryview): try: @@ -185,10 +207,16 @@ class MetaParser: protocol = meta["protocol"] if protocol in self.enrichers: self.currentMetaData = meta = self.enrichers[protocol].enrich(meta, self.receive) - self.handler.write_metadata(meta) + yield meta def receive(self, meta): # we may have moved on in the meantime if meta is not self.currentMetaData: return - self.handler.write_metadata(meta) + self.writer.write(pickle.dumps(meta)) + + def setDialFrequency(self, freq): + self.band = Bandplan.getSharedInstance().findBand(freq) + + def getBand(self): + return self.band