fix: tray main-thread message loop, numpy <2.0 pin, installer config copy
- Rewrite tray to run on main thread (pystray owns message loop, uvicorn in background thread) — fixes unresponsive confirmation dialogs - Use native Windows MessageBoxW instead of tkinter (embedded Python has no tkinter) - Pin numpy <2.0 to fix soundcard's numpy.fromstring (removed in 2.0) - Strip transitive numpy 2.x wheels in build script - Installer copies config.example.yaml as config.yaml on fresh install - Suppress noisy screen_brightness_control warnings
This commit is contained in:
+36
-9
@@ -51,6 +51,9 @@ def setup_logging():
|
||||
handlers=[handler],
|
||||
)
|
||||
|
||||
# Suppress noisy third-party loggers
|
||||
logging.getLogger("screen_brightness_control").setLevel(logging.ERROR)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
@@ -240,23 +243,47 @@ def main():
|
||||
print("\nAuthentication is DISABLED (no tokens configured)")
|
||||
return
|
||||
|
||||
# Start system tray icon (unless disabled)
|
||||
tray_icon = None
|
||||
if not args.no_tray:
|
||||
from .tray import start_tray
|
||||
from .tray import PYSTRAY_AVAILABLE, TrayManager
|
||||
|
||||
tray_icon = start_tray(args.host, args.port)
|
||||
use_tray = PYSTRAY_AVAILABLE and not args.no_tray
|
||||
|
||||
try:
|
||||
if use_tray:
|
||||
import asyncio
|
||||
import threading
|
||||
|
||||
# Run uvicorn in a background thread so tray owns the main thread message loop
|
||||
uv_config = uvicorn.Config(
|
||||
"media_server.main:app",
|
||||
host=args.host,
|
||||
port=args.port,
|
||||
log_level=settings.log_level.lower(),
|
||||
)
|
||||
server = uvicorn.Server(uv_config)
|
||||
|
||||
def run_server():
|
||||
loop = asyncio.new_event_loop()
|
||||
asyncio.set_event_loop(loop)
|
||||
loop.run_until_complete(server.serve())
|
||||
|
||||
server_thread = threading.Thread(target=run_server, daemon=True)
|
||||
server_thread.start()
|
||||
|
||||
# Tray on main thread (blocking)
|
||||
tray = TrayManager(
|
||||
port=args.port,
|
||||
on_exit=lambda: setattr(server, "should_exit", True),
|
||||
)
|
||||
tray.run()
|
||||
|
||||
# Tray exited — wait for server to finish graceful shutdown
|
||||
server_thread.join(timeout=10)
|
||||
else:
|
||||
uvicorn.run(
|
||||
"media_server.main:app",
|
||||
host=args.host,
|
||||
port=args.port,
|
||||
reload=False,
|
||||
)
|
||||
finally:
|
||||
if tray_icon is not None:
|
||||
tray_icon.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user