fix: previews follow the app volume; volume bar fill always accent

The preview backend never received a volume — clips played at the crate
default (0.7) regardless of the slider, even muted. The session now sets
the preview volume from the app store (mute → 0) before the first load and
mirrors it live while the modal is open; the debug overlay's PREVIEW row
exposes the backend's resting volume as proof.

The player-bar volume (and fallback seek) fill is now always the accent
color — matching the waveform scrubber's played region — stepping up to
the hover shade on hover instead of white-until-hover.

Also syncs package-lock to the soulstream name + alpha version.
This commit is contained in:
KeelrLeek committed 2026-07-23 16:25:42 -05:00
1 parent 793f78370e
commit 691fdcdc9a
10 files changed
+63 -10

No files matched your search

+5
View File
@@ -79,6 +79,8 @@ pub struct DebugStats {
pub normalization_enabled: bool,
pub target_lufs: f64,
pub loudness: Option<crate::loudness::CurrentTrack>,
/// The preview voices' resting volume (mirrors the app volume; 0 = muted).
pub preview_volume: Option<f32>,
}
#[tauri::command]
@@ -163,6 +165,9 @@ pub fn debug_stats(app: tauri::AppHandle, state: State<'_, DiagState>) -> DebugS
normalization_enabled,
target_lufs,
loudness,
preview_volume: app
.try_state::<crate::preview::PreviewState>()
.map(|s| crate::preview::target_volume(&s)),
}
}
+10 -3
View File
@@ -34,9 +34,10 @@ const PREVIEW_POSITION_INTERVAL: Duration = Duration::from_millis(100);
/// smooth — while each step is one cheap volume command to the sink.
const FADE_TICK: Duration = Duration::from_millis(15);
/// The preview voices' resting volume. The player crate's own default; the
/// renderer never sets a preview volume today, so fades ramp to this unless
/// a `volume` control changes the target.
/// The preview voices' resting volume before the renderer speaks. Since
/// 2026-07-23 the renderer mirrors the APP volume (mute → 0) via the
/// `volume` control at session open and live while the modal is up, so
/// this default only covers the instant before that first set arrives.
const DEFAULT_TARGET_VOL: f32 = 0.7;
/// Lease-lifetime constants, mirroring `src/lib/preview/lease.js` — the two
@@ -111,6 +112,12 @@ impl PreviewState {
}
}
/// The preview voices' current resting volume — diagnostics readout, so the
/// debug overlay can prove the renderer's app-volume mirror actually lands.
pub fn target_volume(state: &PreviewState) -> f32 {
state.target()
}
/// How long a crossfade waits for the incoming voice to become audible
/// before ramping anyway. Local-file decode start is tens of ms; hitting
/// this means the clip is broken (its error event fails the item) and the