Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • aura/engine
  • hermannschwaerzler/engine
  • sumpfralle/aura-engine
3 results
Show changes
#!/bin/bash
mode="engine"
docker="false"
#
# Run Script for AURA Engine
#
# Call with one of these parameters:
#
# - init
# - engine
# - core
# - lqs
# - recreate-database
# - docker:engine
# - docker:build
# - docker:push
#
if [[ $* =~ ^(init|env|engine|core|lqs)$ ]]; then
mode=$1
fi
if [[ "$1" == *"docker:"* ]]; then
docker="true"
mode=${1#*:}
fi
echo "[ Run mode=$mode ]"
echo "[ Docker=$docker ]"
# Find the correct Python version (3.7 or 3.8)
if hash python3.8 2>/dev/null; then
PYTHON_EXEC="python3.8"
echo "[ Using Python 3.8 ]"
else
PYTHON_EXEC="python3.7"
echo "[ Using Python 3.7 ]"
fi
# +++ DEFAULT COMMANDS +++ #
if [[ $docker == "false" ]]; then
### Initializes the environment & installs dependencies ###
if [[ $mode == "init" ]]; then
mkdir -p logs
pip3 install -r requirements.txt
fi
### Runs Engine Core & Liquidsoap ###
if [[ $mode == "engine" ]]; then
eval $(opam env)
/usr/bin/env $PYTHON_EXEC engine-core.py
fi
### Runs Engine Core only ###
if [[ $mode == "core" ]]; then
/usr/bin/env $PYTHON_EXEC engine-core.py --without-lqs
fi
### Runs Liquidsoap only ###
if [[ $mode == "lqs" ]]; then
lqs=$(/usr/bin/env $PYTHON_EXEC engine-core.py --get-lqs-command)
eval "$lqs"
fi
### CAUTION: This deletes everything in your database ###
if [[ $mode == "recreate-database" ]]; then
/usr/bin/env $PYTHON_EXEC engine-core.py --recreate-database
fi
fi
# +++ DOCKER COMMANDS +++ #
if [[ $docker == "true" ]]; then
BASE_D=$(realpath "${BASH_SOURCE%/*}/")
### Runs Engine Core & Liquidsoap ###
if [[ $mode == "engine" ]]; then
exec sudo docker run \
--network="host" \
--name aura-engine \
--rm -d \
-u $UID:$GID \
-v "$BASE_D":/srv \
-v "$BASE_D/audio/source":/var/audio/source:ro \
-v "$BASE_D/configuration/docker":/etc/aura \
-v "/dev/snd":/dev/snd \
--privileged \
--tmpfs /var/log/aura/ \
autoradio/engine
fi
### Create Docker Image from local project ###
if [[ $mode == "build" ]]; then
exec sudo docker build -t autoradio/engine .
fi
### Pushes the latest Docker Image to Docker Hub ###
if [[ $mode == "push" ]]; then
exec sudo docker push autoradio/engine
fi
fi
\ No newline at end of file
#!/bin/bash
if getent passwd 'engineuser' > /dev/null 2>&1; then
echo "User 'engineuser' exists already.";
else
echo "Creating Engine User ..."
adduser engineuser
adduser engineuser audio
fi
\ No newline at end of file
#!/bin/bash
#
# Prepare folders and permissions for installing engine on production.
#
# You'll need sudo/root privileges.
#
echo "Create Log Directory '/var/log/aura/'"
mkdir -p /var/log/aura
echo "Create Configuration Directory '/etc/aura/'"
mkdir -p /etc/aura
echo "Set Ownership of '/opt/aura/engine', '/var/log/aura/' and '/etc/aura/engine.ini' to Engine User"
chown -R engineuser:engineuser /opt/aura
chown -R engineuser:engineuser /etc/aura
chown -R engineuser:engineuser /var/log/aura
chown -R engineuser:engineuser /var/log/supervisor
echo "Copy Systemd unit files to '/etc/systemd/system/'"
cp -n /opt/aura/engine/configuration/systemd/* /etc/systemd/system/
\ No newline at end of file
#!/bin/bash
opam update -y
opam init -y
opam switch create 4.08.0
opam install depext -y
opam depext taglib mad lame vorbis flac opus cry samplerate pulseaudio bjack alsa ssl liquidsoap -y
opam install taglib mad lame vorbis flac opus cry samplerate pulseaudio bjack alsa ssl liquidsoap -y
eval $(opam env)
#!/bin/bash
# Check if databases are already set-up
if test -f "$LOCKFILE_DB"; then
echo "Aura Engine Databases are already existing! Skipping..."
else
# Create random password
PASS_ENGINE="$(openssl rand -base64 24)"
# Create databases and users
echo "--- SETTING UP DATABASE AND USERS ---"
echo "Please enter the MySQL/MariaDB root password!"
stty -echo
printf "Password: "
read rootpasswd
stty echo
printf "\n"
echo "---"
echo "Creating database for Aura Engine..."
mysql -uroot -p${rootpasswd} -e "CREATE DATABASE aura_engine CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
mysql -uroot -p${rootpasswd} -e "CREATE USER 'aura'@'localhost' IDENTIFIED BY '${PASS_ENGINE}';"
mysql -uroot -p${rootpasswd} -e "GRANT ALL PRIVILEGES ON aura_engine.* TO 'aura'@'localhost';"
mysql -uroot -p${rootpasswd} -e "FLUSH PRIVILEGES;"
echo "Done."
echo
echo
echo "Please note your database credentials for the next configuration steps:"
echo "-----------------------------------------------------------------------"
echo " Database: 'aura_engine'"
echo " User: 'aura'"
echo " Password: '${PASS_ENGINE}'"
echo "-----------------------------------------------------------------------"
echo
fi
\ No newline at end of file
#!/bin/bash
#
# Setup Database
#
# Set LOCK file location
LOCKFILE_DB=.engine.install-db.lock
# Check if databases are already set-up
if test -f "$LOCKFILE_DB"; then
echo "Aura Engine Databases are already existing! Skipping..."
else
echo "Setting up database ..."
echo
echo "Which database system do you want to use? (Press '1' or '2')"
echo " [1] MariaDB"
echo " [2] Other / Manually"
echo
while true; do
read -rsn1 input
if [ "$input" = "1" ]; then
echo "Creating DB for MariaDB ..."
bash script/setup-db-mariadb.sh
break
fi
if [ "$input" = "2" ]; then
echo "Manual database setup selected."
break
fi
done
# Create lockfile to avoid accidential re-creation of the database
touch $LOCKFILE_DB
fi
; supervisor config file
[unix_http_server]
file=/opt/aura/engine/tmp/supervisor.sock ; (the path to the socket file)
chmod=0700 ; sockef file mode (default 0700)
chown=engineuser:engineuser
[supervisord]
logfile=/var/log/supervisor/supervisord.log ; (main log file;default $CWD/supervisord.log)
pidfile=/opt/aura/engine/tmp/supervisord.pid ; (supervisord pidfile;default supervisord.pid)
childlogdir=/var/log/supervisor ; ('AUTO' child log dir, default $TEMP)
; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface
[supervisorctl]
serverurl=unix:///opt/aura/engine/tmp/supervisor.sock ; use a unix:// URL for a unix socket
; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
; newlines). It can also contain wildcards. The filenames are
; interpreted as relative to this file. Included files *cannot*
; include files themselves.
[include]
; files = /etc/supervisor/conf.d/*.conf
files = /opt/aura/engine/configuration/supervisor/*.conf
#
# 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 urllib
import json
from modules.core.engine import SoundSystem
from modules.base.config import AuraConfig
# ------------------------------------------------------------------------------------------ #
class ConnectionTester(AuraConfig):
# ------------------------------------------------------------------------------------------ #
def __init__(self):
super(ConnectionTester, self).__init__()
# ------------------------------------------------------------------------------------------ #
def get_connection_status(self):
status = dict()
status["db"] = False # self.test_db_conn()
status["pv"] = self.test_pv_conn()
status["lqs"] = self.test_lqs_conn()
status["lqsr"] = False # self.test_lqsr_conn()
status["tank"] = self.test_tank_conn()
status["redis"] = self.test_redis_conn()
return json.dumps(status)
# ------------------------------------------------------------------------------------------ #
# def test_db_conn(self):
# try:
# ScheduleEntry.select_all()
# except:
# return False
#
# return True
# ------------------------------------------------------------------------------------------ #
def test_lqs_conn(self):
try:
lsc = SoundSystem(self.config)
lsc.mixer_status()
return True
except Exception as e:
return False
# ------------------------------------------------------------------------------------------ #
def test_lqsr_conn(self):
try:
lsc = SoundSystem(self.config)
lsc.get_recorder_status()
return True
except Exception as e:
return False
# ------------------------------------------------------------------------------------------ #
def test_pv_conn(self):
return self.test_url_connection(self.config.get("calendarurl"))
# ------------------------------------------------------------------------------------------ #
def test_tank_conn(self):
# test load of playlist 1
return self.test_url_connection(self.config.get("importerurl")+"1")
# ------------------------------------------------------------------------------------------ #
def test_redis_conn(self):
from modules.cli.redis.adapter import ClientRedisAdapter
try:
cra = ClientRedisAdapter()
cra.publish("aura", "status")
except:
return False
return True
def test_url_connection(self, url):
try:
request = urllib.request.Request(url)
response = urllib.request.urlopen(request)
response.read()
except Exception as e:
return False
return True
\ No newline at end of file
File: ernie_mayne_sugar.mp3
Title: Sugar, Performed by Ernie Mayne
License: Public Domain
Source: http://www.digitalhistory.uh.edu/music/music.cfm
\ No newline at end of file
File added
set("log.file.path", "./<script>.log")
#%include "readini.liq"
#ini = read_ini("/etc/aura/engine.ini")
# output_source = mksafe(blank())
# %include "stream.liq"
# stream = get_stream(0)
# output_stream = input.external("arecord -f S16_LE -c2 -r44100 -t raw -D dsnoop:1,0 -")
output.icecast(
%vorbis(quality = 0.5),
mount="aura-test.ogg",
host="develop.servus.at",
port=8000,
name="LQSTest",
user="source",
password="A7E7tst1",
fallible=true,
input.alsa(device="pcm.plugj")
)
#
# 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 unittest
import validators
from datetime import datetime
from modules.base.logger import AuraLogger
from modules.base.config import AuraConfig
from modules.base.models import Schedule, TrackService
# modules
from modules.core.engine import SoundSystem
from modules.scheduling.scheduler import AuraScheduler
class TestLogger(unittest.TestCase):
aura_logger = None
def setUp(self):
self.config = AuraConfig()
self.aura_logger = AuraLogger(self.config)
def test_logger(self):
self.assertTrue(self.aura_logger.logger.hasHandlers())
class TestConfig(unittest.TestCase):
aura_config = None
def setUp(self):
self.aura_config = AuraConfig()
def test_config(self):
# is ini path correct set?
self.assertEqual(self.config.ini_path, "/etc/aura/engine.ini")
# install_dir is set by runtime. is it a directory?
self.assertTrue(os.path.isdir(self.config.get("install_dir")))
# calendarurl and importerurl set and valid urls?
self.assertTrue(validators.url(self.config.get("calendarurl")))
self.assertTrue(validators.url(self.config.get("importerurl")))
# is liquidsoap socketdir set and a directory?
self.assertTrue(os.path.isdir(self.config.get("socketdir")))
# database settings set?
self.assertIsNotNone(self.config.get("db_user"))
self.assertIsNotNone(self.config.get("db_pass"))
self.assertIsNotNone(self.config.get("db_name"))
self.assertIsNotNone(self.config.get("db_host"))
class TestSchedule(unittest.TestCase):
schedule = None
def setUp(self):
self.schedule = Schedule()
def test_schedule(self):
# select one and check if its not None and a Schedule
entry = self.schedule.select_by_id(1)
self.assertIsNotNone(entry)
self.assertIsInstance(entry, Schedule)
class TestScheduleEntry(unittest.TestCase):
schedule_entry = None
def setUp(self):
self.schedule_entry = ScheduleEntry()
def test_schedule_entry(self):
# select one playlist and check if its not None, a ScheduleEntry
entry = self.schedule_entry.select_playlist(2)
self.assertIsNotNone(entry)
self.assertIsInstance(entry, list)
self.assertGreaterEqual(len(entry), 1)
class TestTrackService(unittest.TestCase):
track_service = None
def setUp(self):
self.track_service = TrackService()
def test_track_service(self):
day = datetime.strptime("19.03.2018", "%d.%m.%Y")
entry = self.track_service.select_by_day(day)
self.assertIsNotNone(entry)
self.assertIsInstance(entry, list)
class TestAuraUser(unittest.TestCase):
aura_user = None
def setUp(self):
self.aura_user = AuraUser()
def test_add_user(self):
username = "user"
password = "password"
role = "admin"
login_cnt = len(self.aura_user.getLogins())
# insert user
key = self.aura_user.insertUser(username, password, role)
self.assertGreaterEqual(len(self.aura_user.getLogins()), login_cnt)
# selecting user and check data
user = self.aura_user.getUserByKey(key)
self.assertEqual(user["username"], username)
# TODO: no encrypted storage.., but usermgm not really in use
self.assertEqual(user["password"], password)
self.assertEqual(user["role"], role)
class TestLQSComm(unittest.TestCase):
comm = None
def setUp(self):
# wosn do passiert?
p = AuraConfig().config
self.soundsystem = SoundSystem(p)
self.soundsystem.scheduler = AuraScheduler(p)
self.soundsystem.init_player()
def test_get_active_channel(self):
active_channel = self.comm.get_active_channel()
print(active_channel)
if __name__ == '__main__':
unittest.main()
\ No newline at end of file
#
# engine
#
# Playout Daemon for autoradio project
#
#
# Copyright (C) 2017-2018 Gottfried Gaisbauer <gottfried.gaisbauer@servus.at>
#
# This file is part of engine.
#
# engine is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# engine 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with engine. If not, see <http://www.gnu.org/licenses/>.
#
set("log.file.path", "./<script>.log")
set("server.telnet", true)
set("server.telnet.bind_addr", "0.0.0.0")
set("server.telnet.port", 1234)
# ALSA / pulse settings
# durch ausprobieren herausgefunden für asus xonar dgx 5.1
# chip: CMI8788
# driver: snd_oxygen
set("frame.duration", 0.30)
set("alsa.alsa_buffer", 8192) # 7168) # 6144) # 8192) # 10240) #15876
set("alsa.buffer_length", 25)
set("alsa.periods", 0) # assertion error when setting periods other than 0 => alsa default
input_linein = input.alsa(id="linein", bufferize = false)
#input_fs = single(id="fs", "/var/audio/fallback/output.flac")
#input_http = input.http(id="http", "http://stream.fro.at/fro-128.ogg")
#mixer = mix(id="mixer", [input_fs, input_http, input_linein])
#output.alsa(id="lineout", bufferize = false, mixer)
#
# engine
#
# Playout Daemon for autoradio project
#
#
# Copyright (C) 2017-2018 David Trattnig <david@subsquare.at>
#
# This file is part of engine.
#
# engine is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# any later version.
#
# engine 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with engine. If not, see <http://www.gnu.org/licenses/>.
#
set("log.file.path", "./<script>.log")
set("server.telnet", true)
set("server.telnet.bind_addr", "0.0.0.0")
set("server.telnet.port", 1234)
set("frame.duration", 0.30)
set("alsa.alsa_buffer", 8192)
set("alsa.buffer_length", 25)
set("alsa.periods", 0) # assertion error when setting periods other than 0 => alsa default
#input_linein = input.alsa(id="linein", bufferize = false)
audio1 = single(id="fs1", "./sources/1.flac")
audio2 = single(id="fs2", "./sources/2.flac")
#input_http = input.http(id="http", "http://stream.fro.at/fro-128.ogg")
#mixer = mix(id="mixer", [audio1, audio2])
#mixer = mix(id="mixer", [input_fs, input_http, input_linein])
mixed = add([audio1, audio2])
output.alsa(id="lineout", bufferize = false, mixed)
#!/bin/sh
''''which python3.8 >/dev/null 2>&1 && exec python3.8 "$0" "$@" # '''
''''which python3.7 >/dev/null 2>&1 && exec python3.7 "$0" "$@" # '''
''''exec echo "Error: Snaaakey Python, where are you?" # '''
#
# 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 json
import logging
import sqlalchemy
import decimal
from modules.core.engine import SoundSystem
from modules.base.config import AuraConfig
from modules.base.models import Schedule, ScheduleEntry
from modules.scheduling.scheduler import AuraScheduler, AuraCalendarService
def alchemyencoder(obj):
"""JSON encoder function for SQLAlchemy special classes."""
if isinstance(obj, datetime.date):
return obj.isoformat()
elif isinstance(obj, decimal.Decimal):
return float(obj)
elif isinstance(obj, sqlalchemy.orm.state.InstanceState):
return ""
#elif isinstance(obj, Schedule):
# return json.dumps([obj._asdict()], default=alchemyencoder)
else:
return str(obj)
# programme_as_string = json.dumps([se[0]._asdict()], default=alchemyencoder)
# print(programme_as_string)
def select_current_programme():
# select_programme()
config = AuraConfig()
config.read_config()
soundsystem = SoundSystem(config.config)
sched = AuraScheduler(config.config)
soundsystem.scheduler = sched
sched.soundsystem = soundsystem
programme = sched.load_programme_from_db()
for show in programme:
print(show)
def fadeout(lsc):
entry = ScheduleEntry.select_programme()
lsc.fade_out(entry, 2)
def fadein(lsc):
entry = ScheduleEntry.select_programme()
lsc.fade_in(entry, 1)
def fetch_new_programme():
config = AuraConfig()
config.read_config()
acs = AuraCalendarService(config.config)
queue = acs.get_queue()
# start fetching thread
acs.start()
# wait for the end
response = queue.get()
# # ## ## ## ## ## # #
# # ENTRY FUNCTION # #
# # ## ## ## ## ## # #
def main():
fetch_new_programme()
# # ## ## ## ## ## ## # #
# # End ENTRY FUNCTION # #
# # ## ## ## ## ## ## # #
if __name__ == "__main__":
main()