Commit 4d4a2566 authored by David Trattnig's avatar David Trattnig
Browse files

Default playlist handling. #52

parent 2372c56d
......@@ -119,11 +119,22 @@ class ApiFetcher(threading.Thread):
self.logger.critical(SU.red("No timeslots fetched from API!"))
return None
for timeslot in self.fetched_timeslot_data:
# FIXME Workaround until https://gitlab.servus.at/aura/steering/-/issues/54 is implemented
if "schedule_fallback_id" in timeslot:
timeslot["default_schedule_playlist_id"] = timeslot["schedule_fallback_id"]
timeslot["schedule_fallback_id"] = None
if "show_fallback_id" in timeslot:
timeslot["default_show_playlist_id"] = timeslot["show_fallback_id"]
timeslot["show_fallback_id"] = None
self.logger.debug("Fetching playlists from TANK")
self.fetch_playlists()
try:
for timeslot in self.fetched_timeslot_data:
# Skip timeslot if no start or end is given
if "start" not in timeslot:
self.logger.warning("No start of timeslot given. Skipping timeslot: " + str(timeslot))
......@@ -131,13 +142,6 @@ class ApiFetcher(threading.Thread):
if "end" not in timeslot:
self.logger.warning("No end of timeslot given. Skipping timeslot: " + str(timeslot))
timeslot = None
if "playlist" not in timeslot \
and "show_fallback" not in timeslot \
and "schedule_fallback" not in timeslot \
and "station_fallback" not in timeslot:
self.logger.warning("No playlist for timeslot given. Skipping timeslot: " + str(timeslot))
timeslot = None
if timeslot:
return_data.append(timeslot)
......@@ -191,18 +195,22 @@ class ApiFetcher(threading.Thread):
try:
for timeslot in self.fetched_timeslot_data:
# Get IDs of playlists
# Get IDs of specific, default and fallback playlists
playlist_id = self.get_playlist_id(timeslot, "playlist_id")
schedule_fallback_id = self.get_playlist_id(timeslot, "schedule_fallback_id")
default_schedule_playlist_id = self.get_playlist_id(timeslot, "default_schedule_playlist_id")
default_show_playlist_id = self.get_playlist_id(timeslot, "default_show_playlist_id")
schedule_fallback_id = self.get_playlist_id(timeslot, "schedule_fallback_id")
show_fallback_id = self.get_playlist_id(timeslot, "show_fallback_id")
station_fallback_id = self.get_playlist_id(timeslot, "station_fallback_id")
# Retrieve playlist and the fallback playlists for every timeslot.
# Retrieve playlist, default and the fallback playlists for every timeslot.
# If a playlist (like station_fallback) is already fetched, it is not fetched again but reused
timeslot["playlist"] = self.fetch_playlist(playlist_id, fetched_entries)
timeslot["schedule_fallback"] = self.fetch_playlist(schedule_fallback_id, fetched_entries)
timeslot["show_fallback"] = self.fetch_playlist(show_fallback_id, fetched_entries)
timeslot["station_fallback"] = self.fetch_playlist(station_fallback_id, fetched_entries)
timeslot["playlist"] = self.fetch_playlist(playlist_id, fetched_entries)
timeslot["default_schedule_playlist"] = self.fetch_playlist(default_schedule_playlist_id, fetched_entries)
timeslot["default_show_playlist"] = self.fetch_playlist(default_show_playlist_id, fetched_entries)
timeslot["schedule_fallback"] = self.fetch_playlist(schedule_fallback_id, fetched_entries)
timeslot["show_fallback"] = self.fetch_playlist(show_fallback_id, fetched_entries)
timeslot["station_fallback"] = self.fetch_playlist(station_fallback_id, fetched_entries)
except Exception as e:
self.logger.error("Error while fetching playlists from API endpoints: " + str(e), e)
......@@ -214,14 +222,15 @@ class ApiFetcher(threading.Thread):
Fetches the playlist for a given timeslot.
Args:
id_name (String): The type of playlist to fetch (e.g. normal vs. fallback)
fetched_playlists ([]): Previously fetched playlists to avoid re-fetching
playlist_id (String): The ID of the playlist
fetched_playlists ([dict]): Previously fetched playlists to avoid re-fetching
Returns:
(Playlist): Playlist of type `id_name`
(Playlist): Playlist for `playlist_id`
"""
if not playlist_id:
return None
playlist = None
url = self.tank_playlist_url.replace("${ID}", playlist_id)
headers = {
......@@ -255,7 +264,17 @@ class ApiFetcher(threading.Thread):
def get_playlist_id(self, timeslot, id_name):
"""
Extracts the playlist ID for a given playlist (fallback) type.
Args:
timeslot (dict): The timeslot dictionary
id_name (String): The dictionary key holding the playlist ID
Returns:
(Integer): The playlist ID
"""
if not id_name in timeslot:
return None
playlist_id = str(timeslot[id_name])
if not playlist_id or playlist_id == "None":
self.logger.debug("No value defined for '%s' in timeslot '#%s'" % (id_name, timeslot["id"]))
......@@ -264,6 +283,7 @@ class ApiFetcher(threading.Thread):
return playlist_id
def polish_timeslots(self, timeslots):
"""
Removes all timeslots which are not relevant for further processing,
......
......@@ -201,11 +201,10 @@ class FallbackManager:
Returns:
(FallbackType, Playlist)
"""
planned_playlist = None
fallback_type = None
planned_playlist = self.engine.scheduler.programme.get_current_playlist(timeslot)
if self.validate_playlist(timeslot, "playlist"):
planned_playlist = timeslot.playlist
if planned_playlist:
fallback_type = FallbackType.NONE
else:
(fallback_type, planned_playlist) = self.get_fallback_playlist(timeslot)
......
......@@ -117,9 +117,9 @@ class ProgrammeService():
return None
# Check for scheduled playlist
current_playlist = current_timeslot.playlist
current_playlist = self.get_current_playlist(current_timeslot)
if not current_playlist:
msg = "There's no playlist assigned to the current timeslot. Most likely a fallback will make things okay again."
msg = "There's no (default) playlist assigned to the current timeslot. Most likely a fallback will make things okay again."
self.logger.warning(SU.red(msg))
return None
......@@ -161,6 +161,25 @@ class ProgrammeService():
def get_current_playlist(self, timeslot):
"""
Retrieves the playlist to be scheduled. If no specific playlist is assigned,
the default schedule or show playlist is returned. This method does not
respect any defined fallback playlists.
Returns:
(FallbackType, Playlist): The currently assigned playlist
"""
playlist = timeslot.playlist
if not playlist:
playlist = timeslot.default_schedule_playlist
if not playlist:
playlist = timeslot.default_show_playlist
return playlist
def get_next_timeslots(self, max_count=0):
"""
Retrieves the timeslots to be played after the current one.
......@@ -274,6 +293,10 @@ class ProgrammeStore():
# Store assigned playlists
self.store_playlist(timeslot_db, timeslot_db.playlist_id, timeslot["playlist"])
if timeslot_db.default_schedule_playlist_id:
self.store_playlist(timeslot_db, timeslot_db.default_schedule_playlist_id, timeslot["default_schedule_playlist"])
if timeslot_db.default_show_playlist_id:
self.store_playlist(timeslot_db, timeslot_db.default_show_playlist_id, timeslot["default_show_playlist"])
if timeslot_db.schedule_fallback_id:
self.store_playlist(timeslot_db, timeslot_db.schedule_fallback_id, timeslot["schedule_fallback"])
if timeslot_db.show_fallback_id:
......@@ -351,9 +374,18 @@ class ProgrammeStore():
timeslot_db.topic = timeslot["show_topics"]
timeslot_db.musicfocus = timeslot["show_musicfocus"]
timeslot_db.playlist_id = timeslot["playlist_id"]
timeslot_db.schedule_fallback_id = timeslot["schedule_fallback_id"]
timeslot_db.show_fallback_id = timeslot["show_fallback_id"]
timeslot_db.station_fallback_id = timeslot["station_fallback_id"]
# Optional API properties
if "default_schedule_playlist_id" in timeslot:
timeslot_db.default_schedule_playlist_id = timeslot["default_schedule_playlist_id"]
if "default_show_playlist_id" in timeslot:
timeslot_db.default_show_playlist_id = timeslot["default_show_playlist_id"]
if "schedule_fallback_id" in timeslot:
timeslot_db.schedule_fallback_id = timeslot["schedule_fallback_id"]
if "show_fallback_id" in timeslot:
timeslot_db.show_fallback_id = timeslot["show_fallback_id"]
if "station_fallback_id" in timeslot:
timeslot_db.station_fallback_id = timeslot["station_fallback_id"]
timeslot_db.store(add=havetoadd, commit=True)
return timeslot_db
......@@ -415,8 +447,9 @@ class ProgrammeStore():
entry_db.entry_num = entry_num
entry_db.duration = SU.nano_to_seconds(entry["duration"])
# FIXME Refactor mix of uri/filename/file/source
if "uri" in entry:
# FIXME Refactor mix of uri/filename/file/source
entry_db.uri = entry["uri"]
entry_db.source = entry["uri"]
if "filename" in entry:
......@@ -450,6 +483,7 @@ class ProgrammeStore():
entry_num += 1
def expand_entry_duration(self, timeslot_db, fetched_playlist):
"""
If some playlist entry doesn't have a duration assigned, its duration is expanded to the
......
......@@ -121,7 +121,7 @@ class AuraScheduler(threading.Thread):
#
# EVENTS
# EVENT HANDLERS
#
......@@ -262,8 +262,9 @@ class AuraScheduler(threading.Thread):
# Schedule any available fallback playlist
self.fallback.queue_fallback_playlist(next_timeslot)
if next_timeslot.playlist:
self.queue_playlist_entries(next_timeslot, next_timeslot.playlist.entries, False, True)
playlist = self.programme.get_current_playlist(next_timeslot)
if playlist:
self.queue_playlist_entries(next_timeslot, playlist.entries, False, True)
self.logger.info(SU.green("Finished queuing programme."))
......@@ -278,7 +279,7 @@ class AuraScheduler(threading.Thread):
# Queue the (rest of the) currently playing timeslot upon startup
if current_timeslot:
current_playlist = current_timeslot.playlist
current_playlist = self.programme.get_current_playlist(current_timeslot)
if current_playlist:
active_entry = self.programme.get_current_entry()
......
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