91 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.6 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| from owrx.config.core import CoreConfig
 | |
| from owrx.config import Config
 | |
| from csdr.chain.fft import FftChain
 | |
| import threading
 | |
| from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass
 | |
| from owrx.property import PropertyStack
 | |
| 
 | |
| 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.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 += [
 | |
|             self.props.filter("fft_size", "fft_compression").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),
 | |
|         ]
 | |
| 
 | |
|         threading.Thread(target=self.dsp.pump(self.sdrSource.writeSpectrumData)).start()
 | |
| 
 | |
|         if self.sdrSource.isAvailable():
 | |
|             self.dsp.setInput(self.sdrSource.getBuffer())
 | |
| 
 | |
|     def stop(self):
 | |
|         if self.dsp is None:
 | |
|             return
 | |
|         self.dsp.stop()
 | |
|         self.dsp = None
 | |
|         self.sdrSource.removeClient(self)
 | |
|         while self.subscriptions:
 | |
|             self.subscriptions.pop().cancel()
 | |
| 
 | |
|     def restart(self, *args, **kwargs):
 | |
|         self.stop()
 | |
|         self.start()
 | |
| 
 | |
|     def getClientClass(self) -> SdrClientClass:
 | |
|         return SdrClientClass.USER
 | |
| 
 | |
|     def onStateChange(self, state: SdrSourceState):
 | |
|         if state is SdrSourceState.STOPPING:
 | |
|             self.dsp.stop()
 | |
|         elif state == SdrSourceState.RUNNING:
 | |
|             if self.dsp is None:
 | |
|                 self.start()
 | |
|             else:
 | |
|                 self.dsp.setInput(self.sdrSource.getBuffer())
 | |
| 
 | |
|     def onFail(self):
 | |
|         self.dsp.stop()
 | |
| 
 | |
|     def onShutdown(self):
 | |
|         self.dsp.stop()
 | 
