Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Lars Kruse
aura-engine
Commits
94c38f18
Commit
94c38f18
authored
Jul 29, 2021
by
david
Browse files
Default playlists for show and schedule-level. #52
parent
e87be140
Changes
9
Hide whitespace changes
Inline
Side-by-side
src/engine.py
View file @
94c38f18
...
...
@@ -374,41 +374,41 @@ class Player:
def
start_fallback_playlist
(
self
,
entries
):
"""
Sets any scheduled fallback playlist and performs a fade-in.
Args:
entries ([Entry]): The playlist entries
"""
self
.
preload_group
(
entries
,
ChannelType
.
FALLBACK_QUEUE
)
self
.
play
(
entries
[
0
],
TransitionType
.
FADE
)
self
.
event_dispatcher
.
on_fallback_updated
(
entries
)
def
stop_fallback_playlist
(
self
):
"""
Performs a fade-out and clears any scheduled fallback playlist.
"""
dirty_channel
=
self
.
channel_router
.
get_active
(
ChannelType
.
FALLBACK_QUEUE
)
self
.
logger
.
info
(
f
"Fading out channel '
{
dirty_channel
}
'"
)
self
.
connector
.
enable_transaction
()
self
.
mixer_fallback
.
fade_out
(
dirty_channel
)
self
.
connector
.
disable_transaction
()
def
clean_up
():
# Wait a little, if there is some long fade-out. Note, this also means,
# this channel should not be used for at least some seconds (including clearing time).
time
.
sleep
(
2
)
self
.
connector
.
enable_transaction
()
self
.
mixer_fallback
.
channel_activate
(
dirty_channel
.
value
,
False
)
res
=
self
.
queue_clear
(
dirty_channel
)
self
.
logger
.
info
(
"Clear Fallback Queue Response: "
+
res
)
self
.
connector
.
disable_transaction
()
self
.
event_dispatcher
.
on_fallback_cleaned
(
dirty_channel
)
Thread
(
target
=
clean_up
).
start
()
#
def start_fallback_playlist(self, entries):
#
"""
#
Sets any scheduled fallback playlist and performs a fade-in.
#
Args:
#
entries ([Entry]): The playlist entries
#
"""
#
self.preload_group(entries, ChannelType.FALLBACK_QUEUE)
#
self.play(entries[0], TransitionType.FADE)
#
self.event_dispatcher.on_fallback_updated(entries)
#
def stop_fallback_playlist(self):
#
"""
#
Performs a fade-out and clears any scheduled fallback playlist.
#
"""
#
dirty_channel = self.channel_router.get_active(ChannelType.FALLBACK_QUEUE)
#
self.logger.info(f"Fading out channel '{dirty_channel}'")
#
self.connector.enable_transaction()
#
self.mixer_fallback.fade_out(dirty_channel)
#
self.connector.disable_transaction()
#
def clean_up():
#
# Wait a little, if there is some long fade-out. Note, this also means,
#
# this channel should not be used for at least some seconds (including clearing time).
#
time.sleep(2)
#
self.connector.enable_transaction()
#
self.mixer_fallback.channel_activate(dirty_channel.value, False)
#
res = self.queue_clear(dirty_channel)
#
self.logger.info("Clear Fallback Queue Response: " + res)
#
self.connector.disable_transaction()
#
self.event_dispatcher.on_fallback_cleaned(dirty_channel)
#
Thread(target=clean_up).start()
...
...
src/events.py
View file @
94c38f18
...
...
@@ -89,7 +89,7 @@ class EngineEventDispatcher():
self
.
logger
=
logging
.
getLogger
(
"AuraEngine"
)
self
.
config
=
AuraConfig
.
config
()
self
.
engine
=
engine
binding
=
self
.
attach
(
AuraMailer
)
binding
.
subscribe
(
"on_critical"
)
binding
.
subscribe
(
"on_sick"
)
...
...
@@ -183,33 +183,33 @@ class EngineEventDispatcher():
"""
Called when the engine has finished booting and is ready to play.
"""
def
func
(
self
,
param
):
def
func
(
self
,
param
):
self
.
logger
.
debug
(
"on_ready(..)"
)
self
.
scheduler
.
on_ready
()
self
.
call_event
(
"on_ready"
,
param
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
None
))
thread
.
start
()
thread
.
start
()
def
on_timeslot_start
(
self
,
timeslot
):
"""
Called when a timeslot starts.
"""
def
func
(
self
,
timeslot
):
def
func
(
self
,
timeslot
):
self
.
logger
.
debug
(
"on_timeslot_start(..)"
)
self
.
fallback_manager
.
on_timeslot_start
(
timeslot
)
self
.
call_event
(
"on_timeslot_start"
,
timeslot
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
timeslot
))
thread
.
start
()
thread
.
start
()
def
on_timeslot_end
(
self
,
timeslot
):
"""
Called when a timeslot ends.
"""
def
func
(
self
,
timeslot
):
def
func
(
self
,
timeslot
):
self
.
logger
.
debug
(
"on_timeslot_end(..)"
)
self
.
fallback_manager
.
on_timeslot_end
(
timeslot
)
self
.
call_event
(
"on_timeslot_end"
,
timeslot
)
...
...
@@ -227,7 +227,7 @@ class EngineEventDispatcher():
Args:
source (String): The `PlaylistEntry` object
"""
def
func
(
self
,
entry
):
def
func
(
self
,
entry
):
self
.
logger
.
debug
(
"on_play(..)"
)
# Assign timestamp indicating start play time. Use the actual playtime when possible.
entry
.
entry_start_actual
=
datetime
.
datetime
.
now
()
...
...
@@ -235,63 +235,63 @@ class EngineEventDispatcher():
self
.
call_event
(
"on_play"
,
entry
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
entry
))
thread
.
start
()
thread
.
start
()
def
on_metadata
(
self
,
data
):
"""
Event called by the soundsystem implementation (i.e. Liquidsoap) when some entry is actually playing.
This does not include live or stream sources, since they ain't have metadata and are triggered from
Event called by the soundsystem implementation (i.e. Liquidsoap) when some entry is actually playing.
This does not include live or stream sources, since they ain't have metadata and are triggered from
engine core (see `on_play(..)`).
Args:
data (dict): A collection of metadata related to the current track
"""
def
func
(
self
,
data
):
def
func
(
self
,
data
):
self
.
logger
.
debug
(
"on_metadata(..)"
)
self
.
fallback_manager
.
on_metadata
(
data
)
self
.
call_event
(
"on_metadata"
,
data
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
data
))
thread
.
start
()
thread
.
start
()
def
on_stop
(
self
,
entry
):
"""
The entry on the assigned channel has been stopped playing.
"""
def
func
(
self
,
entry
):
def
func
(
self
,
entry
):
self
.
logger
.
debug
(
"on_stop(..)"
)
self
.
call_event
(
"on_stop"
,
entry
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
entry
))
thread
.
start
()
thread
.
start
()
def
on_fallback_updated
(
self
,
playlist_uri
):
"""
Called when the scheduled fallback playlist has been updated.
This event does not indicate that the fallback is actually playing.
"""
def
func
(
self
,
playlist_uri
):
self
.
logger
.
debug
(
"on_fallback_updated(..)"
)
self
.
call_event
(
"on_fallback_updated"
,
playlist_uri
)
#
def on_fallback_updated(self, playlist_uri):
#
"""
#
Called when the scheduled fallback playlist has been updated.
#
This event does not indicate that the fallback is actually playing.
#
"""
#
def func(self, playlist_uri):
#
self.logger.debug("on_fallback_updated(..)")
#
self.call_event("on_fallback_updated", playlist_uri)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
playlist_uri
))
thread
.
start
()
#
thread = Thread(target = func, args = (self, playlist_uri))
#
thread.start()
def
on_fallback_cleaned
(
self
,
cleaned_channel
):
"""
Called when the scheduled fallback queue has been cleaned up.
This event does not indicate that some fallback is actually playing.
"""
def
func
(
self
,
cleaned_channel
):
self
.
logger
.
debug
(
"on_fallback_cleaned(..)"
)
self
.
call_event
(
"on_fallback_cleaned"
,
cleaned_channel
)
#
def on_fallback_cleaned(self, cleaned_channel):
#
"""
#
Called when the scheduled fallback queue has been cleaned up.
#
This event does not indicate that some fallback is actually playing.
#
"""
#
def func(self, cleaned_channel):
#
self.logger.debug("on_fallback_cleaned(..)")
#
self.call_event("on_fallback_cleaned", cleaned_channel)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
cleaned_channel
))
thread
.
start
()
#
thread = Thread(target = func, args = (self, cleaned_channel))
#
thread.start()
def
on_fallback_active
(
self
,
timeslot
,
fallback_type
):
...
...
@@ -299,57 +299,57 @@ class EngineEventDispatcher():
Called when a fallback is activated for the given timeslot,
since no default playlist is available.
"""
def
func
(
self
,
timeslot
,
fallback_type
):
def
func
(
self
,
timeslot
,
fallback_type
):
self
.
logger
.
debug
(
"on_fallback_active(..)"
)
self
.
call_event
(
"on_fallback_active"
,
timeslot
,
fallback_type
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
timeslot
,
fallback_type
))
thread
.
start
()
thread
.
start
()
def
on_queue
(
self
,
entries
):
"""
One or more entries have been queued and are currently pre-loaded.
"""
def
func
(
self
,
entries
):
def
func
(
self
,
entries
):
self
.
logger
.
debug
(
"on_queue(..)"
)
self
.
call_event
(
"on_queue"
,
entries
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
entries
))
thread
.
start
()
thread
.
start
()
def
on_sick
(
self
,
data
):
"""
Called when the engine is in some unhealthy state.
"""
def
func
(
self
,
data
):
def
func
(
self
,
data
):
self
.
logger
.
debug
(
"on_sick(..)"
)
self
.
call_event
(
"on_sick"
,
data
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
data
))
thread
.
start
()
thread
.
start
()
def
on_resurrect
(
self
,
data
):
"""
Called when the engine turned healthy again after being sick.
"""
def
func
(
self
,
data
):
def
func
(
self
,
data
):
self
.
logger
.
debug
(
"on_resurrect(..)"
)
self
.
call_event
(
"on_resurrect"
,
data
)
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
data
))
thread
.
start
()
thread
.
start
()
def
on_critical
(
self
,
subject
,
message
,
data
=
None
):
"""
Callend when some critical event occurs
"""
def
func
(
self
,
subject
,
message
,
data
):
def
func
(
self
,
subject
,
message
,
data
):
self
.
logger
.
debug
(
"on_critical(..)"
)
self
.
call_event
(
"on_critical"
,
(
subject
,
message
,
data
))
thread
=
Thread
(
target
=
func
,
args
=
(
self
,
subject
,
message
,
data
))
thread
.
start
()
\ No newline at end of file
thread
.
start
()
\ No newline at end of file
src/plugins/trackservice.py
View file @
94c38f18
...
...
@@ -22,7 +22,6 @@ import logging
import
requests
from
collections
import
deque
from
datetime
import
datetime
,
timedelta
from
src.base.config
import
AuraConfig
from
src.base.utils
import
SimpleUtil
as
SU
...
...
@@ -181,7 +180,7 @@ class TrackServiceHandler():
"""
planned_playlist
=
None
if
self
.
engine
.
scheduler
:
(
fallback
_type
,
planned_playlist
)
=
self
.
engine
.
scheduler
.
get_active_playlist
()
(
playlist
_type
,
planned_playlist
)
=
self
.
engine
.
scheduler
.
get_active_playlist
()
(
past_timeslot
,
current_timeslot
,
next_timeslot
)
=
self
.
playlog
.
get_timeslots
()
data
=
dict
()
...
...
@@ -349,21 +348,29 @@ class Playlog:
data ({}): The dictionary holding the (virtual) timeslot
timeslot (Timeslot): The actual timeslot object to retrieve fallback info from
"""
fallback
_type
=
None
playlist
_type
=
None
playlist
=
None
if
timeslot
:
fallback
_type
,
playlist
=
self
.
engine
.
scheduler
.
fallback
.
resolve_playlist
(
timeslot
)
playlist
_type
,
playlist
=
self
.
engine
.
scheduler
.
resolve_playlist
(
timeslot
)
if
playlist
:
data
[
"playlist_id"
]
=
playlist
.
playlist_id
else
:
data
[
"playlist_id"
]
=
-
1
if
fallback_type
:
data
[
"fallback_type"
]
=
fallback_type
.
id
else
:
data
[
"fallback_type"
]
=
FallbackType
.
STATION
.
id
#FIXME "fallback_type" should be a more generic "playout_state"? (compare meta#42)
#FIXME Add field for "playlist_type", which now differs from playout-state
#FIXME Remove dependency to "scheduler" and "scheduler.fallback" module
data
[
"fallback_type"
]
=
0
if
self
.
engine
.
scheduler
:
playout_state
=
self
.
engine
.
scheduler
.
fallback
.
get_playout_state
()
data
[
"fallback_type"
]
=
playout_state
.
id
# if playlist_type:
# data["fallback_type"] = playlist_type.id
# else:
# data["fallback_type"] = FallbackType.STATION.id
def
get_timeslots
(
self
):
...
...
src/scheduling/api.py
View file @
94c38f18
...
...
@@ -37,7 +37,7 @@ class ApiFetcher(threading.Thread):
"""
config
=
None
logging
=
None
queue
=
None
queue
=
None
has_already_fetched
=
False
fetched_timeslot_data
=
None
stop_event
=
None
...
...
@@ -62,7 +62,7 @@ class ApiFetcher(threading.Thread):
self
.
tank_secret
=
self
.
config
.
get
(
"api_tank_secret"
)
self
.
queue
=
queue
.
Queue
()
self
.
stop_event
=
threading
.
Event
()
threading
.
Thread
.
__init__
(
self
)
threading
.
Thread
.
__init__
(
self
)
...
...
@@ -121,14 +121,13 @@ class ApiFetcher(threading.Thread):
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"
]
if
"schedule_default_playlist_id"
in
timeslot
:
timeslot
[
"default_schedule_playlist_id"
]
=
timeslot
[
"schedule_default_playlist_id"
]
timeslot
[
"schedule_fallback_id"
]
=
None
if
"show_
fallback
_id"
in
timeslot
:
timeslot
[
"default_show_playlist_id"
]
=
timeslot
[
"show_
fallback
_id"
]
if
"show_
default_playlist
_id"
in
timeslot
:
timeslot
[
"default_show_playlist_id"
]
=
timeslot
[
"show_
default_playlist
_id"
]
timeslot
[
"show_fallback_id"
]
=
None
self
.
logger
.
debug
(
"Fetching playlists from TANK"
)
self
.
fetch_playlists
()
...
...
@@ -163,15 +162,15 @@ class ApiFetcher(threading.Thread):
"""
timeslots
=
None
headers
=
{
"content-type"
:
"application/json"
}
try
:
self
.
logger
.
debug
(
"Fetch timeslots from Steering API..."
)
self
.
logger
.
debug
(
"Fetch timeslots from Steering API..."
)
response
=
requests
.
get
(
self
.
steering_calendar_url
,
data
=
None
,
headers
=
headers
)
if
not
response
.
status_code
==
200
:
self
.
logger
.
critical
(
SU
.
red
(
"HTTP Status: %s | Timeslots could not be fetched! Response: %s"
%
\
(
str
(
response
.
status_code
),
response
.
text
)))
return
None
timeslots
=
response
.
json
()
return
None
timeslots
=
response
.
json
()
except
Exception
as
e
:
self
.
logger
.
critical
(
SU
.
red
(
"Error while requesting timeslots from Steering!"
),
e
)
...
...
@@ -198,8 +197,8 @@ class ApiFetcher(threading.Thread):
# Get IDs of specific, default and fallback playlists
playlist_id
=
self
.
get_playlist_id
(
timeslot
,
"playlist_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"
)
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"
)
...
...
@@ -208,7 +207,7 @@ class ApiFetcher(threading.Thread):
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
[
"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
)
...
...
@@ -232,9 +231,9 @@ class ApiFetcher(threading.Thread):
return
None
playlist
=
None
url
=
self
.
tank_playlist_url
.
replace
(
"${ID}"
,
playlist_id
)
url
=
self
.
tank_playlist_url
.
replace
(
"${ID}"
,
playlist_id
)
headers
=
{
"Authorization"
:
"Bearer %s:%s"
%
(
self
.
tank_session
,
self
.
tank_secret
),
"Authorization"
:
"Bearer %s:%s"
%
(
self
.
tank_session
,
self
.
tank_secret
),
"content-type"
:
"application/json"
}
...
...
@@ -243,22 +242,22 @@ class ApiFetcher(threading.Thread):
if
playlist
[
"id"
]
==
playlist_id
:
self
.
logger
.
debug
(
"Playlist #%s already fetched"
%
playlist_id
)
return
playlist
try
:
self
.
logger
.
debug
(
"Fetch playlist from Tank API..."
)
self
.
logger
.
debug
(
"Fetch playlist from Tank API..."
)
response
=
requests
.
get
(
url
,
data
=
None
,
headers
=
headers
)
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
)))
return
None
playlist
=
response
.
json
()
return
None
playlist
=
response
.
json
()
except
Exception
as
e
:
self
.
logger
.
critical
(
SU
.
red
(
"Error while requesting playlist #%s from Tank"
%
str
(
playlist_id
)),
e
)
return
None
fetched_playlists
.
append
(
playlist
)
return
playlist
def
get_playlist_id
(
self
,
timeslot
,
id_name
):
...
...
@@ -279,7 +278,7 @@ class ApiFetcher(threading.Thread):
if
not
playlist_id
or
playlist_id
==
"None"
:
self
.
logger
.
debug
(
"No value defined for '%s' in timeslot '#%s'"
%
(
id_name
,
timeslot
[
"id"
]))
return
None
return
playlist_id
...
...
src/scheduling/fallback.py
View file @
94c38f18
...
...
@@ -36,14 +36,12 @@ class FallbackType(Enum):
"""
Types of fallbacks.
NONE: No fallback active, default playout
SCHEDULE: The first played when some default playlist fails
SHOW: The second played when the timeslot fallback fails
STATION: The last played when everything else fails
NONE: No fallback active, default playout as planned
STATION: The station fallback is played when everything else fails
"""
NONE
=
{
"id"
:
0
,
"name"
:
"default"
,
"channels"
:
[
Channel
.
QUEUE_A
,
Channel
.
QUEUE_B
]
}
SCHEDULE
=
{
"id"
:
1
,
"name"
:
"schedule"
,
"channels"
:
[
Channel
.
FALLBACK_QUEUE_A
,
Channel
.
FALLBACK_QUEUE_B
]
}
SHOW
=
{
"id"
:
2
,
"name"
:
"show"
,
"channels"
:
[
Channel
.
FALLBACK_QUEUE_A
,
Channel
.
FALLBACK_QUEUE_B
]
}
#
SCHEDULE = { "id": 1, "name": "schedule", "channels": [ Channel.FALLBACK_QUEUE_A, Channel.FALLBACK_QUEUE_B ] }
#
SHOW = { "id": 2, "name": "show", "channels": [ Channel.FALLBACK_QUEUE_A, Channel.FALLBACK_QUEUE_B ] }
STATION
=
{
"id"
:
3
,
"name"
:
"station"
,
"channels"
:
[
Channel
.
FALLBACK_STATION_FOLDER
,
Channel
.
FALLBACK_STATION_PLAYLIST
]
}
@
property
...
...
@@ -61,14 +59,13 @@ class FallbackType(Enum):
class
FallbackManager
:
"""
Handles all types of fallbacks in case there is an outage or missing schedules
for the radio programme.
"""
Manages if engine is in normal or fallback play-state.
"""
config
=
None
logger
=
None
engine
=
None
state
=
None
def
__init__
(
self
,
engine
):
"""
...
...
@@ -80,9 +77,9 @@ class FallbackManager:
self
.
config
=
AuraConfig
.
config
()
self
.
logger
=
logging
.
getLogger
(
"AuraEngine"
)
self
.
engine
=
engine
self
.
state
=
{
self
.
state
=
{
"fallback_type"
:
FallbackType
.
NONE
,
"previous_fallback_type"
:
None
,
"previous_fallback_type"
:
None
,
"timeslot"
:
None
}
...
...
@@ -101,7 +98,7 @@ class FallbackManager:
def
on_timeslot_end
(
self
,
timeslot
):
"""
The timeslot has ended and the state is updated. The method ensures that any intermediate state
The timeslot has ended and the state is updated. The method ensures that any intermediate state
update doesn't get overwritten.
"""
if
self
.
state
[
"timeslot"
]
==
timeslot
:
...
...
@@ -110,11 +107,11 @@ class FallbackManager:
def
on_play
(
self
,
entry
):
"""
Event Handler which is called by the engine when some entry is actually playing.
Event Handler which is called by the engine when some entry is actually playing.
Args:
source (String): The `PlaylistEntry` object
"""
"""
content_class
=
ResourceUtil
.
get_content_class
(
entry
.
get_content_type
())
if
content_class
==
ResourceClass
.
FILE
:
# Files are handled by "on_metadata" called via Liquidsoap
...
...
@@ -125,8 +122,8 @@ class FallbackManager:
def
on_metadata
(
self
,
data
):
"""
Event called by the soundsystem implementation (i.e. Liquidsoap) when some entry is actually playing.
This does not include live or stream sources, since they ain't have metadata and are triggered from
Event called by the soundsystem implementation (i.e. Liquidsoap) when some entry is actually playing.
This does not include live or stream sources, since they ain't have metadata and are triggered from
engine core (see `on_play(..)`).
Args:
...
...
@@ -151,6 +148,13 @@ class FallbackManager:
#
def
get_playout_state
(
self
):
"""
Returns the current playout state, like normal or fallback.
"""
return
self
.
state
[
"fallback_type"
]
def
update_fallback_state
(
self
,
channel
):
"""
Update the current and previously active fallback state.
...
...
@@ -168,151 +172,150 @@ class FallbackManager:
"""
Retrieves the matching fallback type for the given source.
"""
if
source
in
[
str
(
i
)
for
i
in
FallbackType
.
SCHEDULE
.
channels
]:
return
FallbackType
.
SCHEDULE
if
source
in
[
str
(
i
)
for
i
in
FallbackType
.
SHOW
.
channels
]:
return
FallbackType
.
SHOW
#
if source in [str(i) for i in FallbackType.SCHEDULE.channels]:
#
return FallbackType.SCHEDULE
#
if source in [str(i) for i in FallbackType.SHOW.channels]:
#
return FallbackType.SHOW
if
source
in
[
str
(
i
)
for
i
in
FallbackType
.
STATION
.
channels
]:
return
FallbackType
.
STATION
return
FallbackType
.
NONE
def
queue_fallback_playlist
(
self
,
timeslot
):
"""
Evaluates the scheduled fallback and queues it using a timed thread.
"""
(
fallback_type
,
playlist
)
=
self
.
get_fallback_playlist
(
timeslot
)
#
def queue_fallback_playlist(self, timeslot):
#
"""
#
Evaluates the scheduled fallback and queues it using a timed thread.
#
"""
#
(fallback_type, playlist) = self.get_fallback_playlist(timeslot)
if
playlist
:
self
.
logger
.
info
(
f
"Resolved
{
fallback_type
.
value
}
fallback"
)
return
FallbackCommand
(
timeslot
,
playlist
.
entries
)
else
:
msg
=
f
"There is no timeslot- or show-
fallback
defined for timeslot#
{
timeslot
.
timeslot_id
}
. "
msg
+=
f
"The station fallback will be used automatically."
self
.
logger
.
info
(
msg
)
#
if playlist:
#
self.logger.info(f"Resolved {fallback_type.value} fallback")
#
return FallbackCommand(timeslot, playlist.entries)
#
else:
#
msg = f"There is no
fallback playlist on
timeslot- or show-
level
defined for timeslot#{timeslot.timeslot_id}. "
#
msg += f"The station fallback will be used automatically."
#
self.logger.info(msg)
def
resolve_playlist
(
self
,
timeslot
):
"""
Retrieves the currently planned
(
fallback
)
playlist. If a normal playlist is available,
this one is returned. In case of station fallback no playlist is returned.
#
def resolve_playlist(self, timeslot):
#
"""
#
Retrieves the currently planned
, default or
fallback playlist. If a normal playlist is available,
#
this one is returned. In case of
a
station fallback
to be triggered,
no playlist is returned.
Args:
timeslot (Timeslot)