93 lines
3.0 KiB
Python
93 lines
3.0 KiB
Python
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())
|