- FastAPI server for Windows media control via WinRT/SMTC - Home Assistant custom integration with media player entity - Script button entities for system commands - Position tracking with grace period for track skip handling - Server availability detection in HA entity Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
113 lines
2.9 KiB
Python
113 lines
2.9 KiB
Python
"""Media Server - FastAPI application entry point."""
|
|
|
|
import argparse
|
|
import logging
|
|
import sys
|
|
from contextlib import asynccontextmanager
|
|
|
|
import uvicorn
|
|
from fastapi import FastAPI
|
|
from fastapi.middleware.cors import CORSMiddleware
|
|
|
|
from .config import settings, generate_default_config, get_config_dir
|
|
from .routes import health_router, media_router, scripts_router
|
|
|
|
|
|
def setup_logging():
|
|
"""Configure application logging."""
|
|
logging.basicConfig(
|
|
level=getattr(logging, settings.log_level.upper()),
|
|
format="%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
handlers=[logging.StreamHandler(sys.stdout)],
|
|
)
|
|
|
|
|
|
@asynccontextmanager
|
|
async def lifespan(app: FastAPI):
|
|
"""Application lifespan handler."""
|
|
setup_logging()
|
|
logger = logging.getLogger(__name__)
|
|
logger.info(f"Media Server starting on {settings.host}:{settings.port}")
|
|
logger.info(f"API Token: {settings.api_token[:8]}...")
|
|
yield
|
|
logger.info("Media Server shutting down")
|
|
|
|
|
|
def create_app() -> FastAPI:
|
|
"""Create and configure the FastAPI application."""
|
|
app = FastAPI(
|
|
title="Media Server",
|
|
description="REST API for controlling system media playback",
|
|
version="1.0.0",
|
|
lifespan=lifespan,
|
|
)
|
|
|
|
# Add CORS middleware for cross-origin requests
|
|
app.add_middleware(
|
|
CORSMiddleware,
|
|
allow_origins=["*"],
|
|
allow_credentials=True,
|
|
allow_methods=["*"],
|
|
allow_headers=["*"],
|
|
)
|
|
|
|
# Register routers
|
|
app.include_router(health_router)
|
|
app.include_router(media_router)
|
|
app.include_router(scripts_router)
|
|
|
|
return app
|
|
|
|
|
|
app = create_app()
|
|
|
|
|
|
def main():
|
|
"""Main entry point for running the server."""
|
|
parser = argparse.ArgumentParser(description="Media Server")
|
|
parser.add_argument(
|
|
"--host",
|
|
default=settings.host,
|
|
help=f"Host to bind to (default: {settings.host})",
|
|
)
|
|
parser.add_argument(
|
|
"--port",
|
|
type=int,
|
|
default=settings.port,
|
|
help=f"Port to bind to (default: {settings.port})",
|
|
)
|
|
parser.add_argument(
|
|
"--generate-config",
|
|
action="store_true",
|
|
help="Generate a default configuration file and exit",
|
|
)
|
|
parser.add_argument(
|
|
"--show-token",
|
|
action="store_true",
|
|
help="Show the current API token and exit",
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
if args.generate_config:
|
|
config_path = generate_default_config()
|
|
print(f"Configuration file generated at: {config_path}")
|
|
print(f"API Token has been saved to the config file.")
|
|
return
|
|
|
|
if args.show_token:
|
|
print(f"API Token: {settings.api_token}")
|
|
print(f"Config directory: {get_config_dir()}")
|
|
return
|
|
|
|
uvicorn.run(
|
|
"media_server.main:app",
|
|
host=args.host,
|
|
port=args.port,
|
|
reload=False,
|
|
)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|