Initial commit: Media server and Home Assistant integration
- 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>
This commit is contained in:
112
media_server/main.py
Normal file
112
media_server/main.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""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()
|
||||
Reference in New Issue
Block a user