Merge branch '2.1.x' of dev.sourcefabric.org:airtime into 2.1.x
This commit is contained in:
commit
42ad8fe35d
|
@ -5,6 +5,8 @@ Python part of radio playout (pypo)
|
||||||
from optparse import OptionParser
|
from optparse import OptionParser
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
import telnetlib
|
||||||
|
|
||||||
import time
|
import time
|
||||||
import sys
|
import sys
|
||||||
import signal
|
import signal
|
||||||
|
@ -50,6 +52,15 @@ parser.add_option("-c", "--check", help="Check the cached schedule and exit", de
|
||||||
#need to wait for Python 2.7 for this..
|
#need to wait for Python 2.7 for this..
|
||||||
#logging.captureWarnings(True)
|
#logging.captureWarnings(True)
|
||||||
|
|
||||||
|
# configure logging
|
||||||
|
try:
|
||||||
|
logging.config.fileConfig("logging.cfg")
|
||||||
|
logger = logging.getLogger()
|
||||||
|
LogWriter.override_std_err(logger)
|
||||||
|
except Exception, e:
|
||||||
|
print "Couldn't configure logging"
|
||||||
|
sys.exit()
|
||||||
|
|
||||||
def configure_locale():
|
def configure_locale():
|
||||||
logger.debug("Before %s", locale.nl_langinfo(locale.CODESET))
|
logger.debug("Before %s", locale.nl_langinfo(locale.CODESET))
|
||||||
current_locale = locale.getlocale()
|
current_locale = locale.getlocale()
|
||||||
|
@ -61,8 +72,8 @@ def configure_locale():
|
||||||
if default_locale[1] is None:
|
if default_locale[1] is None:
|
||||||
logger.debug("No default locale exists. Let's try loading from /etc/default/locale")
|
logger.debug("No default locale exists. Let's try loading from /etc/default/locale")
|
||||||
if os.path.exists("/etc/default/locale"):
|
if os.path.exists("/etc/default/locale"):
|
||||||
config = ConfigObj('/etc/default/locale')
|
locale_config = ConfigObj('/etc/default/locale')
|
||||||
lang = config.get('LANG')
|
lang = locale_config.get('LANG')
|
||||||
new_locale = lang
|
new_locale = lang
|
||||||
else:
|
else:
|
||||||
logger.error("/etc/default/locale could not be found! Please run 'sudo update-locale' from command-line.")
|
logger.error("/etc/default/locale could not be found! Please run 'sudo update-locale' from command-line.")
|
||||||
|
@ -84,14 +95,6 @@ def configure_locale():
|
||||||
logger.error("Need a UTF-8 locale. Currently '%s'. Exiting..." % current_locale_encoding)
|
logger.error("Need a UTF-8 locale. Currently '%s'. Exiting..." % current_locale_encoding)
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
# configure logging
|
|
||||||
try:
|
|
||||||
logging.config.fileConfig("logging.cfg")
|
|
||||||
logger = logging.getLogger()
|
|
||||||
LogWriter.override_std_err(logger)
|
|
||||||
except Exception, e:
|
|
||||||
print "Couldn't configure logging"
|
|
||||||
sys.exit()
|
|
||||||
|
|
||||||
configure_locale()
|
configure_locale()
|
||||||
|
|
||||||
|
@ -118,9 +121,26 @@ def keyboardInterruptHandler(signum, frame):
|
||||||
logger.info('\nKeyboard Interrupt\n')
|
logger.info('\nKeyboard Interrupt\n')
|
||||||
sys.exit(0)
|
sys.exit(0)
|
||||||
|
|
||||||
|
def liquidsoap_running_test(telnet_lock, host, port, logger):
|
||||||
|
logger.debug("Checking to see if Liquidsoap is running")
|
||||||
|
success = True
|
||||||
|
try:
|
||||||
|
telnet_lock.acquire()
|
||||||
|
tn = telnetlib.Telnet(host, port)
|
||||||
|
msg = "version\n"
|
||||||
|
tn.write(msg)
|
||||||
|
tn.write("exit\n")
|
||||||
|
logger.info("Liquidsoap version %s", tn.read_all())
|
||||||
|
except Exception, e:
|
||||||
|
logger.error(str(e))
|
||||||
|
success = False
|
||||||
|
finally:
|
||||||
|
telnet_lock.release()
|
||||||
|
|
||||||
|
return success
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
logger = logging.getLogger()
|
|
||||||
logger.info('###########################################')
|
logger.info('###########################################')
|
||||||
logger.info('# *** pypo *** #')
|
logger.info('# *** pypo *** #')
|
||||||
logger.info('# Liquidsoap Scheduled Playout System #')
|
logger.info('# Liquidsoap Scheduled Playout System #')
|
||||||
|
@ -129,17 +149,24 @@ if __name__ == '__main__':
|
||||||
#Although all of our calculations are in UTC, it is useful to know what timezone
|
#Although all of our calculations are in UTC, it is useful to know what timezone
|
||||||
#the local machine is, so that we have a reference for what time the actual
|
#the local machine is, so that we have a reference for what time the actual
|
||||||
#log entries were made
|
#log entries were made
|
||||||
logger.info("Timezone: %s" % time.tzname)
|
logger.info("Timezone: %s" % str(time.tzname))
|
||||||
logger.info("UTC time: %s" % datetime.utcnow())
|
logger.info("UTC time: %s" % str(datetime.utcnow()))
|
||||||
|
|
||||||
signal.signal(signal.SIGINT, keyboardInterruptHandler)
|
signal.signal(signal.SIGINT, keyboardInterruptHandler)
|
||||||
|
|
||||||
# initialize
|
# initialize
|
||||||
g = Global()
|
g = Global()
|
||||||
|
|
||||||
while not g.selfcheck(): time.sleep(5)
|
while not g.selfcheck():
|
||||||
|
time.sleep(5)
|
||||||
|
|
||||||
logger = logging.getLogger()
|
telnet_lock = Lock()
|
||||||
|
|
||||||
|
ls_host = config['ls_host']
|
||||||
|
ls_port = config['ls_port']
|
||||||
|
while not liquidsoap_running_test(telnet_lock, ls_host, ls_port, logger):
|
||||||
|
logger.warning("Liquidsoap not started yet. Sleeping one second and trying again")
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
if options.test:
|
if options.test:
|
||||||
g.test_api()
|
g.test_api()
|
||||||
|
@ -152,7 +179,7 @@ if __name__ == '__main__':
|
||||||
recorder_q = Queue()
|
recorder_q = Queue()
|
||||||
pypoPush_q = Queue()
|
pypoPush_q = Queue()
|
||||||
|
|
||||||
telnet_lock = Lock()
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
This queue is shared between pypo-fetch and pypo-file, where pypo-file
|
This queue is shared between pypo-fetch and pypo-file, where pypo-file
|
||||||
|
|
|
@ -71,7 +71,8 @@ class PypoPush(Thread):
|
||||||
#We get to the following lines only if a schedule was received.
|
#We get to the following lines only if a schedule was received.
|
||||||
liquidsoap_queue_approx = self.get_queue_items_from_liquidsoap()
|
liquidsoap_queue_approx = self.get_queue_items_from_liquidsoap()
|
||||||
|
|
||||||
current_event_chain, original_chain = self.get_current_chain(chains)
|
tnow = datetime.utcnow()
|
||||||
|
current_event_chain, original_chain = self.get_current_chain(chains, tnow)
|
||||||
if len(current_event_chain) > 0 and len(liquidsoap_queue_approx) == 0:
|
if len(current_event_chain) > 0 and len(liquidsoap_queue_approx) == 0:
|
||||||
#Something is scheduled but Liquidsoap is not playing anything!
|
#Something is scheduled but Liquidsoap is not playing anything!
|
||||||
#Need to schedule it immediately..this might happen if Liquidsoap crashed.
|
#Need to schedule it immediately..this might happen if Liquidsoap crashed.
|
||||||
|
@ -89,7 +90,7 @@ class PypoPush(Thread):
|
||||||
media_chain = filter(lambda item: (item["type"] == "file"), current_event_chain)
|
media_chain = filter(lambda item: (item["type"] == "file"), current_event_chain)
|
||||||
self.handle_new_media_schedule(media_schedule, liquidsoap_queue_approx, media_chain)
|
self.handle_new_media_schedule(media_schedule, liquidsoap_queue_approx, media_chain)
|
||||||
|
|
||||||
next_media_item_chain = self.get_next_schedule_chain(chains)
|
next_media_item_chain = self.get_next_schedule_chain(chains, tnow)
|
||||||
|
|
||||||
self.logger.debug("Next schedule chain: %s", next_media_item_chain)
|
self.logger.debug("Next schedule chain: %s", next_media_item_chain)
|
||||||
if next_media_item_chain is not None:
|
if next_media_item_chain is not None:
|
||||||
|
@ -98,9 +99,8 @@ class PypoPush(Thread):
|
||||||
except ValueError, e:
|
except ValueError, e:
|
||||||
self.logger.error(str(e))
|
self.logger.error(str(e))
|
||||||
|
|
||||||
tnow = datetime.utcnow()
|
|
||||||
chain_start = datetime.strptime(next_media_item_chain[0]['start'], "%Y-%m-%d-%H-%M-%S")
|
chain_start = datetime.strptime(next_media_item_chain[0]['start'], "%Y-%m-%d-%H-%M-%S")
|
||||||
time_until_next_play = self.date_interval_to_seconds(chain_start - tnow)
|
time_until_next_play = self.date_interval_to_seconds(chain_start - datetime.utcnow())
|
||||||
self.logger.debug("Blocking %s seconds until show start", time_until_next_play)
|
self.logger.debug("Blocking %s seconds until show start", time_until_next_play)
|
||||||
else:
|
else:
|
||||||
self.logger.debug("Blocking indefinitely since no show scheduled")
|
self.logger.debug("Blocking indefinitely since no show scheduled")
|
||||||
|
@ -109,11 +109,10 @@ class PypoPush(Thread):
|
||||||
#We only get here when a new chain of tracks are ready to be played.
|
#We only get here when a new chain of tracks are ready to be played.
|
||||||
self.push_to_liquidsoap(next_media_item_chain)
|
self.push_to_liquidsoap(next_media_item_chain)
|
||||||
|
|
||||||
next_media_item_chain = self.get_next_schedule_chain(chains)
|
next_media_item_chain = self.get_next_schedule_chain(chains, datetime.utcnow())
|
||||||
if next_media_item_chain is not None:
|
if next_media_item_chain is not None:
|
||||||
tnow = datetime.utcnow()
|
|
||||||
chain_start = datetime.strptime(next_media_item_chain[0]['start'], "%Y-%m-%d-%H-%M-%S")
|
chain_start = datetime.strptime(next_media_item_chain[0]['start'], "%Y-%m-%d-%H-%M-%S")
|
||||||
time_until_next_play = self.date_interval_to_seconds(chain_start - tnow)
|
time_until_next_play = self.date_interval_to_seconds(chain_start - datetime.utcnow())
|
||||||
self.logger.debug("Blocking %s seconds until show start", time_until_next_play)
|
self.logger.debug("Blocking %s seconds until show start", time_until_next_play)
|
||||||
else:
|
else:
|
||||||
self.logger.debug("Blocking indefinitely since no show scheduled next")
|
self.logger.debug("Blocking indefinitely since no show scheduled next")
|
||||||
|
@ -287,8 +286,7 @@ class PypoPush(Thread):
|
||||||
but
|
but
|
||||||
chains.remove(original) won't
|
chains.remove(original) won't
|
||||||
"""
|
"""
|
||||||
def get_current_chain(self, chains):
|
def get_current_chain(self, chains, tnow):
|
||||||
tnow = datetime.utcnow()
|
|
||||||
current_chain = []
|
current_chain = []
|
||||||
original_chain = None
|
original_chain = None
|
||||||
|
|
||||||
|
@ -313,10 +311,9 @@ class PypoPush(Thread):
|
||||||
of media_items where the end time of media_item 'n' is the start time of media_item
|
of media_items where the end time of media_item 'n' is the start time of media_item
|
||||||
'n+1'
|
'n+1'
|
||||||
"""
|
"""
|
||||||
def get_next_schedule_chain(self, chains):
|
def get_next_schedule_chain(self, chains, tnow):
|
||||||
#all media_items are now divided into chains. Let's find the one that
|
#all media_items are now divided into chains. Let's find the one that
|
||||||
#starts closest in the future.
|
#starts closest in the future.
|
||||||
tnow = datetime.utcnow()
|
|
||||||
closest_start = None
|
closest_start = None
|
||||||
closest_chain = None
|
closest_chain = None
|
||||||
for chain in chains:
|
for chain in chains:
|
||||||
|
|
Loading…
Reference in New Issue