Always emit quality format updates with fallbacks

Send file/device audio-quality notifications even when stream metadata is incomplete by deriving sane defaults from the requested quality level, so controller quality icons stay in sync.
This commit is contained in:
joren
2026-03-31 23:33:56 +02:00
parent c3cad15719
commit 20d5ecf231

View File

@@ -418,6 +418,16 @@ fn msg_device_audio_quality_changed(
build_qconnect_message(27, &payload)
}
fn quality_fallback_audio_params(quality: u32) -> (u32, u32, u32) {
match quality {
1 => (44100, 16, 2), // MP3
2 => (44100, 16, 2), // CD
3 => (96000, 24, 2), // Hi-Res up to 96kHz
4 | 5 => (192000, 24, 2), // Hi-Res up to 192/384kHz (use 192kHz fallback)
_ => (44100, 16, 2),
}
}
/// RNDR_SRVR_VOLUME_MUTED (29): renderer confirms mute state.
fn msg_volume_muted(muted: bool) -> Vec<u8> {
let payload = encode_field_varint(1, if muted { 1 } else { 0 });
@@ -1117,24 +1127,26 @@ async fn run_connection(
duration_ms,
start_position_ms: requested_pos.unwrap_or(0),
});
if let (Some(sr), Some(bits)) = (stream_sr, stream_bits) {
let ch = stream_ch.unwrap_or(2).max(1);
let file_msg = msg_file_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
max_audio_quality as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &file_msg).into())).await?;
msg_id += 1;
let dev_msg = msg_device_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &dev_msg).into())).await?;
msg_id += 1;
}
let (fallback_sr, fallback_bits, fallback_ch) =
quality_fallback_audio_params(max_audio_quality);
let sr = stream_sr.unwrap_or(fallback_sr).max(1);
let bits = stream_bits.unwrap_or(fallback_bits).max(1);
let ch = stream_ch.unwrap_or(fallback_ch).max(1);
let file_msg = msg_file_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
max_audio_quality as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &file_msg).into())).await?;
msg_id += 1;
let dev_msg = msg_device_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &dev_msg).into())).await?;
msg_id += 1;
current_buffer_state = 2; // OK
}
Err(e) => {
@@ -1374,24 +1386,26 @@ async fn run_connection(
duration_ms,
start_position_ms: 0,
});
if let (Some(sr), Some(bits)) = (stream_sr, stream_bits) {
let ch = stream_ch.unwrap_or(2).max(1);
let file_msg = msg_file_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
*quality as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &file_msg).into())).await?;
msg_id += 1;
let dev_msg = msg_device_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &dev_msg).into())).await?;
msg_id += 1;
}
let (fallback_sr, fallback_bits, fallback_ch) =
quality_fallback_audio_params(*quality);
let sr = stream_sr.unwrap_or(fallback_sr).max(1);
let bits = stream_bits.unwrap_or(fallback_bits).max(1);
let ch = stream_ch.unwrap_or(fallback_ch).max(1);
let file_msg = msg_file_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
*quality as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &file_msg).into())).await?;
msg_id += 1;
let dev_msg = msg_device_audio_quality_changed(
sr as u64,
bits as u64,
ch as u64,
);
ws_tx.send(Message::Binary(build_payload_frame(msg_id, &dev_msg).into())).await?;
msg_id += 1;
// Re-emit quality confirmation after successful restart
// so controllers observing the currently active stream update promptly.
let confirm = msg_max_audio_quality_changed(*quality as u64, None);