feat(client): initial implementation of jellyfin htpc client with yatse remote and youtube playback
This commit is contained in:
+84
@@ -0,0 +1,84 @@
|
||||
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()
|
||||
Reference in New Issue
Block a user