forked from Keelrleek/SoulStream
CatalogTrack gains artist_id — Deezer sends it on every search row and it was simply unparsed — and rank, its 0-1,000,000 popularity figure. Together they let a listener count be resolved for the PERFORMING artist of each row rather than for the query's top artist, so a "panda bear" search shows Daft Punk's "Doin' it Right (feat. Panda Bear)" at its real 464,046. Resolution rides the existing deezer_linked_mbid -> lastfm_listener_ranks chain behind a new catalog_track_listeners command, deliberately kept separate from catalog_search: that one is typed against per keystroke and must never wait on MusicBrainz's 1 req/s gate. catalog_artist_profile backs the hero's middle third — MusicBrainz tags off the cached artist document plus one Last.fm artist.getinfo. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
151 lines
5.8 KiB
Rust
151 lines
5.8 KiB
Rust
mod commands;
|
|
mod config;
|
|
mod cover_logo;
|
|
mod diagnostics;
|
|
mod hero_crop;
|
|
mod hero_detector;
|
|
mod loudness;
|
|
mod pipeline;
|
|
mod playback;
|
|
mod preview;
|
|
mod state;
|
|
|
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
|
pub fn run() {
|
|
tauri::Builder::default()
|
|
.manage(state::AppState::default())
|
|
.setup(|app| {
|
|
app.handle().plugin(
|
|
tauri_plugin_log::Builder::default()
|
|
.level(log::LevelFilter::Info)
|
|
.clear_targets()
|
|
.target(tauri_plugin_log::Target::new(
|
|
tauri_plugin_log::TargetKind::Stdout,
|
|
))
|
|
.build(),
|
|
)?;
|
|
app.handle().plugin(tauri_plugin_dialog::init())?;
|
|
// Must run before anything touches the app-data dir.
|
|
config::migrate_app_data(app.handle());
|
|
// Prepare the small local vision model while the user is still on
|
|
// the app shell, so a first artist visit pays only warm inference.
|
|
hero_detector::warm_up(app.handle().clone());
|
|
playback::init(app.handle());
|
|
playback::prune_cache(app.handle());
|
|
preview::init(app.handle());
|
|
loudness::init(app.handle());
|
|
diagnostics::init(app.handle());
|
|
if let Err(e) = pipeline::init(app.handle()) {
|
|
log::error!("library init failed: {e}");
|
|
}
|
|
Ok(())
|
|
})
|
|
.invoke_handler(tauri::generate_handler![
|
|
commands::app_status,
|
|
commands::excluded_search_phrases,
|
|
commands::get_credentials,
|
|
commands::connect_and_login,
|
|
commands::connect_stored,
|
|
commands::disconnect,
|
|
commands::start_search,
|
|
commands::stop_search,
|
|
commands::download_file,
|
|
commands::copy_stream_to_folder,
|
|
commands::save_to_library,
|
|
commands::cancel_download,
|
|
commands::show_in_folder,
|
|
commands::refresh_artist_art,
|
|
commands::play_stream,
|
|
commands::play_local,
|
|
commands::preload_local,
|
|
commands::player_control,
|
|
commands::player_state,
|
|
commands::waveform,
|
|
commands::library_albums,
|
|
commands::album_tracks,
|
|
commands::album_art,
|
|
commands::refresh_album_art,
|
|
commands::refresh_all_album_art,
|
|
commands::get_settings,
|
|
commands::set_settings,
|
|
commands::forget_credentials,
|
|
commands::pick_folder,
|
|
commands::open_external,
|
|
commands::record_play,
|
|
commands::add_play_seconds,
|
|
commands::artist_play_stats,
|
|
commands::recent_albums,
|
|
commands::clear_play_history,
|
|
commands::play_row_count,
|
|
commands::list_playlists,
|
|
commands::create_playlist,
|
|
commands::delete_playlist,
|
|
commands::playlist_tracks,
|
|
commands::add_to_playlist,
|
|
commands::remove_from_playlist,
|
|
commands::catalog_search,
|
|
commands::catalog_artist,
|
|
commands::catalog_artist_art,
|
|
commands::catalog_artist_logos,
|
|
commands::catalog_artist_identity,
|
|
commands::catalog_artist_socials,
|
|
commands::remember_fused_artist_portrait,
|
|
commands::catalog_artist_bio,
|
|
commands::catalog_cached_cover_logo,
|
|
commands::catalog_cover_logo,
|
|
commands::catalog_cover_logo_debug,
|
|
commands::catalog_ocr_experiment,
|
|
commands::catalog_artist_hero_seed,
|
|
commands::catalog_artist_overview,
|
|
commands::catalog_artist_popular,
|
|
commands::pick_artist_hero,
|
|
commands::clear_artist_hero,
|
|
commands::catalog_related,
|
|
commands::catalog_track_listeners,
|
|
commands::catalog_artist_profile,
|
|
commands::catalog_album,
|
|
commands::catalog_album_info,
|
|
commands::catalog_art,
|
|
commands::catalog_cover,
|
|
commands::invalidate_catalog_cover,
|
|
commands::catalog_hero_preview,
|
|
commands::catalog_hero_gpu_source,
|
|
commands::catalog_cached_hero_art,
|
|
commands::catalog_hero_art,
|
|
commands::preload_stream,
|
|
commands::preload_cached_stream,
|
|
commands::stream_waveform,
|
|
preview::preview_resolve,
|
|
preview::preview_prewarm,
|
|
preview::preview_load,
|
|
preview::preview_control,
|
|
preview::preview_dispose,
|
|
preview::player_pause_acked,
|
|
preview::player_fade_pause_acked,
|
|
preview::player_fade_resume,
|
|
diagnostics::debug_stats,
|
|
])
|
|
.run({
|
|
#[allow(unused_mut)]
|
|
let mut context = tauri::generate_context!();
|
|
// Debug builds expose CDP on 9222 for instrumentation (see HANDOFF.md).
|
|
// wry always sets AdditionalBrowserArguments programmatically, so the
|
|
// WEBVIEW2_ADDITIONAL_BROWSER_ARGUMENTS env var is ignored; the flag has
|
|
// to go through the window config. Explicit args replace wry's defaults,
|
|
// so those are restated here.
|
|
#[cfg(debug_assertions)]
|
|
{
|
|
for window in &mut context.config_mut().app.windows {
|
|
window.additional_browser_args = Some(
|
|
"--disable-features=msWebOOUI,msPdfOOUI,msSmartScreenProtection \
|
|
--autoplay-policy=no-user-gesture-required \
|
|
--remote-debugging-port=9222"
|
|
.into(),
|
|
);
|
|
}
|
|
}
|
|
context
|
|
})
|
|
.expect("error while running tauri application");
|
|
}
|