LyricsData.kt
Each line, with the release that last changed it.
| 0.5.0 | 1 | package dev.stave.lyrics |
| 2 | ||
| 3 | import kotlinx.serialization.Serializable | |
| 4 | import kotlin.time.Duration | |
| 5 | import kotlin.time.Duration.Companion.milliseconds | |
| 6 | ||
| 7 | /** | |
| 8 | * Raw response shape from `https://lrclib.net/api/get`. LRCLIB is generous about which | |
| 9 | * fields it returns — plain-text-only tracks get `syncedLyrics = null`, instrumentals | |
| 10 | * get `instrumental = true` with both lyrics fields null, tracks it has no record of | |
| 11 | * return a 404 which we surface as [LyricsResult.NotFound]. | |
| 12 | */ | |
| 13 | @Serializable | |
| 14 | data class LrclibResponse( | |
| 15 | val id: Long? = null, | |
| 16 | val trackName: String? = null, | |
| 17 | val artistName: String? = null, | |
| 18 | val albumName: String? = null, | |
| 19 | val duration: Double? = null, | |
| 20 | val instrumental: Boolean = false, | |
| 21 | val plainLyrics: String? = null, | |
| 22 | val syncedLyrics: String? = null, | |
| 23 | ) | |
| 24 | ||
| 25 | /** | |
| 26 | * One LRC line = timestamp + text. Timestamp is the start of the line; the line's end | |
| 27 | * is the next line's start (or the track's duration for the last one). | |
| 28 | */ | |
| 29 | data class LrcLine(val start: Duration, val text: String) { | |
| 30 | companion object { | |
| 31 | fun at(millis: Long, text: String) = LrcLine(millis.milliseconds, text) | |
| 32 | } | |
| 33 | } | |
| 34 | ||
| 35 | /** | |
| 36 | * Everything the lyrics UI needs for one track. Synced lyrics give us line-level | |
| 37 | * highlighting during playback; plain lyrics are shown as a static block. Both may | |
| 38 | * be present; if only plain is present we show that. | |
| 39 | */ | |
| 40 | sealed interface LyricsResult { | |
| 41 | /** Still fetching from LRCLIB (or from the on-disk cache). */ | |
| 42 | data object Loading : LyricsResult | |
| 43 | ||
| 44 | /** Track exists in LRCLIB and has lyrics. [synced] is non-empty when the track has | |
| 45 | * timestamped lyrics; [plain] is the plain-text version (may also be non-null). */ | |
| 46 | data class Loaded( | |
| 47 | val synced: List<LrcLine>, | |
| 48 | val plain: String?, | |
| 49 | ) : LyricsResult | |
| 50 | ||
| 51 | /** LRCLIB knows this track but the rightsholder marked it instrumental. */ | |
| 52 | data object Instrumental : LyricsResult | |
| 53 | ||
| 54 | /** LRCLIB has no record of this track. */ | |
| 55 | data object NotFound : LyricsResult | |
| 56 | ||
| 57 | /** External calls are disabled in privacy settings. UI surfaces this with a | |
| 58 | * pointer to the setting rather than pretending we searched and found nothing. */ | |
| 59 | data object PrivacyDisabled : LyricsResult | |
| 60 | ||
| 61 | /** Network / parse / anything else went sideways. */ | |
| 62 | data class Error(val message: String) : LyricsResult | |
| 63 | } |


