#!/usr/bin/env python3 """ Startup script for the separated lighting controller architecture. Starts the control server, sound detector, and UI client. """ import subprocess import sys import time import signal import os from pathlib import Path def start_process(command, name, cwd=None): """Start a subprocess and return the process object.""" print(f"Starting {name}...") try: process = subprocess.Popen( command, shell=True, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, preexec_fn=os.setsid if os.name != 'nt' else None ) print(f"{name} started with PID {process.pid}") return process except Exception as e: print(f"Failed to start {name}: {e}") return None def main(): """Main startup function.""" print("Starting Lighting Controller (Separated Architecture)") print("=" * 50) # Get the project directory project_dir = Path(__file__).parent processes = [] try: # Start control server control_process = start_process( "python src/control_server.py", "Control Server", cwd=project_dir ) if control_process: processes.append(("Control Server", control_process)) # Wait a moment for the control server to start time.sleep(2) # Start sound detector sound_process = start_process( "python src/sound.py", "Sound Detector", cwd=project_dir ) if sound_process: processes.append(("Sound Detector", sound_process)) # Wait a moment for the sound detector to start time.sleep(1) # Start UI client ui_process = start_process( "python src/ui_client.py", "UI Client", cwd=project_dir ) if ui_process: processes.append(("UI Client", ui_process)) print("\nAll components started successfully!") print("Press Ctrl+C to stop all components...") # Wait for processes try: while True: time.sleep(1) # Check if any process has died for name, process in processes: if process.poll() is not None: print(f"Warning: {name} has stopped unexpectedly") except KeyboardInterrupt: print("\nShutting down all components...") except Exception as e: print(f"Error during startup: {e}") finally: # Clean up all processes for name, process in processes: if process and process.poll() is None: print(f"Stopping {name}...") try: if os.name != 'nt': os.killpg(os.getpgid(process.pid), signal.SIGTERM) else: process.terminate() process.wait(timeout=5) except subprocess.TimeoutExpired: print(f"Force killing {name}...") if os.name != 'nt': os.killpg(os.getpgid(process.pid), signal.SIGKILL) else: process.kill() except Exception as e: print(f"Error stopping {name}: {e}") print("All components stopped.") if __name__ == "__main__": main()