cbd-web: end the volume slider where the server clamps
The slider was `max="1.5"` while the engine clamps to 1.1, so its right third was unreachable — the fill stopped at 73% of the track and the rest stayed empty however far the thumb was dragged. `max` is now a named `MAX_VOLUME` that has to track `PlayerEngine::set_volume`'s clamp. It cannot be imported: `audio-player` is native-only and this client is wasm, so a comment on each end keeps the pair honest. Raising the engine clamp was the alternative, but 1.1 is deliberate headroom and more gain risks clipping, so the slider moved. The tooltip now reports the level as a percentage too — the web counterpart of the TUI's `Volume: 85%`. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
034737d14f
commit
1db88e0f5a
|
|
@ -21,6 +21,13 @@ use crate::state::{
|
||||||
|
|
||||||
const VOLUME_STEP: f32 = 0.1;
|
const VOLUME_STEP: f32 = 0.1;
|
||||||
|
|
||||||
|
/// The highest level the server will accept — it clamps to this in
|
||||||
|
/// `PlayerEngine::set_volume`, and now reports back the level it took, so a
|
||||||
|
/// slider that ran past this point had a dead stretch at its right end that
|
||||||
|
/// filled and then sprang back. Must track the engine's clamp; the audio
|
||||||
|
/// crate is native-only, so the value cannot be imported from it.
|
||||||
|
const MAX_VOLUME: f32 = 1.1;
|
||||||
|
|
||||||
/// How far one seek press moves the playing position, in milliseconds — the
|
/// How far one seek press moves the playing position, in milliseconds — the
|
||||||
/// unit the wire speaks (architecture/seek.md D3). The step lives in the
|
/// unit the wire speaks (architecture/seek.md D3). The step lives in the
|
||||||
/// client; the server only ever receives an offset and applies it to the live
|
/// client; the server only ever receives an offset and applies it to the live
|
||||||
|
|
@ -1266,10 +1273,10 @@ fn Transport(store: Store) -> impl IntoView {
|
||||||
<input
|
<input
|
||||||
type="range"
|
type="range"
|
||||||
min="0"
|
min="0"
|
||||||
max="1.5"
|
max=MAX_VOLUME.to_string()
|
||||||
step="0.05"
|
step="0.05"
|
||||||
prop:value=move || store.volume.get().to_string()
|
prop:value=move || store.volume.get().to_string()
|
||||||
title="volume (J/K)"
|
title=move || format!("volume {:.0}% (J/K)", store.volume.get() * 100.0)
|
||||||
on:input=on_volume
|
on:input=on_volume
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,13 @@ the queue toolbar shows how many entries are waiting). Seek is there too —
|
||||||
`,` and `.` move 15 seconds back and forward (`<` and `>` skip a whole
|
`,` and `.` move 15 seconds back and forward (`<` and `>` skip a whole
|
||||||
track), as do the `⏪`/`⏩`
|
track), as do the `⏪`/`⏩`
|
||||||
buttons in
|
buttons in
|
||||||
the transport bar. The `/` live filter is TUI-only for now.
|
the transport bar, and the progress bar is clickable — a click seeks to
|
||||||
|
that point in the track. The `/` live filter is TUI-only for now.
|
||||||
|
|
||||||
|
The volume slider spans the server's whole accepted range, ending at 110%
|
||||||
|
— the server clamps there, so a slider that went further would have a
|
||||||
|
dead stretch at its right end. Its tooltip reports the current level as a
|
||||||
|
percentage; the TUI shows the same figure in its now-playing pane.
|
||||||
|
|
||||||
## How it is served
|
## How it is served
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1587,3 +1587,23 @@ Not covered by a test: `Player::new` is only reachable through `Playback::new`,
|
||||||
and the engine thread opens an audio device, so there is no device-free way to
|
and the engine thread opens an audio device, so there is no device-free way to
|
||||||
construct one here. `is_muted()` (a new engine getter — only `toggle_mute`
|
construct one here. `is_muted()` (a new engine getter — only `toggle_mute`
|
||||||
existed, which cannot be used to *ask*) is likewise verified by reading.
|
existed, which cannot be used to *ask*) is likewise verified by reading.
|
||||||
|
|
||||||
|
## Web volume slider bound (2026-07-27)
|
||||||
|
|
||||||
|
The slider was `max="1.5"` while the engine clamps to `1.1`, so its right third
|
||||||
|
was unreachable: the fill stopped at 73% of the track and the rest stayed empty
|
||||||
|
no matter how far the thumb was dragged. Fixing the server to broadcast the
|
||||||
|
level it actually took (previous entry) is what made this visible — the thumb
|
||||||
|
now springs back from that dead stretch instead of sitting where it was
|
||||||
|
dropped.
|
||||||
|
|
||||||
|
`max` is now a named `MAX_VOLUME` constant that has to track
|
||||||
|
`PlayerEngine::set_volume`'s clamp. It cannot be imported: `audio-player` is
|
||||||
|
native-only and the web client is wasm, so the two ends of this pair are kept
|
||||||
|
in agreement by the comment on each.
|
||||||
|
|
||||||
|
Raising the engine's clamp instead was the alternative — 1.1 is deliberate
|
||||||
|
headroom, and more gain risks clipping — so the slider was the side to move.
|
||||||
|
|
||||||
|
The tooltip also reports the level as a percentage now, which is the web
|
||||||
|
counterpart of the TUI's `Volume: 85%`.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue