mirror of
https://github.com/Dummi26/musicdb.git
synced 2025-12-14 20:06:16 +01:00
add QueueMove operation
This commit is contained in:
@@ -559,6 +559,71 @@ impl Database {
|
||||
Command::QueueRemove(index) => {
|
||||
self.queue.remove_by_index(&index, 0);
|
||||
}
|
||||
Command::QueueMove(index_from, mut index_to) => 'queue_move: {
|
||||
if index_to.len() == 0 || index_to.starts_with(&index_from) {
|
||||
break 'queue_move;
|
||||
}
|
||||
// if same parent path, perform folder move operation instead
|
||||
if index_from[0..index_from.len() - 1] == index_to[0..index_to.len() - 1] {
|
||||
if let Some(parent) = self
|
||||
.queue
|
||||
.get_item_at_index_mut(&index_from[0..index_from.len() - 1], 0)
|
||||
{
|
||||
if let QueueContent::Folder(folder) = parent.content_mut() {
|
||||
let i1 = index_from[index_from.len() - 1];
|
||||
let mut i2 = index_to[index_to.len() - 1];
|
||||
if i2 > i1 {
|
||||
i2 -= 1;
|
||||
}
|
||||
// this preserves "is currently active queue element" status
|
||||
folder.move_elem(i1, i2);
|
||||
break 'queue_move;
|
||||
}
|
||||
}
|
||||
}
|
||||
// otherwise, remove then insert
|
||||
let was_current = self.queue.is_current(&index_from);
|
||||
if let Some(elem) = self.queue.remove_by_index(&index_from, 0) {
|
||||
if index_to.len() >= index_from.len()
|
||||
&& index_to.starts_with(&index_from[0..index_from.len() - 1])
|
||||
&& index_to[index_from.len() - 1] > index_from[index_from.len() - 1]
|
||||
{
|
||||
index_to[index_from.len() - 1] -= 1;
|
||||
}
|
||||
if let Some(parent) = self
|
||||
.queue
|
||||
.get_item_at_index_mut(&index_to[0..index_to.len() - 1], 0)
|
||||
{
|
||||
parent.insert(vec![elem], index_to[index_to.len() - 1]);
|
||||
if was_current {
|
||||
self.queue.set_index_inner(&index_to, 0, vec![]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::QueueMoveInto(index_from, mut parent_to) => 'queue_move_into: {
|
||||
if parent_to.starts_with(&index_from) {
|
||||
break 'queue_move_into;
|
||||
}
|
||||
// remove then insert
|
||||
let was_current = self.queue.is_current(&index_from);
|
||||
if let Some(elem) = self.queue.remove_by_index(&index_from, 0) {
|
||||
if parent_to.len() >= index_from.len()
|
||||
&& parent_to.starts_with(&index_from[0..index_from.len() - 1])
|
||||
&& parent_to[index_from.len() - 1] > index_from[index_from.len() - 1]
|
||||
{
|
||||
parent_to[index_from.len() - 1] -= 1;
|
||||
}
|
||||
if let Some(parent) = self.queue.get_item_at_index_mut(&parent_to, 0) {
|
||||
if let Some(i) = parent.add_to_end(vec![elem]) {
|
||||
if was_current {
|
||||
parent_to.push(i);
|
||||
self.queue.set_index_inner(&parent_to, 0, vec![]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Command::QueueGoto(index) => Queue::set_index_db(self, &index),
|
||||
Command::QueueShuffle(path) => {
|
||||
if let Some(elem) = self.queue.get_item_at_index_mut(&path, 0) {
|
||||
|
||||
@@ -41,6 +41,21 @@ impl Queue {
|
||||
QueueContent::Loop(..) => None,
|
||||
}
|
||||
}
|
||||
pub fn is_current(&self, index: &[usize]) -> bool {
|
||||
if index.is_empty() {
|
||||
return true;
|
||||
}
|
||||
match self.content() {
|
||||
QueueContent::Song(_) => true,
|
||||
QueueContent::Folder(folder) => {
|
||||
folder.index == index[0]
|
||||
&& folder
|
||||
.get_current_immut()
|
||||
.is_some_and(|c| c.is_current(&index[1..]))
|
||||
}
|
||||
QueueContent::Loop(_, _, inner) => index[0] == 0 && inner.is_current(&index[1..]),
|
||||
}
|
||||
}
|
||||
pub fn insert(&mut self, v: Vec<Self>, index: usize) -> bool {
|
||||
match &mut self.content {
|
||||
QueueContent::Song(_) => false,
|
||||
@@ -198,16 +213,11 @@ impl Queue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_index_db(db: &mut Database, index: &Vec<usize>) {
|
||||
pub fn set_index_db(db: &mut Database, index: &[usize]) {
|
||||
db.queue.reset_index();
|
||||
db.queue.set_index_inner(index, 0, vec![]);
|
||||
}
|
||||
pub fn set_index_inner(
|
||||
&mut self,
|
||||
index: &Vec<usize>,
|
||||
depth: usize,
|
||||
mut build_index: Vec<usize>,
|
||||
) {
|
||||
pub fn set_index_inner(&mut self, index: &[usize], depth: usize, mut build_index: Vec<usize>) {
|
||||
let i = if let Some(i) = index.get(depth) {
|
||||
*i
|
||||
} else {
|
||||
@@ -245,7 +255,7 @@ impl Queue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_item_at_index(&self, index: &Vec<usize>, depth: usize) -> Option<&Self> {
|
||||
pub fn get_item_at_index(&self, index: &[usize], depth: usize) -> Option<&Self> {
|
||||
if let Some(i) = index.get(depth) {
|
||||
match &self.content {
|
||||
QueueContent::Song(_) => None,
|
||||
@@ -262,7 +272,7 @@ impl Queue {
|
||||
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: &[usize], depth: usize) -> Option<&mut Self> {
|
||||
if let Some(i) = index.get(depth) {
|
||||
match &mut self.content {
|
||||
QueueContent::Song(_) => None,
|
||||
@@ -280,7 +290,7 @@ impl Queue {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn remove_by_index(&mut self, index: &Vec<usize>, depth: usize) -> Option<Self> {
|
||||
pub fn remove_by_index(&mut self, index: &[usize], depth: usize) -> Option<Self> {
|
||||
if let Some(i) = index.get(depth) {
|
||||
match &mut self.content {
|
||||
QueueContent::Song(_) => None,
|
||||
@@ -450,6 +460,46 @@ impl QueueFolder {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
pub fn move_elem(&mut self, index_from: usize, index_to: usize) -> bool {
|
||||
fn vec_move<T>(vec: &mut Vec<T>, from: usize, to: usize) -> bool {
|
||||
if from < vec.len() && to < vec.len() {
|
||||
if from == to {
|
||||
return true;
|
||||
}
|
||||
unsafe {
|
||||
if from < to {
|
||||
let elem = vec.as_mut_ptr().add(from).read();
|
||||
for i in from..to {
|
||||
vec[i] = vec.as_mut_ptr().add(i + 1).read();
|
||||
}
|
||||
vec[to] = elem;
|
||||
} else {
|
||||
let elem = vec.as_mut_ptr().add(from).read();
|
||||
for i in (to..from).rev() {
|
||||
vec[i + 1] = vec.as_mut_ptr().add(i).read();
|
||||
}
|
||||
vec[to] = elem;
|
||||
}
|
||||
}
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
if self.index == index_from {
|
||||
self.index = index_to;
|
||||
} else if index_from < self.index && self.index <= index_to {
|
||||
self.index -= 1;
|
||||
} else if index_to <= self.index && self.index < index_from {
|
||||
self.index += 1;
|
||||
}
|
||||
if let Some(order) = &mut self.order {
|
||||
vec_move(order, index_from, index_to)
|
||||
} else {
|
||||
vec_move(&mut self.content, index_from, index_to)
|
||||
}
|
||||
}
|
||||
}
|
||||
pub struct QueueFolderIter<'a> {
|
||||
folder: &'a QueueFolder,
|
||||
|
||||
@@ -39,6 +39,10 @@ pub enum Command {
|
||||
QueueAdd(Vec<usize>, Vec<Queue>),
|
||||
QueueInsert(Vec<usize>, usize, Vec<Queue>),
|
||||
QueueRemove(Vec<usize>),
|
||||
/// Move an element from A to B
|
||||
QueueMove(Vec<usize>, Vec<usize>),
|
||||
/// 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>),
|
||||
@@ -283,8 +287,10 @@ const BYTE_QUEUE_UPDATE: u8 = 0b10_000_000;
|
||||
const BYTE_QUEUE_ADD: u8 = 0b10_000_001;
|
||||
const BYTE_QUEUE_INSERT: u8 = 0b10_000_010;
|
||||
const BYTE_QUEUE_REMOVE: u8 = 0b10_000_100;
|
||||
const BYTE_QUEUE_GOTO: u8 = 0b10_001_000;
|
||||
const BYTE_QUEUE_ACTION: u8 = 0b10_100;
|
||||
const BYTE_QUEUE_MOVE: u8 = 0b10_001_000;
|
||||
const BYTE_QUEUE_MOVE_INTO: u8 = 0b10_001_001;
|
||||
const BYTE_QUEUE_GOTO: u8 = 0b10_001_010;
|
||||
const BYTE_QUEUE_ACTION: u8 = 0b10_001_100;
|
||||
const SUBBYTE_ACTION_SHUFFLE: u8 = 0b01_000_001;
|
||||
const SUBBYTE_ACTION_SET_SHUFFLE: u8 = 0b01_000_010;
|
||||
const SUBBYTE_ACTION_UNSHUFFLE: u8 = 0b01_000_100;
|
||||
@@ -348,6 +354,16 @@ impl ToFromBytes for Command {
|
||||
s.write_all(&[BYTE_QUEUE_REMOVE])?;
|
||||
index.to_bytes(s)?;
|
||||
}
|
||||
Self::QueueMove(a, b) => {
|
||||
s.write_all(&[BYTE_QUEUE_MOVE])?;
|
||||
a.to_bytes(s)?;
|
||||
b.to_bytes(s)?;
|
||||
}
|
||||
Self::QueueMoveInto(a, b) => {
|
||||
s.write_all(&[BYTE_QUEUE_MOVE_INTO])?;
|
||||
a.to_bytes(s)?;
|
||||
b.to_bytes(s)?;
|
||||
}
|
||||
Self::QueueGoto(index) => {
|
||||
s.write_all(&[BYTE_QUEUE_GOTO])?;
|
||||
index.to_bytes(s)?;
|
||||
@@ -529,6 +545,8 @@ impl ToFromBytes for Command {
|
||||
BYTE_QUEUE_ADD => Self::QueueAdd(from_bytes!(), from_bytes!()),
|
||||
BYTE_QUEUE_INSERT => Self::QueueInsert(from_bytes!(), from_bytes!(), from_bytes!()),
|
||||
BYTE_QUEUE_REMOVE => Self::QueueRemove(from_bytes!()),
|
||||
BYTE_QUEUE_MOVE => Self::QueueMove(from_bytes!(), from_bytes!()),
|
||||
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!()),
|
||||
|
||||
Reference in New Issue
Block a user