play next (#278)

* add play next feature

* fix play_next insertion order

* fix play_next call for playable

* document play_next shortcut + reformat

Co-authored-by: Henrik Friedrichsen <henrik@affekt.org>
This commit is contained in:
Moshe Sherman
2020-10-04 17:58:55 +03:00
committed by GitHub
parent 7bf0cac6c0
commit fc79889665
15 changed files with 97 additions and 4 deletions

View File

@@ -189,6 +189,16 @@ impl ListItem for Album {
}
}
fn play_next(&mut self, queue: Arc<Queue>) {
self.load_tracks(queue.get_spotify());
if let Some(tracks) = self.tracks.as_ref() {
for t in tracks.iter().rev() {
queue.insert_after_current(Playable::Track(t.clone()));
}
}
}
fn queue(&mut self, queue: Arc<Queue>) {
self.load_tracks(queue.get_spotify());

View File

@@ -185,6 +185,16 @@ impl ListItem for Artist {
}
}
fn play_next(&mut self, queue: Arc<Queue>) {
self.load_albums(queue.get_spotify());
if let Some(tracks) = self.tracks.as_ref() {
for t in tracks.iter().rev() {
queue.insert_after_current(Playable::Track(t.clone()));
}
}
}
fn queue(&mut self, queue: Arc<Queue>) {
self.load_albums(queue.get_spotify());

View File

@@ -83,6 +83,7 @@ pub enum Command {
Next,
Clear,
Queue,
PlayNext,
Play,
UpdateLibrary,
Save,
@@ -117,6 +118,7 @@ impl fmt::Display for Command {
Command::Next => "next".to_string(),
Command::Clear => "clear".to_string(),
Command::Queue => "queue".to_string(),
Command::PlayNext => "play next".to_string(),
Command::Play => "play".to_string(),
Command::UpdateLibrary => "update".to_string(),
Command::Save => "save".to_string(),
@@ -208,6 +210,7 @@ pub fn parse(input: &str) -> Option<Command> {
"previous" => Some(Command::Previous),
"next" => Some(Command::Next),
"clear" => Some(Command::Clear),
"playnext" => Some(Command::PlayNext),
"queue" => Some(Command::Queue),
"play" => Some(Command::Play),
"update" => Some(Command::UpdateLibrary),

View File

@@ -177,6 +177,7 @@ impl CommandManager {
| Command::Move(_, _)
| Command::Shift(_, _)
| Command::Play
| Command::PlayNext
| Command::Queue
| Command::Save
| Command::Delete
@@ -269,6 +270,7 @@ impl CommandManager {
kb.insert(">".into(), Command::Next);
kb.insert("c".into(), Command::Clear);
kb.insert("Space".into(), Command::Queue);
kb.insert("n".into(), Command::PlayNext);
kb.insert("Enter".into(), Command::Play);
kb.insert("s".into(), Command::Save);
kb.insert("Ctrl+s".into(), Command::SaveQueue);

View File

@@ -84,6 +84,10 @@ impl ListItem for Episode {
queue.play(index, true, false);
}
fn play_next(&mut self, queue: Arc<Queue>) {
queue.insert_after_current(Playable::Episode(self.clone()));
}
fn queue(&mut self, queue: Arc<Queue>) {
queue.append(Playable::Episode(self.clone()));
}

View File

@@ -88,6 +88,10 @@ impl ListItem for Playable {
self.as_listitem().play(queue)
}
fn play_next(&mut self, queue: Arc<Queue>) {
self.as_listitem().play_next(queue)
}
fn queue(&mut self, queue: Arc<Queue>) {
self.as_listitem().queue(queue)
}

View File

@@ -165,6 +165,16 @@ impl ListItem for Playlist {
}
}
fn play_next(&mut self, queue: Arc<Queue>) {
self.load_tracks(queue.get_spotify());
if let Some(tracks) = self.tracks.as_ref() {
for track in tracks.iter().rev() {
queue.insert_after_current(Playable::Track(track.clone()));
}
}
}
fn queue(&mut self, queue: Arc<Queue>) {
self.load_tracks(queue.get_spotify());

View File

@@ -96,6 +96,28 @@ impl Queue {
*self.current_track.read().unwrap()
}
pub fn insert_after_current(&self, track: Playable) {
if let Some(index) = self.get_current_index() {
let mut random_order = self.random_order.write().unwrap();
if let Some(order) = random_order.as_mut() {
let next_i = order.iter().position(|&i| i == index).unwrap();
// shift everything after the insertion in order
let size = order.len();
for i in 0..size {
if order[i] > index {
order[i] += 1;
}
}
// finally, add the next track index
order.insert(next_i + 1, index + 1);
}
let mut q = self.queue.write().unwrap();
q.insert(index + 1, track);
} else {
self.append(track);
}
}
pub fn append(&self, track: Playable) {
let mut random_order = self.random_order.write().unwrap();
if let Some(order) = random_order.as_mut() {

View File

@@ -124,6 +124,16 @@ impl ListItem for Show {
queue.play(index, true, true);
}
fn play_next(&mut self, queue: Arc<Queue>) {
self.load_episodes(queue.get_spotify());
if let Some(episodes) = self.episodes.as_ref() {
for ep in episodes.iter().rev() {
queue.insert_after_current(Playable::Episode(ep.clone()));
}
}
}
fn queue(&mut self, queue: Arc<Queue>) {
self.load_episodes(queue.get_spotify());

View File

@@ -46,12 +46,12 @@ use url::Url;
use core::task::Poll;
use std::pin::Pin;
use std::str::FromStr;
use std::sync::atomic::{AtomicU16, Ordering};
use std::sync::RwLock;
use std::thread;
use std::time::{Duration, SystemTime};
use std::{env, io};
use std::str::FromStr;
use crate::artist::Artist;
use crate::config;
@@ -401,7 +401,7 @@ impl Spotify {
) {
let bitrate_str = cfg.bitrate.unwrap_or(320).to_string();
let bitrate = Bitrate::from_str(&bitrate_str);
if bitrate.is_err(){
if bitrate.is_err() {
error!("invalid bitrate, will use 320 instead")
}

View File

@@ -154,7 +154,7 @@ impl ListItem for Track {
}
fn display_center(&self) -> String {
format!("{}", self.album)
self.album.to_string()
}
fn display_right(&self, library: Arc<Library>) -> String {
@@ -175,6 +175,10 @@ impl ListItem for Track {
queue.play(index, true, false);
}
fn play_next(&mut self, queue: Arc<Queue>) {
queue.insert_after_current(Playable::Track(self.clone()));
}
fn queue(&mut self, queue: Arc<Queue>) {
queue.append(Playable::Track(self.clone()));
}

View File

@@ -19,6 +19,7 @@ pub trait ListItem: Sync + Send + 'static {
fn display_right(&self, library: Arc<Library>) -> String;
fn play(&mut self, queue: Arc<Queue>);
fn queue(&mut self, queue: Arc<Queue>);
fn play_next(&mut self, queue: Arc<Queue>);
fn toggle_saved(&mut self, library: Arc<Library>);
fn save(&mut self, library: Arc<Library>);
fn unsave(&mut self, library: Arc<Library>);

View File

@@ -338,6 +338,15 @@ impl<I: ListItem + Clone> ViewExt for ListView<I> {
return Ok(CommandResult::Consumed(None));
}
Command::PlayNext => {
info!("played next");
let mut content = self.content.write().unwrap();
if let Some(item) = content.get_mut(self.selected) {
item.play_next(self.queue.clone());
}
return Ok(CommandResult::Consumed(None));
}
Command::Queue => {
let mut content = self.content.write().unwrap();
if let Some(item) = content.get_mut(self.selected) {

View File

@@ -95,6 +95,9 @@ impl ViewExt for QueueView {
self.queue.play(self.list.get_selected_index(), true, false);
return Ok(CommandResult::Consumed(None));
}
Command::PlayNext => {
return Ok(CommandResult::Ignored);
}
Command::Queue => {
return Ok(CommandResult::Ignored);
}