"""The catalogue registry. Beefy Player speaks to internet radio through :class:`RadioProvider` implementations (see :mod:`beefy_player.providers.base`). Each provider is registered here once; the app looks its provider up by slug, and ``--provider`` on the command line is validated against :func:`available_providers`. Adding a catalogue is meant to be a small, contained change: 1. write the package (``beefy_player/providers//``) with a :class:`~beefy_player.providers.base.RadioProvider` subclass, 2. add one instance to :data:`PROVIDERS` below, 3. that is it — the UI, the player, the spectrum and the media session do not care where the stations came from. """ from __future__ import annotations from .base import RadioProvider from .bassdrive import BassdriveProvider from .community import ( AnonradioProvider, CashmereProvider, DatafruitsProvider, DublabProvider, LotProvider, LylProvider, RefugeProvider, RinseProvider, ) from .radiobrowser import RadioBrowserProvider from .radioparadise import RadioParadiseProvider from .somafm import SomaFMProvider from .tilderadio import TilderadioProvider __all__ = [ "DEFAULT_PROVIDER", "PROVIDERS", "RadioProvider", "available_providers", "get_provider", ] #: Every catalogue the app can talk to, keyed by its slug. The picker, the #: help screen and ``--list`` all read this order: alphabetical by name. PROVIDERS: dict[str, RadioProvider] = { provider.id: provider for provider in sorted( ( SomaFMProvider(), TilderadioProvider(), BassdriveProvider(), RadioBrowserProvider(), RadioParadiseProvider(), DublabProvider(), RinseProvider(), RefugeProvider(), LylProvider(), LotProvider(), CashmereProvider(), DatafruitsProvider(), AnonradioProvider(), ), key=lambda provider: provider.name.casefold(), ) } #: Provider used when nothing else is configured. DEFAULT_PROVIDER = SomaFMProvider.id def available_providers() -> tuple[str, ...]: """Registered provider slugs, for ``--provider`` and the config file.""" return tuple(PROVIDERS) def get_provider(provider_id: str | None = None) -> RadioProvider: """Look a provider up by slug, falling back to the default one. An unknown slug is a stale config file or a typo, not a reason to refuse to start; the help screen and ``--list`` always name what is in use. """ key = (provider_id or "").strip().lower() if key in PROVIDERS: return PROVIDERS[key] return PROVIDERS[DEFAULT_PROVIDER]