From 128ac911a5bc97b0ce1178ccd079245ed86beeb0 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Sun, 25 Apr 2021 23:05:31 +0100 Subject: [PATCH] Add File Manager to clear music-tmp on show load. --- file_manager.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++ player_handler.py | 7 ++++- server.py | 21 ++++++++++++++- 3 files changed, 94 insertions(+), 2 deletions(-) create mode 100644 file_manager.py diff --git a/file_manager.py b/file_manager.py new file mode 100644 index 0000000..b4ab37a --- /dev/null +++ b/file_manager.py @@ -0,0 +1,68 @@ +import time +from helpers.os_environment import resolve_external_file_path +from typing import List +from setproctitle import setproctitle +from multiprocessing import current_process, Queue +from time import sleep +import os + +from helpers.logging_manager import LoggingManager +from helpers.the_terminator import Terminator + + +class FileManager: + logger: LoggingManager + + def __init__(self, channel_from_q: List[Queue], server_config): + + self.logger = LoggingManager("FileManager") + process_title = "File Manager" + setproctitle(process_title) + current_process().name = process_title + + terminator = Terminator() + channel_count = len(channel_from_q) + channel_received = None + try: + + while not terminator.terminate: + # If all channels have received the delete command, reset for the next one. + if (channel_received == None or channel_received == [True]*channel_count): + channel_received = [False]*channel_count + + for channel in range(channel_count): + try: + message = channel_from_q[channel].get_nowait() + #source = message.split(":")[0] + command = message.split(":",2)[1] + if command == "GET_PLAN": + + if channel_received != [False]*channel_count and channel_received[channel] != True: + # We've already received a delete trigger on a channel, let's not delete the folder more than once. + # If the channel was already in the process of being deleted, the user has requested it again, so allow it. + + channel_received[channel] = True + continue + + # Delete the previous show files! + # Note: The players load into RAM. If something is playing over the load, the source file can still be deleted. + path: str = resolve_external_file_path("/music-tmp/") + + if not os.path.isdir(path): + self.logger.log.warning("Music-tmp folder is missing, not handling.") + continue + + files = [f for f in os.listdir(path) if os.path.isfile(os.path.join(path, f))] + for file in files: + os.remove(path+"/"+file) + channel_received[channel] = True + + + except Exception: + pass + + sleep(1) + except Exception as e: + self.logger.log.exception( + "Received unexpected exception: {}".format(e)) + del self.logger diff --git a/player_handler.py b/player_handler.py index 1aab6a7..1377f23 100644 --- a/player_handler.py +++ b/player_handler.py @@ -10,7 +10,7 @@ from helpers.the_terminator import Terminator class PlayerHandler: logger: LoggingManager - def __init__(self, channel_from_q, websocket_to_q, ui_to_q, controller_to_q): + def __init__(self, channel_from_q, websocket_to_q, ui_to_q, controller_to_q, file_to_q): self.logger = LoggingManager("PlayerHandler") process_title = "Player Handler" @@ -25,6 +25,11 @@ class PlayerHandler: try: message = channel_from_q[channel].get_nowait() source = message.split(":")[0] + command = message.split(":")[1] + if command == "GET_PLAN": + file_to_q[channel].put(message) + + # TODO ENUM if source in ["ALL", "WEBSOCKET"]: websocket_to_q[channel].put(message) diff --git a/server.py b/server.py index 517340e..cd0c6fe 100644 --- a/server.py +++ b/server.py @@ -12,6 +12,7 @@ Date: October, November 2020 """ +from file_manager import FileManager import multiprocessing from multiprocessing.queues import Queue import multiprocessing.managers as m @@ -75,6 +76,7 @@ class BAPSicleServer: ui_to_q: List[Queue] = [] websocket_to_q: List[Queue] = [] controller_to_q: List[Queue] = [] + file_to_q: List[Queue] = [] api_from_q: Queue api_to_q: Queue @@ -82,6 +84,7 @@ class BAPSicleServer: websockets_server: Optional[multiprocessing.Process] = None controller_handler: Optional[multiprocessing.Process] = None player_handler: Optional[multiprocessing.Process] = None + file_manager: Optional[multiprocessing.Process] = None webserver: Optional[multiprocessing.Process] = None def __init__(self): @@ -118,10 +121,18 @@ class BAPSicleServer: log_function("Player Handler not running, (re)starting.") self.player_handler = multiprocessing.Process( target=PlayerHandler, - args=(self.player_from_q, self.websocket_to_q, self.ui_to_q, self.controller_to_q), + args=(self.player_from_q, self.websocket_to_q, self.ui_to_q, self.controller_to_q, self.file_to_q), ) self.player_handler.start() + if not self.file_manager or not self.file_manager.is_alive(): + log_function("File Manager not running, (re)starting.") + self.file_manager = multiprocessing.Process( + target=FileManager, + args=(self.file_to_q, self.state), + ) + self.file_manager.start() + if not self.websockets_server or not self.websockets_server.is_alive(): log_function("Websocket Server not running, (re)starting.") self.websockets_server = multiprocessing.Process( @@ -182,6 +193,7 @@ class BAPSicleServer: self.ui_to_q.append(multiprocessing.Queue()) self.websocket_to_q.append(multiprocessing.Queue()) self.controller_to_q.append(multiprocessing.Queue()) + self.file_to_q.append(multiprocessing.Queue()) print("Welcome to BAPSicle Server version: {}, build: {}.".format(package.VERSION, package.BUILD)) print("The Server UI is available at http://{}:{}".format(self.state.get()["host"], self.state.get()["port"])) @@ -247,11 +259,18 @@ class BAPSicleServer: self.player_handler.join(timeout=PROCESS_KILL_TIMEOUT_S) del self.player_handler + print("Stopping File Manager") + if self.file_manager: + self.file_manager.terminate() + self.file_manager.join(timeout=PROCESS_KILL_TIMEOUT_S) + del self.file_manager + print("Stopping Controllers") if self.controller_handler: self.controller_handler.terminate() self.controller_handler.join(timeout=PROCESS_KILL_TIMEOUT_S) del self.controller_handler + print("Stopped all processes.") if __name__ == "__main__":