From 4a4f55fbe950544a310220d52ba0d444256faf62 Mon Sep 17 00:00:00 2001 From: oberon Date: Thu, 19 Feb 2026 09:32:21 +0100 Subject: [PATCH] fix for auto-start timer, added status to json-file --- app/routes/api.py | 71 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) diff --git a/app/routes/api.py b/app/routes/api.py index ab7557a..5dd68d2 100644 --- a/app/routes/api.py +++ b/app/routes/api.py @@ -19,6 +19,7 @@ audio_lock = threading.Lock() auto_random_lock = threading.Lock() auto_random_timer = None auto_random_params = {} +AUTO_STATE_PATH = os.path.join(Config.LOG_DIR, 'auto_random_state.json') # Sound-Cache: path -> pygame.mixer.Sound loaded_sounds = {} @@ -135,12 +136,35 @@ def _auto_random_tick(): auto_random_timer = threading.Timer(delay, _auto_random_tick) auto_random_timer.daemon = True auto_random_timer.start() + _persist_auto_state() def rand_between(a, b): return a + random.random() * (b - a) +def _persist_auto_state(clear=False): + try: + if clear: + if os.path.exists(AUTO_STATE_PATH): + os.remove(AUTO_STATE_PATH) + return + data = { + "active": state.auto_random_active, + "next_ts": auto_random_params.get('next_ts'), + "imin": auto_random_params.get('imin'), + "imax": auto_random_params.get('imax'), + "dmin": auto_random_params.get('dmin'), + "dmax": auto_random_params.get('dmax'), + "theme": auto_random_params.get('theme') + } + os.makedirs(os.path.dirname(AUTO_STATE_PATH), exist_ok=True) + with open(AUTO_STATE_PATH, 'w', encoding='utf-8') as f: + json.dump(data, f) + except Exception as e: + logger.error(f"Persist auto-random state fehlgeschlagen: {e}") + + def _prune_history(sound_id, now): dq = random_history[sound_id] while dq and now - dq[0] > WINDOW_SECONDS: @@ -440,10 +464,12 @@ def api_soundboard_auto_start(): auto_random_params['dmin'] = dmin auto_random_params['dmax'] = dmax auto_random_params['next_ts'] = time.time() + delay + auto_random_params['theme'] = state.current_soundboard.get('filename') global auto_random_timer auto_random_timer = threading.Timer(delay, _auto_random_tick) auto_random_timer.daemon = True auto_random_timer.start() + _persist_auto_state() logger.info(f"Auto-Random gestartet (delay {delay/60:.1f} min, intervall {imin}-{imax} min)") return jsonify({"success": True, "message": "Auto-Random gestartet", "next_seconds": delay}) @@ -464,6 +490,8 @@ def api_soundboard_current(): @api_bp.route('/soundboard/status', methods=['GET']) def api_soundboard_status(): + # Wiederherstellen, falls Prozess neu gestartet und State aus Datei verfügbar + _restore_auto_state() with auto_random_lock: active = state.auto_random_active next_ts = auto_random_params.get('next_ts') @@ -494,9 +522,52 @@ def _stop_auto_random_internal(): stopped = True state.auto_random_active = False auto_random_params.clear() + _persist_auto_state(clear=True) return stopped +def _restore_auto_state(): + try: + if not os.path.exists(AUTO_STATE_PATH): + return + with open(AUTO_STATE_PATH, 'r', encoding='utf-8') as f: + data = json.load(f) + if not data.get('active'): + return + next_ts = data.get('next_ts') + if not next_ts or next_ts < time.time(): + return # abgelaufen + theme = data.get('theme') + # Theme laden, falls nicht gesetzt + if theme and (state.current_soundboard is None or state.current_soundboard.get('filename') != theme): + try: + sb = load_soundboard_config(theme, + current_app.config['SOUNDBOARD_CONFIG_DIR'], + current_app.config['SOUNDS_DIR']) + state.current_soundboard = sb + except Exception: + return + with auto_random_lock: + if state.auto_random_active: + return + state.auto_random_active = True + auto_random_params.update({ + 'imin': data.get('imin', 5), + 'imax': data.get('imax', 10), + 'dmin': data.get('dmin', 3), + 'dmax': data.get('dmax', 12), + 'next_ts': next_ts, + 'theme': theme + }) + delay = max(1, next_ts - time.time()) + global auto_random_timer + auto_random_timer = threading.Timer(delay, _auto_random_tick) + auto_random_timer.daemon = True + auto_random_timer.start() + except Exception as e: + logger.error(f"Restore auto-random state fehlgeschlagen: {e}") + + @api_bp.route('/stop_sound', methods=['POST']) def api_stop_sound(): try: