Commit 522904b0 authored by David Trattnig's avatar David Trattnig
Browse files

Rename "schedule" to "timeslot". #50

parent ac6edaff
...@@ -77,7 +77,7 @@ api_engine_store_health="http://localhost:8008/api/v1/source/health/${ENGINE_NUM ...@@ -77,7 +77,7 @@ api_engine_store_health="http://localhost:8008/api/v1/source/health/${ENGINE_NUM
# How often should the calendar be fetched in seconds. This determines the time of the last changes applied, before a specific show aired # How often should the calendar be fetched in seconds. This determines the time of the last changes applied, before a specific show aired
fetching_frequency=30 fetching_frequency=30
# The scheduling window defines when the entries of each schedule are queued for play-out in an ideal scenario. # The scheduling window defines when the entries of each timeslot are queued for play-out in an ideal scenario.
# The actual window (scheduling_window_start - scheduling_window_end) should be higher then the `fetching_frequency` to allow proper queuing. # The actual window (scheduling_window_start - scheduling_window_end) should be higher then the `fetching_frequency` to allow proper queuing.
# Otherwise the fetch might never hit the scheduling window, because the scheduling logic is attached to the fetching logic. # Otherwise the fetch might never hit the scheduling window, because the scheduling logic is attached to the fetching logic.
...@@ -88,7 +88,7 @@ fetching_frequency=30 ...@@ -88,7 +88,7 @@ fetching_frequency=30
# - Update/Delete/Assignment of playlists and entries: Those are accepted until the **end** of the the scheduling window; existing queued entries are updated # - Update/Delete/Assignment of playlists and entries: Those are accepted until the **end** of the the scheduling window; existing queued entries are updated
# #
# After the end of the scheduling window the pre-loading phase starts. # After the end of the scheduling window the pre-loading phase starts.
# Note, the values for windows is defined as a offset minus the actual start of the schedule in seconds. # Note, the values for windows is defined as a offset minus the actual start of the timeslot in seconds.
scheduling_window_start=120 scheduling_window_start=120
scheduling_window_end=15 scheduling_window_end=15
# How many seconds before the actual schedule time the entry should be pre-rolled. Note to provide enough timeout for # How many seconds before the actual schedule time the entry should be pre-rolled. Note to provide enough timeout for
......
...@@ -77,7 +77,7 @@ api_engine_store_health="http://127.0.0.1:8008/api/v1/source/health/${ENGINE_NUM ...@@ -77,7 +77,7 @@ api_engine_store_health="http://127.0.0.1:8008/api/v1/source/health/${ENGINE_NUM
# How often should the calendar be fetched in seconds. This determines the time of the last changes applied, before a specific show aired # How often should the calendar be fetched in seconds. This determines the time of the last changes applied, before a specific show aired
fetching_frequency=300 fetching_frequency=300
# The scheduling window defines when the entries of each schedule are queued for play-out in an ideal scenario. # The scheduling window defines when the entries of each timeslot are queued for play-out in an ideal scenario.
# The actual window (scheduling_window_start - scheduling_window_end) should be higher then the `fetching_frequency` to allow proper queuing. # The actual window (scheduling_window_start - scheduling_window_end) should be higher then the `fetching_frequency` to allow proper queuing.
# Otherwise the fetch might never hit the scheduling window, because the scheduling logic is attached to the fetching logic. # Otherwise the fetch might never hit the scheduling window, because the scheduling logic is attached to the fetching logic.
...@@ -88,7 +88,7 @@ fetching_frequency=300 ...@@ -88,7 +88,7 @@ fetching_frequency=300
# - Update/Delete/Assignment of playlists and entries: Those are accepted until the **end** of the the scheduling window; existing queued entries are updated # - Update/Delete/Assignment of playlists and entries: Those are accepted until the **end** of the the scheduling window; existing queued entries are updated
# #
# After the end of the scheduling window the pre-loading phase starts. # After the end of the scheduling window the pre-loading phase starts.
# Note, the values for windows is defined as a offset minus the actual start of the schedule in seconds. # Note, the values for windows is defined as a offset minus the actual start of the timeslot in seconds.
scheduling_window_start=600 scheduling_window_start=600
scheduling_window_end=60 scheduling_window_end=60
# How many seconds before the actual schedule time the entry should be pre-rolled. Note to provide enough timeout for # How many seconds before the actual schedule time the entry should be pre-rolled. Note to provide enough timeout for
......
...@@ -77,7 +77,7 @@ api_engine_store_health="http://localhost:8008/api/v1/source/health/${ENGINE_NUM ...@@ -77,7 +77,7 @@ api_engine_store_health="http://localhost:8008/api/v1/source/health/${ENGINE_NUM
# How often should the calendar be fetched in seconds. This determines the time of the last changes applied, before a specific show aired # How often should the calendar be fetched in seconds. This determines the time of the last changes applied, before a specific show aired
fetching_frequency=300 fetching_frequency=300
# The scheduling window defines when the entries of each schedule are queued for play-out in an ideal scenario. # The scheduling window defines when the entries of each timeslot are queued for play-out in an ideal scenario.
# The actual window (scheduling_window_start - scheduling_window_end) should be higher then the `fetching_frequency` to allow proper queuing. # The actual window (scheduling_window_start - scheduling_window_end) should be higher then the `fetching_frequency` to allow proper queuing.
# Otherwise the fetch might never hit the scheduling window, because the scheduling logic is attached to the fetching logic. # Otherwise the fetch might never hit the scheduling window, because the scheduling logic is attached to the fetching logic.
...@@ -88,7 +88,7 @@ fetching_frequency=300 ...@@ -88,7 +88,7 @@ fetching_frequency=300
# - Update/Delete/Assignment of playlists and entries: Those are accepted until the **end** of the the scheduling window; existing queued entries are updated # - Update/Delete/Assignment of playlists and entries: Those are accepted until the **end** of the the scheduling window; existing queued entries are updated
# #
# After the end of the scheduling window the pre-loading phase starts. # After the end of the scheduling window the pre-loading phase starts.
# Note, the values for windows is defined as a offset minus the actual start of the schedule in seconds. # Note, the values for windows is defined as a offset minus the actual start of the timeslot in seconds.
scheduling_window_start=600 scheduling_window_start=600
scheduling_window_end=60 scheduling_window_end=60
# How many seconds before the actual schedule time the entry should be pre-rolled. Note to provide enough timeout for # How many seconds before the actual schedule time the entry should be pre-rolled. Note to provide enough timeout for
......
...@@ -29,7 +29,7 @@ For example: ...@@ -29,7 +29,7 @@ For example:
- Steering, to get the main incredient of an play-out engine: schedules (or "timeslots" in Steering terms), - Steering, to get the main incredient of an play-out engine: schedules (or "timeslots" in Steering terms),
which hold the actual information on playlists and their entries. which hold the actual information on playlists and their entries.
- Dashboard, to have a neat interface, being able to programm the schedules - Dashboard, to have a neat interface, being able to programm the timeslots
- Tank, to get the references to audio files and other audio sources. Plus the actual files. - Tank, to get the references to audio files and other audio sources. Plus the actual files.
If you need to test and develop against the Engine's API you'll also need to get the `engine-api` project running. If you need to test and develop against the Engine's API you'll also need to get the `engine-api` project running.
...@@ -63,7 +63,7 @@ When you start Engine the following is happening: ...@@ -63,7 +63,7 @@ When you start Engine the following is happening:
2. Python `run.py`: Start Liquidsoap. 2. Python `run.py`: Start Liquidsoap.
3. Liquidsoap: When Liquidsoap finished its startup, it creates a socket file as configured in `socketdir` of `engine.ini`. 3. Liquidsoap: When Liquidsoap finished its startup, it creates a socket file as configured in `socketdir` of `engine.ini`.
4. Python `src/core/liquidsoap/client.py`: Connects to that socket file. 4. Python `src/core/liquidsoap/client.py`: Connects to that socket file.
5. Python `src/schedulung/scheduler.py`: Continously loads schedules from the API endpoints, stores them in the local database and starts the playout as per the schedules. 5. Python `src/schedulung/scheduler.py`: Continously loads timeslots from the API endpoints, stores them in the local database and starts the playout as per the timeslots.
## More infos for debugging ## More infos for debugging
......
...@@ -51,7 +51,7 @@ To configure your Icecast connectivity check-out the `[stream]` section in your ...@@ -51,7 +51,7 @@ To configure your Icecast connectivity check-out the `[stream]` section in your
Engine provide a scheduling functionality by polling external API endpoints frequently. Engine provide a scheduling functionality by polling external API endpoints frequently.
Scheduling is split into multiple phase. Below you see a timline with one schedule planned at a certain Scheduling is split into multiple phase. Below you see a timline with one timeslot planned at a certain
point in time and the involved phase before: point in time and the involved phase before:
```ascii ```ascii
...@@ -72,29 +72,29 @@ point in time and the involved phase before: ...@@ -72,29 +72,29 @@ point in time and the involved phase before:
It does not involve related playlists and their entries. Those can still be modified after the It does not involve related playlists and their entries. Those can still be modified after the
scheduling window has started. scheduling window has started.
The start and the end of the window is defined by the start of the schedule minus The start and the end of the window is defined by the start of the timeslot minus
a configured amount of seconds (see `scheduling_window_start` and `scheduling_window_end` a configured amount of seconds (see `scheduling_window_start` and `scheduling_window_end`
in `engine.ini`). in `engine.ini`).
During the scheduling window, the external API Endpoints are pulled continiously, to During the scheduling window, the external API Endpoints are pulled continiously, to
check for updated schedules and related playlists. Also, any changes to playlists and check for updated timeslots and related playlists. Also, any changes to playlists and
its entries are respected within that window (see `fetching_frequency` in `engine.ini`). its entries are respected within that window (see `fetching_frequency` in `engine.ini`).
> Important: It's vital that the the scheduling window is wider than the fetching frequency. > Important: It's vital that the the scheduling window is wider than the fetching frequency.
Otherwise one fetch might never hit a scheduling window, hence not being able to schedule stuff. Otherwise one fetch might never hit a scheduling window, hence not being able to schedule stuff.
- **Queuing and Pre-Loading**: Before any playlist entries of the schedule can be turned into - **Queuing and Pre-Loading**: Before any playlist entries of the timeslot can be turned into
sound, they need to be queued and pre-loaded. Ideally the pre-loading happens somewhat before sound, they need to be queued and pre-loaded. Ideally the pre-loading happens somewhat before
the scheduled play-out time to avoid any delays in timing. Set the maximum time reserved for the scheduled play-out time to avoid any delays in timing. Set the maximum time reserved for
pre-loading in your configuration (compare `preload_offset`in `engine.ini`). pre-loading in your configuration (compare `preload_offset`in `engine.ini`).
> Important: The offset should not exceed the time between the end of the scheduling-window and the > Important: The offset should not exceed the time between the end of the scheduling-window and the
start of the actual schedule playout. start of the actual timeslot playout.
- **Play-out**: Finally the actual play-out is happening. The faders of the virtual mixers are pushed - **Play-out**: Finally the actual play-out is happening. The faders of the virtual mixers are pushed
all the way up, as soon it's "time to play" for one of the pre-loaded entries. all the way up, as soon it's "time to play" for one of the pre-loaded entries.
Transitions between playlist entries with different types of sources (file, stream and analog Transitions between playlist entries with different types of sources (file, stream and analog
inputs) are performed automatically. At the end of each schedule the channel is faded-out, inputs) are performed automatically. At the end of each timeslot the channel is faded-out,
no matter if the total length of the playlist entries would require a longer timeslot. no matter if the total length of the playlist entries would require a longer timeslot.
If for some reason the playout is corrupted, stopped or too silent to make any sense, then If for some reason the playout is corrupted, stopped or too silent to make any sense, then
...@@ -114,7 +114,7 @@ The available fallbacks are evaluated in following order: ...@@ -114,7 +114,7 @@ The available fallbacks are evaluated in following order:
It's important to note, in case that playlists containing anything different than It's important to note, in case that playlists containing anything different than
file entries, are ignored (i.e. live or stream content). file entries, are ignored (i.e. live or stream content).
2. **Show Fallback**: If the schedule for some show has no playlist assigned, the 2. **Show Fallback**: If the timeslot for some show has no playlist assigned, the
playlist assigned as a *show fallback* is used instead. In the dashboard this can playlist assigned as a *show fallback* is used instead. In the dashboard this can
be done as seen in the screenshot below. be done as seen in the screenshot below.
......
...@@ -23,7 +23,7 @@ ...@@ -23,7 +23,7 @@
class NoProgrammeLoadedException(Exception): class NoProgrammeLoadedException(Exception):
pass pass
class NoActiveScheduleException(Exception): class NoActiveTimeslotException(Exception):
pass pass
......
...@@ -292,7 +292,7 @@ class Player: ...@@ -292,7 +292,7 @@ class Player:
def play(self, entry, transition): def play(self, entry, transition):
""" """
Plays a new `Entry`. In case of a new schedule (or some intented, immediate transition), Plays a new `Entry`. In case of a new timeslot (or some intented, immediate transition),
a clean channel is selected and transitions between old and new channel is performed. a clean channel is selected and transitions between old and new channel is performed.
This method expects that the entry is pre-loaded using `preload(..)` or `preload_group(self, entries)` This method expects that the entry is pre-loaded using `preload(..)` or `preload_group(self, entries)`
......
...@@ -260,15 +260,15 @@ class EngineEventDispatcher(): ...@@ -260,15 +260,15 @@ class EngineEventDispatcher():
thread.start() thread.start()
def on_schedule_change(self, schedule): def on_timeslot_change(self, timeslot):
""" """
Called when the playlist or entries of the current schedule have changed. Called when the playlist or entries of the current timeslot have changed.
""" """
def func(self, schedule): def func(self, timeslot):
self.logger.debug("on_schedule_change(..)") self.logger.debug("on_timeslot_change(..)")
self.call_event("on_schedule_change", schedule) self.call_event("on_timeslot_change", timeslot)
thread = Thread(target = func, args = (self, schedule)) thread = Thread(target = func, args = (self, timeslot))
thread.start() thread.start()
......
...@@ -96,9 +96,9 @@ class TrackServiceHandler(): ...@@ -96,9 +96,9 @@ class TrackServiceHandler():
data["track_num"] = entry.entry_num data["track_num"] = entry.entry_num
data["track_type"] = content_class.numeric data["track_type"] = content_class.numeric
data["playlist_id"] = entry.playlist.playlist_id data["playlist_id"] = entry.playlist.playlist_id
data["schedule_id"] = entry.playlist.schedule.schedule_id data["timeslot_id"] = entry.playlist.timeslot.timeslot_id
data["show_id"] = entry.playlist.schedule.show_id data["show_id"] = entry.playlist.timeslot.show_id
data["show_name"] = entry.playlist.schedule.show_name data["show_name"] = entry.playlist.timeslot.show_name
data["log_source"] = self.config.get("api_engine_number") data["log_source"] = self.config.get("api_engine_number")
self.store_trackservice(data) self.store_trackservice(data)
...@@ -130,9 +130,9 @@ class TrackServiceHandler(): ...@@ -130,9 +130,9 @@ class TrackServiceHandler():
# This is a playlog according to the scheduled playlist (normal or fallback) # This is a playlog according to the scheduled playlist (normal or fallback)
data["track_num"] = entry.entry_num data["track_num"] = entry.entry_num
data["playlist_id"] = entry.playlist.playlist_id data["playlist_id"] = entry.playlist.playlist_id
data["schedule_id"] = entry.playlist.schedule.schedule_id data["timeslot_id"] = entry.playlist.timeslot.timeslot_id
data["show_id"] = entry.playlist.schedule.show_id data["show_id"] = entry.playlist.timeslot.show_id
data["show_name"] = entry.playlist.schedule.show_name data["show_name"] = entry.playlist.timeslot.show_name
else: else:
# This is a fallback playlog which wasn't scheduled actually (e.g. station fallback) # This is a fallback playlog which wasn't scheduled actually (e.g. station fallback)
(past, timeslot, next) = self.playlog.get_timeslots() (past, timeslot, next) = self.playlog.get_timeslots()
...@@ -193,10 +193,10 @@ class TrackServiceHandler(): ...@@ -193,10 +193,10 @@ class TrackServiceHandler():
data["current_playlist"]["entries"].append(entry) data["current_playlist"]["entries"].append(entry)
if current_timeslot: if current_timeslot:
data["current_schedule"] = current_timeslot data["current_timeslot"] = current_timeslot
if next_timeslot: if next_timeslot:
data["next_schedule"] = next_timeslot data["next_timeslot"] = next_timeslot
data = SU.clean_dictionary(data) data = SU.clean_dictionary(data)
...@@ -251,20 +251,20 @@ class Playlog: ...@@ -251,20 +251,20 @@ class Playlog:
""" """
data = {} data = {}
self.assign_fallback_playlist(data, None) self.assign_fallback_playlist(data, None)
data["schedule_id"] = -1 data["timeslot_id"] = -1
data["show_id"] = -1 data["show_id"] = -1
data["show_name"] = "" data["show_name"] = ""
if self.previous_timeslot: if self.previous_timeslot:
data["schedule_start"] = self.previous_timeslot.get("schedule_end") data["timeslot_start"] = self.previous_timeslot.get("timeslot_end")
else: else:
data["schedule_start"] = datetime.now() data["timeslot_start"] = datetime.now()
if next_timeslot: if next_timeslot:
data["schedule_end"] = next_timeslot.schedule_start data["timeslot_end"] = next_timeslot.timeslot_start
else: else:
# Fake the end, because the timeslot is actually not existing # Fake the end, because the timeslot is actually not existing
data["schedule_end"] = datetime.now() + timedelta(hours=1) data["timeslot_end"] = datetime.now() + timedelta(hours=1)
self.current_timeslot = data self.current_timeslot = data
...@@ -281,7 +281,7 @@ class Playlog: ...@@ -281,7 +281,7 @@ class Playlog:
timeslot (Timeslot): The current timeslot timeslot (Timeslot): The current timeslot
""" """
if timeslot and self.previous_timeslot: if timeslot and self.previous_timeslot:
if self.previous_timeslot.get("schedule_start") == timeslot.schedule_start: if self.previous_timeslot.get("timeslot_start") == timeslot.timeslot_start:
return # Avoid overwrite by multiple calls in a row return # Avoid overwrite by multiple calls in a row
data = {} data = {}
...@@ -294,16 +294,16 @@ class Playlog: ...@@ -294,16 +294,16 @@ class Playlog:
# A valid timeslot from the scheduler is available # A valid timeslot from the scheduler is available
if timeslot: if timeslot:
self.assign_fallback_playlist(data, timeslot) self.assign_fallback_playlist(data, timeslot)
data["schedule_id"] = timeslot.schedule_id data["timeslot_id"] = timeslot.timeslot_id
data["schedule_start"] = timeslot.schedule_start data["timeslot_start"] = timeslot.timeslot_start
data["schedule_end"] = timeslot.schedule_end data["timeslot_end"] = timeslot.timeslot_end
data["show_id"] = timeslot.show_id data["show_id"] = timeslot.show_id
data["show_name"] = timeslot.show_name data["show_name"] = timeslot.show_name
data = SU.clean_dictionary(data) data = SU.clean_dictionary(data)
# Any previous (fake) timeslots should get the proper end now # Any previous (fake) timeslots should get the proper end now
if not self.previous_timeslot: if not self.previous_timeslot:
self.current_timeslot["schedule_end"] = timeslot.schedule_start self.current_timeslot["timeslot_end"] = timeslot.timeslot_start
self.previous_timeslot = self.current_timeslot self.previous_timeslot = self.current_timeslot
self.current_timeslot = data self.current_timeslot = data
...@@ -315,9 +315,9 @@ class Playlog: ...@@ -315,9 +315,9 @@ class Playlog:
if next_timeslot: if next_timeslot:
ns = {} ns = {}
self.assign_fallback_playlist(ns, next_timeslot) self.assign_fallback_playlist(ns, next_timeslot)
ns["schedule_id"] = next_timeslot.schedule_id ns["timeslot_id"] = next_timeslot.timeslot_id
ns["schedule_start"] = next_timeslot.schedule_start ns["timeslot_start"] = next_timeslot.timeslot_start
ns["schedule_end"] = next_timeslot.schedule_end ns["timeslot_end"] = next_timeslot.timeslot_end
ns["show_id"] = next_timeslot.show_id ns["show_id"] = next_timeslot.show_id
ns["show_name"] = next_timeslot.show_name ns["show_name"] = next_timeslot.show_name
ns["playlist_id"] = next_timeslot.playlist_id ns["playlist_id"] = next_timeslot.playlist_id
......
...@@ -27,7 +27,7 @@ import logging ...@@ -27,7 +27,7 @@ import logging
from datetime import datetime from datetime import datetime
from src.base.utils import SimpleUtil as SU from src.base.utils import SimpleUtil as SU
from src.scheduling.models import Schedule, Playlist, PlaylistEntry, PlaylistEntryMetaData from src.scheduling.models import Timeslot, Playlist, PlaylistEntry, PlaylistEntryMetaData
from src.scheduling.calender_fetcher import CalendarFetcher from src.scheduling.calender_fetcher import CalendarFetcher
...@@ -48,7 +48,7 @@ class AuraCalendarService(threading.Thread): ...@@ -48,7 +48,7 @@ class AuraCalendarService(threading.Thread):
queue = None queue = None
config = None config = None
logger = None logger = None
fetched_schedule_data = None fetched_timeslot_data = None
calendar_fetcher = None calendar_fetcher = None
stop_event = None stop_event = None
...@@ -84,80 +84,80 @@ class AuraCalendarService(threading.Thread): ...@@ -84,80 +84,80 @@ class AuraCalendarService(threading.Thread):
deleted schedules. deleted schedules.
Returns Returns
Schedule ([]): An arrar of retrieved schedules passed via `self.queue` Timeslot ([]): An arrar of retrieved timeslots passed via `self.queue`
""" """
result = [] result = []
now_unix = SU.timestamp() now_unix = SU.timestamp()
scheduling_window_start = self.config.get("scheduling_window_start") scheduling_window_start = self.config.get("scheduling_window_start")
try: try:
fetched_schedule_data = self.calendar_fetcher.fetch() fetched_timeslot_data = self.calendar_fetcher.fetch()
self.logger.debug("Schedule data fetched from API: " + str(fetched_schedule_data)) self.logger.debug("Timeslot data fetched from API: " + str(fetched_timeslot_data))
# If nothing is fetched, return # If nothing is fetched, return
if not fetched_schedule_data: if not fetched_timeslot_data:
self.queue.put("fetching_aborted Nothing fetched") self.queue.put("fetching_aborted Nothing fetched")
return return
# Check if existing schedules have been deleted # Check if existing timeslots have been deleted
local_schedules = Schedule.select_programme(datetime.now()) local_timeslots = Timeslot.select_programme(datetime.now())
for local_schedule in local_schedules: for local_timeslot in local_timeslots:
# Only allow deletion of schedules which are deleted before the start of the scheduling window # Only allow deletion of timeslots which are deleted before the start of the scheduling window
if local_schedule.start_unix > now_unix: if local_timeslot.start_unix > now_unix:
if (local_schedule.start_unix - scheduling_window_start) > now_unix: if (local_timeslot.start_unix - scheduling_window_start) > now_unix:
# Filter the local schedule from the fetched ones # Filter the local timeslot from the fetched ones
existing_schedule = list(filter(lambda new_schedule: \ existing_timeslot = list(filter(lambda new_timeslot: \
new_schedule["schedule_id"] == local_schedule.schedule_id, fetched_schedule_data)) new_timeslot["timeslot_id"] == local_timeslot.timeslot_id, fetched_timeslot_data))
if existing_schedule: if existing_timeslot:
# self.logger.debug("Schedule #%s is still existing remotely!" % (local_schedule.schedule_id)) # self.logger.debug("Timeslot #%s is still existing remotely!" % (local_timeslot.timeslot_id))
pass pass
else: else:
self.logger.info("Schedule #%s has been deleted remotely, hence also delete it locally [%s]" % \ self.logger.info("Timeslot #%s has been deleted remotely, hence also delete it locally [%s]" % \
(local_schedule.schedule_id, str(local_schedule))) (local_timeslot.timeslot_id, str(local_timeslot)))
local_schedule.delete(commit=True) local_timeslot.delete(commit=True)
self.logger.info("Deleted local schedule #%s from database" % local_schedule.schedule_id) self.logger.info("Deleted local timeslot #%s from database" % local_timeslot.timeslot_id)
else: else:
msg = "Schedule #%s has been deleted remotely. Since the scheduling window has already started, it won't be deleted locally." % \ msg = "Timeslot #%s has been deleted remotely. Since the scheduling window has already started, it won't be deleted locally." % \
local_schedule.schedule_id local_timeslot.timeslot_id
self.logger.error(SU.red(msg)) self.logger.error(SU.red(msg))
# Process fetched schedules # Process fetched timeslots
for schedule in fetched_schedule_data: for timeslot in fetched_timeslot_data:
# Check schedule for validity # Check timeslot for validity
if "start" not in schedule: if "start" not in timeslot:
self.logger.warning("No 'start' of schedule given. Skipping the schedule: %s " % str(schedule)) self.logger.warning("No 'start' of timeslot given. Skipping the timeslot: %s " % str(timeslot))
continue continue
if "end" not in schedule: if "end" not in timeslot:
self.logger.warning("No 'end' of schedule given. Skipping the schedule: %s " % str(schedule)) self.logger.warning("No 'end' of timeslot given. Skipping the timeslot: %s " % str(timeslot))
continue continue
# Store the schedule # Store the timeslot
schedule_db = self.store_schedule(schedule) timeslot_db = self.store_timeslot(timeslot)
# Store playlists to play # Store playlists to play
self.store_playlist(schedule_db, schedule_db.playlist_id, schedule["playlist"]) self.store_playlist(timeslot_db, timeslot_db.playlist_id, timeslot["playlist"])
if schedule_db.schedule_fallback_id: if timeslot_db.timeslot_fallback_id:
self.store_playlist(schedule_db, schedule_db.schedule_fallback_id, schedule["schedule_fallback"]) self.store_playlist(timeslot_db, timeslot_db.timeslot_fallback_id, timeslot["timeslot_fallback"])
if schedule_db.show_fallback_id: if timeslot_db.show_fallback_id:
self.store_playlist(schedule_db, schedule_db.show_fallback_id, schedule["show_fallback"]) self.store_playlist(timeslot_db, timeslot_db.show_fallback_id, timeslot["show_fallback"])
if schedule_db.station_fallback_id: if timeslot_db.station_fallback_id:
self.store_playlist(schedule_db, schedule_db.station_fallback_id, schedule["station_fallback"]) self.store_playlist(timeslot_db, timeslot_db.station_fallback_id, timeslot["station_fallback"])
# self.store_playlist(schedule_db, schedule_db.playlist_id, schedule["playlist"], PlaylistType.DEFAULT.id) # self.store_playlist(timeslot_db, timeslot_db.playlist_id, timeslot["playlist"], PlaylistType.DEFAULT.id)
# if schedule_db.schedule_fallback_id: # if timeslot_db.timeslot_fallback_id:
# self.store_playlist(schedule_db, schedule_db.schedule_fallback_id, schedule["schedule_fallback"], PlaylistType.TIMESLOT.id) # self.store_playlist(timeslot_db, timeslot_db.timeslot_fallback_id, timeslot["timeslot_fallback"], PlaylistType.TIMESLOT.id)
# if schedule_db.show_fallback_id: # if timeslot_db.show_fallback_id:
# self.store_playlist(schedule_db, schedule_db.show_fallback_id, schedule["show_fallback"], PlaylistType.SHOW.id) # self.store_playlist(timeslot_db, timeslot_db.show_fallback_id, timeslot["show_fallback"], PlaylistType.SHOW.id)
# if schedule_db.station_fallback_id: # if timeslot_db.station_fallback_id:
# self.store_playlist(schedule_db, schedule_db.station_fallback_id, schedule["station_fallback"], PlaylistType.STATION.id) # self.store_playlist(timeslot_db, timeslot_db.station_fallback_id, timeslot["station_fallback"], PlaylistType.STATION.id)
result.append(schedule_db) result.append(timeslot_db)
# Release the mutex # Release the mutex
self.queue.put(result) self.queue.put(result)
...@@ -171,49 +171,49 @@ class AuraCalendarService(threading.Thread): ...@@ -171,49 +171,49 @@ class AuraCalendarService(threading.Thread):
def store_schedule(self, schedule): def store_timeslot(self, timeslot):
""" """
Stores the given schedule to the database. Stores the given timeslot to the database.
Args: Args:
schedule (Schedule): The schedule timeslot (Timeslot): The timeslot
""" """
schedule_db = Schedule.select_show_on_datetime(schedule["start"]) timeslot_db = Timeslot.select_show_on_datetime(timeslot["start"])
havetoadd = False havetoadd = False
if not schedule_db: if not timeslot_db:
self.logger.debug("no schedule with given schedule id in database => create new") self.logger.debug("no timeslot with given timeslot id in database => create new")
schedule_db = Schedule() timeslot_db = Timeslot()