Commit 57a74d4f authored by David Trattnig's avatar David Trattnig
Browse files

Expand missing playlist entry duration. #24

parent 4cf5840c
......@@ -179,6 +179,34 @@ class SimpleUtil:
return datetime.datetime.fromtimestamp(timestamp).strftime('%H:%M:%S')
@staticmethod
def nano_to_seconds(nanoseconds):
"""
Converts nano-seconds to senconds
Args:
(Integer) nanoseconds
Returns:
(Float): seconds
"""
return float(nanoseconds / 1000000000)
@staticmethod
def seconds_to_nano(seconds):
"""
Converts senconds to nano-seconds
Args:
(Integer) seconds
Returns:
(Float): nanoseconds
"""
return int(seconds * 1000000000)
@staticmethod
def timestamp(date_and_time=None):
"""
......
......@@ -27,7 +27,7 @@ import logging
from datetime import datetime
from modules.scheduling.types import PlaylistType
from modules.base.utils import SimpleUtil
from modules.base.utils import SimpleUtil as SU
from modules.base.models import Schedule, Playlist, PlaylistEntry, PlaylistEntryMetaData
from modules.scheduling.calender_fetcher import CalendarFetcher
......@@ -87,7 +87,7 @@ class AuraCalendarService(threading.Thread):
Schedule ([]): An arrar of retrieved schedules passed via `self.queue`
"""
result = []
now_unix = SimpleUtil.timestamp()
now_unix = SU.timestamp()
scheduling_window_start = self.config.get("scheduling_window_start")
try:
......@@ -121,8 +121,9 @@ class AuraCalendarService(threading.Thread):
self.logger.info("Deleted local schedule #%s from database" % local_schedule.schedule_id)
else:
msg = "Schedule #%s has been deleted remotely. Since the scheduling window has already started, it won't be deleted locally." % local_schedule.schedule_id
self.logger.warn(SimpleUtil.red(msg))
msg = "Schedule #%s has been deleted remotely. Since the scheduling window has already started, it won't be deleted locally." % \
local_schedule.schedule_id
self.logger.error(SU.red(msg))
# Process fetched schedules
for schedule in fetched_schedule_data:
......@@ -243,8 +244,7 @@ class AuraCalendarService(threading.Thread):
entry_num = 0
time_marker = playlist_db.start_unix
# If existing playlist entries are beyond the count of the new playlist entries,
# then delete those first
self.expand_entry_duration(schedule_db, fetched_playlist)
self.delete_orphaned_entries(playlist_db, fetched_playlist)
for entry in fetched_playlist["entries"]:
......@@ -257,16 +257,7 @@ class AuraCalendarService(threading.Thread):
entry_db.entry_start = datetime.fromtimestamp(time_marker)
entry_db.artificial_playlist_id = playlist_db.artificial_id
entry_db.entry_num = entry_num
if "file" in entry and "duration" in entry["file"]:
# Convert nano-seconds to seconds
duration = int(float(entry["file"]["duration"]) / 1000000000)
else:
# No duration means it's playing until the end of the schedule
self.logger.debug("Missing duration - setting duration of entry to end-of-schedule")
duration = SimpleUtil.timestamp(schedule_db.schedule_end) - time_marker
entry_db.duration = duration
entry_db.duration = SU.nano_to_seconds(entry["duration"])
if "uri" in entry:
# FIXME Refactor mix of uri/filename/file/source
......@@ -281,7 +272,7 @@ class AuraCalendarService(threading.Thread):
self.store_playlist_entry_metadata(entry_db, entry["file"]["metadata"])
entry_num = entry_num + 1
time_marker += duration
time_marker += entry_db.duration
......@@ -299,10 +290,41 @@ class AuraCalendarService(threading.Thread):
for entry_num in range(new_last_idx, existing_last_idx+1, 1):
PlaylistEntry.delete_entry(playlist_db.artificial_id, entry_num)
self.logger.info(SimpleUtil.yellow("Deleted playlist entry %s:%s" % (playlist_db.artificial_id, entry_num)))
self.logger.info(SU.yellow("Deleted playlist entry %s:%s" % (playlist_db.artificial_id, entry_num)))
entry_num += 1
def expand_entry_duration(self, schedule_db, fetched_playlist):
"""
If some playlist entry doesn't have a duration assigned, its duration is expanded to the
remaining duration of the playlist (= schedule duration minus playlist entries with duration).
If there's more than one entry without duration, such entries are removed from the playlist.
"""
total_seconds = (schedule_db.schedule_end - schedule_db.schedule_start).total_seconds()
total_duration = SU.seconds_to_nano(total_seconds)
actual_duration = 0
missing_duration = []
idx = 0
for entry in fetched_playlist["entries"]:
if not "duration" in entry:
missing_duration.append(idx)
else:
actual_duration += entry["duration"]
idx += 1
if len(missing_duration) == 1:
fetched_playlist["entries"][missing_duration[0]]["duration"] = total_duration - actual_duration
self.logger.info("Expanded duration of playlist entry #%s:%s" % (fetched_playlist["id"], missing_duration[0]))
elif len(missing_duration) > 1:
# This case should actually never happen, as TANK doesn't allow more than one entry w/o duration anymore
for i in reversed(missing_duration[1:-1]):
self.logger.error(SU.red("Deleted Playlist Entry without duration: %s" % \
str(fetched_playlist["entries"][i])))
del fetched_playlist["entries"][i]
def store_playlist_entry_metadata(self, entry_db, metadata):
"""
......
......@@ -125,7 +125,6 @@ class CalendarFetcher:
try:
self.logger.debug("Fetch schedules from Steering API...")
response = requests.get(self.steering_calendar_url, data=None, headers=headers)
self.logger.debug("Steering API response: %s" % response.status_code)
if not response.status_code == 200:
self.logger.critical(SU.red("HTTP Status: %s | Schedules could not be fetched! Response: %s" % \
(str(response.status_code), response.text)))
......@@ -209,7 +208,6 @@ class CalendarFetcher:
try:
self.logger.debug("Fetch playlist from Tank API...")
response = requests.get(url, data=None, headers=headers)
self.logger.info("Tank API response: %s" % response.status_code)
if not response.status_code == 200:
self.logger.critical(SU.red("HTTP Status: %s | Playlist #%s could not be fetched or is not available! Response: %s" % \
(str(response.status_code), str(playlist_id), response.text)))
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment