# francescograzioso/meld architecture

> Architecture diagram of the GitHub repository francescograzioso/meld, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-05-13). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/francescograzioso/meld
- Repository: https://github.com/francescograzioso/meld

## Overview

1. Meld is a multi-module Android music client built in Kotlin. The app’s core idea is split across two external ecosystems: Spotify provides identity, personalization, search, and library metadata; YouTube Music provides actual audio playback.

2. The main Android application lives in `app/` and is organized as a Compose-based single-app shell with feature screens, ViewModels, a DI layer, and a set of background services/receivers. `MainActivity` and `App` bootstrap navigation and theme, while most user-facing logic is pushed into `viewmodels/` and `ui/screens/`.

3. `app/` is also the orchestration layer for local state. It uses Room (`db/`) for persistent music data, match caches, playlists, history, recognition history, and override records, plus DataStore utilities for preferences and account/configuration state. The many schema snapshots indicate explicit migration management is a first-class concern.

4. The Spotify boundary is isolated in the `spotify/` module. It handles Spotify login, token handling, GraphQL/REST access, response models, and a Spotify-specific mapping layer. In the app, this data feeds home content, search, top tracks/artists, playlists, liked songs, and recommendation inputs.

5. The YouTube Music boundary is isolated in the `innertube/` module. It contains the InnerTube client, request/response models, page parsers, and YouTube URL parsing helpers. This module is the app’s main gateway for browsing YouTube Music content and resolving playback streams.

6. Playback is centered around `MusicService`, `MediaLibrarySessionCallback`, and `PlayerConnection`. The playback stack uses an ExoPlayer-based service, queue abstractions, download/caching support, and audio processors for features like skip silence, equalization, and playback normalization. Sleep timer and sponsor-block style processing are part of the same playback domain.

7. A key architectural flow is Spotify-to-YouTube matching. Spotify track metadata is resolved to a playable YouTube Music item through `SpotifyYouTubeMapper`, cached locally, and optionally overridden manually by the user. The app’s recommendation engine uses Spotify taste data to build radio-like queues before playback resolution happens.

8. Lyrics are a separate integration layer, not just UI decoration. `LyricsProviderRegistry` coordinates multiple providers: Better Lyrics, LrcLib, KuGou, Paxsenix, and YouTube-based sources, with translation helpers and UI components layered on top. The standalone `betterlyrics/` module exists as a parser/runtime dependency for time-synced lyric rendering.

9. Social and external integrations are modularized as well. `kizzy/` implements Discord Rich Presence over the Discord gateway. `lastfm/` provides Last.fm auth/scrobbling support. `listen together` classes handle peer synchronization with a protocol/client/server split. Cast support is flavor-dependent, with separate sources for Google Play Services-enabled builds and fallback variants.

10. The app has many Android entrypoints beyond the main UI: widgets, quick settings tiles, media/session callbacks, alarm receivers, recognition foreground services, and shortcut definitions. These are wired around the same core services so playback, recognition, and remote control all converge on the shared media/session state.

11. Recognition is its own pipeline: quick settings and widget entrypoints start a foreground recognition service, which generates audio signatures and returns track identity. The result is persisted in the local database for history and reuse.

12. The repo is intentionally split into build/runtime boundaries that mirror service risk and platform availability. `gms`, `foss`, and `izzy` source sets provide flavor-specific implementations for cast and related Google Play Services behavior, while `app/src/main/assets` contains token/cipher/PoToken tooling used in playback resolution and YouTube access.

13. In diagram terms, the central hub is `app/`: UI and user actions flow into ViewModels, then into local persistence and the Spotify/YouTube client modules, and finally into the playback service. Everything else—lyrics, scrobbling, Discord, recognition, widgets, cast, and listen-together—hangs off that same shared session/state core.

Main entry points: [`app/src/main/kotlin/com/metrolist/music/playback/MusicService.kt`](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/playback/MusicService.kt) (Playback core), [`innertube/src/main/kotlin/com/metrolist/innertube/InnerTube.kt`](https://github.com/francescograzioso/meld/blob/main/innertube/src/main/kotlin/com/metrolist/innertube/InnerTube.kt) (InnerTube), [`app/src/main/kotlin/com/metrolist/music/db/MusicDatabase.kt`](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/db/MusicDatabase.kt) (Room DB), [`app/src/main/kotlin/com/metrolist/music/lyrics/LyricsProviderRegistry.kt`](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/lyrics/LyricsProviderRegistry.kt) (Lyrics)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_app["App shell"]
  node_app_entry["App<br/>[App.kt]"]
  node_main_activity["Main UI<br/>activity<br/>[MainActivity.kt]"]
  node_nav_ui["Navigation<br/>compose UI<br/>[AppNavigation.kt]"]
  node_screens["Screens"]
  node_vms["ViewModels<br/>state layer"]
  node_db[("Room DB<br/>persistent store<br/>[MusicDatabase.kt]")]
  node_prefs["DataStore<br/>preferences<br/>[DataStore.kt]"]
  node_playback["Playback core<br/>media service<br/>[MusicService.kt]"]
  node_mapper["Track matcher<br/>spotify→youtube"]
  node_reco["Recommendations<br/>queue engine"]
end

subgraph group_clients["Client modules"]
  node_spotify_mod["Spotify<br/>client module<br/>[Spotify.kt]"]
  node_yt_mod["InnerTube<br/>client module<br/>[InnerTube.kt]"]
  node_betterlyrics_mod["BetterLyrics<br/>parser module<br/>[BetterLyrics.kt]"]
end

subgraph group_integrations["Integrations"]
  node_lyrics["Lyrics<br/>integration hub"]
  node_recognition["Recognition<br/>audio pipeline"]
  node_listen_together["Listen Together<br/>sync protocol"]
  node_discord_mod["Kizzy RPC<br/>discord presence<br/>[KizzyRPC.kt]"]
  node_lastfm_mod["Last.fm<br/>scrobble client<br/>[LastFM.kt]"]
end

subgraph group_infra["Infrastructure"]
  node_cast_flavors["Cast flavors<br/>variant impls<br/>[CastManager.kt]"]
  node_assets_tools["Playback assets<br/>tooling assets"]
end

node_main_activity -->|"bootstraps"| node_app_entry
node_app_entry -->|"hosts"| node_nav_ui
node_nav_ui -->|"routes"| node_screens
node_screens -->|"reads state"| node_vms
node_vms -->|"persists"| node_db
node_vms -->|"stores prefs"| node_prefs
node_playback -->|"uses cache"| node_db
node_playback -->|"resolves tracks"| node_mapper
node_playback -->|"builds queues"| node_reco
node_mapper -->|"reads metadata"| node_spotify_mod
node_mapper -->|"finds media"| node_yt_mod
node_reco -->|"uses taste"| node_spotify_mod
node_lyrics -->|"parses synced"| node_betterlyrics_mod
node_lyrics -->|"youtube source"| node_yt_mod
node_lyrics -->|"renders in UI"| node_app_entry
node_recognition -->|"logs history"| node_db
node_listen_together -->|"syncs session"| node_playback
node_discord_mod -->|"presence from player"| node_playback
node_lastfm_mod -->|"scrobbles"| node_playback
node_cast_flavors -->|"casts session"| node_playback
node_assets_tools -->|"supports access"| node_yt_mod
node_assets_tools -->|"enables playback"| node_playback
node_recognition -->|"launches flows"| node_screens
node_spotify_mod -->|"fills caches"| node_db
node_yt_mod -->|"provides media"| node_playback

click node_app_entry "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/App.kt"
click node_main_activity "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/MainActivity.kt"
click node_nav_ui "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/ui/component/AppNavigation.kt"
click node_screens "https://github.com/francescograzioso/meld/tree/main/app/src/main/kotlin/com/metrolist/music/ui/screens"
click node_vms "https://github.com/francescograzioso/meld/tree/main/app/src/main/kotlin/com/metrolist/music/viewmodels"
click node_db "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/db/MusicDatabase.kt"
click node_prefs "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/utils/DataStore.kt"
click node_playback "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/playback/MusicService.kt"
click node_mapper "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/playback/SpotifyYouTubeMapper.kt"
click node_reco "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/playback/SpotifyRecommendationEngine.kt"
click node_lyrics "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/lyrics/LyricsProviderRegistry.kt"
click node_recognition "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/recognition/MusicRecognitionService.kt"
click node_listen_together "https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/listentogether/ListenTogetherManager.kt"
click node_spotify_mod "https://github.com/francescograzioso/meld/blob/main/spotify/src/main/kotlin/com/metrolist/spotify/Spotify.kt"
click node_yt_mod "https://github.com/francescograzioso/meld/blob/main/innertube/src/main/kotlin/com/metrolist/innertube/InnerTube.kt"
click node_betterlyrics_mod "https://github.com/francescograzioso/meld/blob/main/betterlyrics/src/main/kotlin/com/metrolist/music/betterlyrics/BetterLyrics.kt"
click node_discord_mod "https://github.com/francescograzioso/meld/blob/main/kizzy/src/main/kotlin/com/my/kizzy/rpc/KizzyRPC.kt"
click node_lastfm_mod "https://github.com/francescograzioso/meld/blob/main/lastfm/src/main/kotlin/com/metrolist/lastfm/LastFM.kt"
click node_cast_flavors "https://github.com/francescograzioso/meld/blob/main/app/src/gms/kotlin/com/metrolist/music/cast/CastManager.kt"
click node_assets_tools "https://github.com/francescograzioso/meld/tree/main/app/src/main/assets"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_app_entry,node_main_activity,node_nav_ui,node_screens,node_vms,node_db,node_prefs,node_playback,node_mapper,node_reco toneBlue
class node_spotify_mod,node_yt_mod,node_betterlyrics_mod toneAmber
class node_lyrics,node_recognition,node_listen_together,node_discord_mod,node_lastfm_mod toneMint
class node_cast_flavors,node_assets_tools toneRose
```

## Components

### App shell

Main Android application, UI, state, and orchestration.

- [App](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/App.kt): Android app · Application bootstrap and theme/navigation host. · `app/src/main/kotlin/com/metrolist/music/App.kt`
- [Main UI](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/MainActivity.kt): activity · Primary activity that launches the Compose shell. · `app/src/main/kotlin/com/metrolist/music/MainActivity.kt`
- [Navigation](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/ui/component/AppNavigation.kt): compose UI · App navigation graph and screen wiring. · `app/src/main/kotlin/com/metrolist/music/ui/component/AppNavigation.kt`
- [Screens](https://github.com/francescograzioso/meld/tree/main/app/src/main/kotlin/com/metrolist/music/ui/screens): compose screens · Feature screens for home, library, search, settings, and player flows. · `app/src/main/kotlin/com/metrolist/music/ui/screens`
- [ViewModels](https://github.com/francescograzioso/meld/tree/main/app/src/main/kotlin/com/metrolist/music/viewmodels): state layer · Screen and feature state holders coordinating UI actions and data. · `app/src/main/kotlin/com/metrolist/music/viewmodels`
- [Room DB](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/db/MusicDatabase.kt): persistent store · Local music, playlist, match, history, and recognition persistence with explicit migrations. · `app/src/main/kotlin/com/metrolist/music/db/MusicDatabase.kt`
- [DataStore](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/utils/DataStore.kt): preferences · Local preferences and account/configuration state management. · `app/src/main/kotlin/com/metrolist/music/utils/DataStore.kt`
- [Playback core](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/playback/MusicService.kt): media service · ExoPlayer-backed service, queue, session, caching, timers, sponsor-block, and mapping flow. · `app/src/main/kotlin/com/metrolist/music/playback/MusicService.kt`
- [Track matcher](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/playback/SpotifyYouTubeMapper.kt): spotify→youtube · Resolves Spotify metadata into playable YouTube Music items with local cache and overrides. · `app/src/main/kotlin/com/metrolist/music/playback/SpotifyYouTubeMapper.kt`
- [Recommendations](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/playback/SpotifyRecommendationEngine.kt): queue engine · Builds radio-like queues from Spotify profile and taste data. · `app/src/main/kotlin/com/metrolist/music/playback/SpotifyRecommendationEngine.kt`

### Client modules

External service boundaries and shared runtime modules.

- [Spotify](https://github.com/francescograzioso/meld/blob/main/spotify/src/main/kotlin/com/metrolist/spotify/Spotify.kt): client module · Spotify auth, API access, models, and mapping helpers. · `spotify/src/main/kotlin/com/metrolist/spotify/Spotify.kt`
- [InnerTube](https://github.com/francescograzioso/meld/blob/main/innertube/src/main/kotlin/com/metrolist/innertube/InnerTube.kt): client module · YouTube Music browsing, parsing, and playback request/response client. · `innertube/src/main/kotlin/com/metrolist/innertube/InnerTube.kt`
- [BetterLyrics](https://github.com/francescograzioso/meld/blob/main/betterlyrics/src/main/kotlin/com/metrolist/music/betterlyrics/BetterLyrics.kt): parser module · Time-synced TTML lyric parsing runtime used by the lyrics stack. · `betterlyrics/src/main/kotlin/com/metrolist/music/betterlyrics/BetterLyrics.kt`

### Integrations

Optional social, lyrics, recognition, and casting features.

- [Lyrics](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/lyrics/LyricsProviderRegistry.kt): integration hub · Coordinates lyric providers, translation, and synced lyric UI. · `app/src/main/kotlin/com/metrolist/music/lyrics/LyricsProviderRegistry.kt`
- [Recognition](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/recognition/MusicRecognitionService.kt): audio pipeline · Foreground track recognition service and signature generation. · `app/src/main/kotlin/com/metrolist/music/recognition/MusicRecognitionService.kt`
- [Listen Together](https://github.com/francescograzioso/meld/blob/main/app/src/main/kotlin/com/metrolist/music/listentogether/ListenTogetherManager.kt): sync protocol · Peer synchronization client/server and session messaging. · `app/src/main/kotlin/com/metrolist/music/listentogether/ListenTogetherManager.kt`
- [Kizzy RPC](https://github.com/francescograzioso/meld/blob/main/kizzy/src/main/kotlin/com/my/kizzy/rpc/KizzyRPC.kt): discord presence · Discord gateway and rich presence implementation. · `kizzy/src/main/kotlin/com/my/kizzy/rpc/KizzyRPC.kt`
- [Last.fm](https://github.com/francescograzioso/meld/blob/main/lastfm/src/main/kotlin/com/metrolist/lastfm/LastFM.kt): scrobble client · Last.fm authentication and scrobbling support. · `lastfm/src/main/kotlin/com/metrolist/lastfm/LastFM.kt`

### Infrastructure

Build/runtime tooling and supporting assets.

- [Cast flavors](https://github.com/francescograzioso/meld/blob/main/app/src/gms/kotlin/com/metrolist/music/cast/CastManager.kt): variant impls · Flavor-specific Cast and Google Play Services implementations. · `app/src/gms/kotlin/com/metrolist/music/cast/CastManager.kt`
- [Playback assets](https://github.com/francescograzioso/meld/tree/main/app/src/main/assets): tooling assets · Cipher, PoToken, and player-asset tooling used for YouTube access and playback resolution. · `app/src/main/assets`

## Connections

- Main UI → App: bootstraps · Activity enters the Compose application shell.
- App → Navigation: hosts · Application sets up navigation and theme.
- Navigation → Screens: routes · Navigation selects feature screens.
- Screens → ViewModels: reads state · Screens observe and drive ViewModels.
- ViewModels → Room DB: persists · ViewModels read and write local music state.
- ViewModels → DataStore: stores prefs · ViewModels and app logic use preference state.
- Playback core → Room DB: uses cache · Playback consults local matches, queues, and history.
- Playback core → Track matcher: resolves tracks · Playback mapping turns Spotify items into playable YouTube media.
- Playback core → Recommendations: builds queues · Recommendation engine seeds radio-style playback queues.
- Track matcher → Spotify: reads metadata · Uses Spotify track, album, artist, and playlist data.
- Track matcher → InnerTube: finds media · Resolves YouTube Music candidates and streams.
- Recommendations → Spotify: uses taste · Consumes Spotify profile and recommendation inputs.
- Lyrics → BetterLyrics: parses synced · Uses parser/runtime support for synced lyrics rendering.
- Lyrics → InnerTube: youtube source · Can derive lyrics from YouTube content and subtitles.
- Lyrics → App: renders in UI · Lyrics registry feeds lyric screens and components.
- Recognition → Room DB: logs history · Recognition results are stored for reuse and history.
- Listen Together → Playback core: syncs session · Peer sync is anchored to the shared playback/session state.
- Kizzy RPC → Playback core: presence from player · Rich presence mirrors current playback state.
- Last.fm → Playback core: scrobbles · Scrobbling is driven by playback events.
- Cast flavors → Playback core: casts session · Flavor-specific cast handlers plug into the media session.
- Playback assets → InnerTube: supports access · Token and cipher tooling help YouTube access and stream resolution.
- Playback assets → Playback core: enables playback · Playback resolution depends on asset-backed tooling.
- Recognition → Screens: launches flows · Widget and quick settings entrypoints reach recognition screens.
- Spotify → Room DB: fills caches · Spotify-derived matches and library data are cached locally.
- InnerTube → Playback core: provides media · YouTube Music content and stream data feed playback.
