mirror of
https://github.com/johrpan/musicus.git
synced 2025-10-26 19:57:25 +01:00
Keep playing random tracks after the playlist ends
This commit is contained in:
parent
42d1d047e3
commit
487fd0a048
3 changed files with 35 additions and 7 deletions
|
|
@ -1,5 +1,6 @@
|
||||||
use crate::{Backend, BackendState, Player, Result};
|
use crate::{Backend, BackendState, Player, Result};
|
||||||
use gio::prelude::*;
|
use gio::prelude::*;
|
||||||
|
use glib::clone;
|
||||||
use log::warn;
|
use log::warn;
|
||||||
use musicus_database::Database;
|
use musicus_database::Database;
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
@ -41,10 +42,16 @@ impl Backend {
|
||||||
let mut db_path = path.clone();
|
let mut db_path = path.clone();
|
||||||
db_path.push("musicus.db");
|
db_path.push("musicus.db");
|
||||||
|
|
||||||
let database = Database::new(db_path.to_str().unwrap())?;
|
let database = Rc::new(Database::new(db_path.to_str().unwrap())?);
|
||||||
self.database.replace(Some(Rc::new(database)));
|
self.database.replace(Some(Rc::clone(&database)));
|
||||||
|
|
||||||
let player = Player::new(path);
|
let player = Player::new(path);
|
||||||
|
|
||||||
|
// Keep adding random tracks in case the playlist ends.
|
||||||
|
player.set_generate_next_track_cb(clone!(@weak database => @default-panic, move || {
|
||||||
|
database.random_track().unwrap()
|
||||||
|
}));
|
||||||
|
|
||||||
self.player.replace(Some(player));
|
self.player.replace(Some(player));
|
||||||
|
|
||||||
self.set_state(BackendState::Ready);
|
self.set_state(BackendState::Ready);
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ pub struct Player {
|
||||||
current_track: Cell<Option<usize>>,
|
current_track: Cell<Option<usize>>,
|
||||||
playing: Cell<bool>,
|
playing: Cell<bool>,
|
||||||
duration: Cell<u64>,
|
duration: Cell<u64>,
|
||||||
|
generate_next_track_cb: RefCell<Option<Box<dyn Fn() -> Track>>>,
|
||||||
playlist_cbs: RefCell<Vec<Box<dyn Fn(Vec<Track>)>>>,
|
playlist_cbs: RefCell<Vec<Box<dyn Fn(Vec<Track>)>>>,
|
||||||
track_cbs: RefCell<Vec<Box<dyn Fn(usize)>>>,
|
track_cbs: RefCell<Vec<Box<dyn Fn(usize)>>>,
|
||||||
duration_cbs: RefCell<Vec<Box<dyn Fn(u64)>>>,
|
duration_cbs: RefCell<Vec<Box<dyn Fn(u64)>>>,
|
||||||
|
|
@ -44,6 +45,7 @@ impl Player {
|
||||||
current_track: Cell::new(None),
|
current_track: Cell::new(None),
|
||||||
playing: Cell::new(false),
|
playing: Cell::new(false),
|
||||||
duration: Cell::new(0),
|
duration: Cell::new(0),
|
||||||
|
generate_next_track_cb: RefCell::new(None),
|
||||||
playlist_cbs: RefCell::new(Vec::new()),
|
playlist_cbs: RefCell::new(Vec::new()),
|
||||||
track_cbs: RefCell::new(Vec::new()),
|
track_cbs: RefCell::new(Vec::new()),
|
||||||
duration_cbs: RefCell::new(Vec::new()),
|
duration_cbs: RefCell::new(Vec::new()),
|
||||||
|
|
@ -144,6 +146,10 @@ impl Player {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_generate_next_track_cb<F: Fn() -> Track + 'static>(&self, cb: F) {
|
||||||
|
self.generate_next_track_cb.replace(Some(Box::new(cb)));
|
||||||
|
}
|
||||||
|
|
||||||
pub fn add_playlist_cb<F: Fn(Vec<Track>) + 'static>(&self, cb: F) {
|
pub fn add_playlist_cb<F: Fn(Vec<Track>) + 'static>(&self, cb: F) {
|
||||||
self.playlist_cbs.borrow_mut().push(Box::new(cb));
|
self.playlist_cbs.borrow_mut().push(Box::new(cb));
|
||||||
}
|
}
|
||||||
|
|
@ -270,7 +276,9 @@ impl Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn has_next(&self) -> bool {
|
pub fn has_next(&self) -> bool {
|
||||||
if let Some(current_track) = self.current_track.get() {
|
if self.generate_next_track_cb.borrow().is_some() {
|
||||||
|
true
|
||||||
|
} else if let Some(current_track) = self.current_track.get() {
|
||||||
let playlist = self.playlist.borrow();
|
let playlist = self.playlist.borrow();
|
||||||
current_track + 1 < playlist.len()
|
current_track + 1 < playlist.len()
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -285,9 +293,11 @@ impl Player {
|
||||||
))
|
))
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let playlist = self.playlist.borrow();
|
if current_track + 1 < self.playlist.borrow().len() {
|
||||||
|
current_track += 1;
|
||||||
if current_track + 1 < playlist.len() {
|
} else if let Some(cb) = &*self.generate_next_track_cb.borrow() {
|
||||||
|
let new_track = cb();
|
||||||
|
self.add_item(new_track)?;
|
||||||
current_track += 1;
|
current_track += 1;
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::Other(String::from("No existing next track.")));
|
return Err(Error::Other(String::from("No existing next track.")));
|
||||||
|
|
|
||||||
|
|
@ -49,7 +49,7 @@ struct MediumRow {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Table data for a [`Track`].
|
/// Table data for a [`Track`].
|
||||||
#[derive(Insertable, Queryable, Debug, Clone)]
|
#[derive(Insertable, Queryable, QueryableByName, Debug, Clone)]
|
||||||
#[table_name = "tracks"]
|
#[table_name = "tracks"]
|
||||||
struct TrackRow {
|
struct TrackRow {
|
||||||
pub id: String,
|
pub id: String,
|
||||||
|
|
@ -224,6 +224,17 @@ impl Database {
|
||||||
Ok(tracks)
|
Ok(tracks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get a random track from the database.
|
||||||
|
pub fn random_track(&self) -> Result<Track> {
|
||||||
|
let row = diesel::sql_query("SELECT * FROM tracks ORDER BY RANDOM() LIMIT 1")
|
||||||
|
.load::<TrackRow>(&self.connection)?
|
||||||
|
.into_iter()
|
||||||
|
.next()
|
||||||
|
.ok_or(Error::Other("Failed to generate random track"))?;
|
||||||
|
|
||||||
|
self.get_track_from_row(row)
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve all available information on a medium from related tables.
|
/// Retrieve all available information on a medium from related tables.
|
||||||
fn get_medium_data(&self, row: MediumRow) -> Result<Medium> {
|
fn get_medium_data(&self, row: MediumRow) -> Result<Medium> {
|
||||||
let track_rows = tracks::table
|
let track_rows = tracks::table
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue