openwebrx/owrx/fft.py

110 lines
3.2 KiB
Python
Raw Normal View History

from owrx.config import Config
from csdr.chain.fft import FftChain
from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass
from owrx.property import PropertyStack
from pycsdr.modules import Buffer
import threading
import logging
logger = logging.getLogger(__name__)
class SpectrumThread(SdrSourceEventClient):
def __init__(self, sdrSource):
self.sdrSource = sdrSource
super().__init__()
stack = PropertyStack()
stack.addLayer(0, self.sdrSource.props)
stack.addLayer(1, Config.get())
self.props = stack.filter(
"samp_rate",
"fft_size",
"fft_fps",
"fft_voverlap_factor",
"fft_compression",
)
self.dsp = None
self.reader = None
self.subscriptions = []
logger.debug("Spectrum thread initialized successfully.")
def start(self):
if self.dsp is not None:
return
self.dsp = FftChain(
self.props['samp_rate'],
self.props['fft_size'],
self.props['fft_voverlap_factor'],
self.props['fft_fps'],
self.props['fft_compression']
)
self.sdrSource.addClient(self)
self.subscriptions += [
2021-09-27 17:29:51 +02:00
self.props.filter("fft_size").wire(self.restart),
# these props can be set on the fly
self.props.wireProperty("samp_rate", self.dsp.setSampleRate),
self.props.wireProperty("fft_fps", self.dsp.setFps),
self.props.wireProperty("fft_voverlap_factor", self.dsp.setVOverlapFactor),
self.props.wireProperty("fft_compression", self._setCompression),
]
if self.sdrSource.isAvailable():
self.dsp.setReader(self.sdrSource.getBuffer().getReader())
def _setCompression(self, compression):
if self.reader:
self.reader.stop()
try:
self.dsp.setCompression(compression)
except ValueError:
# expected since the compressions have different formats
pass
buffer = Buffer(self.dsp.getOutputFormat())
self.dsp.setWriter(buffer)
self.reader = buffer.getReader()
threading.Thread(target=self.dsp.pump(self.reader.read, self.sdrSource.writeSpectrumData)).start()
2024-01-28 17:04:35 +01:00
def stopDsp(self):
2024-01-31 02:06:53 +01:00
if self.dsp is not None:
self.dsp.stop()
self.dsp = None
if self.reader is not None:
self.reader.stop()
self.reader = None
2024-01-28 17:04:35 +01:00
def stop(self):
self.stopDsp()
self.sdrSource.removeClient(self)
while self.subscriptions:
self.subscriptions.pop().cancel()
def restart(self, *args, **kwargs):
self.stop()
self.start()
2021-02-20 22:54:07 +01:00
def getClientClass(self) -> SdrClientClass:
return SdrClientClass.USER
2021-02-20 22:54:07 +01:00
def onStateChange(self, state: SdrSourceState):
if state is SdrSourceState.STOPPING:
2024-01-28 17:04:35 +01:00
self.stopDsp()
2021-07-15 18:09:39 +02:00
elif state == SdrSourceState.RUNNING:
if self.dsp is None:
self.start()
else:
2021-08-16 16:41:18 +02:00
self.dsp.setReader(self.sdrSource.getBuffer().getReader())
def onFail(self):
2024-01-28 17:04:35 +01:00
self.stopDsp()
def onShutdown(self):
2024-01-28 17:04:35 +01:00
self.stopDsp()