diff --git a/modules/scheduling/fallback_manager.py b/modules/scheduling/fallback_manager.py
new file mode 100644
index 0000000000000000000000000000000000000000..1d5300caa783f94a0d0037f3d75d02c86bd8f0ff
--- /dev/null
+++ b/modules/scheduling/fallback_manager.py
@@ -0,0 +1,229 @@
+
+#
+#  Aura Engine
+#
+#  Playout Daemon for autoradio project
+#
+#
+#  Copyright (C) 2020 David Trattnig <david.trattnig@subsquare.at>
+#
+#  This file is part of engine.
+#
+#  engine is free software: you can redistribute it and/or modify
+#  it under the terms of the GNU General Public License as published by
+#  the Free Software Foundation, either version 3 of the License, or
+#  any later version.
+#
+#  engine is distributed in the hope that it will be useful,
+#  but WITHOUT ANY WARRANTY; without even the implied warranty of
+#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+#  GNU General Public License for more details.
+#
+#  You should have received a copy of the GNU General Public License
+#  along with engine. If not, see <http://www.gnu.org/licenses/>.
+#
+
+# Meta
+__version__ = '0.0.1'
+__license__ = "GNU General Public License (GPL) Version 3"
+__version_info__ = (0, 0, 1)
+__author__ = 'David Trattnig <david.trattnig@subsquare.at>'
+
+
+import os, os.path
+import logging
+import random
+
+from accessify import private, protected
+from modules.base.simpleutil import SimpleUtil
+from modules.communication.mail import AuraMailer
+
+
+class FallbackManager:
+    """
+    Handles all types of fallbacks in case there is an outage
+    for the regular radio programme.
+
+    Attributes:
+        config (AuraConfig):        The engine configuration
+        logger (AuraLogger):        The logger
+        mail   (AuraMailer):        Mail service
+        scheduler (AuraScheduler):  The scheduler
+        fallback_history (Dict):    Holds a 24h history of played, local tracks to avoid re-play
+        last_fallback (Integer):    Timestamp, when the last local file fallback was played
+        is_processing (Boolean):    Flag to avoid race-conditions, as Liquidsoap sends plenty of requests at once
+    """
+
+    config = None
+    logger = None
+    mailer = None
+    scheduler = None
+    fallback_history = {}
+    last_fallback = 0
+    is_processing = False
+
+
+    def __init__(self, config, logger, scheduler):
+        """
+        Constructor
+
+        Args:
+            config (AuraConfig):    Holds the engine configuration
+        """
+        self.config = config
+        self.mailer = AuraMailer(self.config)
+        self.scheduler = scheduler
+        self.logger = logger
+
+
+    #
+    #   PUBLIC METHODS
+    #
+
+
+    def get_fallback_for(self, fallbackname):
+        """
+        Retrieves a random fallback audio source for any of the types:
+            - timeslot/schedule
+            - show
+            - station
+        
+        Args:
+            fallbackname (String):      Fallback type
+
+        Returns:
+            (String):                   Absolute path to the file
+        """
+        file = ""
+        media_type = "PLAYLIST"
+        active_schedule, active_playlist = self.scheduler.get_active_playlist()
+
+        # Block access to avoid race-conditions
+        if self.is_processing:
+            return None
+        else:
+            self.is_processing = True
+
+        # Get fallback track(s) by fallback-type
+        if fallbackname == "timeslot":
+            file = self.get_playlist_items(active_schedule, "schedule_fallback")
+
+        elif fallbackname == "show":
+            file = self.get_playlist_items(active_schedule, "show_fallback")
+
+        elif fallbackname == "station":
+            file = self.get_playlist_items(active_schedule, "station_fallback")
+
+            if not file:
+                media_type = "TRACK"
+                file = self.get_random_local_track()
+
+                if not file:
+                    self.logger.critical("Got no file for station fallback! Playing default test track, to play anything at all.")
+                    file = "../../testing/content/ernie_mayne_sugar.mp3"
+                    media_type = "DEFAULT TRACK"
+        else:
+            file = ""
+            self.logger.critical("Should set next fallback file for " + fallbackname + ", but this fallback is unknown!")
+
+        # Send admin email to notify about the fallback state
+        if file:
+            if not active_playlist:
+                active_playlist = "n/a"
+            msg = "AURA ENGINE %s FALLBACK DETECTED!\n\n" % fallbackname
+            msg += "Expected, active Schedule: %s \n" % active_schedule
+            msg += "Expected, active Playlist: %s \n\n" % active_playlist
+            msg += "Providing FALLBACK-%s for %s '%s'\n\n" % (media_type, fallbackname, file)
+            msg += "Please review the schedules or contact your Aura Engine administrator."
+            self.mailer.send_admin_mail("CRITICAL - Detected fallback for %s" % fallbackname, msg)
+            self.logger.critical("Sent admin email:\n──────────────────────────────────────\n" + msg)
+
+        self.is_processing = False
+        return file
+
+
+
+    #
+    #   PRIVATE METHODS
+    #
+
+
+    def get_playlist_items(self, schedule, fallback_key):
+        """
+        Retrieves the list of tracks from a playlist defined by `fallback_key`.
+        """
+        playlist_files = ""
+
+        if hasattr(schedule, fallback_key):
+            playlist = getattr(schedule, fallback_key)
+            if len(playlist) > 0:
+                playlist = playlist[0]
+                if playlist and playlist.entries:
+                    for entry in playlist.entries:
+                        playlist_files += entry.filename + "\n"
+
+        return playlist_files
+
+
+
+    def get_random_local_track(self):
+        """
+        Retrieves a random audio track from the local station-fallback directory.
+
+        Returns:
+            (String):   Absolute path to an audio file
+        """
+        dir = self.config.fallback_music_folder
+        files = os.listdir(dir)
+        audio_files = list(filter(lambda f: self.is_audio_file(dir, f), files))
+        
+        if not dir or not audio_files:
+            self.logger.error("Folder 'fallback_music_folder = %s' is empty!" % dir)
+            return None
+
+        # If last played fallback is > 24 hours ago, ignore play history
+        # This should save used memory if the engine runs for a long time
+        if self.last_fallback < SimpleUtil.timestamp() - (60*60*24):
+            self.fallback_history = {}
+        self.last_fallback = SimpleUtil.timestamp()
+        
+        # Retrieve files which haven't been played yet
+        history = set(self.fallback_history.keys())
+        left_audio_files = list(set(audio_files).difference(history))
+
+        # If nothing left, clear history and start with all files again
+        if not len(left_audio_files):
+            self.fallback_history = {}
+            left_audio_files = audio_files
+
+        # Select random track from directory
+        i = random.randint(0, len(left_audio_files)-1)
+        file = os.path.join(dir, left_audio_files[i])
+
+        # Store track in history, to avoid playing it multiple times
+        if file:
+            self.fallback_history[left_audio_files[i]] = SimpleUtil.timestamp()
+
+        return file
+
+
+
+    def is_audio_file(self, dir, file):
+        """
+        Checks if the passed file is an audio file i.e. has a file-extension
+        known for audio files.
+
+        Args:
+            (File): file:   the file object.
+
+        Returns:
+            (Boolean):      True, if it's an audio file.
+        """
+        audio_extensions = [".wav", ".flac", ".mp3", ".ogg"]
+        ext = os.path.splitext(file)[1]
+        abs_path = os.path.join(dir, file)
+
+        if os.path.isfile(abs_path):
+            if any(ext in s for s in audio_extensions):
+                return True
+        return False
\ No newline at end of file
diff --git a/modules/scheduling/scheduler.py b/modules/scheduling/scheduler.py
index f85448009fba67c8ff062140dc348ec84b0cfadf..4487272b0976a66fc9092ecbad5e90d9b99b1d8d 100644
--- a/modules/scheduling/scheduler.py
+++ b/modules/scheduling/scheduler.py
@@ -35,7 +35,6 @@ import datetime
 import decimal
 import traceback
 import sqlalchemy
-
 import logging
 import threading
 
@@ -44,6 +43,7 @@ from operator import attrgetter
 from modules.base.simpleutil import SimpleUtil
 from modules.communication.redis.messenger import RedisMessenger
 from modules.scheduling.calendar import AuraCalendarService
+from modules.scheduling.fallback_manager import FallbackManager
 from libraries.database.broadcasts import Schedule, Playlist, AuraDatabaseModel
 from libraries.exceptions.exception_logger import ExceptionLogger
 from libraries.enum.auraenumerations import ScheduleEntryType, TimerType, TerminalColors
@@ -90,11 +90,10 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
     exit_event = None
     liquidsoapcommunicator = None
     last_successful_fetch = None
-
     programme = None
     active_entry = None
     message_timer = []
-
+    fallback_manager = None
     #schedule_entries = None
     client = None
     
@@ -110,7 +109,7 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
         self.logger = logging.getLogger("AuraEngine")
         self.init_error_messages()
         self.init_database()
-
+        self.fallback_manager = FallbackManager(config, self.logger, self)
         self.redismessenger = RedisMessenger(config)
 
         # init threading
@@ -276,35 +275,20 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
 
     def get_next_file_for(self, fallbackname):
         """
-        Evaluates the next **fallback files/folders** to be played for a given fallback-type.
+        Evaluates the next **fallback files/playlists** to be played for a given fallback-type.
         Valid fallback-types are:
 
             * timeslot
             * show
             * station
 
+        Args:
+            fallbackname (String):  The name of the fallback-type
+
         Returns:
             (String):   Absolute path to the file to be played as a fallback.
         """
-        
-        file = None
-        # next_entry = None
-
-        # if not self.active_entry:
-        #     self.get_active_entry()
-        #     next_entry = self.active_entry
-        # else:    
-        #     next_entry = self.get_next_entry()
-
-        if fallbackname == "timeslot":
-            file = "/home/david/Music/ab.mp3"
-        elif fallbackname == "show":
-            file = "/home/david/Code/aura/engine2/testing/content/ernie_mayne_sugar.mp3"
-        elif fallbackname == "station":
-            file = "/home/david/Code/aura/engine2/testing/content/ernie_mayne_sugar.mp3"
-        else:
-            file = ""
-            self.logger.critical("Should set next fallback file for " + fallbackname + ", but this fallback is unknown!")
+        file = self.fallback_manager.get_fallback_for(fallbackname)
 
         if file:
             self.logger.info("Got next file '%s' (type: %s)" % (file, fallbackname))
@@ -336,14 +320,15 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
         current_playlist = None
 
         # Iterate over all shows and playlists and find the one to be played right now
-        for schedule in self.programme:
-            if schedule.start_unix < now_unix < schedule.end_unix:
-                current_schedule = schedule
-                for playlist in schedule.playlist:
-                    if playlist.start_unix < now_unix < playlist.end_unix:
-                        current_playlist = playlist 
-                        break
-                break
+        if self.programme:
+            for schedule in self.programme:
+                if schedule.start_unix < now_unix < schedule.end_unix:
+                    current_schedule = schedule
+                    for playlist in schedule.playlist:
+                        if playlist.start_unix < now_unix < playlist.end_unix:
+                            current_playlist = playlist 
+                            break
+                    break
 
         return (current_schedule, current_playlist)
 
@@ -523,9 +508,9 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
         # Always load latest programme from the database
         self.last_successful_fetch = lsf
         self.load_programme_from_db()
-        self.logger.info("Finished loading current programme from database")
+        self.logger.info("Finished loading current programme from database (%s schedules)" % str(len(self.programme)))
         for schedule in self.programme:
-            self.logger.debug("\tSchedule %s with Playlist %s" % (str(schedule), str(schedule.playlist[0])))
+            self.logger.debug("\tSchedule %s with Playlist %s" % (str(schedule), str(schedule.playlist)))
 
 
 
@@ -542,31 +527,9 @@ class AuraScheduler(ExceptionLogger, threading.Thread):
             self.logger.critical("Could not load programme from database. We are in big trouble my friend!")
             return
 
-        # FIXME That's very likely not needed - review!
-        # planned_entries = []
-
-        # for schedule in self.programme:
-        #     # playlist to play
-        #     #schedule.playlist = [Playlist.select_playlist_for_schedule(schedule.schedule_start, schedule.playlist_id)]
-
-
-        #     # show fallback is played when playlist fails
-        #     #schedule.showfallback = Playlist.select_playlist(schedule.show_fallback_id)
-        #     # timeslot fallback is played when show fallback fails
-        #     #schedule.timeslotfallback = Playlist.select_playlist(schedule.timeslot_fallback_id)
-        #     # station fallback is played when timeslot fallback fails
-        #     #schedule.stationfallback = Playlist.select_playlist(schedule.station_fallback_id)
-
-        #     for p in schedule.playlist:
-        #         planned_entries.append(p)
-
-        # FIXME Same playlists are repeated over time - test with different schedules/timeslots/playlists
-        # Therefore only passing the first playlist for now:
-        # self.logger.warn("ONLY PASSING 1ST PLAYLIST OF PROGRAMME")
-        # self.enable_entries(planned_entries[0])
-       
 
 
+    # FIXME Still needed?
     def enable_entries(self, playlist):
         """
         Iterates over all playlist entries and assigs their start time.