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
Select Git revision
  • dev-old
  • dev-old-david
  • develop
  • lars-tests
  • master
  • master-old
  • topic/filesystem-fallbacks
  • topic/tank_connection
  • topic/tank_connection_david
  • user/equinox/docker
10 results

Target

Select target project
  • aura/engine
  • hermannschwaerzler/engine
  • sumpfralle/aura-engine
3 results
Select Git revision
  • 122-synchronized-ci
  • feat-use-docker-main-tag
  • fix-aura-sysuser
  • fix-broken-pipe-153
  • fix-docker-release
  • fix-push-latest-with-tag
  • fix-streamchannel-retries
  • gitlab-templates
  • improve-test-coverage-137
  • improve-test-coverage-143
  • main
  • orm-less-scheduling
  • remove-mailer
  • update-changelog-alpha3
  • virtual-timeslots-131
  • 1.0.0-alpha1
  • 1.0.0-alpha2
  • 1.0.0-alpha3
  • 1.0.0-alpha4
  • 1.0.0-alpha5
20 results
Show changes
Showing
with 1034 additions and 0 deletions
<h3>{{ _('Scheduler Jobs') }}</h3>
<table class="table table-striped scheduler-jobs">
<tr>
<th>{{ _('Job') }}</th>
<th>{{ _('Time') }}</th>
<th>{{ _('Until') }}</th>
</tr>
{% for job in jobs %}
<tr>
<td>{{ job.job }}</td>
<td>{{ job.time }}</td>
<td>{{ job.until }}</td>
</tr>
{% endfor %}
</table>
\ No newline at end of file
{% extends "layout.html" %}
{% block title %}Start{% endblock %}
{% block customcss %}<link rel="stylesheet" href="{{ url_for('static', filename='css/lib/jquery-ui.min.css') }}" type="text/css">{% endblock %}
{% block pagetitle %}{{ _('Search for broadcasts') }}{% endblock %}
{% block body %}
<form id="searchForm" classs="form-horizontal" method="POST" action="/search">
<div class="form-group">
<label class="col-sm-2 control-label" for="search">{{ _('Text/Name') }}:</label>
<div class="col-sm-10">
<input class="form-control" id="search" name="search" type="text" value="{{ query.search }}" />
</div>
</div>
<div class="clearfix"></div>
<div class="col-sm-12 form-group"><h4>{{ _('Date Search') }}</h4></div>
<div class="form-group">
<div>
<label class="col-sm-2 control-label" for="from">{{ _('from') }}:</label>
<div class="col-sm-4">
<input class="datepicker form-control" id="from" placeholder="2014-01-01" name="from" type="text" value="{{ query.from }}" />
</div>
<label class="col-sm-2 control-label" for="to">{{ _('to') }}:</label>
<div class="col-sm-4">
<input class="datepicker form-control" id="to" placeholder="2014-12-31" name="to" type="text" value="{{ query.to }}" />
</div>
</div>
</div>
<div class="clearfix"></div>
<div class="col-sm-offset-2 col-sm-10">
<br />
<div class="btn-toolbar" role="toolbar">
<div class="btn-group">
<button class="btn btn-default" type="submit" value="fo"> <span class="glyphicon glyphicon-search"></span> {{ _('Search') }}</button>
<button id="reset_button" class="btn btn-default" type="button" value="reset"> <span class="glyphicon glyphicon-remove"> </span>{{ _('Reset') }}</button>
</div>
</div>
</div>
<div class="clearfix"></div>
<br />
<uL class="list-group">
{% for event in eventlist %}
<li id="li-{{ event.id }}" class="list-group-item">
<div class="col-md-6">
{% if event.overwrite_event %}
<a href="/search/reset/{{ event.id }}" data-hash="li-{{ event.id }}" class="pull-right btn btn-default btn-sm eventResetBtn" >
Zurücksetzen
</a>
{% else %}
<a href="/search/modal/{{ event.id }}" data-hash="li-{{ event.id }}" class="pull-right btn btn-default btn-sm eventOverwriteBtn" >
Überschreiben
</a>
{% endif %}
<h3 {% if event.overwrite_event %} style="text-decoration:line-through" {% endif %}>{{ event.title }}</h3> <!-- Button trigger modal -->
{% if event.overwrite_event %}
<h3>{{ event.overwrite_event.title }}</h3>
{% endif %}
<div>{{ event.start | formatdate }} - {{ event.end | formatdate }}</div>
{% if event.overwrite_event %}
<div>{% if event.overwrite_event.rerun %}{{ _('Repetition of') }} {{ event.overwrite_event.replay_of_datetime | formatdate }}{% endif %}</div>
{% else %}
<div>{% if event.rerun %}{{ _('Repetition of') }} {{ event.replay_of_datetime | formatdate }}{% endif %}</div>
{% endif %}
<div>{{ event.subject }}</div>
{% if event.filename %}
<div><strong>{{ _('File') }}:</strong> {{ event.filename }} <span class="glyphicon {% if event.fileExists() %}glyphicon-ok text-success{% else %}glyphicon-minus text-danger{% endif %}" aria-hidden="true"></span></div>
{% endif %}
<h4><a data-toggle="collapse" href="#{{ event.id }}"><span class="caret"> </span> {{ event.tracks|length }} Tracks </a></h4>
<div class="collapse" id="{{ event.id }}">
<uL>
{% for track in event.tracks %}
<li>{{ track.filename }} <span class="glyphicon {% if track.fileExists() %}glyphicon-ok text-success{% else %}glyphicon-minus text-danger{% endif %}" aria-hidden="true"></span></li>
{% endfor %}
</uL>
</div>
</div>
<div class="col-md-6">
<div class="well well-small">
<h4 class="text-info">{{ _('Preproduction') }}</h4>
{% if event.overrides.count() > 0 %}
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="{{ event.procOverrides }}" aria-valuemax="100" aria-valuemin="0" style="width: {{ event.procOverrides }}%;">
{{ event.procOverrides }}%
</div>
</div>
{% endif %}
<br />
<a class="btn btn-xs btn-default" href="{{ url_for('preprod', eventid=event.id ) }}"><span class="glyphicon glyphicon-{% if event.overrides.count() > 0 %}pencil{% else %}plus{% endif %}">{% if event.overrides.count() > 0 %} {{ _('Edit') }}{% else %} {{ _('Add') }}{% endif %}</span></a>
</div>
</div>
<div class="clearfix"></div>
</li>
{% endfor %}
</uL>
<ul class=pagination>
{%- for page in pagination.iter_pages() %}
{% if page %}
{% if page == pagination.page %}
<li class="active"><a class="link active" href="#">{{ page }}</a></li>
{% else %}
<li><a class="link" data-page="{{ page }}" href="{{ url_for('search') }}">{{ page }}</a></li>
{% endif %}
{% else %}
<li><span class=ellipsis></span></li>
{% endif %}
{%- endfor %}
</ul>
<input type="hidden" id="form-page" name="page" value="{{ page }}">
</form>
<!-- Modal -->
<div class="modal fade" id="myModal" tabindex="-1" data-keyboard="false" data-backdrop="static">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
<h4 class="modal-title" id="myModalLabel">Suche</h4>
</div>
<div class="modal-body">
<iframe src="" style="zoom:0.60" frameborder="0" height="450" width="99.6%"></iframe>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ _('Cancel') }}</button>
</div>
</div>
</div>
</div>
{% endblock %}
{% block customjs %}
<script src="{{ url_for('static', filename='js/lib/jquery-1.10.2.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/lib/bootstrap.min.js') }}"></script>
<script src="{{ url_for('static', filename='js/lib/jquery-ui.min.js') }}"></script>
<script>
function closeModal() {
$('#myModal').modal('hide')
window.location.reload(true)
}
$('.eventOverwriteBtn').click(function(e){
e.preventDefault()
var link = $(this).attr("href");
window.location.hash = $(this).attr("data-hash");
$('iframe').attr("src",link);
$('#myModal').modal({show:true})
});
$('.eventResetBtn').click(function(e){
e.preventDefault()
var link = $(this).attr("href");
var hash = $(this).attr("data-hash");
jQuery.ajax ({
url: link,
cache: false,
success: function (response) {
window.location.hash = hash;
window.location.reload(true)
},
error: function () {
console.log('Hat nicht geklappt');
}
});
});
$(function() {
$('#reset_button').click(function(e){
$('#from').val("")
$('#to').val("")
$('#search').val("")
$('#searchForm').submit()
});
$('.pagination .link').click(function(ev){
ev.preventDefault();
if (!$(this).attr('data-page')) {
return;
}
$('#form-page').val($(this).attr('data-page'));
$('#searchForm').submit();
});
$( ".datepicker" ).datepicker({dateFormat: "yy-mm-dd"});
});
</script>
{% endblock %}
\ No newline at end of file
<h3>Streaming</h3>
<div class="info"><span class="text-info">{{ message }}</span></div>
{% for mount in mounts %}
<div>
<h4>{{ _('Current running title') }}: {{ mount.Title }}</h4>
</div>
<table class="table table-striped channels">
<tbody>
<tr>
<th>{{ _('ListenURL') }}</th>
<td>{{ mount.ListenURL }}</td>
</tr>
<tr>
<th>{{ _('Mountpoint') }}</th>
<td>{{ mount.Name }}</td>
</tr>
<tr>
<th>{{ _('StreamStart') }}</th>
<td>{{ mount.StreamStart }}</td>
</tr>
<tr>
<th>{{ _('AudioInfo') }}</th>
<td>{{ mount.AudioInfo }}</td>
</tr>
<tr>
<th>{{ _('Genre') }}</th>
<td>{{ mount.Genre }}</td>
</tr>
<tr>
<th>{{ _('ListenerCount') }}</th>
<td>{{ mount.ListenerCount }}</td>
</tr>
<tr>
<th>{{ _('ListenerPeak') }}</th>
<td>{{ mount.ListenerPeak }}</td>
</tr>
<tr>
<th>{{ _('Public') }}</th>
<td>{{ mount.Public }}</td>
</tr>
<tr>
<th>{{ _('ServerDescription') }}</th>
<td>{{ mount.ServerDescription }}</td>
</tr>
<tr>
<th>{{ _('ServerName') }}</th>
<td>{{ mount.ServerName }}</td>
</tr>
<tr>
<th>{{ _('ServerType') }}</th>
<td>{{ mount.ServerType }}</td>
</tr>
<tr>
<th>{{ _('ServerURL') }}</th>
<td>{{ mount.ServerURL }}</td>
</tr>
<tr>
<th>{{ _('SlowListeners') }}</th>
<td>{{ mount.SlowListeners }}</td>
</tr>
<tr>
<th>{{ _('SourceIP') }}</th>
<td>{{ mount.SourceIP }}</td>
</tr>
<tr>
<th>{{ _('TotalBytesRead') }}</th>
<td>{{ mount.TotalBytesRead }}</td>
</tr>
<tr>
<th>{{ _('TotalBytesSent') }}</th>
<td>{{ mount.TotalBytesSent }}</td>
</tr>
</tbody>
</table>
{% endfor %}
<div>
<h2>System</h2>
<table class="table table-bordered">
<tr>
<th>{{ _('Load') }}</th>
<th>{{ _('Free Space') }}</th>
</tr>
<tr>
<td>{{ load }}</td>
<td>{{ diskfree }}</td>
</tr>
</table>
</div>
<div class="row-fluid">
<h2>{{ _('Modules') }}</h2>
{% for state in componentStates %}
<div class="col-sm-4 col-md-3 col-lg-2">
<div id="controller-alive" class="alive {% if state.state %}bg-success{% else %}bg-danger{% endif %}">
<div class="center-block">
<h4>{{ state.title }}</h4>
<p>{% if state.state %}
{{ state.title }} is alive
{% else %}
{{ state.title }} is down
{% endif %}
</p>
</div>
</div>
</div>
{% endfor %}
</div>
<div class="clearfix"></div>
<div>
<table class="table table-striped">
<tr>
<th>{{ _('Playlist Status') }}</th>
<td>
{% if playerState %}
<div><strong>{{ _('File') }}:</strong> {{ playerState.file }}</div>
{% if not playerState.complete %}
<div class="text-warning">
<strong>{{ _('Warning: recording was interrupted at') }} {{ playerState.recorded }}%!!!</strong>
</div>
{% endif %}
{% else %}
{{ _('Playlist not playing') }}
{% endif %}
</td>
<td>
{% if playerState %}
{{ _('Next event') }}: <i>play audio <strong>{{ trackStart.location }}</strong> at {{ trackStart.starts }}</i>
{% else %}
{{ _('Next Start') }} {{ playlistStart }}
{% endif %}
</td>
</tr>
<tr>
<th width="20%">{{ _('Recorder Status') }}</th>
<td>{% if recorderState %}
<div class="center-block text-center">{{ recorderState.file }}</div>
<div class="clearfix"></div>
<div class="progress">
<div class="progress-bar progress-bar-success progress-bar-striped active" role="progressbar" aria-valuenow="{{ recorderState.recorded }}" aria-valuemin="0" aria-valuemax="100" style="width: {{ recorderState.recorded }}%;">
{{ recorderState.recorded }}%
</div>
</div>
{% else %}
{{ _('Not recording') }}
{% endif %}</td>
<td>
{{ _('Next event') }}: <i>record <strong>{{ recordStart.location }}</strong> at {{ recordStart.starts }}</i>
</td>
</tr>
</table>
</div>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
{{ length }} trackservice entries on {{ selected_date }} found
{% for entry in trackservice_entries %}
{{ entry.start }}
{% endfor %}
</body>
</html>
\ No newline at end of file
sqlalchemy==1.3.13
Flask==1.1.1
Flask-SQLAlchemy==2.4.1
Flask-RESTful==0.3.8
flask-marshmallow==0.11.0
flask-cors==3.0.8
marshmallow-sqlalchemy==0.22.2
apispec==3.3.0
apispec-webframeworks==0.5.2
mysqlclient==1.3.12
redis==3.4.1
mutagen==1.44.0
validators==0.12.1
simplejson==3.17.0
accessify==0.3.1
librosa==0.7.2
\ No newline at end of file
#/usr/bin/bash
mode="engine"
debug="--debug"
#debug="--debug --verbose"
if [ -n "$1" ]; then
if [[ $1 =~ ^(engine|lqs|api)$ ]]; then
mode=$1
fi
fi
echo "[ Run mode=$mode ]"
if [ $mode == "engine" ]; then
/usr/bin/python3.7 aura.py
fi
if [ $mode == "lqs" ]; then
(cd modules/liquidsoap/ && /usr/bin/liquidsoap $debug ./engine.liq)
fi
if [ $mode == "api" ]; then
echo "Building Web Applications"
sh ./script/build-web.sh
echo "Starting API Server"
/usr/bin/python3.7 api.py
fi
\ No newline at end of file
echo "Building AURA Clock ..."
(
cd contrib/aura-clock
npm run build
)
cp contrib/aura-clock/public/build/aura-clock-bundle.css web/css/aura-clock-bundle.css
cp contrib/aura-clock/public/build/aura-clock-bundle.js web/js/aura-clock-bundle.js
echo "Building AURA Player ..."
(
cd contrib/aura-player
npm run build
)
cp contrib/aura-player/public/build/aura-player-bundle.css web/css/aura-player-bundle.css
cp contrib/aura-player/public/build/aura-player-bundle.js web/js/aura-player-bundle.js
echo "Installing AURA Clock Packages ..."
(cd contrib/aura-clock && npm install)
echo "Installing AURA Player Packages ..."
(cd contrib/aura-player && npm install)
[Unit]
Description=Aura Engine - Playout Server
After=network.target
[Service]
Type=simple
User=david
WorkingDirectory=/home/david/Code/aura/engine
ExecStart=/home/david/Code/aura/engine/aura.py
ExecStop=/home/david/Code/aura/engine/guru.py --shutdown --quiet
Restart=always
[Install]
WantedBy=multi-user.target
[Unit]
Description=Aura Engine - Liquidsoap Server
After=network.target aura-engine.service
Wants=aura-engine.service
[Service]
Type=simple
User=david
ExecStart=/usr/bin/liquidsoap /home/david/Code/aura/engine/modules/liquidsoap/engine.liq
Restart=always
[Install]
WantedBy=multi-user.target
#!/usr/bin/python3.7
#
# 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/>.
#
from libraries.database.broadcasts import *
import json
import logging
import sqlalchemy
import decimal
from modules.communication.liquidsoap.communicator import LiquidSoapCommunicator
from modules.monitoring.diskspace_watcher import DiskSpaceWatcher
from libraries.base.config import AuraConfig
from libraries.database.broadcasts 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 start_diskspace_watcher():
config = AuraConfig()
config.read_config()
diskspace_watcher = DiskSpaceWatcher(config.config, logging.getLogger("AuraEngine"), LiquidSoapCommunicator(config.config))
diskspace_watcher.run()
def select_act_programme():
# start_diskspace_watcher()
# select_act_programme()
config = AuraConfig()
config.read_config()
liquidsoapcommunicator = LiquidSoapCommunicator(config.config)
sched = AuraScheduler(config.config)
liquidsoapcommunicator.scheduler = sched
sched.liquidsoapcommunicator = liquidsoapcommunicator
programme = sched.load_programme_from_db()
for show in programme:
print(show)
def fadeout(lsc):
entry = ScheduleEntry.select_act_programme()
lsc.fade_out(entry, 2)
def fadein(lsc):
entry = ScheduleEntry.select_act_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()
#
# 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/>.
#
import urllib
import logging
import json
from modules.communication.liquidsoap.communicator import LiquidSoapCommunicator
#from libraries.database.broadcasts import ScheduleEntry
from libraries.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 = LiquidSoapCommunicator(self.config)
lsc.get_mixer_status()
return True
except Exception as e:
return False
# ------------------------------------------------------------------------------------------ #
def test_lqsr_conn(self):
try:
lsc = LiquidSoapCommunicator(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.communication.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")
)
import os
import unittest
import validators
from datetime import datetime
# libraries.base
from libraries.base.logger import AuraLogger
from libraries.base.config import AuraConfig
# libraries.database
from libraries.database.broadcasts import Schedule, TrackService
# libraries.security
# from libraries.security.user import AuraUser
# modules
from modules.communication.liquidsoap.communicator import LiquidSoapCommunicator
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.comm = LiquidSoapCommunicator(p)
self.comm.scheduler = AuraScheduler(p)
self.comm.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)
html, body {
position: relative;
width: 100%;
height: 100%;
}
body {
color: #333;
margin: 0;
padding: 8px;
box-sizing: border-box;
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
}
a {
color: rgb(0,100,200);
text-decoration: none;
}
a:hover {
text-decoration: underline;
}
a:visited {
color: rgb(0,80,160);
}
label {
display: block;
}
input, button, select, textarea {
font-family: inherit;
font-size: inherit;
padding: 0.4em;
margin: 0 0 0.5em 0;
box-sizing: border-box;
border: 1px solid #ccc;
border-radius: 2px;
}
input:disabled {
color: #ccc;
}
input[type="range"] {
height: 0;
}
button {
color: #333;
background-color: #f4f4f4;
outline: none;
}
button:disabled {
color: #999;
}
button:not(:disabled):active {
background-color: #ddd;
}
button:focus {
border-color: #666;
}