queue: shuffle is now usable

This commit is contained in:
Mark 2023-09-24 21:29:32 +02:00
parent 30b466b2ff
commit 36da1ab189
6 changed files with 254 additions and 173 deletions

View File

@ -3,7 +3,7 @@ use std::collections::VecDeque;
use musicdb_lib::{ use musicdb_lib::{
data::{ data::{
database::Database, database::Database,
queue::{Queue, QueueContent}, queue::{Queue, QueueContent, ShuffleState},
song::Song, song::Song,
AlbumId, ArtistId, AlbumId, ArtistId,
}, },
@ -116,7 +116,7 @@ impl QueueViewer {
GuiElemCfg::at(Rectangle::from_tuples((0.5, 0.5), (1.0, 1.0))) GuiElemCfg::at(Rectangle::from_tuples((0.5, 0.5), (1.0, 1.0)))
.w_mouse(), .w_mouse(),
vec![], vec![],
QueueContent::Shuffle(0, vec![], vec![], 0).into(), QueueContent::Shuffle { inner: Box::new(QueueContent::Folder(0, vec![], String::new()).into()), state: ShuffleState::NotShuffled }.into(),
false, false,
) )
.alwayscopy(), .alwayscopy(),
@ -237,9 +237,9 @@ fn queue_gui(
} }
QueueContent::Loop(_, _, inner) => { QueueContent::Loop(_, _, inner) => {
let mut p = path.clone(); let mut p = path.clone();
p.push(0);
let mut p1 = path.clone(); let mut p1 = path.clone();
let p2 = p1.pop().unwrap_or(0) + 1; let p2 = p1.pop().unwrap_or(0) + 1;
p.push(0);
target.push(( target.push((
GuiElem::new(QueueLoop::new(cfg.clone(), path, queue.clone(), current)), GuiElem::new(QueueLoop::new(cfg.clone(), path, queue.clone(), current)),
line_height * 0.8, line_height * 0.8,
@ -262,7 +262,7 @@ fn queue_gui(
} }
QueueContent::Random(q) => { QueueContent::Random(q) => {
target.push(( target.push((
GuiElem::new(QueueRandom::new(cfg, path.clone(), queue.clone(), current)), GuiElem::new(QueueRandom::new(cfg.clone(), path.clone(), queue.clone(), current)),
line_height, line_height,
)); ));
for (i, inner) in q.iter().enumerate() { for (i, inner) in q.iter().enumerate() {
@ -280,29 +280,37 @@ fn queue_gui(
false, false,
); );
} }
} let mut p1 = path.clone();
QueueContent::Shuffle(c, map, elems, _) => { let p2 = p1.pop().unwrap_or(0) + 1;
target.push(( target.push((
GuiElem::new(QueueShuffle::new(cfg, path.clone(), queue.clone(), current)), GuiElem::new(QueueIndentEnd::new(cfg, (p1, p2))),
line_height * 0.4,
));
}
QueueContent::Shuffle { inner, state: _ } => {
target.push((
GuiElem::new(QueueShuffle::new(cfg.clone(), path.clone(), queue.clone(), current)),
line_height * 0.8, line_height * 0.8,
)); ));
for (i, inner) in map.iter().enumerate() { let mut p = path.clone();
if let Some(inner) = elems.get(*inner) { p.push(0);
let mut p = path.clone(); queue_gui(
p.push(i); inner,
queue_gui( db,
inner, depth + depth_inc_by,
db, depth_inc_by,
depth + depth_inc_by, line_height,
depth_inc_by, target,
line_height, p,
target, current,
p, true,
current && i == *c, );
false, let mut p1 = path.clone();
); let p2 = p1.pop().unwrap_or(0) + 1;
} target.push((
} GuiElem::new(QueueIndentEnd::new(cfg, (p1, p2))),
line_height * 0.4,
));
} }
} }
} }
@ -1101,7 +1109,7 @@ impl QueueShuffle {
children: vec![GuiElem::new(Label::new( children: vec![GuiElem::new(Label::new(
GuiElemCfg::default(), GuiElemCfg::default(),
match queue.content() { match queue.content() {
QueueContent::Shuffle(..) => { QueueContent::Shuffle { .. } => {
format!("shuffle") format!("shuffle")
} }
_ => "[???]".to_string(), _ => "[???]".to_string(),
@ -1200,7 +1208,8 @@ impl GuiElemTrait for QueueShuffle {
} }
fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> { fn dragged(&mut self, dragged: Dragging) -> Vec<GuiAction> {
if !self.always_copy { if !self.always_copy {
let p = self.path.clone(); let mut p = self.path.clone();
p.push(0);
dragged_add_to_queue(dragged, move |q| Command::QueueAdd(p, q)) dragged_add_to_queue(dragged, move |q| Command::QueueAdd(p, q))
} else { } else {
vec![] vec![]

View File

@ -12,7 +12,7 @@ use crate::{load::ToFromBytes, server::Command};
use super::{ use super::{
album::Album, album::Album,
artist::Artist, artist::Artist,
queue::{Queue, QueueContent}, queue::{Queue, QueueContent, ShuffleState},
song::Song, song::Song,
AlbumId, ArtistId, CoverId, DatabaseLocation, SongId, AlbumId, ArtistId, CoverId, DatabaseLocation, SongId,
}; };
@ -250,42 +250,68 @@ impl Database {
} }
Command::SyncDatabase(a, b, c) => self.sync(a, b, c), Command::SyncDatabase(a, b, c) => self.sync(a, b, c),
Command::QueueUpdate(index, new_data) => { Command::QueueUpdate(index, new_data) => {
if let Some(v) = self.queue.get_item_at_index_mut(&index, 0) { let mut actions = vec![];
if let Some(v) = self.queue.get_item_at_index_mut(&index, 0, &mut actions) {
*v = new_data; *v = new_data;
} }
Queue::handle_actions(self, actions);
} }
Command::QueueAdd(mut index, new_data) => { Command::QueueAdd(mut index, new_data) => {
if let Some(v) = self.queue.get_item_at_index_mut(&index, 0) { let mut actions = vec![];
if let Some(v) = self.queue.get_item_at_index_mut(&index, 0, &mut actions) {
if let Some(i) = v.add_to_end(new_data) { if let Some(i) = v.add_to_end(new_data) {
index.push(i); index.push(i);
if let Some(q) = self.queue.get_item_at_index_mut(&index, 0) { if let Some(q) = self.queue.get_item_at_index_mut(&index, 0, &mut actions) {
let mut actions = Vec::new(); let mut actions = Vec::new();
q.init(index, &mut actions); q.init(index, &mut actions);
Queue::handle_actions(self, actions); Queue::handle_actions(self, actions);
} }
} }
} }
Queue::handle_actions(self, actions);
} }
Command::QueueInsert(mut index, pos, mut new_data) => { Command::QueueInsert(mut index, pos, mut new_data) => {
if let Some(v) = self.queue.get_item_at_index_mut(&index, 0) { let mut actions = vec![];
if let Some(v) = self.queue.get_item_at_index_mut(&index, 0, &mut actions) {
index.push(pos); index.push(pos);
let mut actions = Vec::new(); let mut actions = Vec::new();
new_data.init(index, &mut actions); new_data.init(index, &mut actions);
v.insert(new_data, pos); v.insert(new_data, pos);
Queue::handle_actions(self, actions); Queue::handle_actions(self, actions);
} }
Queue::handle_actions(self, actions);
} }
Command::QueueRemove(index) => { Command::QueueRemove(index) => {
self.queue.remove_by_index(&index, 0); self.queue.remove_by_index(&index, 0);
} }
Command::QueueGoto(index) => Queue::set_index_db(self, &index), Command::QueueGoto(index) => Queue::set_index_db(self, &index),
Command::QueueSetShuffle(path, map, next) => { Command::QueueSetShuffle(path, order) => {
if let Some(elem) = self.queue.get_item_at_index_mut(&path, 0) { let mut actions = vec![];
if let QueueContent::Shuffle(_, m, _, n) = elem.content_mut() { if let Some(elem) = self.queue.get_item_at_index_mut(&path, 0, &mut actions) {
*m = map; if let QueueContent::Shuffle { inner, state } = elem.content_mut() {
*n = next; if let QueueContent::Folder(_, v, _) = inner.content_mut() {
let mut o = std::mem::replace(v, vec![])
.into_iter()
.map(|v| Some(v))
.collect::<Vec<_>>();
for &i in order.iter() {
if let Some(a) = o.get_mut(i).and_then(Option::take) {
v.push(a);
} else {
eprintln!("[warn] Can't properly apply requested order to Queue/Shuffle: no element at index {i}. Index may be out of bounds or used twice. Len: {}, Order: {order:?}.", v.len());
}
}
}
*state = ShuffleState::Shuffled;
} else {
eprintln!(
"[warn] can't QueueSetShuffle - element at path {path:?} isn't Shuffle"
);
} }
} else {
eprintln!("[warn] can't QueueSetShuffle - no element at path {path:?}");
} }
Queue::handle_actions(self, actions);
} }
Command::AddSong(song) => { Command::AddSong(song) => {
self.add_song_new(song); self.add_song_new(song);

View File

@ -1,9 +1,6 @@
use std::collections::VecDeque; use std::collections::VecDeque;
use rand::{ use rand::seq::{IteratorRandom, SliceRandom};
seq::{IteratorRandom, SliceRandom},
Rng,
};
use crate::{load::ToFromBytes, server::Command}; use crate::{load::ToFromBytes, server::Command};
@ -20,12 +17,21 @@ pub enum QueueContent {
Folder(usize, Vec<Queue>, String), Folder(usize, Vec<Queue>, String),
Loop(usize, usize, Box<Queue>), Loop(usize, usize, Box<Queue>),
Random(VecDeque<Queue>), Random(VecDeque<Queue>),
Shuffle(usize, Vec<usize>, Vec<Queue>, usize), Shuffle {
inner: Box<Queue>,
state: ShuffleState,
},
}
#[derive(Clone, Copy, Debug)]
pub enum ShuffleState {
NotShuffled,
Modified,
Shuffled,
} }
pub enum QueueAction { pub enum QueueAction {
AddRandomSong(Vec<usize>), AddRandomSong(Vec<usize>),
SetShuffle(Vec<usize>, Vec<usize>, usize), SetShuffle(Vec<usize>, bool),
} }
impl Queue { impl Queue {
@ -51,11 +57,7 @@ impl Queue {
q.push_back(v); q.push_back(v);
Some(q.len() - 1) Some(q.len() - 1)
} }
QueueContent::Shuffle(_, map, elems, _) => { QueueContent::Shuffle { .. } => None,
map.push(elems.len());
elems.push(v);
Some(map.len() - 1)
}
} }
} }
pub fn insert(&mut self, v: Self, index: usize) -> bool { pub fn insert(&mut self, v: Self, index: usize) -> bool {
@ -72,16 +74,9 @@ impl Queue {
false false
} }
} }
QueueContent::Shuffle(_, map, elems, _) => { QueueContent::Loop(..) | QueueContent::Random(..) | QueueContent::Shuffle { .. } => {
if index <= map.len() { false
map.insert(index, elems.len());
elems.push(v);
true
} else {
false
}
} }
QueueContent::Loop(..) | QueueContent::Random(..) => false,
} }
} }
@ -100,7 +95,7 @@ impl Queue {
*total * inner.len() *total * inner.len()
} }
} }
QueueContent::Shuffle(_, _, v, _) => v.iter().map(|v| v.len()).sum(), QueueContent::Shuffle { inner, state: _ } => inner.len(),
} }
} }
@ -118,7 +113,7 @@ impl Queue {
} }
QueueContent::Loop(_, _, inner) => inner.get_current(), QueueContent::Loop(_, _, inner) => inner.get_current(),
QueueContent::Random(v) => v.get(v.len().saturating_sub(2))?.get_current(), QueueContent::Random(v) => v.get(v.len().saturating_sub(2))?.get_current(),
QueueContent::Shuffle(i, map, elems, _) => elems.get(*map.get(*i)?), QueueContent::Shuffle { inner, state: _ } => inner.get_current(),
} }
} }
pub fn get_current_song(&self) -> Option<&SongId> { pub fn get_current_song(&self) -> Option<&SongId> {
@ -164,7 +159,7 @@ impl Queue {
} }
} }
QueueContent::Random(v) => v.get(v.len().saturating_sub(1))?.get_current(), QueueContent::Random(v) => v.get(v.len().saturating_sub(1))?.get_current(),
QueueContent::Shuffle(i, map, elems, _) => elems.get(*map.get(*i + 1)?), QueueContent::Shuffle { inner, state: _ } => inner.get_next(),
} }
} }
pub fn get_first(&self) -> Option<&Self> { pub fn get_first(&self) -> Option<&Self> {
@ -173,13 +168,7 @@ impl Queue {
QueueContent::Folder(_, v, _) => v.first(), QueueContent::Folder(_, v, _) => v.first(),
QueueContent::Loop(_, _, q) => q.get_first(), QueueContent::Loop(_, _, q) => q.get_first(),
QueueContent::Random(q) => q.front(), QueueContent::Random(q) => q.front(),
QueueContent::Shuffle(i, _, v, next) => { QueueContent::Shuffle { inner, state: _ } => inner.get_first(),
if *i == 0 {
v.get(*i)
} else {
v.get(*next)
}
}
} }
} }
@ -192,12 +181,27 @@ impl Queue {
pub fn init(&mut self, path: Vec<usize>, actions: &mut Vec<QueueAction>) { pub fn init(&mut self, path: Vec<usize>, actions: &mut Vec<QueueAction>) {
match &mut self.content { match &mut self.content {
QueueContent::Song(..) => {} QueueContent::Song(..) => {}
QueueContent::Folder(_, v, _) => { QueueContent::Folder(i, v, _) => {
*i = 0;
if let Some(v) = v.first_mut() { if let Some(v) = v.first_mut() {
v.init(path, actions); v.init(
{
let mut p = path.clone();
p.push(0);
p
},
actions,
);
} }
} }
QueueContent::Loop(_, _, inner) => inner.init(path, actions), QueueContent::Loop(_, _, inner) => inner.init(
{
let mut p = path.clone();
p.push(0);
p
},
actions,
),
QueueContent::Random(q) => { QueueContent::Random(q) => {
if q.len() == 0 { if q.len() == 0 {
actions.push(QueueAction::AddRandomSong(path.clone())); actions.push(QueueAction::AddRandomSong(path.clone()));
@ -207,21 +211,17 @@ impl Queue {
q.init(path, actions) q.init(path, actions)
} }
} }
QueueContent::Shuffle(current, map, elems, next) => { QueueContent::Shuffle { inner, state } => {
let mut new_map = (0..elems.len()).filter(|v| *v != *next).collect::<Vec<_>>(); let mut p = path.clone();
new_map.shuffle(&mut rand::thread_rng()); p.push(0);
if let Some(first) = new_map.first_mut() { if matches!(state, ShuffleState::NotShuffled | ShuffleState::Modified) {
let was_first = std::mem::replace(first, *next); actions.push(QueueAction::SetShuffle(
new_map.push(was_first); path,
} else if *next < elems.len() { matches!(state, ShuffleState::Modified),
new_map.push(*next); ));
*state = ShuffleState::Shuffled;
} }
let new_next = if elems.is_empty() { inner.init(p, actions);
0
} else {
rand::thread_rng().gen_range(0..elems.len())
};
actions.push(QueueAction::SetShuffle(path, new_map, new_next));
} }
} }
} }
@ -238,15 +238,36 @@ impl Queue {
} }
} }
} }
QueueAction::SetShuffle(path, shuf, next) => { QueueAction::SetShuffle(path, partial) => {
if !db.is_client() { if !db.is_client() {
db.apply_command(Command::QueueSetShuffle(path, shuf, next)); let mut actions = vec![];
if let Some(QueueContent::Shuffle { inner, state: _ }) = db
.queue
.get_item_at_index_mut(&path, 0, &mut actions)
.map(|v| v.content_mut())
{
if let QueueContent::Folder(i, v, _) = inner.content_mut() {
let mut order = (0..v.len()).collect::<Vec<usize>>();
if partial && *i + 1 < v.len() {
// shuffle only elements after the current one
order[*i + 1..].shuffle(&mut rand::thread_rng());
} else {
order.shuffle(&mut rand::thread_rng());
}
db.apply_command(Command::QueueSetShuffle(path, order));
}
}
Queue::handle_actions(db, actions);
} }
} }
} }
} }
} }
fn advance_index_inner(&mut self, path: Vec<usize>, actions: &mut Vec<QueueAction>) -> bool { fn advance_index_inner(
&mut self,
mut path: Vec<usize>,
actions: &mut Vec<QueueAction>,
) -> bool {
match &mut self.content { match &mut self.content {
QueueContent::Song(_) => false, QueueContent::Song(_) => false,
QueueContent::Folder(index, contents, _) => { QueueContent::Folder(index, contents, _) => {
@ -278,9 +299,8 @@ impl Queue {
} }
} }
QueueContent::Loop(total, current, inner) => { QueueContent::Loop(total, current, inner) => {
let mut p = path.clone(); path.push(0);
p.push(0); if inner.advance_index_inner(path.clone(), actions) {
if inner.advance_index_inner(p, actions) {
true true
} else { } else {
*current += 1; *current += 1;
@ -316,28 +336,15 @@ impl Queue {
false false
} }
} }
QueueContent::Shuffle(current, map, elems, _) => { QueueContent::Shuffle { inner, state } => {
if map let mut p = path.clone();
.get(*current) p.push(0);
.and_then(|i| elems.get_mut(*i)) if !inner.advance_index_inner(p, actions) {
.is_some_and(|q| { *state = ShuffleState::Shuffled;
let mut p = path.clone(); actions.push(QueueAction::SetShuffle(path, false));
p.push(*current); false
q.advance_index_inner(p, actions)
})
{
true
} else { } else {
*current += 1; true
if *current < map.len() {
if let Some(elem) = map.get(*current).and_then(|i| elems.get_mut(*i)) {
elem.init(path, actions);
}
true
} else {
*current = 0;
false
}
} }
} }
} }
@ -345,6 +352,7 @@ impl Queue {
pub fn set_index_db(db: &mut Database, index: &Vec<usize>) { pub fn set_index_db(db: &mut Database, index: &Vec<usize>) {
let mut actions = vec![]; let mut actions = vec![];
db.queue.reset_index();
db.queue.set_index_inner(index, 0, vec![], &mut actions); db.queue.set_index_inner(index, 0, vec![], &mut actions);
Self::handle_actions(db, actions); Self::handle_actions(db, actions);
} }
@ -377,15 +385,29 @@ impl Queue {
inner.set_index_inner(index, depth + 1, build_index, actions) inner.set_index_inner(index, depth + 1, build_index, actions)
} }
QueueContent::Random(_) => {} QueueContent::Random(_) => {}
QueueContent::Shuffle(current, map, elems, next) => { QueueContent::Shuffle { inner, state: _ } => {
if i != *current { inner.init(build_index.clone(), actions);
*current = i; inner.set_index_inner(index, depth + 1, build_index, actions)
} }
if let Some(c) = map.get(i).and_then(|i| elems.get_mut(*i)) { }
c.init(build_index.clone(), actions); }
c.set_index_inner(index, depth + 1, build_index, actions); pub fn reset_index(&mut self) {
match self.content_mut() {
QueueContent::Song(_) => {}
QueueContent::Folder(i, v, _) => {
*i = 0;
for v in v {
v.reset_index();
} }
} }
QueueContent::Loop(_, done, i) => {
*done = 0;
i.reset_index();
}
QueueContent::Random(_) => {}
QueueContent::Shuffle { inner, state: _ } => {
inner.reset_index();
}
} }
} }
@ -402,34 +424,52 @@ impl Queue {
} }
QueueContent::Loop(_, _, inner) => inner.get_item_at_index(index, depth + 1), QueueContent::Loop(_, _, inner) => inner.get_item_at_index(index, depth + 1),
QueueContent::Random(vec) => vec.get(*i)?.get_item_at_index(index, depth + 1), QueueContent::Random(vec) => vec.get(*i)?.get_item_at_index(index, depth + 1),
QueueContent::Shuffle(_, map, elems, _) => map QueueContent::Shuffle { inner, state: _ } => {
.get(*i) inner.get_item_at_index(index, depth + 1)
.and_then(|i| elems.get(*i)) }
.and_then(|elem| elem.get_item_at_index(index, depth + 1)),
} }
} else { } else {
Some(self) Some(self)
} }
} }
pub fn get_item_at_index_mut(&mut self, index: &Vec<usize>, depth: usize) -> Option<&mut Self> { pub fn get_item_at_index_mut(
&mut self,
index: &Vec<usize>,
depth: usize,
actions: &mut Vec<QueueAction>,
) -> Option<&mut Self> {
if let Some(i) = index.get(depth) { if let Some(i) = index.get(depth) {
match &mut self.content { match &mut self.content {
QueueContent::Song(_) => None, QueueContent::Song(_) => None,
QueueContent::Folder(_, v, _) => { QueueContent::Folder(_, v, _) => {
if let Some(v) = v.get_mut(*i) { if let Some(v) = v.get_mut(*i) {
v.get_item_at_index_mut(index, depth + 1) v.get_item_at_index_mut(index, depth + 1, actions)
} else { } else {
None None
} }
} }
QueueContent::Loop(_, _, inner) => inner.get_item_at_index_mut(index, depth + 1), QueueContent::Loop(_, _, inner) => {
QueueContent::Random(vec) => { inner.get_item_at_index_mut(index, depth + 1, actions)
vec.get_mut(*i)?.get_item_at_index_mut(index, depth + 1) }
QueueContent::Random(vec) => {
vec.get_mut(*i)?
.get_item_at_index_mut(index, depth + 1, actions)
}
QueueContent::Shuffle { inner, state } => {
// if getting a mutable reference to the Folder that holds our songs,
// it may have been modified
if depth + 1 == index.len() && matches!(state, ShuffleState::Shuffled) {
*state = ShuffleState::Modified;
}
if matches!(state, ShuffleState::NotShuffled | ShuffleState::Modified) {
actions.push(QueueAction::SetShuffle(
index[0..depth].to_vec(),
matches!(state, ShuffleState::Modified),
));
*state = ShuffleState::Shuffled;
}
inner.get_item_at_index_mut(index, depth + 1, actions)
} }
QueueContent::Shuffle(_, map, elems, _) => map
.get(*i)
.and_then(|i| elems.get_mut(*i))
.and_then(|elem| elem.get_item_at_index_mut(index, depth + 1)),
} }
} else { } else {
Some(self) Some(self)
@ -468,23 +508,8 @@ impl Queue {
} }
} }
QueueContent::Random(v) => v.remove(*i), QueueContent::Random(v) => v.remove(*i),
QueueContent::Shuffle(current, map, elems, next) => { QueueContent::Shuffle { inner, state: _ } => {
if *i < *current { inner.remove_by_index(index, depth + 1)
*current -= 1;
}
if *i < *next {
*next -= 1;
}
if *i < map.len() {
let elem = map.remove(*i);
if elem < elems.len() {
Some(elems.remove(elem))
} else {
None
}
} else {
None
}
} }
} }
} else { } else {
@ -550,12 +575,10 @@ impl ToFromBytes for QueueContent {
s.write_all(&[0b00110000])?; s.write_all(&[0b00110000])?;
q.to_bytes(s)?; q.to_bytes(s)?;
} }
Self::Shuffle(current, map, elems, next) => { Self::Shuffle { inner, state } => {
s.write_all(&[0b00001100])?; s.write_all(&[0b00001100])?;
current.to_bytes(s)?; inner.to_bytes(s)?;
map.to_bytes(s)?; state.to_bytes(s)?;
elems.to_bytes(s)?;
next.to_bytes(s)?;
} }
} }
Ok(()) Ok(())
@ -579,13 +602,42 @@ impl ToFromBytes for QueueContent {
Box::new(ToFromBytes::from_bytes(s)?), Box::new(ToFromBytes::from_bytes(s)?),
), ),
0b00110000 => Self::Random(ToFromBytes::from_bytes(s)?), 0b00110000 => Self::Random(ToFromBytes::from_bytes(s)?),
0b00001100 => Self::Shuffle( 0b00001100 => Self::Shuffle {
ToFromBytes::from_bytes(s)?, inner: Box::new(ToFromBytes::from_bytes(s)?),
ToFromBytes::from_bytes(s)?, state: ToFromBytes::from_bytes(s)?,
ToFromBytes::from_bytes(s)?, },
ToFromBytes::from_bytes(s)?,
),
_ => Self::Folder(0, vec![], "<invalid byte received>".to_string()), _ => Self::Folder(0, vec![], "<invalid byte received>".to_string()),
}) })
} }
} }
impl ToFromBytes for ShuffleState {
fn to_bytes<T>(&self, s: &mut T) -> Result<(), std::io::Error>
where
T: std::io::Write,
{
s.write_all(&[match self {
Self::NotShuffled => 1,
Self::Modified => 2,
Self::Shuffled => 4,
}])
}
fn from_bytes<T>(s: &mut T) -> Result<Self, std::io::Error>
where
T: std::io::Read,
{
let mut b = [0];
s.read_exact(&mut b)?;
Ok(match b[0] {
1 => Self::NotShuffled,
2 => Self::Modified,
4 => Self::Shuffled,
_ => {
eprintln!(
"[warn] received {} as ShuffleState, which is invalid. defaulting to Shuffled.",
b[0]
);
Self::Shuffled
}
})
}
}

View File

@ -1,7 +1,7 @@
use std::{ use std::{
fmt::Display, fmt::Display,
io::{Read, Write}, io::{Read, Write},
path::{Path, PathBuf}, path::PathBuf,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
thread::JoinHandle, thread::JoinHandle,
}; };

View File

@ -37,7 +37,7 @@ pub enum Command {
QueueInsert(Vec<usize>, usize, Queue), QueueInsert(Vec<usize>, usize, Queue),
QueueRemove(Vec<usize>), QueueRemove(Vec<usize>),
QueueGoto(Vec<usize>), QueueGoto(Vec<usize>),
QueueSetShuffle(Vec<usize>, Vec<usize>, usize), QueueSetShuffle(Vec<usize>, Vec<usize>),
/// .id field is ignored! /// .id field is ignored!
AddSong(Song), AddSong(Song),
/// .id field is ignored! /// .id field is ignored!
@ -232,11 +232,10 @@ impl ToFromBytes for Command {
s.write_all(&[0b00011011])?; s.write_all(&[0b00011011])?;
index.to_bytes(s)?; index.to_bytes(s)?;
} }
Self::QueueSetShuffle(path, map, next) => { Self::QueueSetShuffle(path, map) => {
s.write_all(&[0b10011011])?; s.write_all(&[0b10011011])?;
path.to_bytes(s)?; path.to_bytes(s)?;
map.to_bytes(s)?; map.to_bytes(s)?;
next.to_bytes(s)?;
} }
Self::AddSong(song) => { Self::AddSong(song) => {
s.write_all(&[0b01010000])?; s.write_all(&[0b01010000])?;
@ -313,11 +312,9 @@ impl ToFromBytes for Command {
), ),
0b00011001 => Self::QueueRemove(ToFromBytes::from_bytes(s)?), 0b00011001 => Self::QueueRemove(ToFromBytes::from_bytes(s)?),
0b00011011 => Self::QueueGoto(ToFromBytes::from_bytes(s)?), 0b00011011 => Self::QueueGoto(ToFromBytes::from_bytes(s)?),
0b10011011 => Self::QueueSetShuffle( 0b10011011 => {
ToFromBytes::from_bytes(s)?, Self::QueueSetShuffle(ToFromBytes::from_bytes(s)?, ToFromBytes::from_bytes(s)?)
ToFromBytes::from_bytes(s)?, }
ToFromBytes::from_bytes(s)?,
),
0b01010000 => Self::AddSong(ToFromBytes::from_bytes(s)?), 0b01010000 => Self::AddSong(ToFromBytes::from_bytes(s)?),
0b01010011 => Self::AddAlbum(ToFromBytes::from_bytes(s)?), 0b01010011 => Self::AddAlbum(ToFromBytes::from_bytes(s)?),
0b01011100 => Self::AddArtist(ToFromBytes::from_bytes(s)?), 0b01011100 => Self::AddArtist(ToFromBytes::from_bytes(s)?),

View File

@ -663,7 +663,7 @@ fn build_queue_content_build(
} }
} }
} }
QueueContent::Shuffle(cur, map, content, _) => { QueueContent::Shuffle { inner, state: _ } => {
for v in if current { for v in if current {
&state.html.queue_shuffle_current &state.html.queue_shuffle_current
} else { } else {
@ -674,18 +674,15 @@ fn build_queue_content_build(
HtmlPart::Insert(key) => match key.as_str() { HtmlPart::Insert(key) => match key.as_str() {
"path" => html.push_str(&path), "path" => html.push_str(&path),
"content" => { "content" => {
for (i, v) in map.iter().filter_map(|i| content.get(*i)).enumerate()
{
build_queue_content_build( build_queue_content_build(
db, db,
state, state,
html, html,
&v, &inner,
format!("{path}-0"), format!("{path}-0"),
current && i == *cur, current,
true, true,
) )
}
} }
_ => {} _ => {}
}, },