refactor(qconnect): hoist queue-track / volume / loop-mode mappers into qconnect-app (slice 6)

Move the pure protocol mappers model_track_to_core_queue_track,
normalize_volume_to_fraction, qconnect_repeat_mode_from_loop_mode (+ the
QCONNECT_REMOTE_QUEUE_SOURCE tag) into qconnect-app/src/renderer.rs so the
renderer orchestration that calls them (hoisted in a later step) can live there
too. The src-tauri mod.rs re-exports them, so corebridge + tests compile
unchanged. The load-dedup predicates and audio-quality report helpers move
alongside their orchestration / report consumers in the next steps (cohesion +
avoids churning the AUDIO_QUALITY_* consts now).

src-tauri qconnect 42 green.

cc
This commit is contained in:
vicrodh committed 2026-06-02 17:16:41 -06:00
1 parent 1133b8b45d
commit 76a9169e2f
3 files changed
+82 -63

No files matched your search

+7 -63
View File
@@ -29,9 +29,13 @@ pub use session::{QconnectRendererInfo, QconnectSessionState};
pub(super) use session::QconnectSessionRendererState;
pub use types::*;
use qbz_models::{QueueTrack, RepeatMode, Track};
const QCONNECT_REMOTE_QUEUE_SOURCE: &str = "qobuz_connect_remote";
/// The renderer-side pure mappers now live in the frontend-agnostic
/// `qconnect_app::renderer` module (slice 6). Re-exported here so existing
/// `super::…` references inside this module compile unchanged.
pub(super) use qconnect_app::renderer::{
model_track_to_core_queue_track, normalize_volume_to_fraction,
qconnect_repeat_mode_from_loop_mode,
};
pub(super) const PLAYING_STATE_UNKNOWN: i32 = 0;
pub(super) const PLAYING_STATE_STOPPED: i32 = 1;
@@ -62,65 +66,5 @@ pub(super) fn qconnect_now_ms() -> u64 {
.unwrap_or(0)
}
pub(super) fn qconnect_repeat_mode_from_loop_mode(loop_mode: i32) -> Option<RepeatMode> {
// QConnect protocol loop mode values: 1 = off, 2 = repeat one, 3 = repeat all.
match loop_mode {
0 | 1 => Some(RepeatMode::Off),
2 => Some(RepeatMode::One),
3 => Some(RepeatMode::All),
_ => None,
}
}
pub(super) fn normalize_volume_to_fraction(volume: i32) -> f32 {
volume.clamp(0, 100) as f32 / 100.0
}
pub(super) fn model_track_to_core_queue_track(track: &Track) -> QueueTrack {
let artwork_url = track
.album
.as_ref()
.and_then(|album| album.image.best().cloned());
let artist = track
.performer
.as_ref()
.map(|performer| performer.name.clone())
.unwrap_or_else(|| "Unknown Artist".to_string());
let album = track
.album
.as_ref()
.map(|album| album.title.clone())
.unwrap_or_else(|| "Unknown Album".to_string());
let album_id = track.album.as_ref().and_then(|album| {
let trimmed = album.id.trim();
if trimmed.is_empty() {
None
} else {
Some(trimmed.to_string())
}
});
let artist_id = track.performer.as_ref().map(|performer| performer.id);
QueueTrack {
id: track.id,
title: track.title.clone(),
version: track.version.clone(),
artist,
album,
duration_secs: track.duration as u64,
artwork_url,
hires: track.hires,
bit_depth: track.maximum_bit_depth,
sample_rate: track.maximum_sampling_rate,
is_local: false,
album_id: album_id.clone(),
artist_id,
streamable: track.streamable,
source: Some(QCONNECT_REMOTE_QUEUE_SOURCE.to_string()),
parental_warning: track.parental_warning,
source_item_id_hint: album_id,
}
}
#[cfg(test)]
mod tests;