Merge refactor/internal/v2-cleanroom-final into pre-release
This commit is contained in:
18 files changed
+533
-27
No files matched your search
@@ -18,6 +18,43 @@ pub enum AudioDevicePresence {
|
||||
Inconclusive,
|
||||
}
|
||||
|
||||
/// Snapshot of which output device is currently in use and whether we're playing.
|
||||
/// Mirrors the legacy `AudioOutputStatus` shape so the frontend type is unchanged.
|
||||
#[derive(Debug, serde::Serialize)]
|
||||
pub struct V2AudioOutputStatus {
|
||||
pub device_name: Option<String>,
|
||||
pub is_playing: bool,
|
||||
}
|
||||
|
||||
/// Get current audio output status (V2 — reads from CoreBridge.player state).
|
||||
///
|
||||
/// Returns the device name actually in use by the audio thread plus whether
|
||||
/// playback is currently active. Used by AudioOutputBadges to render the
|
||||
/// active sink + DAC indicators in the now-playing bar.
|
||||
#[tauri::command]
|
||||
pub async fn v2_get_audio_output_status(
|
||||
bridge: State<'_, CoreBridgeState>,
|
||||
) -> Result<V2AudioOutputStatus, RuntimeError> {
|
||||
let bridge_guard = bridge.get().await;
|
||||
let player = bridge_guard.player();
|
||||
Ok(V2AudioOutputStatus {
|
||||
device_name: player.state.current_device(),
|
||||
is_playing: player.state.is_playing(),
|
||||
})
|
||||
}
|
||||
|
||||
/// List the available CPAL output sinks (V2).
|
||||
///
|
||||
/// Delegates enumeration to `qbz_audio::output_sinks::list_output_sinks`,
|
||||
/// which returns the same `{name, description, volume, is_default}` shape
|
||||
/// the legacy `get_pipewire_sinks` command returned. Used by the audio
|
||||
/// settings UI and AudioOutputBadges to populate the device picker and
|
||||
/// label the currently-routed sink.
|
||||
#[tauri::command]
|
||||
pub fn v2_get_pipewire_sinks() -> Result<Vec<qbz_audio::OutputSinkInfo>, RuntimeError> {
|
||||
qbz_audio::list_output_sinks().map_err(RuntimeError::Internal)
|
||||
}
|
||||
|
||||
/// Snapshot the presence of the user's currently-selected output
|
||||
/// device. Frontend calls this on demand (e.g. when a
|
||||
/// `audio:device-missing` toast button fires Retry).
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
use tauri::State;
|
||||
|
||||
use qbz_models::{
|
||||
Album, Artist, AwardPageData, DiscoverAlbum, DiscoverData, DiscoverPlaylistsResponse,
|
||||
DiscoverResponse, GenreInfo, LabelExploreResponse, LabelGetListResponse, LabelListPage,
|
||||
LabelPageData, LabelStoryResponse, PageArtistResponse, Playlist, PlaylistTag,
|
||||
SearchResultsPage, Track,
|
||||
Album, Artist, ArtistAlbums, AwardPageData, DiscoverAlbum, DiscoverData,
|
||||
DiscoverPlaylistsResponse, DiscoverResponse, GenreInfo, LabelExploreResponse,
|
||||
LabelGetListResponse, LabelListPage, LabelPageData, LabelStoryResponse, PageArtistResponse,
|
||||
Playlist, PlaylistTag, ReleasesGridResponse, SearchResultsPage, Track, TracksContainer,
|
||||
};
|
||||
|
||||
use crate::artist_blacklist::BlacklistState;
|
||||
@@ -399,6 +399,127 @@ pub async fn v2_get_artist_with_albums(
|
||||
.map_err(RuntimeError::Internal)
|
||||
}
|
||||
|
||||
/// Get an artist's albums collection (V2 - returns only the `ArtistAlbums` envelope).
|
||||
#[tauri::command]
|
||||
#[allow(non_snake_case)]
|
||||
pub async fn v2_get_artist_albums(
|
||||
artistId: u64,
|
||||
limit: Option<u32>,
|
||||
offset: Option<u32>,
|
||||
bridge: State<'_, CoreBridgeState>,
|
||||
runtime: State<'_, RuntimeManagerState>,
|
||||
) -> Result<ArtistAlbums, RuntimeError> {
|
||||
runtime
|
||||
.manager()
|
||||
.check_requirements(CommandRequirement::RequiresCoreBridgeAuth)
|
||||
.await?;
|
||||
|
||||
log::info!(
|
||||
"[V2] get_artist_albums: {} limit={:?} offset={:?}",
|
||||
artistId,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
let bridge = bridge.get().await;
|
||||
bridge
|
||||
.get_artist_albums(artistId, limit, offset)
|
||||
.await
|
||||
.map_err(RuntimeError::Internal)
|
||||
}
|
||||
|
||||
/// Get artist detail with albums, playlists and appears-on tracks (V2 - uses QbzCore).
|
||||
#[tauri::command]
|
||||
#[allow(non_snake_case)]
|
||||
pub async fn v2_get_artist_detail(
|
||||
artistId: u64,
|
||||
limit: Option<u32>,
|
||||
offset: Option<u32>,
|
||||
bridge: State<'_, CoreBridgeState>,
|
||||
runtime: State<'_, RuntimeManagerState>,
|
||||
) -> Result<Artist, RuntimeError> {
|
||||
runtime
|
||||
.manager()
|
||||
.check_requirements(CommandRequirement::RequiresCoreBridgeAuth)
|
||||
.await?;
|
||||
|
||||
let limit = limit.or(Some(1000));
|
||||
let offset = offset.or(Some(0));
|
||||
log::info!(
|
||||
"[V2] get_artist_detail: {} limit={:?} offset={:?}",
|
||||
artistId,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
let bridge = bridge.get().await;
|
||||
bridge
|
||||
.get_artist_detail(artistId, limit, offset)
|
||||
.await
|
||||
.map_err(RuntimeError::Internal)
|
||||
}
|
||||
|
||||
/// Get an artist's popular/top tracks (V2 - uses QbzCore).
|
||||
#[tauri::command]
|
||||
#[allow(non_snake_case)]
|
||||
pub async fn v2_get_artist_tracks(
|
||||
artistId: u64,
|
||||
limit: Option<u32>,
|
||||
offset: Option<u32>,
|
||||
bridge: State<'_, CoreBridgeState>,
|
||||
runtime: State<'_, RuntimeManagerState>,
|
||||
) -> Result<TracksContainer, RuntimeError> {
|
||||
runtime
|
||||
.manager()
|
||||
.check_requirements(CommandRequirement::RequiresCoreBridgeAuth)
|
||||
.await?;
|
||||
|
||||
let limit = limit.unwrap_or(50);
|
||||
let offset = offset.unwrap_or(0);
|
||||
log::info!(
|
||||
"[V2] get_artist_tracks: {} limit={} offset={}",
|
||||
artistId,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
let bridge = bridge.get().await;
|
||||
bridge
|
||||
.get_artist_tracks(artistId, limit, offset)
|
||||
.await
|
||||
.map_err(RuntimeError::Internal)
|
||||
}
|
||||
|
||||
/// Get an artist's releases grid paginated by release_type (V2 - uses QbzCore).
|
||||
#[tauri::command]
|
||||
#[allow(non_snake_case)]
|
||||
pub async fn v2_get_releases_grid(
|
||||
artistId: u64,
|
||||
releaseType: String,
|
||||
limit: Option<u32>,
|
||||
offset: Option<u32>,
|
||||
sort: Option<String>,
|
||||
bridge: State<'_, CoreBridgeState>,
|
||||
runtime: State<'_, RuntimeManagerState>,
|
||||
) -> Result<ReleasesGridResponse, RuntimeError> {
|
||||
runtime
|
||||
.manager()
|
||||
.check_requirements(CommandRequirement::RequiresCoreBridgeAuth)
|
||||
.await?;
|
||||
|
||||
let limit = limit.unwrap_or(25);
|
||||
let offset = offset.unwrap_or(0);
|
||||
log::info!(
|
||||
"[V2] get_releases_grid: {} type={} limit={} offset={}",
|
||||
artistId,
|
||||
releaseType,
|
||||
limit,
|
||||
offset
|
||||
);
|
||||
let bridge = bridge.get().await;
|
||||
bridge
|
||||
.get_releases_grid(artistId, &releaseType, limit, offset, sort.as_deref())
|
||||
.await
|
||||
.map_err(RuntimeError::Internal)
|
||||
}
|
||||
|
||||
/// Get label page (aggregated: top tracks, releases, playlists, artists)
|
||||
#[tauri::command]
|
||||
#[allow(non_snake_case)]
|
||||
|
||||
@@ -1299,6 +1299,13 @@ pub fn v2_set_qobuz_tos_accepted(
|
||||
crate::config::legal_settings::set_qobuz_tos_accepted(state, accepted)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_get_qobuz_tos_accepted(
|
||||
state: State<'_, crate::config::legal_settings::LegalSettingsState>,
|
||||
) -> Result<bool, String> {
|
||||
crate::config::legal_settings::get_qobuz_tos_accepted(state)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_set_update_check_on_launch(
|
||||
enabled: bool,
|
||||
@@ -1382,6 +1389,13 @@ pub fn v2_mark_flatpak_welcome_shown(
|
||||
crate::updates::mark_flatpak_welcome_shown(state)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_has_flatpak_welcome_been_shown(
|
||||
state: State<'_, crate::updates::UpdatesState>,
|
||||
) -> Result<bool, String> {
|
||||
crate::updates::has_flatpak_welcome_been_shown(state)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_get_backend_logs() -> Vec<String> {
|
||||
crate::logging::get_backend_logs()
|
||||
@@ -1469,6 +1483,16 @@ pub fn v2_is_running_in_flatpak() -> bool {
|
||||
crate::flatpak::is_running_in_flatpak()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_get_flatpak_help_text() -> String {
|
||||
crate::flatpak::get_flatpak_guidance()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_detect_desktop_theme() -> crate::desktop_theme::DesktopThemeInfo {
|
||||
crate::desktop_theme::detect_desktop_theme()
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_is_auto_update_eligible() -> bool {
|
||||
crate::updates::is_auto_update_eligible()
|
||||
@@ -1486,6 +1510,13 @@ pub fn v2_mark_snap_welcome_shown(
|
||||
crate::updates::mark_snap_welcome_shown(state)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub fn v2_has_snap_welcome_been_shown(
|
||||
state: State<'_, crate::updates::UpdatesState>,
|
||||
) -> Result<bool, String> {
|
||||
crate::updates::has_snap_welcome_been_shown(state)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn v2_detect_legacy_cached_files(
|
||||
cache_state: State<'_, OfflineCacheState>,
|
||||
|
||||
@@ -13,10 +13,11 @@ use tokio::sync::RwLock;
|
||||
use qbz_audio::{settings::AudioSettingsStore, AudioDiagnostic, AudioSettings, VisualizerTap};
|
||||
use qbz_core::QbzCore;
|
||||
use qbz_models::{
|
||||
Album, Artist, DiscoverAlbum, DiscoverData, DiscoverPlaylistsResponse, DiscoverResponse,
|
||||
GenreInfo, LabelExploreResponse, LabelGetListResponse, LabelListPage, LabelPageData,
|
||||
LabelStoryResponse, PageArtistResponse, Playlist, PlaylistTag, Quality,
|
||||
QueueState, QueueTrack, RepeatMode, SearchResultsPage, StreamUrl, Track, UserSession,
|
||||
Album, Artist, ArtistAlbums, DiscoverAlbum, DiscoverData, DiscoverPlaylistsResponse,
|
||||
DiscoverResponse, GenreInfo, LabelExploreResponse, LabelGetListResponse, LabelListPage,
|
||||
LabelPageData, LabelStoryResponse, PageArtistResponse, Playlist, PlaylistTag, Quality,
|
||||
QueueState, QueueTrack, ReleasesGridResponse, RepeatMode, SearchResultsPage, StreamUrl, Track,
|
||||
TracksContainer, UserSession,
|
||||
};
|
||||
use qbz_player::{PlaybackState, Player};
|
||||
|
||||
@@ -555,6 +556,60 @@ impl CoreBridge {
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get an artist's albums collection (paginated `ArtistAlbums` only).
|
||||
pub async fn get_artist_albums(
|
||||
&self,
|
||||
artist_id: u64,
|
||||
limit: Option<u32>,
|
||||
offset: Option<u32>,
|
||||
) -> Result<ArtistAlbums, String> {
|
||||
self.core
|
||||
.get_artist_albums(artist_id, limit, offset)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get artist detail (albums, playlists, appears-on tracks).
|
||||
pub async fn get_artist_detail(
|
||||
&self,
|
||||
artist_id: u64,
|
||||
limit: Option<u32>,
|
||||
offset: Option<u32>,
|
||||
) -> Result<Artist, String> {
|
||||
self.core
|
||||
.get_artist_detail(artist_id, limit, offset)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get an artist's popular/top tracks.
|
||||
pub async fn get_artist_tracks(
|
||||
&self,
|
||||
artist_id: u64,
|
||||
limit: u32,
|
||||
offset: u32,
|
||||
) -> Result<TracksContainer, String> {
|
||||
self.core
|
||||
.get_artist_tracks(artist_id, limit, offset)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get an artist's releases grid (paginated by `release_type`).
|
||||
pub async fn get_releases_grid(
|
||||
&self,
|
||||
artist_id: u64,
|
||||
release_type: &str,
|
||||
limit: u32,
|
||||
offset: u32,
|
||||
sort: Option<&str>,
|
||||
) -> Result<ReleasesGridResponse, String> {
|
||||
self.core
|
||||
.get_releases_grid(artist_id, release_type, limit, offset, sort)
|
||||
.await
|
||||
.map_err(|e| e.to_string())
|
||||
}
|
||||
|
||||
/// Get label page (aggregated: top tracks, releases, playlists, artists)
|
||||
pub async fn get_label_page(&self, label_id: u64) -> Result<LabelPageData, String> {
|
||||
self.core
|
||||
|
||||
@@ -1398,6 +1398,7 @@ pub fn run() {
|
||||
commands::playback::get_pipewire_sinks,
|
||||
commands::playback::get_audio_output_status,
|
||||
flatpak::get_flatpak_help_text,
|
||||
commands_v2::v2_get_flatpak_help_text,
|
||||
config::legal_settings::get_qobuz_tos_accepted,
|
||||
updates::has_flatpak_welcome_been_shown,
|
||||
updates::has_snap_welcome_been_shown,
|
||||
@@ -1579,6 +1580,7 @@ pub fn run() {
|
||||
commands_v2::v2_is_running_in_flatpak,
|
||||
commands_v2::v2_is_running_in_snap,
|
||||
commands_v2::v2_mark_snap_welcome_shown,
|
||||
commands_v2::v2_has_snap_welcome_been_shown,
|
||||
commands_v2::v2_detect_legacy_cached_files,
|
||||
commands_v2::v2_reco_log_event,
|
||||
commands_v2::v2_reco_train_scores,
|
||||
@@ -1625,6 +1627,7 @@ pub fn run() {
|
||||
commands_v2::v2_library_refresh_album_metadata_from_files,
|
||||
commands_v2::v2_factory_reset,
|
||||
commands_v2::v2_set_qobuz_tos_accepted,
|
||||
commands_v2::v2_get_qobuz_tos_accepted,
|
||||
commands_v2::v2_get_update_preferences,
|
||||
commands_v2::v2_get_current_version,
|
||||
commands_v2::v2_check_for_updates,
|
||||
@@ -1636,6 +1639,7 @@ pub fn run() {
|
||||
commands_v2::v2_has_whats_new_been_shown,
|
||||
commands_v2::v2_mark_whats_new_shown,
|
||||
commands_v2::v2_mark_flatpak_welcome_shown,
|
||||
commands_v2::v2_has_flatpak_welcome_been_shown,
|
||||
commands_v2::v2_is_auto_update_eligible,
|
||||
commands_v2::v2_get_backend_logs,
|
||||
commands_v2::v2_upload_logs_to_paste,
|
||||
@@ -1699,6 +1703,10 @@ pub fn run() {
|
||||
commands_v2::v2_get_artist_page,
|
||||
commands_v2::v2_get_similar_artists,
|
||||
commands_v2::v2_get_artist_with_albums,
|
||||
commands_v2::v2_get_artist_albums,
|
||||
commands_v2::v2_get_artist_detail,
|
||||
commands_v2::v2_get_artist_tracks,
|
||||
commands_v2::v2_get_releases_grid,
|
||||
commands_v2::v2_get_label_page,
|
||||
commands_v2::v2_get_label_explore,
|
||||
commands_v2::v2_get_label_albums,
|
||||
@@ -1723,6 +1731,8 @@ pub fn run() {
|
||||
commands_v2::v2_prefetch_track,
|
||||
commands_v2::v2_reinit_audio_device,
|
||||
commands_v2::v2_check_audio_device_presence,
|
||||
commands_v2::v2_get_audio_output_status,
|
||||
commands_v2::v2_get_pipewire_sinks,
|
||||
commands_v2::v2_get_audio_settings,
|
||||
commands_v2::v2_set_audio_output_device,
|
||||
commands_v2::v2_set_audio_exclusive_mode,
|
||||
@@ -1868,6 +1878,7 @@ pub fn run() {
|
||||
commands_v2::v2_clear_image_cache,
|
||||
// Desktop theme detection (KDE/Klassy → adaptive window controls)
|
||||
desktop_theme::detect_desktop_theme,
|
||||
commands_v2::v2_detect_desktop_theme,
|
||||
// Mixtapes & Collections
|
||||
commands_v2::v2_list_mixtape_collections,
|
||||
commands_v2::v2_get_mixtape_collection,
|
||||
|
||||
Reference in new issue
Block a user