mirror of
https://github.com/Dummi26/musicdb.git
synced 2025-12-15 04:16:16 +01:00
add reshuffling and update queue ui in client
This commit is contained in:
@@ -89,7 +89,7 @@ impl CacheManager {
|
||||
let mut queue = db.queue.clone();
|
||||
|
||||
let queue_current_song = queue.get_current_song().copied();
|
||||
queue.advance_index_inner();
|
||||
queue.advance_index_inner(&mut Vec::new(), &mut Vec::new());
|
||||
let queue_next_song = queue.get_current_song().copied();
|
||||
|
||||
let mut ids_to_cache = queue_current_song
|
||||
@@ -98,7 +98,7 @@ impl CacheManager {
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
for _ in 2..songs_to_cache {
|
||||
queue.advance_index_inner();
|
||||
queue.advance_index_inner(&mut Vec::new(), &mut Vec::new());
|
||||
if let Some(id) = queue.get_current_song() {
|
||||
if !ids_to_cache.contains(id) {
|
||||
ids_to_cache.push(*id);
|
||||
|
||||
@@ -569,7 +569,7 @@ impl Database {
|
||||
// some commands shouldn't be broadcast. these will broadcast a different command in their specific implementation.
|
||||
match &action {
|
||||
// Will broadcast `QueueSetShuffle`
|
||||
Action::QueueShuffle(_) => (),
|
||||
Action::QueueShuffle(_, _) => (),
|
||||
Action::NextSong if self.queue.is_almost_empty() => (),
|
||||
Action::Pause if !self.playing => (),
|
||||
Action::Resume if self.playing => (),
|
||||
@@ -679,26 +679,31 @@ impl Database {
|
||||
}
|
||||
}
|
||||
Action::QueueGoto(index) => Queue::set_index_db(self, &index),
|
||||
Action::QueueShuffle(path) => {
|
||||
if let Some(elem) = self.queue.get_item_at_index_mut(&path, 0) {
|
||||
if let QueueContent::Folder(QueueFolder {
|
||||
index: _,
|
||||
content,
|
||||
name: _,
|
||||
order: _,
|
||||
}) = elem.content_mut()
|
||||
{
|
||||
let mut ord: Vec<usize> = (0..content.len()).collect();
|
||||
ord.shuffle(&mut thread_rng());
|
||||
self.apply_action_unchecked_seq(Action::QueueSetShuffle(path, ord), client);
|
||||
Action::QueueShuffle(path, set_index) => {
|
||||
if !self.is_client() {
|
||||
if let Some(elem) = self.queue.get_item_at_index_mut(&path, 0) {
|
||||
if let QueueContent::Folder(QueueFolder {
|
||||
index: _,
|
||||
content,
|
||||
name: _,
|
||||
order: _,
|
||||
}) = elem.content_mut()
|
||||
{
|
||||
let mut ord: Vec<usize> = (0..content.len()).collect();
|
||||
ord.shuffle(&mut thread_rng());
|
||||
self.apply_action_unchecked_seq(
|
||||
Action::QueueSetShuffle(path, ord, set_index),
|
||||
client,
|
||||
);
|
||||
} else {
|
||||
eprintln!("(QueueShuffle) QueueElement at {path:?} not a folder!");
|
||||
}
|
||||
} else {
|
||||
eprintln!("(QueueShuffle) QueueElement at {path:?} not a folder!");
|
||||
eprintln!("(QueueShuffle) No QueueElement at {path:?}");
|
||||
}
|
||||
} else {
|
||||
eprintln!("(QueueShuffle) No QueueElement at {path:?}");
|
||||
}
|
||||
}
|
||||
Action::QueueSetShuffle(path, ord) => {
|
||||
Action::QueueSetShuffle(path, ord, set_index) => {
|
||||
if let Some(elem) = self.queue.get_item_at_index_mut(&path, 0) {
|
||||
if let QueueContent::Folder(QueueFolder {
|
||||
index,
|
||||
@@ -708,8 +713,14 @@ impl Database {
|
||||
}) = elem.content_mut()
|
||||
{
|
||||
if ord.len() == content.len() {
|
||||
if let Some(ni) = ord.iter().position(|v| *v == *index) {
|
||||
*index = ni;
|
||||
match set_index {
|
||||
0 => {}
|
||||
1 => {
|
||||
if let Some(ni) = ord.iter().position(|v| *v == *index) {
|
||||
*index = ni;
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
*order = Some(ord);
|
||||
} else {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use std::ops::AddAssign;
|
||||
|
||||
use crate::load::ToFromBytes;
|
||||
use crate::{load::ToFromBytes, server::Action};
|
||||
|
||||
use super::{database::Database, SongId};
|
||||
|
||||
@@ -210,7 +210,11 @@ impl Queue {
|
||||
}
|
||||
|
||||
pub fn advance_index_db(db: &mut Database) -> bool {
|
||||
let o = db.queue.advance_index_inner();
|
||||
let mut actions = Vec::new();
|
||||
let o = db.queue.advance_index_inner(&mut Vec::new(), &mut actions);
|
||||
for action in actions {
|
||||
db.apply_action_unchecked_seq(action, None);
|
||||
}
|
||||
o
|
||||
}
|
||||
pub fn init(&mut self) {
|
||||
@@ -225,20 +229,50 @@ impl Queue {
|
||||
QueueContent::Loop(_, _, inner) => inner.init(),
|
||||
}
|
||||
}
|
||||
pub fn advance_index_inner(&mut self) -> bool {
|
||||
pub fn done(&mut self, path: &Vec<usize>, actions: &mut Vec<Action>) {
|
||||
match &mut self.content {
|
||||
QueueContent::Song(_) => false,
|
||||
QueueContent::Folder(folder) => folder.advance_index_inner(),
|
||||
QueueContent::Loop(total, current, inner) => {
|
||||
if inner.advance_index_inner() {
|
||||
QueueContent::Song(..) => {}
|
||||
QueueContent::Folder(folder) => {
|
||||
if folder.order.is_some() {
|
||||
actions.push(Action::QueueShuffle(path.clone(), 0));
|
||||
}
|
||||
}
|
||||
QueueContent::Loop(_, _, _) => {}
|
||||
}
|
||||
}
|
||||
pub fn advance_index_inner(
|
||||
&mut self,
|
||||
path: &mut Vec<usize>,
|
||||
actions: &mut Vec<Action>,
|
||||
) -> bool {
|
||||
match &mut self.content {
|
||||
QueueContent::Song(_) => {
|
||||
self.done(path, actions);
|
||||
false
|
||||
}
|
||||
QueueContent::Folder(folder) => {
|
||||
if folder.advance_index_inner(path, actions) {
|
||||
true
|
||||
} else {
|
||||
self.done(path, actions);
|
||||
false
|
||||
}
|
||||
}
|
||||
QueueContent::Loop(total, current, inner) => {
|
||||
path.push(0);
|
||||
if inner.advance_index_inner(path, actions) {
|
||||
path.pop();
|
||||
true
|
||||
} else {
|
||||
inner.done(path, actions);
|
||||
path.pop();
|
||||
*current += 1;
|
||||
if *total == 0 || *current < *total {
|
||||
inner.init();
|
||||
true
|
||||
} else {
|
||||
*current = 0;
|
||||
self.done(path, actions);
|
||||
false
|
||||
}
|
||||
}
|
||||
@@ -481,12 +515,20 @@ impl QueueFolder {
|
||||
self.content.first()
|
||||
}
|
||||
}
|
||||
pub fn advance_index_inner(&mut self) -> bool {
|
||||
pub fn advance_index_inner(
|
||||
&mut self,
|
||||
path: &mut Vec<usize>,
|
||||
actions: &mut Vec<Action>,
|
||||
) -> bool {
|
||||
let index = self.index;
|
||||
if let Some(c) = self.get_current_mut() {
|
||||
if c.advance_index_inner() {
|
||||
path.push(index);
|
||||
if c.advance_index_inner(path, actions) {
|
||||
path.pop();
|
||||
// inner value could advance index, do nothing.
|
||||
true
|
||||
} else {
|
||||
path.pop();
|
||||
loop {
|
||||
if self.index + 1 < self.content.len() {
|
||||
// can advance
|
||||
|
||||
@@ -86,8 +86,8 @@ impl Action {
|
||||
| Self::QueueMove(_, _)
|
||||
| Self::QueueMoveInto(_, _)
|
||||
| Self::QueueGoto(_)
|
||||
| Self::QueueShuffle(_)
|
||||
| Self::QueueSetShuffle(_, _)
|
||||
| Self::QueueShuffle(_, _)
|
||||
| Self::QueueSetShuffle(_, _, _)
|
||||
| Self::QueueUnshuffle(_)
|
||||
| Self::RemoveSong(_)
|
||||
| Self::RemoveAlbum(_)
|
||||
@@ -186,10 +186,12 @@ pub enum Action {
|
||||
/// Take an element from A and add it to the end of the folder B
|
||||
QueueMoveInto(Vec<usize>, Vec<usize>),
|
||||
QueueGoto(Vec<usize>),
|
||||
// sent by clients when they want to shuffle a folder
|
||||
QueueShuffle(Vec<usize>),
|
||||
// sent by the server when the folder was shuffled
|
||||
QueueSetShuffle(Vec<usize>, Vec<usize>),
|
||||
/// sent by clients when they want to shuffle a folder
|
||||
/// last parameter: 0 = don't change index, 1 = set folder index to new index of previously active element
|
||||
QueueShuffle(Vec<usize>, u8),
|
||||
/// sent by the server when the folder was shuffled
|
||||
/// last parameter, see QueueShuffle
|
||||
QueueSetShuffle(Vec<usize>, Vec<usize>, u8),
|
||||
QueueUnshuffle(Vec<usize>),
|
||||
|
||||
/// .id field is ignored!
|
||||
@@ -615,16 +617,18 @@ impl ToFromBytes for Action {
|
||||
s.write_all(&[BYTE_QUEUE_GOTO])?;
|
||||
index.to_bytes(s)?;
|
||||
}
|
||||
Self::QueueShuffle(path) => {
|
||||
Self::QueueShuffle(path, set_index) => {
|
||||
s.write_all(&[BYTE_QUEUE_ACTION])?;
|
||||
s.write_all(&[SUBBYTE_ACTION_SHUFFLE])?;
|
||||
path.to_bytes(s)?;
|
||||
set_index.to_bytes(s)?;
|
||||
}
|
||||
Self::QueueSetShuffle(path, map) => {
|
||||
Self::QueueSetShuffle(path, map, set_index) => {
|
||||
s.write_all(&[BYTE_QUEUE_ACTION])?;
|
||||
s.write_all(&[SUBBYTE_ACTION_SET_SHUFFLE])?;
|
||||
path.to_bytes(s)?;
|
||||
map.to_bytes(s)?;
|
||||
set_index.to_bytes(s)?;
|
||||
}
|
||||
Self::QueueUnshuffle(path) => {
|
||||
s.write_all(&[BYTE_QUEUE_ACTION])?;
|
||||
@@ -813,8 +817,10 @@ impl ToFromBytes for Action {
|
||||
BYTE_QUEUE_MOVE_INTO => Self::QueueMoveInto(from_bytes!(), from_bytes!()),
|
||||
BYTE_QUEUE_GOTO => Self::QueueGoto(from_bytes!()),
|
||||
BYTE_QUEUE_ACTION => match s.read_byte()? {
|
||||
SUBBYTE_ACTION_SHUFFLE => Self::QueueShuffle(from_bytes!()),
|
||||
SUBBYTE_ACTION_SET_SHUFFLE => Self::QueueSetShuffle(from_bytes!(), from_bytes!()),
|
||||
SUBBYTE_ACTION_SHUFFLE => Self::QueueShuffle(from_bytes!(), from_bytes!()),
|
||||
SUBBYTE_ACTION_SET_SHUFFLE => {
|
||||
Self::QueueSetShuffle(from_bytes!(), from_bytes!(), from_bytes!())
|
||||
}
|
||||
SUBBYTE_ACTION_UNSHUFFLE => Self::QueueUnshuffle(from_bytes!()),
|
||||
_ => {
|
||||
eprintln!(
|
||||
@@ -943,8 +949,8 @@ fn test_to_from_bytes() {
|
||||
Action::QueueMove(vec![], vec![]),
|
||||
Action::QueueMoveInto(vec![], vec![]),
|
||||
Action::QueueGoto(vec![]),
|
||||
Action::QueueShuffle(vec![]),
|
||||
Action::QueueSetShuffle(vec![], vec![]),
|
||||
Action::QueueShuffle(vec![], 1),
|
||||
Action::QueueSetShuffle(vec![], vec![], 0),
|
||||
Action::QueueUnshuffle(vec![]),
|
||||
// Action::AddSong(Song, Req),
|
||||
// Action::AddAlbum(Album, Req),
|
||||
|
||||
Reference in New Issue
Block a user