EARHORNMUSIC UPnP · Android TV · Phones · Android Auto · GNU/Linux
Release 0.5.0

LyricsData.kt

Each line, with the release that last changed it.

0.5.01package dev.stave.lyrics
2
3import kotlinx.serialization.Serializable
4import kotlin.time.Duration
5import 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
14data 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 */
29data 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 */
40sealed 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}