-
David Trattnig authoredDavid Trattnig authored
engine-core.py 6.02 KiB
#!/usr/bin/env python3.7
#
# Aura Engine (https://gitlab.servus.at/aura/engine)
#
# Copyright (C) 2017-2020 - The Aura Engine Team.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import os
import sys
import signal
import logging
import subprocess
from flask import Flask
from flask_sqlalchemy import SQLAlchemy
from modules.base.logger import AuraLogger
from modules.base.config import AuraConfig
from modules.base.utils import SimpleUtil
config = AuraConfig()
def configure_flask():
app.config["SQLALCHEMY_DATABASE_URI"] = config.get_database_uri()
app.config['BABEL_DEFAULT_LOCALE'] = 'de'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
# FIXME Instatiate SQLAlchemy without the need for Flask
app = Flask(__name__)
configure_flask()
DB = SQLAlchemy(app)
class AuraEngine:
"""
AuraEngine does the following:
1. Initialize the soundsystem and scheduler
2. Initialize Redis
3. Start Liquidsoap in a separate thread which connects to the engine
"""
logger = None
config = None
server = None
messenger = None
controller = None
soundsystem = None
scheduler = None
lqs = None
lqs_startup = None
def __init__(self):
"""
Initializes Engine Core.
"""
self.config = config
def startup(self, lqs_startup):
"""
Starts Engine Core.
"""
AuraLogger(self.config)
self.logger = logging.getLogger("AuraEngine")
from modules.scheduling.scheduler import AuraScheduler
from modules.core.engine import SoundSystem
from modules.communication.redis.adapter import ServerRedisAdapter
# If Liquidsoap should be started automatically
self.lqs_startup = lqs_startup
# Check if the database has to be re-created
if self.config.get("recreate_db") is not None:
AuraScheduler(self.config, None, None)
# Create scheduler and Liquidsoap communicator
self.soundsystem = SoundSystem(self.config)
self.scheduler = AuraScheduler(self.config, self.soundsystem, self.on_initialized)
# Create the Redis adapter
self.messenger = ServerRedisAdapter(self.config)
self.messenger.scheduler = self.scheduler
self.messenger.soundsystem = self.soundsystem
# And finally wait for redis message / start listener thread
self.messenger.start()
def on_initialized(self):
"""
Called when the engine is initialized, before the Liquidsoap connection is established."
"""
self.logger.info(SimpleUtil.green("Engine Core initialized - Waiting for Liquidsoap connection ..."))
if self.lqs_startup:
self.start_lqs(False, False)
else:
self.logger.info(SimpleUtil.yellow("Please note, Liquidsoap needs to be started manually."))
# from modules.communication.redis.adapter import ServerRedisAdapter
# self.messenger = ServerRedisAdapter(self.config)
# self.messenger.scheduler = self.scheduler
# self.messenger.soundsystem = self.soundsystem
# self.messenger.start()
def start_lqs(self, debug_output, verbose_output):
"""
Starts Liquidsoap.
"""
lqs_path = self.config.get("liquidsoap_path")
lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
lqs_output = ""
lqs_output = self.get_debug_flags(debug_output, verbose_output)
self.lqs = subprocess.Popen([lqs_path, lqs_output, "engine.liq"], \
cwd=lqs_cwd, \
stdout=subprocess.PIPE, \
shell=False)
def get_lqs_cmd(self, debug_output, verbose_output):
"""
Returns a shell command string to start Liquidsoap
"""
lqs_path = self.config.get("liquidsoap_path")
lqs_cwd = os.getcwd() + "/" + self.config.get("liquidsoap_working_dir")
lqs_output = self.get_debug_flags(debug_output, verbose_output)
return "(cd %s && %s %s ./engine.liq)" % (lqs_cwd, lqs_path, lqs_output)
def get_debug_flags(self, debug_output, verbose_output):
"""
Build Liquidssoap debug parameters.
"""
output = ""
if debug_output:
output += "--debug "
if verbose_output:
output += "--verbose "
return output
def exit_gracefully(self, signum, frame):
"""
Shutdown of the engine. Also terminates the Liquidsoap thread.
"""
if self.lqs:
self.lqs.terminate()
self.logger.info("Terminated Liquidsoap")
if self.messenger:
self.messenger.terminate()
self.logger.info("Gracefully terminated Aura Engine!" + str(self.lqs))
sys.exit(0)
#
# START THE ENGINE
#
if __name__ == "__main__":
engine = AuraEngine()
lqs_startup = True
lqs_cmd = False
signal.signal(signal.SIGINT, engine.exit_gracefully)
signal.signal(signal.SIGTERM, engine.exit_gracefully)
if len(sys.argv) >= 2:
if "--without-lqs" in sys.argv:
lqs_startup = False
if "--get-lqs-command" in sys.argv:
lqs_cmd = True
if "--use-test-data" in sys.argv:
engine.config.set("use_test_data", True)
if "--recreate-database" in sys.argv:
engine.config.set("recreate_db", True)
if lqs_cmd:
print(engine.get_lqs_cmd(True, True))
else:
engine.startup(lqs_startup)