move the pump mechanism, allowing the old output code to be removed
This commit is contained in:
		| @@ -28,8 +28,6 @@ import threading | |||||||
| import math | import math | ||||||
| from functools import partial | from functools import partial | ||||||
|  |  | ||||||
| from csdr.output import Output |  | ||||||
|  |  | ||||||
| from owrx.aprs.direwolf import DirewolfConfig, DirewolfConfigSubscriber | from owrx.aprs.direwolf import DirewolfConfig, DirewolfConfigSubscriber | ||||||
| from owrx.audio.chopper import AudioChopper | from owrx.audio.chopper import AudioChopper | ||||||
|  |  | ||||||
| @@ -48,7 +46,7 @@ logger = logging.getLogger(__name__) | |||||||
|  |  | ||||||
|  |  | ||||||
| class Dsp(DirewolfConfigSubscriber): | class Dsp(DirewolfConfigSubscriber): | ||||||
|     def __init__(self, output: Output): |     def __init__(self, output): | ||||||
|         self.pycsdr_enabled = True |         self.pycsdr_enabled = True | ||||||
|         self.pycsdr_chain = None |         self.pycsdr_chain = None | ||||||
|         self.pycsdr_client_chain = None |         self.pycsdr_client_chain = None | ||||||
|   | |||||||
| @@ -145,23 +145,3 @@ class Chain(Module): | |||||||
|             return self.workers[-1].getOutputFormat() |             return self.workers[-1].getOutputFormat() | ||||||
|         else: |         else: | ||||||
|             raise BufferError("getOutputFormat on empty chain") |             raise BufferError("getOutputFormat on empty chain") | ||||||
|  |  | ||||||
|     def pump(self, write): |  | ||||||
|         if self.writer is None: |  | ||||||
|             self.setWriter(Buffer(self.getOutputFormat())) |  | ||||||
|         self.clientReader = self.writer.getReader() |  | ||||||
|  |  | ||||||
|         def copy(): |  | ||||||
|             run = True |  | ||||||
|             while run: |  | ||||||
|                 data = None |  | ||||||
|                 try: |  | ||||||
|                     data = self.clientReader.read() |  | ||||||
|                 except ValueError: |  | ||||||
|                     pass |  | ||||||
|                 if data is None: |  | ||||||
|                     run = False |  | ||||||
|                 else: |  | ||||||
|                     write(data) |  | ||||||
|  |  | ||||||
|         return copy |  | ||||||
|   | |||||||
| @@ -29,6 +29,20 @@ class Module(BaseModule, metaclass=ABCMeta): | |||||||
|     def getOutputFormat(self) -> Format: |     def getOutputFormat(self) -> Format: | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|  |     def pump(self, read, write): | ||||||
|  |         def copy(): | ||||||
|  |             while True: | ||||||
|  |                 data = None | ||||||
|  |                 try: | ||||||
|  |                     data = read() | ||||||
|  |                 except ValueError: | ||||||
|  |                     pass | ||||||
|  |                 if data is None or isinstance(data, bytes) and len(data) == 0: | ||||||
|  |                     break | ||||||
|  |                 write(data) | ||||||
|  |  | ||||||
|  |         return copy | ||||||
|  |  | ||||||
|  |  | ||||||
| class AutoStartModule(Module, metaclass=ABCMeta): | class AutoStartModule(Module, metaclass=ABCMeta): | ||||||
|     def _checkStart(self) -> None: |     def _checkStart(self) -> None: | ||||||
| @@ -47,20 +61,6 @@ class AutoStartModule(Module, metaclass=ABCMeta): | |||||||
|     def start(self): |     def start(self): | ||||||
|         pass |         pass | ||||||
|  |  | ||||||
|     def pump(self, read, write): |  | ||||||
|         def copy(): |  | ||||||
|             while True: |  | ||||||
|                 data = None |  | ||||||
|                 try: |  | ||||||
|                     data = read() |  | ||||||
|                 except ValueError: |  | ||||||
|                     pass |  | ||||||
|                 if data is None or isinstance(data, bytes) and len(data) == 0: |  | ||||||
|                     break |  | ||||||
|                 write(data) |  | ||||||
|  |  | ||||||
|         return copy |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class ThreadModule(AutoStartModule, Thread, metaclass=ABCMeta): | class ThreadModule(AutoStartModule, Thread, metaclass=ABCMeta): | ||||||
|     def __init__(self): |     def __init__(self): | ||||||
|   | |||||||
| @@ -1,36 +0,0 @@ | |||||||
| import threading |  | ||||||
| import logging |  | ||||||
|  |  | ||||||
| logger = logging.getLogger(__name__) |  | ||||||
|  |  | ||||||
|  |  | ||||||
| class Output(object): |  | ||||||
|     def send_output(self, t, read_fn): |  | ||||||
|         if not self.supports_type(t): |  | ||||||
|             # TODO rewrite the output mechanism in a way that avoids producing unnecessary data |  | ||||||
|             logger.warning("dumping output of type %s since it is not supported.", t) |  | ||||||
|             threading.Thread(target=self.pump(read_fn, lambda x: None), name="csdr_pump_thread").start() |  | ||||||
|             return |  | ||||||
|         self.receive_output(t, read_fn) |  | ||||||
|  |  | ||||||
|     def receive_output(self, t, read_fn): |  | ||||||
|         pass |  | ||||||
|  |  | ||||||
|     def pump(self, read, write): |  | ||||||
|         def copy(): |  | ||||||
|             run = True |  | ||||||
|             while run: |  | ||||||
|                 data = None |  | ||||||
|                 try: |  | ||||||
|                     data = read() |  | ||||||
|                 except ValueError: |  | ||||||
|                     pass |  | ||||||
|                 if data is None or (isinstance(data, bytes) and len(data) == 0): |  | ||||||
|                     run = False |  | ||||||
|                 else: |  | ||||||
|                     write(data) |  | ||||||
|  |  | ||||||
|         return copy |  | ||||||
|  |  | ||||||
|     def supports_type(self, t): |  | ||||||
|         return True |  | ||||||
							
								
								
									
										10
									
								
								owrx/dsp.py
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								owrx/dsp.py
									
									
									
									
									
								
							| @@ -4,7 +4,6 @@ from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass | |||||||
| from owrx.property import PropertyStack, PropertyLayer, PropertyValidator | from owrx.property import PropertyStack, PropertyLayer, PropertyValidator | ||||||
| from owrx.property.validators import OrValidator, RegexValidator, BoolValidator | from owrx.property.validators import OrValidator, RegexValidator, BoolValidator | ||||||
| from owrx.modes import Modes | from owrx.modes import Modes | ||||||
| from csdr.output import Output |  | ||||||
| from csdr.chain import Chain | from csdr.chain import Chain | ||||||
| from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver | from csdr.chain.demodulator import BaseDemodulatorChain, FixedIfSampleRateChain, FixedAudioRateChain, HdAudio, SecondaryDemodulator, DialFrequencyReceiver | ||||||
| from csdr.chain.selector import Selector | from csdr.chain.selector import Selector | ||||||
| @@ -287,7 +286,7 @@ class ModulationValidator(OrValidator): | |||||||
|         super().__init__(BoolValidator(), RegexValidator(re.compile("^[a-z0-9]+$"))) |         super().__init__(BoolValidator(), RegexValidator(re.compile("^[a-z0-9]+$"))) | ||||||
|  |  | ||||||
|  |  | ||||||
| class DspManager(Output, SdrSourceEventClient): | class DspManager(SdrSourceEventClient): | ||||||
|     def __init__(self, handler, sdrSource): |     def __init__(self, handler, sdrSource): | ||||||
|         self.handler = handler |         self.handler = handler | ||||||
|         self.sdrSource = sdrSource |         self.sdrSource = sdrSource | ||||||
| @@ -540,7 +539,7 @@ class DspManager(Output, SdrSourceEventClient): | |||||||
|  |  | ||||||
|         reader = buffer.getReader() |         reader = buffer.getReader() | ||||||
|         self.readers[t] = reader |         self.readers[t] = reader | ||||||
|         threading.Thread(target=self.pump(reader.read, write), name="dsp_pump_{}".format(t)).start() |         threading.Thread(target=self.chain.pump(reader.read, write), name="dsp_pump_{}".format(t)).start() | ||||||
|  |  | ||||||
|     def _unpickle(self, callback): |     def _unpickle(self, callback): | ||||||
|         def unpickler(data): |         def unpickler(data): | ||||||
| @@ -554,8 +553,9 @@ class DspManager(Output, SdrSourceEventClient): | |||||||
|         return unpickler |         return unpickler | ||||||
|  |  | ||||||
|     def stop(self): |     def stop(self): | ||||||
|         self.chain.stop() |         if self.chain: | ||||||
|         self.chain = None |             self.chain.stop() | ||||||
|  |             self.chain = None | ||||||
|         for reader in self.readers.values(): |         for reader in self.readers.values(): | ||||||
|             reader.stop() |             reader.stop() | ||||||
|         self.readers = {} |         self.readers = {} | ||||||
|   | |||||||
							
								
								
									
										12
									
								
								owrx/fft.py
									
									
									
									
									
								
							
							
						
						
									
										12
									
								
								owrx/fft.py
									
									
									
									
									
								
							| @@ -1,9 +1,9 @@ | |||||||
| from owrx.config.core import CoreConfig |  | ||||||
| from owrx.config import Config | from owrx.config import Config | ||||||
| from csdr.chain.fft import FftChain | from csdr.chain.fft import FftChain | ||||||
| import threading |  | ||||||
| from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass | from owrx.source import SdrSourceEventClient, SdrSourceState, SdrClientClass | ||||||
| from owrx.property import PropertyStack | from owrx.property import PropertyStack | ||||||
|  | from pycsdr.modules import Buffer | ||||||
|  | import threading | ||||||
|  |  | ||||||
| import logging | import logging | ||||||
|  |  | ||||||
| @@ -27,6 +27,7 @@ class SpectrumThread(SdrSourceEventClient): | |||||||
|         ) |         ) | ||||||
|  |  | ||||||
|         self.dsp = None |         self.dsp = None | ||||||
|  |         self.reader = None | ||||||
|  |  | ||||||
|         self.subscriptions = [] |         self.subscriptions = [] | ||||||
|  |  | ||||||
| @@ -53,7 +54,10 @@ class SpectrumThread(SdrSourceEventClient): | |||||||
|             self.props.wireProperty("fft_voverlap_factor", self.dsp.setVOverlapFactor), |             self.props.wireProperty("fft_voverlap_factor", self.dsp.setVOverlapFactor), | ||||||
|         ] |         ] | ||||||
|  |  | ||||||
|         threading.Thread(target=self.dsp.pump(self.sdrSource.writeSpectrumData)).start() |         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() | ||||||
|  |  | ||||||
|         if self.sdrSource.isAvailable(): |         if self.sdrSource.isAvailable(): | ||||||
|             self.dsp.setReader(self.sdrSource.getBuffer().getReader()) |             self.dsp.setReader(self.sdrSource.getBuffer().getReader()) | ||||||
| @@ -63,6 +67,8 @@ class SpectrumThread(SdrSourceEventClient): | |||||||
|             return |             return | ||||||
|         self.dsp.stop() |         self.dsp.stop() | ||||||
|         self.dsp = None |         self.dsp = None | ||||||
|  |         self.reader.stop() | ||||||
|  |         self.reader = None | ||||||
|         self.sdrSource.removeClient(self) |         self.sdrSource.removeClient(self) | ||||||
|         while self.subscriptions: |         while self.subscriptions: | ||||||
|             self.subscriptions.pop().cancel() |             self.subscriptions.pop().cancel() | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Jakob Ketterl
					Jakob Ketterl