From 5228cfd2791d154d2767d7ec1a9f99de1dcf8fe7 Mon Sep 17 00:00:00 2001 From: Matthew Stratford Date: Sun, 1 Nov 2020 00:31:58 +0000 Subject: [PATCH] Better startup and shutdown. --- launch_standalone.py | 19 +++++++++++++++---- player.py | 7 +++++-- server.py | 32 +++++++++++++++++++++++++++++--- state_manager.py | 5 +++++ 4 files changed, 54 insertions(+), 9 deletions(-) diff --git a/launch_standalone.py b/launch_standalone.py index 2681aff..db88dd9 100644 --- a/launch_standalone.py +++ b/launch_standalone.py @@ -3,11 +3,22 @@ import time from server import BAPSicleServer -if __name__ == '__main__': +def startServer(): + # On Windows calling this function is necessary. # Causes all kinds of loops if not present. multiprocessing.freeze_support() - server = multiprocessing.Process(target=BAPSicleServer).start() + + server = multiprocessing.Process(target=BAPSicleServer) + server.start() + while True: - time.sleep(1) - pass + time.sleep(2) + if server and server.is_alive(): + pass + else: + print("Server dead. Exiting.") + sys.exit(0) + +if __name__ == '__main__': + startServer() \ No newline at end of file diff --git a/player.py b/player.py index d00e56b..68f5fce 100644 --- a/player.py +++ b/player.py @@ -10,11 +10,13 @@ import setproctitle import copy import json import time +import os +import sys +os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" from pygame import mixer from state_manager import StateManager from mutagen.mp3 import MP3 -import os -os.environ['PYGAME_HIDE_SUPPORT_PROMPT'] = "hide" + class Player(): @@ -343,6 +345,7 @@ class Player(): print("Quiting player ", channel) self.quit() self._retMsg("EXIT") + sys.exit(0) def showOutput(in_q, out_q): diff --git a/server.py b/server.py index 5f733b3..8b2c05b 100644 --- a/server.py +++ b/server.py @@ -4,6 +4,8 @@ from flask import Flask, render_template, send_from_directory, request import json import sounddevice as sd import setproctitle +import logging +import sys setproctitle.setproctitle("BAPSicle - Server") @@ -18,10 +20,15 @@ class BAPSicleServer(): app = Flask(__name__, static_url_path='') +log = logging.getLogger('werkzeug') +log.disabled = True +app.logger.disabled = True + channel_to_q = [] channel_from_q = [] channel_p = [] +stopping = False @app.errorhandler(404) def page_not_found(e): @@ -147,6 +154,11 @@ def status(channel): return response +@app.route("/quit") +def quit(): + stopServer() + return "Shutting down..." + @app.route("/player/all/stop") def all_stop(): @@ -184,9 +196,23 @@ def stopServer(): for q in channel_to_q: q.put("QUIT") for player in channel_p: - player.join() - global app - app = None + try: + player.join() + except: + pass + print ("Stopped all players.") + global stopping + if stopping == False: + stopping = True + shutdown = request.environ.get('werkzeug.server.shutdown') + if shutdown is None: + print("Shutting down Server.") + + else: + print("Shutting down Flask.") + shutdown() + else: + print(str(stopping)) if __name__ == "__main__": diff --git a/state_manager.py b/state_manager.py index e81cffd..704a59a 100644 --- a/state_manager.py +++ b/state_manager.py @@ -8,6 +8,11 @@ class StateManager: __state = {} def __init__(self, name, default_state=None): + try: + os.mkdir(resolve_external_file_path("/state")) + except FileExistsError: + pass + self.filepath = resolve_external_file_path("/state/" + name + ".json") if not os.path.isfile(self.filepath): self.log("No file found for " + self.filepath)