add play-all
This commit is contained in:
@@ -132,6 +132,7 @@ fn handle(
|
||||
"POST /del {query}",
|
||||
"POST /init {song} (async, returns job id, status 202)",
|
||||
"POST /init/batch {songs:[...]}",
|
||||
"POST /play/all",
|
||||
"POST /skip",
|
||||
"POST /pause",
|
||||
"POST /resume",
|
||||
@@ -412,6 +413,14 @@ fn handle(
|
||||
Err(e) => error_response(e),
|
||||
},
|
||||
|
||||
Route::PlayAll => match state.play_all_random() {
|
||||
Ok(len) => json_response(
|
||||
200,
|
||||
&serde_json::json!({ "queued": len }),
|
||||
),
|
||||
Err(e) => error_response(e),
|
||||
},
|
||||
|
||||
Route::Skip => {
|
||||
state.audio_handle.send(AudioCmd::Stop);
|
||||
// Always clear current — a skip is an explicit decision to
|
||||
@@ -688,6 +697,7 @@ enum Route {
|
||||
Del,
|
||||
InitAsync,
|
||||
InitBatch,
|
||||
PlayAll,
|
||||
Skip,
|
||||
QueueShuffle,
|
||||
QueueClear,
|
||||
@@ -731,6 +741,7 @@ fn route_for(method: &Method, path: &str) -> Route {
|
||||
(Method::Post, "/del") => Route::Del,
|
||||
(Method::Post, "/init") => Route::InitAsync,
|
||||
(Method::Post, "/init/batch") => Route::InitBatch,
|
||||
(Method::Post, "/play/all") => Route::PlayAll,
|
||||
(Method::Post, "/skip") => Route::Skip,
|
||||
(Method::Post, "/queue/shuffle") => Route::QueueShuffle,
|
||||
(Method::Post, "/queue/clear") => Route::QueueClear,
|
||||
|
||||
@@ -450,6 +450,40 @@ impl DaemonState {
|
||||
Ok(song)
|
||||
}
|
||||
|
||||
/// Replace the queue with a shuffled copy of the entire library.
|
||||
///
|
||||
/// Mirrors `/playlists/{name}/play`: clear the queue, re-insert in
|
||||
/// random order, persist to the DB, and refresh `cycle_snapshot` so
|
||||
/// `RepeatMode::All` keeps looping over the same shuffle. The daemon
|
||||
/// tick loop picks up the new head of queue and starts playback
|
||||
/// automatically once the audio engine is idle (same model as
|
||||
/// `/play`); calling `play_all_random` while a song is playing only
|
||||
/// queues the rest of the library behind the current track.
|
||||
///
|
||||
/// Returns the number of songs queued. An empty library surfaces
|
||||
/// `"library is empty"` to the HTTP layer so the GUI/CLI can render
|
||||
/// a useful toast instead of silently doing nothing.
|
||||
pub fn play_all_random(&mut self) -> Result<usize, String> {
|
||||
let mut shuffled = self.all_songs();
|
||||
if shuffled.is_empty() {
|
||||
return Err("library is empty".to_string());
|
||||
}
|
||||
use rand::seq::SliceRandom;
|
||||
shuffled.shuffle(&mut rand::thread_rng());
|
||||
{
|
||||
let conn = self.lock_conn();
|
||||
Self::queue_clear_db(&conn).map_err(|e| e.to_string())?;
|
||||
for s in &shuffled {
|
||||
Self::queue_append_db(&conn, s.id).map_err(|e| e.to_string())?;
|
||||
}
|
||||
}
|
||||
let len = shuffled.len();
|
||||
self.queue = shuffled;
|
||||
self.cycle_snapshot = self.queue.clone();
|
||||
info!("Play-all: queued {len} songs in random order");
|
||||
Ok(len)
|
||||
}
|
||||
|
||||
/// In-place shuffle of the current queue.
|
||||
pub fn shuffle_queue(&mut self) -> Result<(), String> {
|
||||
if self.queue.len() < 2 {
|
||||
|
||||
Reference in New Issue
Block a user