-
-
Notifications
You must be signed in to change notification settings - Fork 55
API Documentation
Internal API reference for developers working with Rhythm's codebase. This covers the actual interfaces, classes, and patterns used in the project.
Note: For the exact implementation details, always refer to the source code. This document provides a high-level overview of key architecture components.
| Package | Purpose |
|---|---|
chromahub.rhythm.app.core.domain |
Domain interfaces and models |
chromahub.rhythm.app.features.local |
Local playback feature |
chromahub.rhythm.app.features.streaming |
Streaming playback feature |
chromahub.rhythm.app.shared |
Shared utilities, themes, navigation |
chromahub.rhythm.app.infrastructure |
Player service, widgets, workers, network |
chromahub.rhythm.app.network |
Retrofit API client configuration |
File: infrastructure/service/player/RhythmPlayerEngine.kt
The core playback engine using Media3 ExoPlayer with a custom DefaultRenderersFactory that enables the FFmpeg decoder extension:
val renderersFactory = object : DefaultRenderersFactory(context) {
override fun buildAudioSink(
context: Context,
enableFloatOutput: Boolean,
enableAudioTrackPlaybackParams: Boolean,
enableOffload: Boolean
): AudioSink {
return DefaultAudioSink.Builder(context)
.setAudioProcessorChain(audioProcessorChain)
.build()
}
}.apply {
setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER)
}Service: infrastructure/service/player/MediaPlaybackService.kt extends MediaLibraryService and manages:
-
MediaLibrarySessionfor external control -
Playerinstance viaRhythmPlayerEngine - Media notification with playback controls
- Audio focus handling
File: core/domain/repository/MusicRepository.kt
interface MusicRepository {
fun getSongs(): Flow<List<PlayableItem>>
fun getAlbums(): Flow<List<AlbumItem>>
fun getArtists(): Flow<List<ArtistItem>>
fun getPlaylists(): Flow<List<PlaylistItem>>
suspend fun getSongById(id: String): PlayableItem?
suspend fun getAlbumById(id: String): AlbumItem?
suspend fun getArtistById(id: String): ArtistItem?
suspend fun getPlaylistById(id: String): PlaylistItem?
suspend fun getSongsForAlbum(albumId: String): List<PlayableItem>
suspend fun searchSongs(query: String): List<PlayableItem>
suspend fun searchAlbums(query: String): List<AlbumItem>
suspend fun searchArtists(query: String): List<ArtistItem>
suspend fun searchPlaylists(query: String): List<PlaylistItem>
}All identifiers are String type. Core models are in core/domain/model/:
| Model | Key Fields |
|---|---|
PlayableItem |
id: String, title: String, artist: String?, album: String?, albumId: String?, duration: Long, uri: String?
|
AlbumItem |
id: String, title: String, artist: String?, year: Int?, artworkUri: Uri?
|
ArtistItem |
id: String, name: String, albumCount: Int, trackCount: Int
|
PlaylistItem |
id: String, name: String, dateCreated: Long, dateModified: Long
|
interface LRCLibApiService {
@GET("api/search")
suspend fun searchLyrics(
@Query("q") query: String
): Response<List<LyricsData>>
}interface DeezerApiService {
@GET("search/track")
suspend fun searchTrack(
@Query("q") query: String
): Response<DeezerSearchResponse>
}interface YouTubeMusicApiService {
@GET("api/music/song")
suspend fun searchSong(
@Query("q") query: String
): Response<YouTubeMusicResponse>
}| Widget | Class |
|---|---|
| Music Player Widget | RhythmMusicWidget : GlanceAppWidget() |
| Lyrics Widget | RhythmLyricsWidget : GlanceAppWidget() |
Widget updates are managed by RhythmWidgetWorker (a CoroutineWorker) and GlanceWidgetUpdater.
-
Playback State: Observed via
Player.Listeneron ExoPlayer'sPlayerinterface -
UI State:
StateFlowin ViewModels, collected as Compose state viacollectAsState() -
Settings:
AppSettingsclass backed byDataStore/SharedPreferences -
Navigation: Compose Navigation with a sealed
Routeclass hierarchy
All flags are true for both fdroid and github flavors:
| Flag | Purpose |
|---|---|
ENABLE_YOUTUBE_MUSIC |
YouTube Music artwork search |
ENABLE_SPOTIFY_SEARCH |
Spotify metadata search |
ENABLE_LYRICALLY_API |
Lyricall API for lyrics |
ENABLE_DEEZER |
Deezer artwork search |
ENABLE_LRCLIB |
LRCLib synchronized lyrics |
| Dependency | Version |
|---|---|
| AGP | 9.2.1 |
| Kotlin | 2.4.0 |
| Compose BOM | 2026.06.00 |
| Material3 | 1.5.0-alpha22 |
| Media3 | 1.10.1 |
| FFmpeg Decoder |
1.9.0+1 (JellyFin fork) |