91 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			91 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
from owrx.config.core import CoreConfig
 | 
						|
from owrx.config import Config
 | 
						|
import csdr
 | 
						|
from csdr.output import Output
 | 
						|
import threading
 | 
						|
from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass
 | 
						|
from owrx.property import PropertyStack
 | 
						|
 | 
						|
import logging
 | 
						|
 | 
						|
logger = logging.getLogger(__name__)
 | 
						|
 | 
						|
 | 
						|
class SpectrumThread(Output, 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 = props = stack.filter(
 | 
						|
            "samp_rate",
 | 
						|
            "fft_size",
 | 
						|
            "fft_fps",
 | 
						|
            "fft_voverlap_factor",
 | 
						|
            "fft_compression",
 | 
						|
        )
 | 
						|
 | 
						|
        self.dsp = dsp = csdr.Dsp(self)
 | 
						|
        dsp.nc_port = self.sdrSource.getPort()
 | 
						|
        dsp.set_demodulator("fft")
 | 
						|
 | 
						|
        def set_fft_averages(changes=None):
 | 
						|
            samp_rate = props["samp_rate"]
 | 
						|
            fft_size = props["fft_size"]
 | 
						|
            fft_fps = props["fft_fps"]
 | 
						|
            fft_voverlap_factor = props["fft_voverlap_factor"]
 | 
						|
 | 
						|
            dsp.set_fft_averages(
 | 
						|
                int(round(1.0 * samp_rate / fft_size / fft_fps / (1.0 - fft_voverlap_factor)))
 | 
						|
                if fft_voverlap_factor > 0
 | 
						|
                else 0
 | 
						|
            )
 | 
						|
 | 
						|
        self.subscriptions = [
 | 
						|
            props.wireProperty("samp_rate", dsp.set_samp_rate),
 | 
						|
            props.wireProperty("fft_size", dsp.set_fft_size),
 | 
						|
            props.wireProperty("fft_fps", dsp.set_fft_fps),
 | 
						|
            props.wireProperty("fft_compression", dsp.set_fft_compression),
 | 
						|
            props.filter("samp_rate", "fft_size", "fft_fps", "fft_voverlap_factor").wire(set_fft_averages),
 | 
						|
        ]
 | 
						|
 | 
						|
        set_fft_averages()
 | 
						|
 | 
						|
        dsp.set_temporary_directory(CoreConfig().get_temporary_directory())
 | 
						|
        logger.debug("Spectrum thread initialized successfully.")
 | 
						|
 | 
						|
    def start(self):
 | 
						|
        self.sdrSource.addClient(self)
 | 
						|
        if self.sdrSource.isAvailable():
 | 
						|
            self.dsp.start()
 | 
						|
 | 
						|
    def supports_type(self, t):
 | 
						|
        return t == "audio"
 | 
						|
 | 
						|
    def receive_output(self, type, read_fn):
 | 
						|
        threading.Thread(target=self.pump(read_fn, self.sdrSource.writeSpectrumData)).start()
 | 
						|
 | 
						|
    def stop(self):
 | 
						|
        self.dsp.stop()
 | 
						|
        self.sdrSource.removeClient(self)
 | 
						|
        for c in self.subscriptions:
 | 
						|
            c.cancel()
 | 
						|
        self.subscriptions = []
 | 
						|
 | 
						|
    def getClientClass(self) -> SdrClientClass:
 | 
						|
        return SdrClientClass.USER
 | 
						|
 | 
						|
    def onStateChange(self, state: SdrSourceState):
 | 
						|
        if state is SdrSourceState.STOPPING:
 | 
						|
            self.dsp.stop()
 | 
						|
        elif state is SdrSourceState.RUNNING:
 | 
						|
            self.dsp.start()
 | 
						|
 | 
						|
    def onFail(self):
 | 
						|
        self.dsp.stop()
 | 
						|
 | 
						|
    def onShutdown(self):
 | 
						|
        self.dsp.stop()
 |