diff --git a/boswatch/inputSource/pulseaudioInput.py b/boswatch/inputSource/pulseaudioInput.py new file mode 100644 index 0000000..39957a6 --- /dev/null +++ b/boswatch/inputSource/pulseaudioInput.py @@ -0,0 +1,77 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- +"""! + ____ ____ ______ __ __ __ _____ + / __ )/ __ \/ ___/ | / /___ _/ /______/ /_ |__ / + / __ / / / /\__ \| | /| / / __ `/ __/ ___/ __ \ /_ < + / /_/ / /_/ /___/ /| |/ |/ / /_/ / /_/ /__/ / / / ___/ / +/_____/\____//____/ |__/|__/\__,_/\__/\___/_/ /_/ /____/ + German BOS Information Script + by Bastian Schroll + +@file: pulseaudioInput.py +@date: 18.04.2020, 29.06.2020 +@author: Philipp von Kirschbaum, b-watch +@description: Input source for PulseAudio +""" +import logging +from boswatch.utils import paths +from boswatch.processManager import ProcessManager +from boswatch.inputSource.inputBase import InputBase + +logging.debug("- %s loaded", __name__) + + +class PulseAudioInput(InputBase): + """!Class for the PulseAudio input source""" + + def _runThread(self, dataQueue, PulseAudioConfig, decoderConfig): + PulseAudioProc = None + mmProc = None + try: + PulseAudioProc = ProcessManager("parec") + PulseAudioProc.addArgument("--channels=1") # supress any other outputs + PulseAudioProc.addArgument("--format=s16le") # set output format (16bit) + PulseAudioProc.addArgument("--rate=22050") # set output sampling rate (22050Hz) + PulseAudioProc.addArgument("--device=" + + str(PulseAudioConfig.get("device", default="boswatch")) + + ".monitor") # sink name + PulseAudioProc.setStderr(open(paths.LOG_PATH + "pulseaudio.log", "a")) + PulseAudioProc.start() + + mmProc = ProcessManager(str(PulseAudioConfig.get("mmPath", default="multimon-ng")), textMode=True) + if decoderConfig.get("fms", default=0): + mmProc.addArgument("-a FMSFSK") + if decoderConfig.get("zvei", default=0): + mmProc.addArgument("-a ZVEI1") + if decoderConfig.get("poc512", default=0): + mmProc.addArgument("-a POCSAG512") + if decoderConfig.get("poc1200", default=0): + mmProc.addArgument("-a POCSAG1200") + if decoderConfig.get("poc2400", default=0): + mmProc.addArgument("-a POCSAG2400") + if PulseAudioConfig.get("mmChar"): + mmProc.addArgument("-C " + str(PulseAudioConfig.get("mmChar"))) + mmProc.addArgument("-f alpha") + mmProc.addArgument("-t raw -") + mmProc.setStdin(PulseAudioProc.stdout) + mmProc.setStderr(open(paths.LOG_PATH + "multimon-ng.log", "a")) + mmProc.start() + + logging.info("start decoding") + while self._isRunning: + if not PulseAudioProc.isRunning: + logging.warning("asla was down - try to restart") + PulseAudioProc.start() + elif not mmProc.isRunning: + logging.warning("multimon was down - try to restart") + mmProc.start() + elif PulseAudioProc.isRunning and mmProc.isRunning: + line = mmProc.readline() + if line: + self.addToQueue(line) + except: + logging.exception("error in PulseAudio input routine") + finally: + mmProc.stop() + PulseAudioProc.stop() diff --git a/bw_client.py b/bw_client.py index 3abe98c..560f05b 100644 --- a/bw_client.py +++ b/bw_client.py @@ -51,6 +51,7 @@ from boswatch.utils import header from boswatch.utils import misc from boswatch.inputSource.sdrInput import SdrInput from boswatch.inputSource.lineInInput import LineInInput +from boswatch.inputSource.pulseaudioInput import PulseAudioInput header.logoToLog() header.infoToLog() @@ -91,6 +92,8 @@ try: inputSource = SdrInput(inputQueue, bwConfig.get("inputSource", "sdr"), bwConfig.get("decoder")) elif bwConfig.get("client", "inputSource") == "lineIn": inputSource = LineInInput(inputQueue, bwConfig.get("inputSource", "lineIn"), bwConfig.get("decoder")) + elif bwConfig.get("client", "inputSource") == "PulseAudio": + inputSource = PulseAudioInput(inputQueue, bwConfig.get("inputSource", "PulseAudio"), bwConfig.get("decoder")) else: logging.fatal("Invalid input source: %s", bwConfig.get("client", "inputSource")) exit(1) diff --git a/docu/docs/config.md b/docu/docs/config.md index a5598a2..c5d38b6 100644 --- a/docu/docs/config.md +++ b/docu/docs/config.md @@ -11,7 +11,7 @@ zwingend in die Konfiguration eingetragen werden. |Feld|Beschreibung|Default| |----|------------|-------| |name|Name zur Identifizierung der Client Instanz|| -|inputSource|Art der zu nutzenden Input Quelle (`sdr` oder `lineIn`)|| +|inputSource|Art der zu nutzenden Input Quelle (`sdr`, `lineIn` oder `PulseAudio`)|| |useBroadcast|Verbindungsdaten per [Broadcast](information/broadcast.md) beziehen|no| |reconnectDelay|Verzögerung für erneuten Verbindungsversuch zum Server|3| |sendTries|Anzahl der Sendeversuche eines Pakets|3| @@ -36,7 +36,7 @@ server: --- ### `inputSource:` -Es gibt die Auswahl zwischen `sdr` oder `lineIn` als Input Quelle +Es gibt die Auswahl zwischen `sdr`, `lineIn` oder `PulseAudio` als Input Quelle #### `sdr:` |Feld|Beschreibung|Default| @@ -114,6 +114,32 @@ inputSource: mmChar: DE ``` +#### `PulseAudio:` +|Feld|Beschreibung|Default| +|----|------------|-------| +|device|Der Sinks-Name der Quelle|boswatch| +|mmPath|Pfad zur multimon-ng Binary|multimon-ng| +|mmChar|multimon-ng Char-Set|not set| + + +**Device herausfinden** +Durch eingabe des Befehls `pacmd list-sinks | grep name:` werden alle Sinks ausgegeben. Beispiel: +```console +bash-5.0# pacmd list-sinks | grep name: + name: +``` + +In der Konfiguration wird das Feld `device` nun auf den den Namen des gewünschten Sinks gesetzt (ohne spitze Klammern, <>). + +**Beispiel:** +```yaml +inputSource: + ... + PulseAudio: + device: boswatch + mmPath: /opt/multimon/multimon-ng + mmChar: DE +``` --- ### `decoder:` |Feld|Beschreibung|Default|