import signal import sys import time import traceback from collections import deque from datetime import datetime from queue import Empty from threading import Thread def keyboardInterruptHandler(signum, frame): logger = logging.getLogger() logger.info("\nKeyboard Interrupt\n") sys.exit(0) signal.signal(signal.SIGINT, keyboardInterruptHandler) class PypoLiqQueue(Thread): def __init__(self, q, pypo_liquidsoap, logger): Thread.__init__(self) self.queue = q self.logger = logger self.pypo_liquidsoap = pypo_liquidsoap def main(self): time_until_next_play = None schedule_deque = deque() media_schedule = None while True: try: if time_until_next_play is None: self.logger.info("waiting indefinitely for schedule") media_schedule = self.queue.get(block=True) else: self.logger.info( "waiting %ss until next scheduled item" % time_until_next_play ) media_schedule = self.queue.get( block=True, timeout=time_until_next_play ) except Empty as e: # Time to push a scheduled item. media_item = schedule_deque.popleft() self.pypo_liquidsoap.play(media_item) if len(schedule_deque): time_until_next_play = self.date_interval_to_seconds( schedule_deque[0]["start"] - datetime.utcnow() ) if time_until_next_play < 0: time_until_next_play = 0 else: time_until_next_play = None else: self.logger.info("New schedule received: %s", media_schedule) # new schedule received. Replace old one with this. schedule_deque.clear() keys = sorted(media_schedule.keys()) for i in keys: schedule_deque.append(media_schedule[i]) if len(keys): time_until_next_play = self.date_interval_to_seconds( media_schedule[keys[0]]["start"] - datetime.utcnow() ) else: time_until_next_play = None def date_interval_to_seconds(self, interval): """ Convert timedelta object into int representing the number of seconds. If number of seconds is less than 0, then return 0. """ seconds = ( interval.microseconds + (interval.seconds + interval.days * 24 * 3600) * 10 ** 6 ) / float(10 ** 6) if seconds < 0: seconds = 0 return seconds def run(self): try: self.main() except Exception as e: self.logger.error("PypoLiqQueue Exception: %s", traceback.format_exc())