mirror of
https://github.com/kilyabin/psysonic.git
synced 2026-07-22 14:35:41 +00:00
refactor(audio): lift PlayInput → BuiltSource dispatch into helper
Pull the 60-LOC match in audio_play that turned a PlayInput into a fully-wrapped rodio source out of audio_play and into play_input::build_source_from_play_input. Returns a small PlaybackSource struct holding both the BuiltSource and a `is_seekable` flag (only the Streaming variant is non-seekable). Behaviour preserved verbatim — same build_source / build_streaming_source calls, same target_rate=0 (no app-level resampling), same spawn_blocking decoder build for Seekable+Streaming, same error path (`audio:error` emit + propagate). audio/commands.rs: 642 → 600 LOC. The remaining audio_play body now reads top-to-bottom as: ghost guard → preview clear → gapless pre-chain check → bump generation → reuse-bytes prep → URL pin → format hint → **select_play_input** → gen check → loudness/RG via gain_inputs → crossfade prep → **build_source_from_play_input** → stream rate switching → sink construction + prefill → swap sink → progress task.
This commit is contained in:
@@ -10,11 +10,13 @@ use rodio::Player;
|
||||
use rodio::Source;
|
||||
use tauri::{AppHandle, Emitter, State};
|
||||
|
||||
use super::decode::{build_source, build_streaming_source, SizedDecoder};
|
||||
use super::decode::build_source;
|
||||
use super::engine::{audio_http_client, AudioEngine};
|
||||
use super::helpers::*;
|
||||
use super::ipc::{maybe_emit_normalization_state, NormalizationStatePayload};
|
||||
use super::play_input::{select_play_input, url_format_hint, PlayInput, PlayInputContext};
|
||||
use super::play_input::{
|
||||
build_source_from_play_input, select_play_input, url_format_hint, PlayInputContext,
|
||||
};
|
||||
use super::preview::preview_clear_for_new_main_playback;
|
||||
use super::progress_task::spawn_progress_task;
|
||||
use super::state::{ChainedInfo, PreloadedTrack};
|
||||
@@ -216,65 +218,22 @@ pub async fn audio_play(
|
||||
let done_flag = Arc::new(AtomicBool::new(false));
|
||||
// Reset sample counter for the new track.
|
||||
state.samples_played.store(0, Ordering::Relaxed);
|
||||
// Always 0 — no application-level resampling. Rodio handles conversion to
|
||||
// the output device rate internally; we let every track play at its native rate.
|
||||
let target_rate: u32 = 0;
|
||||
let mut new_is_seekable = true;
|
||||
let built = match play_input {
|
||||
PlayInput::Bytes(data) => build_source(
|
||||
data,
|
||||
duration_hint,
|
||||
state.eq_gains.clone(),
|
||||
state.eq_enabled.clone(),
|
||||
state.eq_pre_gain.clone(),
|
||||
done_flag.clone(),
|
||||
fade_in_dur,
|
||||
state.samples_played.clone(),
|
||||
target_rate,
|
||||
format_hint.as_deref(),
|
||||
hi_res_enabled,
|
||||
),
|
||||
PlayInput::SeekableMedia { reader, format_hint, tag } => {
|
||||
let decoder = tokio::task::spawn_blocking(move || {
|
||||
SizedDecoder::new_streaming(reader, format_hint.as_deref(), tag)
|
||||
})
|
||||
.await
|
||||
.map_err(|e| e.to_string())??;
|
||||
|
||||
build_streaming_source(
|
||||
decoder,
|
||||
duration_hint,
|
||||
state.eq_gains.clone(),
|
||||
state.eq_enabled.clone(),
|
||||
state.eq_pre_gain.clone(),
|
||||
done_flag.clone(),
|
||||
fade_in_dur,
|
||||
state.samples_played.clone(),
|
||||
target_rate,
|
||||
)
|
||||
}
|
||||
PlayInput::Streaming { reader, format_hint } => {
|
||||
new_is_seekable = false;
|
||||
let decoder = tokio::task::spawn_blocking(move || {
|
||||
SizedDecoder::new_streaming(Box::new(reader), format_hint.as_deref(), "track-stream")
|
||||
})
|
||||
.await
|
||||
.map_err(|e| e.to_string())??;
|
||||
|
||||
build_streaming_source(
|
||||
decoder,
|
||||
duration_hint,
|
||||
state.eq_gains.clone(),
|
||||
state.eq_enabled.clone(),
|
||||
state.eq_pre_gain.clone(),
|
||||
done_flag.clone(),
|
||||
fade_in_dur,
|
||||
state.samples_played.clone(),
|
||||
target_rate,
|
||||
)
|
||||
}
|
||||
}.map_err(|e| { app.emit("audio:error", &e).ok(); e })?;
|
||||
state.current_is_seekable.store(new_is_seekable, Ordering::SeqCst);
|
||||
let playback_source = build_source_from_play_input(
|
||||
play_input,
|
||||
&state,
|
||||
format_hint.as_deref(),
|
||||
done_flag.clone(),
|
||||
fade_in_dur,
|
||||
hi_res_enabled,
|
||||
duration_hint,
|
||||
)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
app.emit("audio:error", &e).ok();
|
||||
e
|
||||
})?;
|
||||
state.current_is_seekable.store(playback_source.is_seekable, Ordering::SeqCst);
|
||||
let built = playback_source.built;
|
||||
let source = built.source;
|
||||
let duration_secs = built.duration_secs;
|
||||
let output_rate = built.output_rate;
|
||||
|
||||
Reference in New Issue
Block a user