feat(playout): load config using shared helpers

- backport >=py38 Literal type
- update configuration sample
- add missing config filepath to systemd service
- make config sections optional

BREAKING CHANGE: the playout config schema has been changed like the following:
- the top section 'pypo' was renamed to 'playout'
- the 'playout.ls_*' entries were renamed to 'playout.liquidsoap_*'
- the 'playout.*_dir' entries were removed
- the 'playout.api_client' entry was removed
- the 'playout.record_file_type' entry was renamed to 'playout.record_file_format'
- the 'playout.base_recorded_files' entry was removed
- the 'playout.poll_interval' entry was removed
- the 'playout.push_interval' entry was removed
- the 'playout.cue_style' entry was removed
This commit is contained in:
jo 2022-01-18 20:59:11 +01:00 committed by Kyle Robbertze
parent 12f96f5043
commit fa7692071c
12 changed files with 142 additions and 214 deletions

View File

@ -9,7 +9,6 @@
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# G E N E R A L S E T T I N G S # G E N E R A L S E T T I N G S
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@ -73,7 +72,6 @@ auth = local
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# D A T A B A S E # D A T A B A S E
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@ -100,38 +98,21 @@ dbpass = airtime
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# ----------------------------------------------------------------------
# RABBITMQ
# ----------------------------------------------------------------------
# ----------------------------------------------------------------------
# R A B B I T M Q
# ----------------------------------------------------------------------
#
# These settings are used to configure the RabbitMQ messaging
# configuration for your Airtime installation.
#
# host: The IP address for the RabbitMQ service.
# The default is 127.0.0.1.
#
# port: The port for the RabbitMQ service.
# The default is 5672.
#
# user: The username for the RabbitMQ user.
# The default is airtime.
#
# password: The password for the RabbitMQ user.
# The default is airtime.
#
# vhost: The virtual host for the RabbitMQ service database.
# The default is /airtime.
#
[rabbitmq] [rabbitmq]
host = 127.0.0.1 # The host for the RabbitMQ service, default is localhost
host = localhost
# The port for the RabbitMQ service, default is 5672
port = 5672 port = 5672
user = airtime # The virtual host for the RabbitMQ service, default is /libretime
password = airtime
vhost = /airtime vhost = /airtime
# # The user for the RabbitMQ user, default is libretime
# ---------------------------------------------------------------------- user = airtime
# The password for the RabbitMQ user, default is libretime
password = airtime
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# S T O R A G E # S T O R A G E
@ -140,7 +121,6 @@ vhost = /airtime
[current_backend] [current_backend]
storage_backend=file storage_backend=file
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# M O N I T # M O N I T
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
@ -157,115 +137,26 @@ password =
# #
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# P Y P O # PLAYOUT
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# [playout]
# api_client: Set the type of client you are using. # Liquidsoap connection host, default is localhost
# Currently supported types: liquidsoap_host = localhost
# 1) 'obp' = Open Broadcast Platform # Liquidsoap connection port, default is 1234
# 2) 'airtime' liquidsoap_port = 1234
# The default is 'airtime'
# # The format for recordings, allowed values ogg|mp3, default is ogg
# cache_dir: The directory for pypo cache files record_file_format = ogg
# The default is '/var/tmp/airtime/pypo/cache/' # The bitrate for recordings, default is 256
#
# file_dir: The directory for pypo media files
# The default is '/var/tmp/airtime/pypo/files/'
#
# tmp_dir: The directory for pypo temp files
# The default is '/var/tmp/airtime/pypo/tmp/'
#
# cache_base_dir: The pypo base cache directory
# The default is '/var/tmp/airtime/pypo/'
#
# log_base_dir: The base directory for Airtime log files
# The default is '/var/log/airtime'
#
# pypo_log_dir: The directory for pypo log files
# The default is '/var/log/airtime/pypo'
#
# liquidsoap_log_dir: The directory for liquidsoap log files
# The default is '/var/log/airtime/pypo-liquidsoap'
#
# ls_host: Liquidsoap connection host
# The default is '127.0.0.1'
#
# ls_port: Liquidsoap connection port
# The default is '1234'
#
# poll_interval: Poll interval in seconds
#
# This will rarely need to be changed because any schedule
# changes are automatically sent to pypo immediately
# This is how often the poll script downloads new schedules
# and files from the server in the event that no changes
# are made to the schedule
# The default is 3600
#
# push_interval: Push interval in seconds
#
# This is how often the push script checks whether it has
# something new to push to liquidsoap
# The default is 1
#
# cue_style: Can be set to 'pre' or 'otf'
# 'pre' cues while playlist preparation
# 'otf' (on the fly) cues while loading into ls
# (needs the post_processor patch)
# The default is 'pre'
#
# record_bitrate: The bitrate for recordings
# The default is 256
#
# record_samplerate: The samplerate for recordings
# The default is 44100
#
# record_channels: The number of channels for recordings
# The default is 2
#
# record_sample_size: The sample size for recordings
# The default is 16
#
# record_file_type: Can be either ogg|mp3, mp3 recording requires
# installation of the package "lame"
# The default is ogg
#
# base_recorded_files: Base path to store recordered shows at
# The default is '/var/tmp/airtime/show-recorder/'
#
[pypo]
api_client = 'airtime'
# ---------- Cache directories - !! Include trailing slash !! ----------
cache_dir = '/var/tmp/airtime/pypo/cache/'
file_dir = '/var/tmp/airtime/pypo/files/'
tmp_dir = '/var/tmp/airtime/pypo/tmp/'
# ------- Setup directories - !! Don't include trailing slash !! -------
cache_base_dir = '/var/tmp/airtime/pypo'
log_base_dir = '/var/log/airtime'
pypo_log_dir = '/var/log/airtime/pypo'
liquidsoap_log_dir = '/var/log/airtime/pypo-liquidsoap'
# ------------------------ Liquidsoap Settings -------------------------
ls_host = '127.0.0.1'
ls_port = '1234'
# -------------------------- Pypo Preferences --------------------------
poll_interval = 3600
push_interval = 1
cue_style = 'pre'
# ---------------------- Recorded Audio Settings -----------------------
record_bitrate = 256 record_bitrate = 256
# The samplerate for recordings, default is 256
record_samplerate = 44100 record_samplerate = 44100
# The number of channels for recordings, default is 2
record_channels = 2 record_channels = 2
# The sample size for recordings, default is 16
record_sample_size = 16 record_sample_size = 16
record_file_type = 'ogg'
base_recorded_files = '/var/tmp/airtime/show-recorder/'
#
# ----------------------------------------------------------------------
#
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
# F A C E B O O K # F A C E B O O K
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------

View File

@ -3,6 +3,7 @@ Description=Libretime Liquidsoap Service
[Service] [Service]
Environment=LIBRETIME_LOG_FILEPATH=/var/log/libretime/liquidsoap.log Environment=LIBRETIME_LOG_FILEPATH=/var/log/libretime/liquidsoap.log
Environment=LIBRETIME_CONFIG_FILEPATH=/etc/airtime/airtime.conf
ExecStart=/usr/local/bin/libretime-liquidsoap ExecStart=/usr/local/bin/libretime-liquidsoap
User=libretime-playout User=libretime-playout

View File

@ -4,6 +4,7 @@ After=network-online.target
[Service] [Service]
Environment=LIBRETIME_LOG_FILEPATH=/var/log/libretime/playout.log Environment=LIBRETIME_LOG_FILEPATH=/var/log/libretime/playout.log
Environment=LIBRETIME_CONFIG_FILEPATH=/etc/airtime/airtime.conf
WorkingDirectory=/var/lib/libretime/playout WorkingDirectory=/var/lib/libretime/playout
ExecStart=/usr/local/bin/libretime-playout ExecStart=/usr/local/bin/libretime-playout

View File

@ -1,4 +1,24 @@
from pathlib import Path from pathlib import Path
from libretime_shared.config import BaseConfig, RabbitMQConfig
from pydantic import BaseModel
from typing_extensions import Literal
CACHE_DIR = Path.cwd() / "scheduler" CACHE_DIR = Path.cwd() / "scheduler"
RECORD_DIR = Path.cwd() / "recorder" RECORD_DIR = Path.cwd() / "recorder"
class PlayoutConfig(BaseModel):
liquidsoap_host: str = "localhost"
liquidsoap_port: int = 1234
record_file_format: Literal["mp3", "ogg"] = "ogg" # record_file_type
record_bitrate: int = 256
record_samplerate: int = 44100
record_channels: int = 2
record_sample_size: int = 16
class Config(BaseConfig):
rabbitmq = RabbitMQConfig()
playout = PlayoutConfig()

View File

@ -11,12 +11,14 @@ import defusedxml.minidom
from libretime_api_client import version1 as api_client from libretime_api_client import version1 as api_client
from loguru import logger from loguru import logger
from .config import Config
class ListenerStat(Thread): class ListenerStat(Thread):
HTTP_REQUEST_TIMEOUT = 30 # 30 second HTTP request timeout HTTP_REQUEST_TIMEOUT = 30 # 30 second HTTP request timeout
def __init__(self, config): def __init__(self, config: Config):
Thread.__init__(self) Thread.__init__(self)
self.config = config self.config = config
self.api_client = api_client.AirtimeApiClient() self.api_client = api_client.AirtimeApiClient()

View File

@ -16,15 +16,14 @@ from threading import Lock
from typing import Optional from typing import Optional
import click import click
from configobj import ConfigObj
from libretime_api_client.version1 import AirtimeApiClient as ApiClient from libretime_api_client.version1 import AirtimeApiClient as ApiClient
from libretime_shared.cli import cli_logging_options from libretime_shared.cli import cli_config_options, cli_logging_options
from libretime_shared.config import DEFAULT_ENV_PREFIX from libretime_shared.config import DEFAULT_ENV_PREFIX
from libretime_shared.logging import level_from_name, setup_logger from libretime_shared.logging import level_from_name, setup_logger
from loguru import logger from loguru import logger
from . import pure from . import pure
from .config import CACHE_DIR, RECORD_DIR from .config import CACHE_DIR, RECORD_DIR, Config
from .listenerstat import ListenerStat from .listenerstat import ListenerStat
from .pypofetch import PypoFetch from .pypofetch import PypoFetch
from .pypofile import PypoFile from .pypofile import PypoFile
@ -81,15 +80,23 @@ def get_liquidsoap_version(version_string):
return None return None
def liquidsoap_startup_test(telnet_lock, ls_host, ls_port): def liquidsoap_startup_test(telnet_lock, liquidsoap_host, liquidsoap_port):
liquidsoap_version_string = liquidsoap_get_info(telnet_lock, ls_host, ls_port) liquidsoap_version_string = liquidsoap_get_info(
telnet_lock,
liquidsoap_host,
liquidsoap_port,
)
while not liquidsoap_version_string: while not liquidsoap_version_string:
logger.warning( logger.warning(
"Liquidsoap doesn't appear to be running!, " + "Sleeping and trying again" "Liquidsoap doesn't appear to be running!, " + "Sleeping and trying again"
) )
time.sleep(1) time.sleep(1)
liquidsoap_version_string = liquidsoap_get_info(telnet_lock, ls_host, ls_port) liquidsoap_version_string = liquidsoap_get_info(
telnet_lock,
liquidsoap_host,
liquidsoap_port,
)
while pure.version_cmp(liquidsoap_version_string, LIQUIDSOAP_MIN_VERSION) < 0: while pure.version_cmp(liquidsoap_version_string, LIQUIDSOAP_MIN_VERSION) < 0:
logger.warning( logger.warning(
@ -98,24 +105,24 @@ def liquidsoap_startup_test(telnet_lock, ls_host, ls_port):
% LIQUIDSOAP_MIN_VERSION % LIQUIDSOAP_MIN_VERSION
) )
time.sleep(1) time.sleep(1)
liquidsoap_version_string = liquidsoap_get_info(telnet_lock, ls_host, ls_port) liquidsoap_version_string = liquidsoap_get_info(
telnet_lock,
liquidsoap_host,
liquidsoap_port,
)
logger.info("Liquidsoap version string found %s" % liquidsoap_version_string) logger.info("Liquidsoap version string found %s" % liquidsoap_version_string)
@click.command() @click.command()
@cli_logging_options() @cli_logging_options()
def cli(log_level: str, log_filepath: Optional[Path]): @cli_config_options()
def cli(log_level: str, log_filepath: Optional[Path], config_filepath: Optional[Path]):
""" """
Run playout. Run playout.
""" """
setup_logger(level_from_name(log_level), log_filepath) setup_logger(level_from_name(log_level), log_filepath)
config = Config(filepath=config_filepath)
# loading config file
try:
config = ConfigObj("/etc/airtime/airtime.conf")
except Exception as e:
logger.error("Error loading config file: %s", e)
try: try:
for dir_path in [CACHE_DIR, RECORD_DIR]: for dir_path in [CACHE_DIR, RECORD_DIR]:
@ -154,16 +161,16 @@ def cli(log_level: str, log_filepath: Optional[Path]):
telnet_lock = Lock() telnet_lock = Lock()
ls_host = config["pypo"]["ls_host"] liquidsoap_host = config.playout.liquidsoap_host
ls_port = config["pypo"]["ls_port"] liquidsoap_port = config.playout.liquidsoap_port
liquidsoap_startup_test(telnet_lock, ls_host, ls_port) liquidsoap_startup_test(telnet_lock, liquidsoap_host, liquidsoap_port)
pypoFetch_q = Queue() pypoFetch_q = Queue()
recorder_q = Queue() recorder_q = Queue()
pypoPush_q = Queue() pypoPush_q = Queue()
pypo_liquidsoap = PypoLiquidsoap(telnet_lock, ls_host, ls_port) pypo_liquidsoap = PypoLiquidsoap(telnet_lock, liquidsoap_host, liquidsoap_port)
""" """
This queue is shared between pypo-fetch and pypo-file, where pypo-file This queue is shared between pypo-fetch and pypo-file, where pypo-file
@ -174,25 +181,30 @@ def cli(log_level: str, log_filepath: Optional[Path]):
media_q = Queue() media_q = Queue()
# Pass only the configuration sections needed; PypoMessageHandler only needs rabbitmq settings # Pass only the configuration sections needed; PypoMessageHandler only needs rabbitmq settings
pmh = PypoMessageHandler(pypoFetch_q, recorder_q, config["rabbitmq"]) pmh = PypoMessageHandler(pypoFetch_q, recorder_q, config.rabbitmq)
pmh.daemon = True pmh.daemon = True
pmh.start() pmh.start()
pfile = PypoFile(media_q, config["pypo"]) pfile = PypoFile(media_q)
pfile.daemon = True pfile.daemon = True
pfile.start() pfile.start()
pf = PypoFetch( pf = PypoFetch(
pypoFetch_q, pypoPush_q, media_q, telnet_lock, pypo_liquidsoap, config["pypo"] pypoFetch_q,
pypoPush_q,
media_q,
telnet_lock,
pypo_liquidsoap,
config,
) )
pf.daemon = True pf.daemon = True
pf.start() pf.start()
pp = PypoPush(pypoPush_q, telnet_lock, pypo_liquidsoap, config["pypo"]) pp = PypoPush(pypoPush_q, telnet_lock, pypo_liquidsoap, config)
pp.daemon = True pp.daemon = True
pp.start() pp.start()
recorder = Recorder(recorder_q) recorder = Recorder(recorder_q, config)
recorder.daemon = True recorder.daemon = True
recorder.start() recorder.start()

View File

@ -2,13 +2,13 @@ import copy
import json import json
import mimetypes import mimetypes
import os import os
from pathlib import Path
import signal import signal
import subprocess import subprocess
import sys import sys
import telnetlib import telnetlib
import time import time
from datetime import datetime from datetime import datetime
from pathlib import Path
from queue import Empty from queue import Empty
from subprocess import PIPE, Popen from subprocess import PIPE, Popen
from threading import Thread, Timer from threading import Thread, Timer
@ -18,7 +18,7 @@ from libretime_api_client import version2 as api_client
from loguru import logger from loguru import logger
from . import pure from . import pure
from .config import CACHE_DIR from .config import CACHE_DIR, Config
from .timeout import ls_timeout from .timeout import ls_timeout
@ -34,7 +34,13 @@ POLL_INTERVAL = 400
class PypoFetch(Thread): class PypoFetch(Thread):
def __init__( def __init__(
self, pypoFetch_q, pypoPush_q, media_q, telnet_lock, pypo_liquidsoap, config self,
pypoFetch_q,
pypoPush_q,
media_q,
telnet_lock,
pypo_liquidsoap,
config: Config,
): ):
Thread.__init__(self) Thread.__init__(self)
@ -186,7 +192,8 @@ class PypoFetch(Thread):
while True: while True:
try: try:
tn = telnetlib.Telnet( tn = telnetlib.Telnet(
self.config["ls_host"], self.config["ls_port"] self.config.playout.liquidsoap_host,
self.config.playout.liquidsoap_port,
) )
tn.write("exit\n".encode("utf-8")) tn.write("exit\n".encode("utf-8"))
tn.read_all() tn.read_all()
@ -219,7 +226,10 @@ class PypoFetch(Thread):
try: try:
self.telnet_lock.acquire() self.telnet_lock.acquire()
tn = telnetlib.Telnet(self.config["ls_host"], self.config["ls_port"]) tn = telnetlib.Telnet(
self.config.playout.liquidsoap_host,
self.config.playout.liquidsoap_port,
)
# update the boot up time of Liquidsoap. Since Liquidsoap is not restarting, # update the boot up time of Liquidsoap. Since Liquidsoap is not restarting,
# we are manually adjusting the bootup time variable so the status msg will get # we are manually adjusting the bootup time variable so the status msg will get
# updated. # updated.
@ -266,7 +276,10 @@ class PypoFetch(Thread):
# TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!! # TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!
try: try:
self.telnet_lock.acquire() self.telnet_lock.acquire()
tn = telnetlib.Telnet(self.config["ls_host"], self.config["ls_port"]) tn = telnetlib.Telnet(
self.config.playout.liquidsoap_host,
self.config.playout.liquidsoap_port,
)
command = ("vars.stream_metadata_type %s\n" % stream_format).encode("utf-8") command = ("vars.stream_metadata_type %s\n" % stream_format).encode("utf-8")
logger.info(command) logger.info(command)
tn.write(command) tn.write(command)
@ -283,7 +296,10 @@ class PypoFetch(Thread):
# TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!! # TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!
try: try:
self.telnet_lock.acquire() self.telnet_lock.acquire()
tn = telnetlib.Telnet(self.config["ls_host"], self.config["ls_port"]) tn = telnetlib.Telnet(
self.config.playout.liquidsoap_host,
self.config.playout.liquidsoap_port,
)
command = ("vars.default_dj_fade %s\n" % fade).encode("utf-8") command = ("vars.default_dj_fade %s\n" % fade).encode("utf-8")
logger.info(command) logger.info(command)
tn.write(command) tn.write(command)
@ -301,7 +317,10 @@ class PypoFetch(Thread):
try: try:
try: try:
self.telnet_lock.acquire() self.telnet_lock.acquire()
tn = telnetlib.Telnet(self.config["ls_host"], self.config["ls_port"]) tn = telnetlib.Telnet(
self.config.playout.liquidsoap_host,
self.config.playout.liquidsoap_port,
)
command = ("vars.station_name %s\n" % station_name).encode("utf-8") command = ("vars.station_name %s\n" % station_name).encode("utf-8")
logger.info(command) logger.info(command)
tn.write(command) tn.write(command)

View File

@ -1,13 +1,10 @@
import configparser
import hashlib import hashlib
import json
import os import os
import shutil import shutil
import stat import stat
import sys import sys
import time import time
import traceback import traceback
from configparser import NoOptionError
from queue import Empty from queue import Empty
from threading import Thread from threading import Thread
@ -16,15 +13,12 @@ from libretime_api_client import version2 as api_client
from loguru import logger from loguru import logger
from requests.exceptions import ConnectionError, HTTPError, Timeout from requests.exceptions import ConnectionError, HTTPError, Timeout
CONFIG_PATH = "/etc/airtime/airtime.conf"
class PypoFile(Thread): class PypoFile(Thread):
def __init__(self, schedule_queue, config): def __init__(self, schedule_queue):
Thread.__init__(self) Thread.__init__(self)
self.media_queue = schedule_queue self.media_queue = schedule_queue
self.media = None self.media = None
self._config = self.read_config_file(CONFIG_PATH)
self.api_client = api_client.AirtimeApiClient() self.api_client = api_client.AirtimeApiClient()
def copy_file(self, media_item): def copy_file(self, media_item):
@ -158,19 +152,6 @@ class PypoFile(Thread):
return media_item return media_item
def read_config_file(self, config_path):
"""Parse the application's config file located at config_path."""
config = configparser.SafeConfigParser(allow_no_value=True)
try:
config.readfp(open(config_path))
except IOError as e:
logger.debug(
"Failed to open config file at %s: %s" % (config_path, e.strerror)
)
sys.exit()
return config
def main(self): def main(self):
while True: while True:
try: try:

View File

@ -12,6 +12,7 @@ from kombu.connection import Connection
from kombu.messaging import Exchange, Queue from kombu.messaging import Exchange, Queue
from kombu.mixins import ConsumerMixin from kombu.mixins import ConsumerMixin
from kombu.simple import SimpleQueue from kombu.simple import SimpleQueue
from libretime_shared.config import RabbitMQConfig
from loguru import logger from loguru import logger
@ -32,7 +33,7 @@ class RabbitConsumer(ConsumerMixin):
class PypoMessageHandler(Thread): class PypoMessageHandler(Thread):
def __init__(self, pq, rq, config): def __init__(self, pq, rq, config: RabbitMQConfig):
Thread.__init__(self) Thread.__init__(self)
self.pypo_queue = pq self.pypo_queue = pq
self.recorder_queue = rq self.recorder_queue = rq
@ -46,10 +47,9 @@ class PypoMessageHandler(Thread):
) )
schedule_queue = Queue("pypo-fetch", exchange=schedule_exchange, key="foo") schedule_queue = Queue("pypo-fetch", exchange=schedule_exchange, key="foo")
with Connection( with Connection(
self.config["host"], f"amqp://{self.config.user}:{self.config.password}"
self.config["user"], f"@{self.config.host}:{self.config.port}"
self.config["password"], f"/{self.config.vhost}",
self.config["vhost"],
heartbeat=5, heartbeat=5,
) as connection: ) as connection:
rabbit = RabbitConsumer(connection, [schedule_queue], self) rabbit = RabbitConsumer(connection, [schedule_queue], self)

View File

@ -9,10 +9,10 @@ from datetime import datetime, timedelta
from queue import Empty, Queue from queue import Empty, Queue
from threading import Thread from threading import Thread
from configobj import ConfigObj
from libretime_api_client import version1 as api_client from libretime_api_client import version1 as api_client
from loguru import logger from loguru import logger
from .config import Config
from .pypofetch import PypoFetch from .pypofetch import PypoFetch
from .pypoliqqueue import PypoLiqQueue from .pypoliqqueue import PypoLiqQueue
from .timeout import ls_timeout from .timeout import ls_timeout
@ -29,7 +29,7 @@ def is_file(media_item):
class PypoPush(Thread): class PypoPush(Thread):
def __init__(self, q, telnet_lock, pypo_liquidsoap, config): def __init__(self, q, telnet_lock, pypo_liquidsoap, config: Config):
Thread.__init__(self) Thread.__init__(self)
self.api_client = api_client.AirtimeApiClient() self.api_client = api_client.AirtimeApiClient()
self.queue = q self.queue = q
@ -119,7 +119,10 @@ class PypoPush(Thread):
def stop_web_stream_all(self): def stop_web_stream_all(self):
try: try:
self.telnet_lock.acquire() self.telnet_lock.acquire()
tn = telnetlib.Telnet(self.config["LS_HOST"], self.config["LS_PORT"]) tn = telnetlib.Telnet(
self.config.playout.liquidsoap_host,
self.config.playout.liquidsoap_port,
)
# msg = 'dynamic_source.read_stop_all xxx\n' # msg = 'dynamic_source.read_stop_all xxx\n'
msg = "http.stop\n" msg = "http.stop\n"

View File

@ -12,11 +12,10 @@ from threading import Thread
import mutagen import mutagen
import pytz import pytz
from configobj import ConfigObj
from libretime_api_client.version1 import AirtimeApiClient as AirtimeApiClientV1 from libretime_api_client.version1 import AirtimeApiClient as AirtimeApiClientV1
from loguru import logger from loguru import logger
from libretime_playout.config import RECORD_DIR from libretime_playout.config import RECORD_DIR, Config
def api_client(): def api_client():
@ -27,13 +26,6 @@ def api_client():
return AirtimeApiClientV1() return AirtimeApiClientV1()
# loading config file
try:
config = ConfigObj("/etc/airtime/airtime.conf")
except Exception as e:
print("Error loading config file: {}".format(e))
sys.exit()
# TODO : add docstrings everywhere in this module # TODO : add docstrings everywhere in this module
@ -57,9 +49,17 @@ PUSH_INTERVAL = 2
class ShowRecorder(Thread): class ShowRecorder(Thread):
def __init__(self, show_instance, show_name, filelength, start_time): def __init__(
self,
show_instance,
show_name,
filelength,
start_time,
config: Config,
):
Thread.__init__(self) Thread.__init__(self)
self.api_client = api_client() self.api_client = api_client()
self.config = config
self.filelength = filelength self.filelength = filelength
self.start_time = start_time self.start_time = start_time
self.show_instance = show_instance self.show_instance = show_instance
@ -71,18 +71,13 @@ class ShowRecorder(Thread):
filename = self.start_time filename = self.start_time
filename = filename.replace(" ", "-") filename = filename.replace(" ", "-")
if config["pypo"]["record_file_type"] in ["mp3", "ogg"]:
filetype = config["pypo"]["record_file_type"]
else:
filetype = "ogg"
joined_path = os.path.join(RECORD_DIR, filename) joined_path = os.path.join(RECORD_DIR, filename)
filepath = "%s.%s" % (joined_path, filetype) filepath = "%s.%s" % (joined_path, self.config.playout.record_file_format)
br = config["pypo"]["record_bitrate"] br = self.config.playout.record_bitrate
sr = config["pypo"]["record_samplerate"] sr = self.config.playout.record_samplerate
c = config["pypo"]["record_channels"] c = self.config.playout.record_channels
ss = config["pypo"]["record_sample_size"] ss = self.config.playout.record_sample_size
# -f:16,2,44100 # -f:16,2,44100
# -b:256 # -b:256
@ -183,9 +178,10 @@ class ShowRecorder(Thread):
class Recorder(Thread): class Recorder(Thread):
def __init__(self, q): def __init__(self, q, config: Config):
Thread.__init__(self) Thread.__init__(self)
self.api_client = api_client() self.api_client = api_client()
self.config = config
self.sr = None self.sr = None
self.shows_to_record = {} self.shows_to_record = {}
self.server_timezone = "" self.server_timezone = ""
@ -316,6 +312,7 @@ class Recorder(Thread):
show_name, show_name,
show_length_seconds, show_length_seconds,
start_time_formatted, start_time_formatted,
self.config,
) )
self.sr.start() self.sr.start()
break break

View File

@ -42,6 +42,7 @@ setup(
"packaging", "packaging",
"pytz", "pytz",
"requests", "requests",
"typing-extensions",
], ],
extras_require={ extras_require={
"dev": [ "dev": [