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

Renderer.kt

Each line, with the release that last changed it.

0.5.01package dev.stave.domain.renderer
2
3import dev.stave.domain.model.DidlItem
4import kotlinx.coroutines.flow.StateFlow
5import kotlin.time.Duration
6
7/**
8 * The thing that actually plays audio. v0.0.1 ships [dev.stave.playback.LocalRenderer] only.
9 * Cast (play flavor) and UPnP AV/OpenHome plug in behind this interface without UI changes.
10 */
11interface Renderer {
12 val state: StateFlow<PlaybackState>
13
14 suspend fun load(tracks: List<DidlItem.Track>, startIndex: Int = 0, autoplay: Boolean = true)
15 /** Append [tracks] to the end of the queue. If the queue is empty, they become the queue
16 * but are NOT auto-started — the user explicitly asked to queue, not to play. */
17 suspend fun enqueue(tracks: List<DidlItem.Track>)
18 /** Insert [tracks] immediately after the currently-playing track. If the queue is empty,
19 * the tracks become the queue AND playback begins. */
20 suspend fun playNext(tracks: List<DidlItem.Track>)
21 /** Jump directly to queue position [index] and start playing. Out-of-range is a no-op. */
22 suspend fun skipToQueueItem(index: Int)
23 /** Remove queue item at [index]. Removing the current item advances to the next; removing
24 * the last remaining item stops playback. */
25 suspend fun removeFromQueue(index: Int)
26 /** Reorder the queue by moving the item at [from] to position [to]. */
27 suspend fun moveInQueue(from: Int, to: Int)
28 /** Empty the queue and stop playback. */
29 suspend fun clearQueue()
30 suspend fun play()
31 suspend fun pause()
32 suspend fun stop()
33 suspend fun seekTo(position: Duration)
34 suspend fun next()
35 suspend fun previous()
36 suspend fun setVolume(volumePercent: Int)
37 /** Cycle repeat mode: OFF → ALL → ONE → OFF. */
38 suspend fun setRepeatMode(mode: RepeatMode)
39 /** Shuffle toggle. Turning on saves the current queue order; turning off restores it.
40 * Implementation is responsible for the save/restore — UI just flips the flag. */
41 suspend fun setShuffle(enabled: Boolean)
42}
43
44enum class RepeatMode { OFF, ALL, ONE }
45
46data class PlaybackState(
47 val current: DidlItem.Track? = null,
48 val queue: List<DidlItem.Track> = emptyList(),
49 val queueIndex: Int = -1,
50 val isPlaying: Boolean = false,
51 val isBuffering: Boolean = false,
52 /** True when the user has explicitly stopped (or nothing has ever been loaded).
53 * Distinguishes from paused-mid-track. Used by the NowPlayingBar visibility rule:
54 * the bar shows while playing OR paused, but hides while stopped even if the queue
55 * still has tracks loaded. */
56 val isStopped: Boolean = true,
57 val position: Duration = Duration.ZERO,
58 val duration: Duration = Duration.ZERO,
59 val volumePercent: Int = 100,
60 val repeatMode: RepeatMode = RepeatMode.OFF,
61 val shuffleEnabled: Boolean = false,
62 val error: String? = null,
63)