Merge branch '2.0.x' into devel
Conflicts: VERSION airtime_mvc/application/Bootstrap.php airtime_mvc/application/controllers/LibraryController.php airtime_mvc/application/controllers/ScheduleController.php airtime_mvc/application/models/Nowplaying.php airtime_mvc/application/models/Show.php airtime_mvc/application/models/airtime/CcShowInstances.php
This commit is contained in:
commit
54cbc86a0a
3234 changed files with 71062 additions and 781848 deletions
|
@ -22,7 +22,7 @@ import base64
|
|||
from configobj import ConfigObj
|
||||
import string
|
||||
|
||||
AIRTIME_VERSION = "2.0.0"
|
||||
AIRTIME_VERSION = "2.0.1"
|
||||
|
||||
def api_client_factory(config):
|
||||
logger = logging.getLogger()
|
||||
|
|
|
@ -131,6 +131,7 @@ class AirtimeMetadata:
|
|||
self.logger.error("Exception %s", e)
|
||||
return None
|
||||
|
||||
#check if file has any metadata
|
||||
if file_info is None:
|
||||
return None
|
||||
#check if file has any metadata
|
||||
|
|
|
@ -261,6 +261,9 @@ class MediaMonitorCommon:
|
|||
return stdout.splitlines()
|
||||
|
||||
def touch_index_file(self):
|
||||
dirname = os.path.dirname(self.timestamp_file)
|
||||
if not os.path.exists(dirname):
|
||||
os.makedirs(dirname)
|
||||
open(self.timestamp_file, "w")
|
||||
|
||||
def organize_new_file(self, pathname):
|
||||
|
|
|
@ -16,8 +16,10 @@ try:
|
|||
|
||||
#Start media-monitor daemon
|
||||
print "* Waiting for media-monitor processes to start..."
|
||||
"""
|
||||
p = Popen("/etc/init.d/airtime-media-monitor stop", shell=True)
|
||||
sts = os.waitpid(p.pid, 0)[1]
|
||||
"""
|
||||
p = Popen("/etc/init.d/airtime-media-monitor start-no-monit", shell=True)
|
||||
sts = os.waitpid(p.pid, 0)[1]
|
||||
except Exception, e:
|
||||
|
|
|
@ -104,15 +104,17 @@ try:
|
|||
|
||||
#restart airtime-playout
|
||||
print "* Waiting for pypo processes to start..."
|
||||
"""
|
||||
if os.environ["liquidsoap_keep_alive"] == "f":
|
||||
print " * Restarting any previous Liquidsoap instances"
|
||||
p = Popen("/etc/init.d/airtime-playout stop", shell=True)
|
||||
p = Popen("/etc/init.d/airtime-playout stop > /dev/null 2>&1", shell=True)
|
||||
sts = os.waitpid(p.pid, 0)[1]
|
||||
else:
|
||||
print " * Keeping any previous Liquidsoap instances running"
|
||||
p = Popen("/etc/init.d/airtime-playout pypo-stop", shell=True)
|
||||
p = Popen("/etc/init.d/airtime-playout pypo-stop > /dev/null 2>&1", shell=True)
|
||||
sts = os.waitpid(p.pid, 0)[1]
|
||||
p = Popen("/etc/init.d/airtime-playout start-no-monit", shell=True)
|
||||
"""
|
||||
p = Popen("/etc/init.d/airtime-playout start-no-monit > /dev/null 2>&1", shell=True)
|
||||
sts = os.waitpid(p.pid, 0)[1]
|
||||
|
||||
except Exception, e:
|
||||
|
|
|
@ -48,6 +48,7 @@ try:
|
|||
remove_file("/etc/monit/conf.d/monit-airtime-playout.cfg")
|
||||
remove_file("/etc/monit/conf.d/monit-airtime-liquidsoap.cfg")
|
||||
remove_file("/etc/monit/conf.d/monit-airtime-generic.cfg")
|
||||
remove_file("/etc/monit/conf.d/monit-airtime-rabbitmq-server.cfg")
|
||||
|
||||
except Exception, e:
|
||||
print e
|
||||
|
|
|
@ -5,10 +5,9 @@ end
|
|||
|
||||
# A function applied to each metadata chunk
|
||||
def append_title(m) =
|
||||
log("Using stream_format #{!stream_metadata_type}")
|
||||
if !stream_metadata_type == 1 then
|
||||
[("artist","#{!show_name} - #{m['artist']}")]
|
||||
#####elsif !stream_metadata_type == 2 then
|
||||
##### [("artist", ""), ("title", !show_name)]
|
||||
elsif !stream_metadata_type == 2 then
|
||||
[("artist",!station_name), ("title", !show_name)]
|
||||
else
|
||||
|
|
|
@ -10,7 +10,6 @@ import string
|
|||
import json
|
||||
import telnetlib
|
||||
import math
|
||||
import socket
|
||||
from threading import Thread
|
||||
from subprocess import Popen, PIPE
|
||||
from datetime import datetime
|
||||
|
@ -21,6 +20,7 @@ import filecmp
|
|||
from kombu.connection import BrokerConnection
|
||||
from kombu.messaging import Exchange, Queue, Consumer, Producer
|
||||
from kombu.exceptions import MessageStateError
|
||||
from kombu.simple import SimpleQueue
|
||||
|
||||
from api_clients import api_client
|
||||
|
||||
|
@ -44,11 +44,11 @@ except Exception, e:
|
|||
class PypoFetch(Thread):
|
||||
def __init__(self, q):
|
||||
Thread.__init__(self)
|
||||
logger = logging.getLogger('fetch')
|
||||
self.api_client = api_client.api_client_factory(config)
|
||||
self.set_export_source('scheduler')
|
||||
self.queue = q
|
||||
self.schedule_data = []
|
||||
logger = logging.getLogger('fetch')
|
||||
logger.info("PypoFetch: init complete")
|
||||
|
||||
def init_rabbit_mq(self):
|
||||
|
@ -57,11 +57,9 @@ class PypoFetch(Thread):
|
|||
try:
|
||||
schedule_exchange = Exchange("airtime-pypo", "direct", durable=True, auto_delete=True)
|
||||
schedule_queue = Queue("pypo-fetch", exchange=schedule_exchange, key="foo")
|
||||
self.connection = BrokerConnection(config["rabbitmq_host"], config["rabbitmq_user"], config["rabbitmq_password"], config["rabbitmq_vhost"])
|
||||
channel = self.connection.channel()
|
||||
consumer = Consumer(channel, schedule_queue)
|
||||
consumer.register_callback(self.handle_message)
|
||||
consumer.consume()
|
||||
connection = BrokerConnection(config["rabbitmq_host"], config["rabbitmq_user"], config["rabbitmq_password"], config["rabbitmq_vhost"])
|
||||
channel = connection.channel()
|
||||
self.simple_queue = SimpleQueue(channel, schedule_queue)
|
||||
except Exception, e:
|
||||
logger.error(e)
|
||||
return False
|
||||
|
@ -72,12 +70,12 @@ class PypoFetch(Thread):
|
|||
Handle a message from RabbitMQ, put it into our yucky global var.
|
||||
Hopefully there is a better way to do this.
|
||||
"""
|
||||
def handle_message(self, body, message):
|
||||
try:
|
||||
def handle_message(self, message):
|
||||
try:
|
||||
logger = logging.getLogger('fetch')
|
||||
logger.info("Received event from RabbitMQ: " + message.body)
|
||||
logger.info("Received event from RabbitMQ: %s" % message)
|
||||
|
||||
m = json.loads(message.body)
|
||||
m = json.loads(message)
|
||||
command = m['event_type']
|
||||
logger.info("Handling command: " + command)
|
||||
|
||||
|
@ -87,17 +85,17 @@ class PypoFetch(Thread):
|
|||
elif command == 'update_stream_setting':
|
||||
logger.info("Updating stream setting...")
|
||||
self.regenerateLiquidsoapConf(m['setting'])
|
||||
elif command == 'update_stream_format':
|
||||
logger.info("Updating stream format...")
|
||||
self.update_liquidsoap_stream_format(m['stream_format'])
|
||||
elif command == 'update_station_name':
|
||||
logger.info("Updating station name...")
|
||||
self.update_liquidsoap_station_name(m['station_name'])
|
||||
elif command == 'cancel_current_show':
|
||||
logger.info("Cancel current show command received...")
|
||||
self.stop_current_show()
|
||||
except Exception, e:
|
||||
logger.error("Exception in handling RabbitMQ message: %s", e)
|
||||
finally:
|
||||
# ACK the message to take it off the queue
|
||||
try:
|
||||
message.ack()
|
||||
except MessageStateError, m:
|
||||
logger.error("Message ACK error: %s", m)
|
||||
|
||||
def stop_current_show(self):
|
||||
logger = logging.getLogger('fetch')
|
||||
|
@ -210,10 +208,7 @@ class PypoFetch(Thread):
|
|||
# restarting pypo.
|
||||
# we could just restart liquidsoap but it take more time somehow.
|
||||
logger.info("Restarting pypo...")
|
||||
#p = Popen("/etc/init.d/airtime-playout restart >/dev/null 2>&1", shell=True)
|
||||
#sts = os.waitpid(p.pid, 0)[1]
|
||||
sys.exit()
|
||||
self.process_schedule(self.schedule_data, "scheduler", False)
|
||||
sys.exit(0)
|
||||
else:
|
||||
logger.info("No change detected in setting...")
|
||||
self.update_liquidsoap_connection_status()
|
||||
|
@ -258,6 +253,39 @@ class PypoFetch(Thread):
|
|||
self.cache_dir = config["cache_dir"] + self.export_source + '/'
|
||||
logger.info("Creating cache directory at %s", self.cache_dir)
|
||||
|
||||
|
||||
def update_liquidsoap_stream_format(self, stream_format):
|
||||
# Push stream metadata to liquidsoap
|
||||
# TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!
|
||||
try:
|
||||
logger = logging.getLogger('fetch')
|
||||
logger.info(LS_HOST)
|
||||
logger.info(LS_PORT)
|
||||
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
|
||||
command = ('vars.stream_metadata_type %s\n' % stream_format).encode('utf-8')
|
||||
logger.info(command)
|
||||
tn.write(command)
|
||||
tn.write('exit\n')
|
||||
tn.read_all()
|
||||
except Exception, e:
|
||||
logger.error("Exception %s", e)
|
||||
|
||||
def update_liquidsoap_station_name(self, station_name):
|
||||
# Push stream metadata to liquidsoap
|
||||
# TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!
|
||||
try:
|
||||
logger = logging.getLogger('fetch')
|
||||
logger.info(LS_HOST)
|
||||
logger.info(LS_PORT)
|
||||
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
|
||||
command = ('vars.station_name %s\n' % station_name).encode('utf-8')
|
||||
logger.info(command)
|
||||
tn.write(command)
|
||||
tn.write('exit\n')
|
||||
tn.read_all()
|
||||
except Exception, e:
|
||||
logger.error("Exception %s", e)
|
||||
|
||||
"""
|
||||
Process the schedule
|
||||
- Reads the scheduled entries of a given range (actual time +/- "prepare_ahead" / "cache_for")
|
||||
|
@ -270,22 +298,6 @@ class PypoFetch(Thread):
|
|||
logger = logging.getLogger('fetch')
|
||||
playlists = schedule_data["playlists"]
|
||||
|
||||
# Push stream metadata to liquidsoap
|
||||
# TODO: THIS LIQUIDSOAP STUFF NEEDS TO BE MOVED TO PYPO-PUSH!!!
|
||||
stream_metadata = schedule_data['stream_metadata']
|
||||
try:
|
||||
logger.info(LS_HOST)
|
||||
logger.info(LS_PORT)
|
||||
tn = telnetlib.Telnet(LS_HOST, LS_PORT)
|
||||
#encode in latin-1 due to telnet protocol not supporting utf-8
|
||||
tn.write(('vars.stream_metadata_type %s\n' % stream_metadata['format']).encode('latin-1'))
|
||||
tn.write(('vars.station_name %s\n' % stream_metadata['station_name']).encode('latin-1'))
|
||||
tn.write('exit\n')
|
||||
tn.read_all()
|
||||
except Exception, e:
|
||||
logger.error("Exception %s", e)
|
||||
status = 0
|
||||
|
||||
# Download all the media and put playlists in liquidsoap "annotate" format
|
||||
try:
|
||||
liquidsoap_playlists = self.prepare_playlists(playlists, bootstrapping)
|
||||
|
@ -295,7 +307,6 @@ class PypoFetch(Thread):
|
|||
scheduled_data = dict()
|
||||
scheduled_data['liquidsoap_playlists'] = liquidsoap_playlists
|
||||
scheduled_data['schedule'] = playlists
|
||||
scheduled_data['stream_metadata'] = schedule_data["stream_metadata"]
|
||||
self.queue.put(scheduled_data)
|
||||
|
||||
# cleanup
|
||||
|
@ -486,28 +497,25 @@ class PypoFetch(Thread):
|
|||
loops = 1
|
||||
while True:
|
||||
logger.info("Loop #%s", loops)
|
||||
try:
|
||||
# Wait for messages from RabbitMQ. Timeout if we
|
||||
# dont get any after POLL_INTERVAL.
|
||||
self.connection.drain_events(timeout=POLL_INTERVAL)
|
||||
status = 1
|
||||
except socket.timeout, se:
|
||||
# We didnt get a message for a while, so poll the server
|
||||
# to get an updated schedule.
|
||||
status, self.schedule_data = self.api_client.get_schedule()
|
||||
try:
|
||||
try:
|
||||
message = self.simple_queue.get(block=True)
|
||||
self.handle_message(message.payload)
|
||||
# ACK the message to take it off the queue
|
||||
message.ack()
|
||||
except MessageStateError, m:
|
||||
logger.error("Message ACK error: %s", m)
|
||||
except Exception, e:
|
||||
"""
|
||||
This Generic exception is thrown whenever the RabbitMQ
|
||||
Service is stopped. In this case let's check every few
|
||||
seconds to see if it has come back up
|
||||
There is a problem with the RabbitMq messenger service. Let's
|
||||
log the error and get the schedule via HTTP polling
|
||||
"""
|
||||
logger.info("Exception, %s", e)
|
||||
return
|
||||
logger.error("Exception, %s", e)
|
||||
|
||||
status, self.schedule_data = self.api_client.get_schedule()
|
||||
if status == 1:
|
||||
self.process_schedule(self.schedule_data, "scheduler", False)
|
||||
|
||||
#return based on the exception
|
||||
|
||||
if status == 1:
|
||||
self.process_schedule(self.schedule_data, "scheduler", False)
|
||||
loops += 1
|
||||
|
||||
"""
|
||||
|
|
|
@ -39,7 +39,6 @@ class PypoPush(Thread):
|
|||
|
||||
self.schedule = dict()
|
||||
self.playlists = dict()
|
||||
self.stream_metadata = dict()
|
||||
|
||||
self.liquidsoap_state_play = True
|
||||
self.push_ahead = 10
|
||||
|
@ -58,13 +57,16 @@ class PypoPush(Thread):
|
|||
def push(self, export_source):
|
||||
logger = logging.getLogger('push')
|
||||
|
||||
timenow = time.time()
|
||||
# get a new schedule from pypo-fetch
|
||||
if not self.queue.empty():
|
||||
scheduled_data = self.queue.get()
|
||||
# make sure we get the latest schedule
|
||||
while not self.queue.empty():
|
||||
scheduled_data = self.queue.get()
|
||||
logger.debug("Received data from pypo-fetch")
|
||||
self.schedule = scheduled_data['schedule']
|
||||
self.playlists = scheduled_data['liquidsoap_playlists']
|
||||
self.stream_metadata = scheduled_data['stream_metadata']
|
||||
|
||||
logger.debug('schedule %s' % json.dumps(self.schedule))
|
||||
logger.debug('playlists %s' % json.dumps(self.playlists))
|
||||
|
||||
|
@ -73,7 +75,6 @@ class PypoPush(Thread):
|
|||
|
||||
currently_on_air = False
|
||||
if schedule:
|
||||
timenow = time.time()
|
||||
tnow = time.gmtime(timenow)
|
||||
tcoming = time.gmtime(timenow + self.push_ahead)
|
||||
str_tnow_s = "%04d-%02d-%02d-%02d-%02d-%02d" % (tnow[0], tnow[1], tnow[2], tnow[3], tnow[4], tnow[5])
|
||||
|
@ -163,7 +164,7 @@ class PypoPush(Thread):
|
|||
|
||||
#Sending schedule table row id string.
|
||||
logger.debug("vars.pypo_data %s\n"%(liquidsoap_data["schedule_id"]))
|
||||
tn.write(("vars.pypo_data %s\n"%liquidsoap_data["schedule_id"]).encode('latin-1'))
|
||||
tn.write(("vars.pypo_data %s\n"%liquidsoap_data["schedule_id"]).encode('utf-8'))
|
||||
|
||||
logger.debug('Preparing to push playlist %s' % pkey)
|
||||
for item in playlist:
|
||||
|
|
|
@ -10,9 +10,6 @@ set_include_path(get_include_path() . PATH_SEPARATOR . realpath(APPLICATION_PATH
|
|||
set_include_path(get_include_path() . PATH_SEPARATOR . APPLICATION_PATH . '/models');
|
||||
echo get_include_path().PHP_EOL;
|
||||
|
||||
//Pear classes.
|
||||
set_include_path(APPLICATION_PATH . get_include_path() . PATH_SEPARATOR . '/../library/pear');
|
||||
|
||||
//Controller plugins.
|
||||
set_include_path(APPLICATION_PATH . get_include_path() . PATH_SEPARATOR . '/controllers/plugins');
|
||||
|
||||
|
|
|
@ -14,8 +14,10 @@ try:
|
|||
|
||||
#start daemon
|
||||
print "* Waiting for show-recorder processes to start..."
|
||||
"""
|
||||
p = Popen("/etc/init.d/airtime-show-recorder stop", shell=True)
|
||||
sts = os.waitpid(p.pid, 0)[1]
|
||||
"""
|
||||
p = Popen("/etc/init.d/airtime-show-recorder start-no-monit", shell=True)
|
||||
sts = os.waitpid(p.pid, 0)[1]
|
||||
except Exception, e:
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue