Commit 7c5e6e04 authored by Gottfried Gaisbauer's avatar Gottfried Gaisbauer
Browse files

aura (soundserver, aurapythonserver and guru for cli manipulations)

parents
<?xml version="1.0" encoding="UTF-8"?>
<module type="PYTHON_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
<component name="TestRunnerService">
<option name="PROJECT_TEST_RUNNER" value="Unittests" />
</component>
</module>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.5.3 (/usr/bin/python3.5)" project-jdk-type="Python SDK" />
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/aura.iml" filepath="$PROJECT_DIR$/.idea/aura.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PreferredVcsStorage">
<preferredVcsName>ApexVCS</preferredVcsName>
</component>
</project>
\ No newline at end of file
This diff is collapsed.
import signal
import sys
import threading
from libraries.base.config import ConfigReader
from libraries.reporting.messenger import AuraMessenger
from modules.communication.zmq.zmqadapter import ServerZMQAdapter
class Aura(threading.Thread):
config = None
messenger = None
def __init__(self):
self.config = ConfigReader()
self.config.loadConfig()
messenger = AuraMessenger()
messenger.setChannel("aura")
server = object
def receive_signal(signum, stack):
print("received signal")
server.reload()
signal.signal(signal.SIGUSR1, receive_signal)
def startListening(self):
# start listener thread
server = ServerZMQAdapter(ip=self.config.get('zmqhostip'), port=int(self.config.get('zmqport')), config=self.config)
try:
while server.is_alive():
print("joining")
server.join(timeout=1.0)
# if cnt % 30 == 0:
# print(datetime.datetime.now().isoformat())
# server.printLastMessages()
# cnt = 0
# cnt = cnt + 1
except (KeyboardInterrupt, SystemExit):
# Dem Server den Shutdown event setzen
# server.shutdown_event.set()
# Der Server wartet auf Eingabe
# Daher einen Client initiieren, der eine Nachricht schickt
server.halt()
sys.exit('Terminated')
# # ## ## ## ## ## # #
# # ENTRY FUNCTION # #
# # ## ## ## ## ## # #
def main():
aura = Aura()
aura.startListening()
# # ## ## ## ## ## ## # #
# # End ENTRY FUNCTION # #
# # ## ## ## ## ## ## # #
if __name__ == "__main__":
main()
\ No newline at end of file
{
"allData": {
"id": "01",
"00": "Global Metadata delivered",
"01": "Could not get Data from Sound Engine"
},
"channel_insert": {
"id": "02",
"00": "On Channel ::channel:: insert ::uri:: at position ::pos::",
"02": "On Channel ::channel:: could not insert ::uri:: at position ::pos::"
},
"channel_move": {
"id": "03",
"00": "On Channel ::channel:: moved Item from ::fromPos:: to position ::toPos::",
"01": "Warning: Position ::fromPos:: out of range",
"02": "Warning: Cannot move to same position",
"03": "On Channel ::channel:: could not move from position ::fromPos:: to position ::toPos::"
},
"channel_off": {
"id": "04",
"00": "Channel ::channel:: off",
"01": "Could not activate Channel ::channel::"
},
"channel_on": {
"id": "05",
"00": "Channel ::channel:: on",
"01": "Could not deactivate Channel ::channel::"
},
"channel_queue": {
"id": "06",
"00": "Channel Queue for ::channel:: delivered",
"01": "Could not get channel queue from channel ::channel::",
"02": "Could not get channel queue from channel ::channel::",
"03": "Could not get channel queue from channel ::channel::"
},
"channel_remove": {
"id": "07",
"00": "Removed item on position ::pos:: from channel ::channel::",
"01": "Could not remove item on position ::pos:: from channel ::channel::",
"02": "Warning: position ::pos:: out of range'"
},
"channel_seek": {
"id": "08",
"00": "Seeked channel ::channel:: ::duration:: seconds",
"01": "Could not seek channel ::channel:: ::duration:: seconds"
},
"channel_skip": {
"id": "09",
"00": "Skipped channel ::channel::",
"01": "0 Channels listed",
"02": "Could not get channels from sound engine",
"03": "Could not skip ::channel::"
},
"channel_volume": {
"id": "10",
"00": "Volume ::volume::% set on channel ::channel::",
"01": "Could not set volume to ::volume::% on channel ::channel::",
"02": "0 Channels listed",
"03": "Could not get channels from sound engine"
},
"currentData": {
"id": "11",
"00": "Current track metadata delivered",
"01": "Nothing seems to be on air",
"02": "Could not detect metadata"
},
"help": {
"id": "12",
"00": "none",
"01": "Could not open help file"
},
"listChannels": {
"id": "13",
"00": "Listed Channels",
"01": "0 Channels listed",
"02": "Could not get channels from sound engine"
},
"message": {
"id": "14",
"00": "none"
},
"playlist_data": {
"id": "15",
"00": "Playlist data delivered"
},
"playlist_flush": {
"id": "16",
"00": "Flushed playlist",
"01": "Could not flush playlist"
},
"playlist_insert":{
"id": "17",
"00": "Insert track ::uri:: on position ::pos::"
},
"playlist_load": {
"id": "18",
"00": "Load Playlist ::uri::",
"01": "Could not load Playlist ::uri::",
"02": "Playlist is not well formed XML"
},
"playlist_move": {
"id": "19",
"00": "Moved playlist track from position ::fromPos:: to ::toPos::"
},
"playlist_pause": {
"id": "20",
"00": "Playlist paused",
"01": "Playlist already paused"
},
"playlist_stop": {
"id": "21",
"00": "Playlist stopped",
"01": "Playlist already stopped"
},
"playlist_play": {
"id": "22",
"00": "Playlist started",
"01": "Playlist already playing",
"02": "0 Channels listed",
"03": "Could not get channels from sound engine"
},
"playlist_push": {
"id": "23",
"00": "Playlist: pushed ::uri::",
"01": "Could not push ::uri::"
},
"playlist_remove":{
"id": "24",
"00": "Removed track on position ::pos:: from playlist",
"01": "Could not remove track on position ::pos:: from playlist"
},
"playlist_seek": {
"id": "25",
"00": "Seeked playlist ::duration:: seconds",
"01": "Could not seek playlist ::duration:: seconds"
},
"playlist_skip": {
"id": "26",
"00": "Skipped playlist",
"00": "Could not skip playlist"
},
"recorder_data": {
"id": "27",
"00": "Delivered recorder data",
"01": "Could not deliver recorder data"
},
"recorder_start": {
"id": "28",
"00": "Recorder started",
"01": "Could not start recorder"
},
"recorder_stop": {
"id": "29",
"00": "Recorder stopped",
"01": "Could not stop recorder"
},
"scheduler_reload": {
"id": "30",
"00": "Reload signal was sent to scheduler",
"01": "Could not find the scheduler process"
},
"sendLqcCommand": {
"id": "31",
"01": "Soundengine not running",
"02": "Recorder not running"
},
"get_channel_state" : {
"id": "32",
"00": "Channels ::channel:: state",
"01": "Could not get channel state from channel ::channel::"
},
"setPassword": {
"id": "33",
"00": "Successfull set password",
"01": "Not enough access rights for this operation"
},
"addUser": {
"id": "34",
"00": "Successfull add user ::username::",
"01": "Not enough access rights for this operation"
},
"delUser": {
"id": "35",
"00": "Successfull removed user ::username::",
"01": "Not enough access rights for this operation"
},
"scheduler_data": {
"id": "36",
"00": "Successfull delivered scheduler config",
"01": "Scheduler config seems to be broken"
},
"scheduler_store": {
"id": "37",
"00": "Successfull stored scheduler config",
"01": "Not enough access rights for this operation",
"02": "Could not store a valid scheduler XML"
},
"getUserlist": {
"id": "38",
"00": "Userlist was successfully delivered",
"01": "Not enough access rights for this operation"
}
}
{
"exec_job": {
"id": "01",
"00": "Execute job ::job::",
"01": "Fatal: Could not execute job ::job::. Command ::exec:: results in Exception ::Exception::. Stopped watcher"
},
"schedule_job": {
"id": "02",
"00": "Scheduled job ::job:: for ::scheduled_for:: at ::scheduled_at::",
"01": "Could not execute job"
},
"load_playlist": {
"id": "03",
"00": "Load playlist ::uri::",
"01": "Could not load playlist ::uri::. File does not exist!",
"02": "Controller failed to load playlist ::uri::. Message was '::message::'"
},
"play_playlist": {
"id": "04",
"00": "Started playlist",
"01": "Controller failed to start playlist. Message was '::message::'"
},
"stop_playlist": {
"id": "05",
"00": "Started playlist",
"01": "Controller failed to start playlist. Message was '::message::'"
},
"start_recording": {
"id": "06",
"00": "Started recording",
"01": "Controller failed to start recording. Message was '::message::'"
},
"stop_recording": {
"id": "07",
"00": "Stopped recording",
"01": "Controller failed to stop recording. Message was '::message::'" },
"precache": {
"id": "08",
"00": "Precached playlists",
"01": "Could not precache playlist."
},
"clean_cached": {
"id": "09",
"00": "Cleaned cache",
"01": "Could not clean cache"
},
"on_start": {
"id": "10",
"00": "Do initial jobs",
"01": "Could not do initial jobs"
},
"lookup_prearranged": {
"id": "11",
"00": "Lookup for prearranged tracks",
"01": "No system channel available"
},
"start_prearranged": {
"id": "12",
"00": "Started preaarranged tracks"
},
"end_prearranged": {
"id": "13",
"00": "Stopped preaarranged tracks"
}
}
#!/usr/bin/python3
import time
from argparse import ArgumentParser
from modules.communication.liquidsoap.LiquidSoapCommunicator import LiquidSoapCommunicator
# from modules.base.calendar import AuraCalendarService
from libraries.base.calendar import AuraCalendarService
from libraries.base.config import ConfigReader
class Guru:
config = ConfigReader()
config.loadConfig()
lsc = LiquidSoapCommunicator(False)
acs = AuraCalendarService(config) # AuraScheduler(lsc.getClient(), "/etc/comba/scheduler.xml")
#fcd = FetchCalendarData()
def __init__(self):
nothing_done = True
try:
parser = ArgumentParser()
# commands
parser.add_argument("-fnp", "--fetch-new-programmes", action="store_true", dest="fetchnewprogramme",
default=False, help="Fetch new programmes from calendarurl in comba.ini")
# getter
parser.add_argument("-gam", "--get-active-mixer", action="store_true", dest="getactivemixer", default=False,
help="Which mixer is activated?")
parser.add_argument("-pms", "--print-mixer-status", action="store_true", dest="printmixerstatus", default=False,
help="Prints all mixer sources and their states")
# manipulation
parser.add_argument("-am", "--select-mixer", action="store", dest="selectmixer", default=-1,
help="Which mixer should be activated?", type=int)
parser.add_argument("-dm", "--de-select-mixer", action="store", dest="deselectmixer", default=-1,
help="Which mixer should be activated?", type=int)
parser.add_argument("-as", "--add-source", action="store", dest="addsource", default="",
help="Add new source to LiquidSoap mixer [Experimental]")
args = parser.parse_args()
except ValueError:
parser.print_help()
exit(1)
if args.fetchnewprogramme:
print("Guru is learning how to fetch new programmes")
self.fetchNewProgrammes()
nothing_done = False
if args.getactivemixer:
self.getactivemixer()
nothing_done = False
if args.printmixerstatus:
self.printmixerstatus()
nothing_done = False
if args.addsource != "":
print("Guru still has to learn to add a source")
nothing_done = False
if args.selectmixer != -1:
self.selectmixer(args.selectmixer)
nothing_done = False
if args.deselectmixer != -1:
self.selectmixer(args.deselectmixer, False)
nothing_done = False
if nothing_done:
parser.print_help()
def fetchNewProgrammes(self):
self.acs.start()
time.sleep(2) # well, ok, here i should listen to a AuraMessenger
nextshows = self.acs.getCalendarData()
for show in nextshows:
print(show)
return nextshows
def selectmixer(self, mixernumber, activate=True):
return self.lsc.switchmixernumber(mixernumber, activate)
def getactivemixer(self):
print("Guru thinking...")
am = self.lsc.getactivemixer()
if len(am) == 0:
print("Guru recognized a problem: No active source!!!")
elif len(am) > 1:
print("Guru recognized a problem: Multiple active sources!!! " + str(am))
else:
print("Guru thinking result: ActiveMixer: " + str(am[0]))
def printmixerstatus(self):
status = self.lsc.getmixerstatus()
for k,v in status.items():
print("source: "+k+"\t status: "+v)
# # ## ## ## ## ## # #
# # ENTRY FUNCTION # #
# # ## ## ## ## ## # #
def main():
guru = Guru()
# # ## ## ## ## ## ## # #
# # End ENTRY FUNCTION # #
# # ## ## ## ## ## ## # #
if __name__ == "__main__":
main()
This diff is collapsed.
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# combabase.py
#
# Copyright 2014 BFR <info@freie-radios.de>
#
# This program 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; Version 3 of the License
#
# 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 General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, the license can be downloaded here:
#
# http://www.gnu.org/licenses/gpl.html
# Meta
__version__ = '0.1.1'
__license__ = "GNU General Public License (GPL) Version 3"
__version_info__ = (0, 1, 1)
__author__ = 'Michael Liebler <michael-liebler@radio-z.net>'
# massively enhanced by Gottfried Gaisbauer <gottfried.gaisbauer@servus.at>
"""
Comba Base Class - lade Config
"""
import os
import sys
#import StringIO
#import ConfigParser
import socket
from io import StringIO
from configparser import RawConfigParser
from configparser import ConfigParser
class ConfigReader(object):
def set(self, key, value):
"""
Eine property setzen
@type key: string
@param key: Der Key
@type value: mixed
@param value: Beliebiger Wert
"""
if(key == "securitylevel"):
self.__dict__[key] = int(value)
else:
self.__dict__[key] = value
# ------------------------------------------------------------------------------------------ #
def get(self, key, default=None):
"""
Eine property holen
@type key: string
@param key: Der Key
@type default: mixed
@param default: Beliebiger Wert
"""
if key not in self.__dict__:
if default:
self.set(key, default)
else:
print("WARNING: Key "+key+" not found!")
return None
return self.__dict__[key]
# ------------------------------------------------------------------------------------------ #
def loadConfig(self):
"""
Set config defaults and load settings from file
:return:
"""
ini_path = self.get('configpath', '/etc/aura/aura.ini')
if not os.path.isfile(ini_path):
print(ini_path + " not found :(")
sys.exit(1)
# INI einlesen
f = open(ini_path, 'r')
ini_str = '[root]\n' + f.read()
f.close()