refactor: modules only need to know the config values they need to know
This commit is contained in:
+2
-2
@@ -430,7 +430,7 @@ def offset(delta: str) -> None:
|
||||
logger.error(parse_error or "Invalid offset delta")
|
||||
sys.exit(1)
|
||||
|
||||
response = ControlClient(config=_app_config).send(
|
||||
response = ControlClient(_app_config.watch.socket_path).send(
|
||||
{"cmd": "offset", "delta": parsed_delta}
|
||||
)
|
||||
if not response.get("ok"):
|
||||
@@ -442,7 +442,7 @@ def offset(delta: str) -> None:
|
||||
@ctl_app.command
|
||||
def status() -> None:
|
||||
"""Print current watch session status as JSON."""
|
||||
response = ControlClient(config=_app_config).send({"cmd": "status"})
|
||||
response = ControlClient(_app_config.watch.socket_path).send({"cmd": "status"})
|
||||
if not response.get("ok"):
|
||||
logger.error(response.get("error", "Unknown error"))
|
||||
sys.exit(1)
|
||||
|
||||
@@ -7,8 +7,6 @@ from typing import TYPE_CHECKING
|
||||
|
||||
from loguru import logger
|
||||
|
||||
from ..config import AppConfig
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .session import WatchCoordinator
|
||||
|
||||
@@ -19,13 +17,9 @@ class ControlServer:
|
||||
_socket_path: Path
|
||||
_server: asyncio.AbstractServer | None
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: AppConfig,
|
||||
socket_path: Path | None = None,
|
||||
) -> None:
|
||||
def __init__(self, socket_path: str) -> None:
|
||||
"""Initialize control server with socket path from config or explicit override."""
|
||||
self._socket_path: Path = socket_path or Path(config.watch.socket_path)
|
||||
self._socket_path = Path(socket_path)
|
||||
self._server: asyncio.AbstractServer | None = None
|
||||
|
||||
async def start(self, session: "WatchCoordinator") -> bool:
|
||||
@@ -107,13 +101,9 @@ class ControlClient:
|
||||
|
||||
_socket_path: Path
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
config: AppConfig,
|
||||
socket_path: Path | None = None,
|
||||
) -> None:
|
||||
def __init__(self, socket_path: str) -> None:
|
||||
"""Initialize control client with socket path from config or explicit override."""
|
||||
self._socket_path: Path = socket_path or Path(config.watch.socket_path)
|
||||
self._socket_path = Path(socket_path)
|
||||
|
||||
async def _send_async(self, cmd: dict[str, object]) -> dict[str, object]:
|
||||
"""Send one JSON command to control server and return JSON response."""
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
import asyncio
|
||||
from typing import Awaitable, Callable, Optional
|
||||
|
||||
from ..config import AppConfig
|
||||
from ..lrc import LRCData
|
||||
from ..models import TrackMeta
|
||||
|
||||
@@ -11,7 +10,7 @@ from ..models import TrackMeta
|
||||
class LyricFetcher:
|
||||
"""Debounces track updates and runs at most one lyric fetch task at a time."""
|
||||
|
||||
_config: AppConfig
|
||||
_watch_debounce_ms: int
|
||||
_fetch_func: Callable[[TrackMeta], Awaitable[Optional[LRCData]]]
|
||||
_on_fetching: Callable[[], Awaitable[None] | None]
|
||||
_on_result: Callable[[Optional[LRCData]], Awaitable[None] | None]
|
||||
@@ -24,10 +23,10 @@ class LyricFetcher:
|
||||
fetch_func: Callable[[TrackMeta], Awaitable[Optional[LRCData]]],
|
||||
on_fetching: Callable[[], Awaitable[None] | None],
|
||||
on_result: Callable[[Optional[LRCData]], Awaitable[None] | None],
|
||||
config: AppConfig,
|
||||
watch_debounce_ms: int,
|
||||
) -> None:
|
||||
"""Initialize fetch callbacks and runtime options."""
|
||||
self._config = config
|
||||
self._watch_debounce_ms = watch_debounce_ms
|
||||
self._fetch_func = fetch_func
|
||||
self._on_fetching = on_fetching
|
||||
self._on_result = on_result
|
||||
@@ -56,7 +55,7 @@ class LyricFetcher:
|
||||
|
||||
async def _debounce_then_fetch(self) -> None:
|
||||
"""Wait debounce window then start a fresh fetch task for latest pending track."""
|
||||
await asyncio.sleep(self._config.watch.debounce_ms / 1000.0)
|
||||
await asyncio.sleep(self._watch_debounce_ms / 1000.0)
|
||||
track = self._pending_track
|
||||
if track is None:
|
||||
return
|
||||
|
||||
@@ -9,7 +9,6 @@ from dbus_next.constants import BusType
|
||||
from dbus_next.message import Message
|
||||
from loguru import logger
|
||||
|
||||
from ..config import AppConfig
|
||||
from ..models import TrackMeta
|
||||
|
||||
|
||||
@@ -75,7 +74,7 @@ def _keyword_match(text: str, keyword: str) -> bool:
|
||||
class PlayerMonitor:
|
||||
"""Tracks MPRIS players and forwards signal-driven state updates to session callbacks."""
|
||||
|
||||
_config: AppConfig
|
||||
_player_blacklist: tuple[str, ...]
|
||||
_on_players_changed: Callable[[], None]
|
||||
_on_seeked: Callable[[str, int], None]
|
||||
_on_playback_status: Callable[[str, str], None]
|
||||
@@ -89,17 +88,15 @@ class PlayerMonitor:
|
||||
on_players_changed: Callable[[], None],
|
||||
on_seeked: Callable[[str, int], None],
|
||||
on_playback_status: Callable[[str, str], None],
|
||||
config: AppConfig,
|
||||
player_blacklist: tuple[str, ...],
|
||||
target: Optional[PlayerTarget] = None,
|
||||
) -> None:
|
||||
"""Initialize monitor callbacks, runtime options, and player target filter."""
|
||||
self._config = config
|
||||
self._player_blacklist = player_blacklist
|
||||
self._on_players_changed = on_players_changed
|
||||
self._on_seeked = on_seeked
|
||||
self._on_playback_status = on_playback_status
|
||||
self._target = target or PlayerTarget(
|
||||
player_blacklist=self._config.general.player_blacklist
|
||||
)
|
||||
self._target = target or PlayerTarget(player_blacklist=self._player_blacklist)
|
||||
self.players: dict[str, PlayerState] = {}
|
||||
self._bus: MessageBus | None = None
|
||||
self._props_cache: dict[str, object] = {}
|
||||
@@ -183,10 +180,7 @@ class PlayerMonitor:
|
||||
for name in reply.body[0]:
|
||||
if not name.startswith("org.mpris.MediaPlayer2."):
|
||||
continue
|
||||
if any(
|
||||
x.lower() in name.lower()
|
||||
for x in self._config.general.player_blacklist
|
||||
):
|
||||
if any(x.lower() in name.lower() for x in self._player_blacklist):
|
||||
continue
|
||||
if not self._target.allows(name):
|
||||
continue
|
||||
@@ -389,7 +383,7 @@ class ActivePlayerSelector:
|
||||
def select(
|
||||
players: dict[str, PlayerState],
|
||||
last_active: str | None,
|
||||
config: AppConfig,
|
||||
preferred_player: str,
|
||||
) -> str | None:
|
||||
"""Select active player by playing state, preferred keyword, and continuity."""
|
||||
if not players:
|
||||
@@ -399,7 +393,7 @@ class ActivePlayerSelector:
|
||||
if len(playing) == 1:
|
||||
return playing[0]
|
||||
|
||||
preferred = config.general.preferred_player.lower().strip()
|
||||
preferred = preferred_player.lower().strip()
|
||||
candidates = playing if playing else list(players.keys())
|
||||
if preferred:
|
||||
for name in candidates:
|
||||
|
||||
@@ -126,12 +126,12 @@ class WatchCoordinator:
|
||||
player_blacklist=self._config.general.player_blacklist,
|
||||
)
|
||||
|
||||
self._control = ControlServer(config=self._config)
|
||||
self._control = ControlServer(socket_path=config.watch.socket_path)
|
||||
self._player_monitor = PlayerMonitor(
|
||||
on_players_changed=self._on_player_change,
|
||||
on_seeked=self._on_seeked,
|
||||
on_playback_status=self._on_playback_status,
|
||||
config=self._config,
|
||||
player_blacklist=self._config.general.player_blacklist,
|
||||
target=self._target,
|
||||
)
|
||||
self._tracker = PositionTracker(
|
||||
@@ -143,7 +143,7 @@ class WatchCoordinator:
|
||||
fetch_func=self._fetch_lyrics,
|
||||
on_fetching=self._on_fetching,
|
||||
on_result=self._on_lyrics_update,
|
||||
config=self._config,
|
||||
watch_debounce_ms=self._config.watch.debounce_ms,
|
||||
)
|
||||
|
||||
async def run(self) -> bool:
|
||||
@@ -234,7 +234,7 @@ class WatchCoordinator:
|
||||
selected = ActivePlayerSelector.select(
|
||||
self._player_monitor.players,
|
||||
self._model.active_player,
|
||||
self._config,
|
||||
self._config.general.preferred_player,
|
||||
)
|
||||
self._model.active_player = selected
|
||||
|
||||
|
||||
Reference in New Issue
Block a user