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:
3 files changed
+82
-63
No files matched your search
@@ -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;
|
||||
Reference in new issue
Block a user