Files
media-player-server/media_server/main.py
alexei.dolgolyov 83acf5f1ec Initial commit: Media Server for remote media control
FastAPI REST API server for controlling system-wide media playback
on Windows, Linux, macOS, and Android.

Features:
- Play/Pause/Stop/Next/Previous track controls
- Volume control and mute
- Seek within tracks
- Current track info (title, artist, album, artwork)
- WebSocket real-time status updates
- Script execution API
- Token-based authentication
- Cross-platform support

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-04 14:41:00 +03:00

124 lines
3.2 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
from .services import get_media_controller
from .services.websocket_manager import ws_manager
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]}...")
# Start WebSocket status monitor
controller = get_media_controller()
await ws_manager.start_status_monitor(controller.get_status)
logger.info("WebSocket status monitor started")
yield
# Stop WebSocket status monitor
await ws_manager.stop_status_monitor()
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()