openwebrx-clone/owrx/audio/chopper.py

88 lines
2.8 KiB
Python
Raw Normal View History

from owrx.modes import Modes, AudioChopperMode
from itertools import groupby
import threading
from owrx.audio import ProfileSourceSubscriber
from owrx.audio.wav import AudioWriter
2021-08-31 20:46:11 +00:00
from owrx.audio.queue import QueueJob
2021-08-31 14:54:37 +00:00
from csdr.chain import Chain
import pickle
import logging
logger = logging.getLogger(__name__)
logger.setLevel(logging.INFO)
2021-08-31 14:54:37 +00:00
class AudioChopper(threading.Thread, Chain, ProfileSourceSubscriber):
# TODO parser typing
def __init__(self, mode_str: str, parser):
self.parser = parser
2021-08-31 20:46:11 +00:00
self.dialFrequency = None
self.doRun = True
self.writers = []
mode = Modes.findByModulation(mode_str)
if mode is None or not isinstance(mode, AudioChopperMode):
raise ValueError("Mode {} is not an audio chopper mode".format(mode_str))
self.profile_source = mode.get_profile_source()
super().__init__()
2021-08-31 14:54:37 +00:00
Chain.__init__(self, [])
def stop_writers(self):
while self.writers:
self.writers.pop().stop()
def setup_writers(self):
self.stop_writers()
sorted_profiles = sorted(self.profile_source.getProfiles(), key=lambda p: p.getInterval())
groups = {interval: list(group) for interval, group in groupby(sorted_profiles, key=lambda p: p.getInterval())}
2021-05-01 14:51:02 +00:00
writers = [
2021-08-31 14:54:37 +00:00
AudioWriter(self, interval, profiles) for interval, profiles in groups.items()
2021-05-01 14:51:02 +00:00
]
2021-04-11 18:10:49 +00:00
for w in writers:
w.start()
2021-04-11 18:10:49 +00:00
self.writers = writers
2021-08-31 14:54:37 +00:00
def setReader(self, reader):
super().setReader(reader)
self.start()
2021-08-31 14:54:37 +00:00
def stop(self):
self.reader.stop()
super().stop()
def run(self) -> None:
logger.debug("Audio chopper starting up")
self.setup_writers()
self.profile_source.subscribe(self)
while self.doRun:
data = None
try:
2021-08-31 14:54:37 +00:00
data = self.reader.read()
except ValueError:
pass
2021-08-31 14:54:37 +00:00
if data is None:
self.doRun = False
else:
for w in self.writers:
2021-08-31 14:54:37 +00:00
w.write(data.tobytes())
logger.debug("Audio chopper shutting down")
self.profile_source.unsubscribe(self)
self.stop_writers()
def onProfilesChanged(self):
logger.debug("profile change received, resetting writers...")
self.setup_writers()
2021-08-31 20:46:11 +00:00
def setDialFrequency(self, frequency: int) -> None:
self.dialFrequency = frequency
def createJob(self, profile, filename):
return QueueJob(profile, self.dialFrequency, self, filename)
def sendResult(self, result):
for line in result.lines:
data = self.parser.parse(result.profile, result.frequency, line)
if data is not None and self.writer is not None:
self.writer.write(pickle.dumps(data))