player: Separate append and append + play

This commit is contained in:
Elias Projahn 2025-03-02 15:47:05 +01:00
parent 8ff56d2878
commit 13fed08ebf
2 changed files with 62 additions and 40 deletions

View file

@ -3,6 +3,7 @@ use std::{
path::PathBuf, path::PathBuf,
}; };
use anyhow::{anyhow, Context, Result};
use fragile::Fragile; use fragile::Fragile;
use gstreamer_play::gst; use gstreamer_play::gst;
use gtk::{ use gtk::{
@ -33,7 +34,7 @@ mod imp {
pub active: Cell<bool>, pub active: Cell<bool>,
#[property(get, set)] #[property(get, set)]
pub playing: Cell<bool>, pub playing: Cell<bool>,
#[property(get, set = Self::set_program)] #[property(get, set)]
pub program: RefCell<Option<Program>>, pub program: RefCell<Option<Program>>,
#[property(get, construct_only)] #[property(get, construct_only)]
pub playlist: OnceCell<gio::ListStore>, pub playlist: OnceCell<gio::ListStore>,
@ -50,17 +51,6 @@ mod imp {
} }
impl Player { impl Player {
pub fn set_program(&self, program: &Program) {
self.program.replace(Some(program.to_owned()));
if !self.obj().active() {
self.obj().set_active(true);
self.obj().generate_items(program);
self.obj().set_current_index(0);
self.obj().play();
}
}
pub fn set_current_index(&self, index: u32) { pub fn set_current_index(&self, index: u32) {
let playlist = self.playlist.get().unwrap(); let playlist = self.playlist.get().unwrap();
@ -275,21 +265,10 @@ impl Player {
items items
} }
pub fn append(&self, items: Vec<PlaylistItem>) { /// Append playlist items to the playlist and return the index of the first newly added item.
let playlist = self.playlist(); /// An error will be returned if `items` is empty.
pub fn append(&self, items: Vec<PlaylistItem>) -> Result<u32> {
for item in items { if !items.is_empty() {
playlist.append(&item);
}
if !self.active() && playlist.n_items() > 0 {
self.set_active(true);
self.set_current_index(0);
self.play();
}
}
pub fn append_and_play(&self, items: Vec<PlaylistItem>) {
let playlist = self.playlist(); let playlist = self.playlist();
let first_index = playlist.n_items(); let first_index = playlist.n_items();
@ -297,11 +276,46 @@ impl Player {
playlist.append(&item); playlist.append(&item);
} }
if playlist.n_items() > first_index { // If playlist was empty:
if first_index == 0 {
self.set_active(true); self.set_active(true);
self.set_current_index(first_index); self.set_current_index(0);
}
Ok(first_index)
} else {
Err(anyhow!("At least one item has to be added to the playlist"))
}
}
/// Append playlist items to the playlist and immediately start playing the first newly added
/// item. This will discard the error if `items` is empty.
pub fn append_and_play(&self, items: Vec<PlaylistItem>) {
match self.append(items) {
Ok(index) => {
self.set_current_index(index);
self.play(); self.play();
} }
Err(err) => {
log::warn!("Failed to append and play items: {err}");
}
}
}
/// Generate new playlist items based on the current program and immediately start playing the
/// first new item.
pub fn play_from_program(&self) {
if let Some(program) = self.program() {
match self.generate_items(&program) {
Ok(index) => {
self.set_current_index(index);
self.play();
}
Err(err) => {
log::warn!("Failed to play from program: {err}");
}
}
}
} }
pub fn play_pause(&self) { pub fn play_pause(&self) {
@ -367,8 +381,10 @@ impl Player {
if self.current_index() < self.playlist().n_items() - 1 { if self.current_index() < self.playlist().n_items() - 1 {
self.set_current_index(self.current_index() + 1); self.set_current_index(self.current_index() + 1);
} else if let Some(program) = self.program() { } else if let Some(program) = self.program() {
self.generate_items(&program); match self.generate_items(&program) {
self.set_current_index(self.current_index() + 1); Ok(index) => self.set_current_index(index),
Err(err) => log::warn!("Failed to continue playing from program: {err}"),
}
} }
} }
@ -434,13 +450,17 @@ impl Player {
.expect("mpris should not be set"); .expect("mpris should not be set");
} }
fn generate_items(&self, program: &Program) { /// Generate new playlist items based on `program` and return the index of the first newly
if let Some(library) = self.library() { /// added item if successful.
// TODO: if program.play_full_recordings() { fn generate_items(&self, program: &Program) -> Result<u32> {
let recording = library.generate_recording(program).unwrap(); let recording = self
.library()
.unwrap()
.generate_recording(program)
.context("Failed to generate playlist items from program")?;
let playlist = self.recording_to_playlist(&recording); let playlist = self.recording_to_playlist(&recording);
self.append(playlist); self.append(playlist)
}
} }
fn library_path_to_file_path(&self, path: &str) -> String { fn library_path_to_file_path(&self, path: &str) -> String {

View file

@ -208,7 +208,7 @@ impl SearchPage {
fn play_button_clicked(&self) { fn play_button_clicked(&self) {
let program = Program::from_query(self.imp().query.get().unwrap().clone()); let program = Program::from_query(self.imp().query.get().unwrap().clone());
self.player().set_program(program); self.player().set_program(program);
self.player().play(); self.player().play_from_program();
} }
#[template_callback] #[template_callback]
@ -218,6 +218,7 @@ impl SearchPage {
if imp.programs_flow_box.is_visible() { if imp.programs_flow_box.is_visible() {
if let Some(program) = imp.programs.borrow().first().cloned() { if let Some(program) = imp.programs.borrow().first().cloned() {
self.player().set_program(program); self.player().set_program(program);
self.player().play_from_program();
} }
} else { } else {
let mut new_query = self.imp().query.get().unwrap().clone(); let mut new_query = self.imp().query.get().unwrap().clone();
@ -263,6 +264,7 @@ impl SearchPage {
fn program_selected(&self, tile: &gtk::FlowBoxChild) { fn program_selected(&self, tile: &gtk::FlowBoxChild) {
self.player() self.player()
.set_program(tile.downcast_ref::<ProgramTile>().unwrap().program()); .set_program(tile.downcast_ref::<ProgramTile>().unwrap().program());
self.player().play_from_program();
} }
#[template_callback] #[template_callback]