/
/
/
1"""Tests for the rate at which stream output is handed to a player."""
2
3from __future__ import annotations
4
5from music_assistant.controllers.streams.constants import output_pacing_args
6
7
8def _value(args: list[str], key: str) -> float:
9 return float(args[args.index(key) + 1])
10
11
12def test_pacing_stays_ahead_of_playback() -> None:
13 """
14 At or below playback rate a player would underrun as soon as its burst ran out.
15
16 The ceiling may be lowered per player, but never to realtime or slower.
17 """
18 assert _value(output_pacing_args(), "-readrate") > 1.0
19 assert _value(output_pacing_args("gapless_burst"), "-readrate") > 1.0
20 assert _value(output_pacing_args("low_latency"), "-readrate") > 1.0
21
22
23def test_the_default_burst_stays_small() -> None:
24 """
25 The default burst covers a track start and nothing more.
26
27 A large burst flushes a realtime source's banked head start to the player,
28 leaving its end-of-track crossfade nothing to mix, and overruns players
29 with a small input buffer (Chromecast is the known case).
30 """
31 assert 1 <= _value(output_pacing_args(), "-readrate_initial_burst") <= 10
32
33
34def test_the_burst_profile_covers_gapless_prefetch() -> None:
35 """A player on the burst profile holds a large opening chunk before it plays gapless."""
36 assert _value(output_pacing_args("gapless_burst"), "-readrate_initial_burst") >= 10
37
38
39def test_the_low_latency_burst_stays_under_a_second() -> None:
40 """A live source's burst is listening delay: the player buffers it ahead of real time."""
41 assert _value(output_pacing_args("low_latency"), "-readrate_initial_burst") <= 1
42