Skip to content
Snippets Groups Projects
Commit 4d4a2566 authored by David Trattnig's avatar David Trattnig
Browse files

Default playlist handling. #52

parent 2372c56d
No related branches found
No related tags found
No related merge requests found
...@@ -119,11 +119,22 @@ class ApiFetcher(threading.Thread): ...@@ -119,11 +119,22 @@ class ApiFetcher(threading.Thread):
self.logger.critical(SU.red("No timeslots fetched from API!")) self.logger.critical(SU.red("No timeslots fetched from API!"))
return None 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.logger.debug("Fetching playlists from TANK")
self.fetch_playlists() self.fetch_playlists()
try: try:
for timeslot in self.fetched_timeslot_data: for timeslot in self.fetched_timeslot_data:
# Skip timeslot if no start or end is given # Skip timeslot if no start or end is given
if "start" not in timeslot: if "start" not in timeslot:
self.logger.warning("No start of timeslot given. Skipping timeslot: " + str(timeslot)) self.logger.warning("No start of timeslot given. Skipping timeslot: " + str(timeslot))
...@@ -131,13 +142,6 @@ class ApiFetcher(threading.Thread): ...@@ -131,13 +142,6 @@ class ApiFetcher(threading.Thread):
if "end" not in timeslot: if "end" not in timeslot:
self.logger.warning("No end of timeslot given. Skipping timeslot: " + str(timeslot)) self.logger.warning("No end of timeslot given. Skipping timeslot: " + str(timeslot))
timeslot = None 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: if timeslot:
return_data.append(timeslot) return_data.append(timeslot)
...@@ -191,18 +195,22 @@ class ApiFetcher(threading.Thread): ...@@ -191,18 +195,22 @@ class ApiFetcher(threading.Thread):
try: try:
for timeslot in self.fetched_timeslot_data: 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") 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") show_fallback_id = self.get_playlist_id(timeslot, "show_fallback_id")
station_fallback_id = self.get_playlist_id(timeslot, "station_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 # 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["playlist"] = self.fetch_playlist(playlist_id, fetched_entries)
timeslot["schedule_fallback"] = self.fetch_playlist(schedule_fallback_id, fetched_entries) timeslot["default_schedule_playlist"] = self.fetch_playlist(default_schedule_playlist_id, fetched_entries)
timeslot["show_fallback"] = self.fetch_playlist(show_fallback_id, fetched_entries) timeslot["default_show_playlist"] = self.fetch_playlist(default_show_playlist_id, fetched_entries)
timeslot["station_fallback"] = self.fetch_playlist(station_fallback_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: except Exception as e:
self.logger.error("Error while fetching playlists from API endpoints: " + str(e), e) self.logger.error("Error while fetching playlists from API endpoints: " + str(e), e)
...@@ -214,14 +222,15 @@ class ApiFetcher(threading.Thread): ...@@ -214,14 +222,15 @@ class ApiFetcher(threading.Thread):
Fetches the playlist for a given timeslot. Fetches the playlist for a given timeslot.
Args: Args:
id_name (String): The type of playlist to fetch (e.g. normal vs. fallback) playlist_id (String): The ID of the playlist
fetched_playlists ([]): Previously fetched playlists to avoid re-fetching fetched_playlists ([dict]): Previously fetched playlists to avoid re-fetching
Returns: Returns:
(Playlist): Playlist of type `id_name` (Playlist): Playlist for `playlist_id`
""" """
if not playlist_id: if not playlist_id:
return None return None
playlist = None playlist = None
url = self.tank_playlist_url.replace("${ID}", playlist_id) url = self.tank_playlist_url.replace("${ID}", playlist_id)
headers = { headers = {
...@@ -255,7 +264,17 @@ class ApiFetcher(threading.Thread): ...@@ -255,7 +264,17 @@ class ApiFetcher(threading.Thread):
def get_playlist_id(self, timeslot, id_name): def get_playlist_id(self, timeslot, id_name):
""" """
Extracts the playlist ID for a given playlist (fallback) type. 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]) playlist_id = str(timeslot[id_name])
if not playlist_id or playlist_id == "None": if not playlist_id or playlist_id == "None":
self.logger.debug("No value defined for '%s' in timeslot '#%s'" % (id_name, timeslot["id"])) self.logger.debug("No value defined for '%s' in timeslot '#%s'" % (id_name, timeslot["id"]))
...@@ -264,6 +283,7 @@ class ApiFetcher(threading.Thread): ...@@ -264,6 +283,7 @@ class ApiFetcher(threading.Thread):
return playlist_id return playlist_id
def polish_timeslots(self, timeslots): def polish_timeslots(self, timeslots):
""" """
Removes all timeslots which are not relevant for further processing, Removes all timeslots which are not relevant for further processing,
......
...@@ -201,11 +201,10 @@ class FallbackManager: ...@@ -201,11 +201,10 @@ class FallbackManager:
Returns: Returns:
(FallbackType, Playlist) (FallbackType, Playlist)
""" """
planned_playlist = None
fallback_type = None fallback_type = None
planned_playlist = self.engine.scheduler.programme.get_current_playlist(timeslot)
if self.validate_playlist(timeslot, "playlist"): if planned_playlist:
planned_playlist = timeslot.playlist
fallback_type = FallbackType.NONE fallback_type = FallbackType.NONE
else: else:
(fallback_type, planned_playlist) = self.get_fallback_playlist(timeslot) (fallback_type, planned_playlist) = self.get_fallback_playlist(timeslot)
......
...@@ -117,9 +117,9 @@ class ProgrammeService(): ...@@ -117,9 +117,9 @@ class ProgrammeService():
return None return None
# Check for scheduled playlist # Check for scheduled playlist
current_playlist = current_timeslot.playlist current_playlist = self.get_current_playlist(current_timeslot)
if not current_playlist: 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)) self.logger.warning(SU.red(msg))
return None return None
...@@ -161,6 +161,25 @@ class ProgrammeService(): ...@@ -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): def get_next_timeslots(self, max_count=0):
""" """
Retrieves the timeslots to be played after the current one. Retrieves the timeslots to be played after the current one.
...@@ -274,6 +293,10 @@ class ProgrammeStore(): ...@@ -274,6 +293,10 @@ class ProgrammeStore():
# Store assigned playlists # Store assigned playlists
self.store_playlist(timeslot_db, timeslot_db.playlist_id, timeslot["playlist"]) 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: if timeslot_db.schedule_fallback_id:
self.store_playlist(timeslot_db, timeslot_db.schedule_fallback_id, timeslot["schedule_fallback"]) self.store_playlist(timeslot_db, timeslot_db.schedule_fallback_id, timeslot["schedule_fallback"])
if timeslot_db.show_fallback_id: if timeslot_db.show_fallback_id:
...@@ -351,9 +374,18 @@ class ProgrammeStore(): ...@@ -351,9 +374,18 @@ class ProgrammeStore():
timeslot_db.topic = timeslot["show_topics"] timeslot_db.topic = timeslot["show_topics"]
timeslot_db.musicfocus = timeslot["show_musicfocus"] timeslot_db.musicfocus = timeslot["show_musicfocus"]
timeslot_db.playlist_id = timeslot["playlist_id"] 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"] # Optional API properties
timeslot_db.station_fallback_id = timeslot["station_fallback_id"] 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) timeslot_db.store(add=havetoadd, commit=True)
return timeslot_db return timeslot_db
...@@ -415,8 +447,9 @@ class ProgrammeStore(): ...@@ -415,8 +447,9 @@ class ProgrammeStore():
entry_db.entry_num = entry_num entry_db.entry_num = entry_num
entry_db.duration = SU.nano_to_seconds(entry["duration"]) entry_db.duration = SU.nano_to_seconds(entry["duration"])
# FIXME Refactor mix of uri/filename/file/source
if "uri" in entry: if "uri" in entry:
# FIXME Refactor mix of uri/filename/file/source
entry_db.uri = entry["uri"] entry_db.uri = entry["uri"]
entry_db.source = entry["uri"] entry_db.source = entry["uri"]
if "filename" in entry: if "filename" in entry:
...@@ -450,6 +483,7 @@ class ProgrammeStore(): ...@@ -450,6 +483,7 @@ class ProgrammeStore():
entry_num += 1 entry_num += 1
def expand_entry_duration(self, timeslot_db, fetched_playlist): 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 If some playlist entry doesn't have a duration assigned, its duration is expanded to the
......
...@@ -121,7 +121,7 @@ class AuraScheduler(threading.Thread): ...@@ -121,7 +121,7 @@ class AuraScheduler(threading.Thread):
# #
# EVENTS # EVENT HANDLERS
# #
...@@ -262,8 +262,9 @@ class AuraScheduler(threading.Thread): ...@@ -262,8 +262,9 @@ class AuraScheduler(threading.Thread):
# Schedule any available fallback playlist # Schedule any available fallback playlist
self.fallback.queue_fallback_playlist(next_timeslot) self.fallback.queue_fallback_playlist(next_timeslot)
if next_timeslot.playlist: playlist = self.programme.get_current_playlist(next_timeslot)
self.queue_playlist_entries(next_timeslot, next_timeslot.playlist.entries, False, True) if playlist:
self.queue_playlist_entries(next_timeslot, playlist.entries, False, True)
self.logger.info(SU.green("Finished queuing programme.")) self.logger.info(SU.green("Finished queuing programme."))
...@@ -278,7 +279,7 @@ class AuraScheduler(threading.Thread): ...@@ -278,7 +279,7 @@ class AuraScheduler(threading.Thread):
# Queue the (rest of the) currently playing timeslot upon startup # Queue the (rest of the) currently playing timeslot upon startup
if current_timeslot: if current_timeslot:
current_playlist = current_timeslot.playlist current_playlist = self.programme.get_current_playlist(current_timeslot)
if current_playlist: if current_playlist:
active_entry = self.programme.get_current_entry() active_entry = self.programme.get_current_entry()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment