feat: show top tracks on artist profile with play/shuffle

- Adds extra=topTracks to artist/page API request
- Embeds a List::Tracks widget at the top of ArtistView showing
  the artist's most popular tracks, with Play and Shuffle buttons
- Bubbles playTrackRequested through MainContent up to MainWindow
- Also adds the viz PCM ring buffer FFI infrastructure (for future
  spectrum widget) to the Rust backend

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
joren
2026-03-25 13:45:19 +01:00
parent 4ba6d00748
commit 6f11b364aa
13 changed files with 151 additions and 9 deletions

View File

@@ -590,6 +590,34 @@ pub unsafe extern "C" fn qobuz_backend_get_user(ptr: *mut Backend) {
});
}
// ---------- Visualizer PCM access ----------
/// Read up to `max_samples` f32 PCM values into `buf`.
/// Returns the number of samples actually read.
#[no_mangle]
pub unsafe extern "C" fn qobuz_backend_viz_read(
ptr: *mut Backend,
buf: *mut f32,
max_samples: u32,
) -> u32 {
let consumer = &(*ptr).0.player.status.viz_consumer;
let Ok(mut lock) = consumer.try_lock() else { return 0 };
let slice = std::slice::from_raw_parts_mut(buf, max_samples as usize);
rb::RbConsumer::read(&mut *lock, slice).unwrap_or(0) as u32
}
/// Returns current sample rate of the audio stream (0 if idle).
#[no_mangle]
pub unsafe extern "C" fn qobuz_backend_viz_sample_rate(ptr: *const Backend) -> u32 {
(*ptr).0.player.status.viz_sample_rate.load(std::sync::atomic::Ordering::Relaxed)
}
/// Returns current channel count (0 if idle).
#[no_mangle]
pub unsafe extern "C" fn qobuz_backend_viz_channels(ptr: *const Backend) -> u32 {
(*ptr).0.player.status.viz_channels.load(std::sync::atomic::Ordering::Relaxed)
}
// ---------- Playlist management ----------
pub const EV_PLAYLIST_CREATED: c_int = 20;