Files
jellyfin-client/src/main.py
T

85 lines
2.3 KiB
Python

from __future__ import annotations
import argparse
import asyncio
import logging
import signal
import sys
from typing import List
from src.config import AppConfig
from src.jellyfin.client import JellyfinClient
from src.player.mpv_controller import MpvController
from src.remotes.kodi_rpc import KodiRpcServer
from src.remotes.rest_api import RestApiServer
logger = logging.getLogger("jellyfin_client")
def parse_args() -> argparse.Namespace:
parser = argparse.ArgumentParser(description="Jellyfin HTPC Client & YouTube Player")
parser.add_argument("-c", "--config", help="Path to config.yaml file")
parser.add_argument("-d", "--debug", action="store_true", help="Enable debug logging")
return parser.parse_args()
async def run_app(config: AppConfig) -> None:
player = MpvController(config.player)
jellyfin = JellyfinClient(config.jellyfin, player)
kodi_rpc = KodiRpcServer(config.kodi_rpc, player)
rest_api = RestApiServer(config.web_api, player)
# Start services
await player.start()
await jellyfin.start()
await kodi_rpc.start()
await rest_api.start()
logger.info("Jellyfin HTPC Client is fully initialized and ready.")
# Setup signal handling for graceful shutdown
loop = asyncio.get_running_loop()
stop_event = asyncio.Event()
def _sig_handler() -> None:
logger.info("Shutdown signal received")
stop_event.set()
for sig in (signal.SIGINT, signal.SIGTERM):
try:
loop.add_signal_handler(sig, _sig_handler)
except NotImplementedError:
pass # Windows or non-main thread
await stop_event.wait()
logger.info("Shutting down services...")
await rest_api.shutdown()
await kodi_rpc.shutdown()
await jellyfin.shutdown()
await player.shutdown()
logger.info("Graceful shutdown complete.")
def main() -> None:
args = parse_args()
log_level = logging.DEBUG if args.debug else logging.INFO
logging.basicConfig(
level=log_level,
format="%(asctime)s [%(levelname)s] (%(name)s) %(message)s",
datefmt="%Y-%m-%d %H:%M:%S",
)
config = AppConfig.load(args.config)
try:
asyncio.run(run_app(config))
except KeyboardInterrupt:
pass
except Exception as e:
logger.critical("Fatal error: %s", e, exc_info=True)
sys.exit(1)
if __name__ == "__main__":
main()