diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index f0b8f08..cc3913e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -45,3 +45,94 @@ After modifying the `.proto` files you need to, **make sure to follow [these ste - Commit both the source `.proto` and the regenerated Python output **together** so they can be compared easily. + +## Architecture + +The main components are: + +- **`Session` class** *(entrypoint)* + + - `Session.Builder` is used to configure and create a session, via one of: + + - username/password + - stored credentials + - OAuth + + - An active session is **required** for all other operations. + +- **`ApiClient` class** + + - A high-level client for making standard HTTPS requests to Spotify's Web API endpoints (e.g., `https://spclient.wg.spotify.com`). + - Accessed via `session.api()`, it provides convenient methods like `get_metadata_4_track()` and handles client tokens automatically. + +- **`MercuryClient` class** + + - The low-level client for Spotify's proprietary `mercury` protocol, which uses `hm://` URIs. + - Accessed via `session.mercury()`, it handles sending and receiving messages over the main session connection for metadata lookups and subscriptions that are not available via the standard Web API. + +- **`DealerClient` class** + + - Manages the persistent WebSocket (`wss://`) connection to Spotify's `dealer` service. + - Accessed via `session.dealer()`, it listens for and dispatches real-time, asynchronous JSON-based events, such as remote player state changes or notifications from other connected devices. + +- **`Session.Receiver` thread** + + - Spawned after authentication to read every encrypted packet coming from the access point. + - Routes decoded commands to subsystems (`MercuryClient`, `AudioKeyManager`, `ChannelManager`, etc.) and responds to keep-alive pings to hold the session open. + +- **Metadata types** + + - The `librespot.metadata` module provides typed identifiers (`TrackId`, `AlbumId`, `PlaylistId`, `EpisodeId`, etc.) used to reference Spotify content throughout the API. + - They are constructed from Spotify identifiers, typically using one of the following methods: + + - `from_uri()`: For all ID types. + - `from_base62()`: For most ID types (e.g., tracks, albums, artists). + +- **`PlayableContentFeeder` class** + + - Retrieves audio streams; is accessed via `session.content_feeder()`. + - `load(playable_id, audio_quality_picker, preload, halt_listener)`: + + - Accepts: + + - a `TrackId` or `EpisodeId` (any `PlayableId`) + - an `AudioQualityPicker` + - a `preload` flag + - an optional `HaltListener` callback (pass `None` if unneeded). + + - Returns a `LoadedStream` that contains the decrypted stream together with: + + - track/episode metadata + - normalization data + - transfer metrics + +- **`audio` module** + + - Contains tools for format selection, quality management, streaming, and decryption. + - `VorbisOnlyAudioQuality` and `LosslessOnlyAudioQuality` choose the best matching `Metadata.AudioFile` for a preferred container/quality combination. + - `CdnManager` acquires and refreshes signed CDN URLs, feeding a `Streamer` that decrypts chunks on the fly while staying seekable. + +- **`AudioKeyManager` and `ChannelManager`** + + - Handle the low-level transport for protected audio: `AudioKeyManager` requests AES keys, and `ChannelManager` can stream encrypted chunks directly from the access point when CDN delivery is unavailable. + - Both are driven transparently by `PlayableContentFeeder`/`CdnManager`, so callers only interact with the decrypted `LoadedStream`. + +- **`EventService` class** + + - Asynchronous publisher that emits telemetry (e.g., fetch metrics, playback events) to `hm://event-service/v1/events` via Mercury. + - Accessible through `session.event_service()` for consumers that need to forward custom events. + +- **`TokenProvider` class** + + - Caches Login5 access tokens per scope, refreshing them proactively as they near expiry. + - Used by `ApiClient` to supply the correct `Authorization` headers for Spotify Web API calls. + +- **`SearchManager` class** + + - High-level wrapper around `hm://searchview/km/v4/search/...` requests sent over Mercury. + - Fills in username, locale, and country defaults from the current session before dispatching the call. + +- **OAuth tokens for Spotify Web API** + + - Can be obtained via `session.tokens().get(scope)` + - Enable authenticated API calls for operations like search, playlist management, and user data access