From 588a9cbd94ef06e1f5a42d8881bcebb34f00ce8b Mon Sep 17 00:00:00 2001 From: MrDulfin Date: Sun, 10 Mar 2024 19:22:31 -0400 Subject: [PATCH] Added more queue functions --- src/music_controller/queue.rs | 192 ++++++++++++++++++++++++++++++---- src/music_player.rs | 2 +- 2 files changed, 175 insertions(+), 19 deletions(-) diff --git a/src/music_controller/queue.rs b/src/music_controller/queue.rs index 8764d8f..f727fea 100644 --- a/src/music_controller/queue.rs +++ b/src/music_controller/queue.rs @@ -1,8 +1,8 @@ use font::opentype::tables::font_variations::InstanceFlags; use uuid::Uuid; -use crate::{music_player::Player, music_storage::library::{Album, Song, URI}}; -use std::{error::Error, path::Path}; +use crate::{music_player::Player, music_storage::library::{Album, MusicLibrary, Song, URI}}; +use std::{error::Error, ops::Add, path::Path, sync::{Arc, RwLock}, thread::sleep, time::Duration}; #[derive(Debug, PartialEq, Clone, Copy)] pub enum QueueState { @@ -19,8 +19,36 @@ pub enum QueueItemType<'a> { Album{ album: Album<'a>, shuffled: bool, + // disc #, track # + current: (i32, i32) }, - None + None, + Test +} +impl QueueItemType<'_> { + fn get_uri(&self, lib: Arc>) -> Option { + use QueueItemType::*; + + let lib = lib.read().unwrap(); + match self { + Song(uuid) => { + if let Some((song, _)) = lib.query_uuid(uuid) { + Some(song.location.clone()) + }else { + Option::None + } + }, + Album{album, shuffled, current: (disc, index)} => { + if !shuffled { + Some(album.track(*disc as usize, *index as usize).unwrap().location.clone()) + }else { + todo!() + } + }, + ExternalSong(uri) => { Some(uri.clone()) }, + _ => { Option::None } + } + } } #[derive(Debug, Clone, PartialEq)] @@ -70,12 +98,6 @@ impl<'a> Queue<'a> { ) } - pub fn set_items(&mut self, tracks: Vec>) { - let mut tracks = tracks; - self.items.clear(); - self.items.append(&mut tracks); - } - pub fn current_index(&mut self) -> i16 { let mut i = 1; let mut e = self.items.iter().filter(|song| song.state == QueueState::Played ).collect::>().len(); @@ -88,12 +110,27 @@ impl<'a> Queue<'a> { e as i16 - 1 } + fn contains_state(&self, state: QueueState) -> bool { + !self.items.iter().filter(|item| item.state == state ).collect::>().is_empty() + } + + fn is_empty(&self) -> bool { + self.items.iter().filter(|item| item.state != QueueState::Played).collect::>().is_empty() + } + + pub fn set_items(&mut self, tracks: Vec>) { + let mut tracks = tracks; + self.items.clear(); + self.items.append(&mut tracks); + } + pub fn add_item(&mut self, item: QueueItemType<'a>, source: QueueSource, by_human: bool) -> Result<(), Box> { use QueueState::*; let ind = self.current_index(); let mut i: i16 = 1; - self.items = self.items.iter().enumerate().map(|(j, item_)| { + self.items = self.items.iter().enumerate().map(|(j, item_)| { let mut item_ = item_.to_owned(); + // get the index of the current AddHere item and give it to i if item_.state == AddHere { i = j as i16 + 1 - ind; item_.state = None; @@ -121,6 +158,33 @@ impl<'a> Queue<'a> { Ok(()) } + pub fn add_item_next(&mut self, item: QueueItemType<'a>, source: QueueSource) { + use QueueState::*; + let ind = self.current_index(); + let empty = self.is_empty(); + + self.items.insert( + // index would go out of bounds if empty ( current index = -1 ) + if empty { + (ind + 1) as usize + }else { + (ind + 2) as usize + }, + QueueItem { + item, + state: if empty { + Current + }else if self.items.get((ind + 1) as usize).is_none() || (!self.contains_state(AddHere) && self.items.get((ind + 1) as usize).is_some()) { + AddHere + }else { + None + }, + source, + by_human: true + } + ) + } + pub fn remove_item(&mut self, index: usize) -> Result<(), Box> { use QueueState::*; let ind = (self.current_index() + index as i16 + 1) as usize; @@ -147,14 +211,15 @@ impl<'a> Queue<'a> { pub fn clear_except(&mut self, index: usize) -> Result<(), Box> { let mut index = index; let ind = self.current_index(); + let empty = self.is_empty(); - if ind != -1 { + if !empty { index += ind as usize; }else { index -=1 } - if !self.is_empty() && index < self.items.len() { + if !empty && index < self.items.len() { let i = self.items[index].clone(); self.items.retain(|item| item.state == QueueState::Played || *item == i ); self.items[(ind+1) as usize].state = QueueState::Current @@ -172,8 +237,65 @@ impl<'a> Queue<'a> { self.items.clear() } - fn is_empty(&self) -> bool { - self.items.iter().filter(|item| item.state != QueueState::Played).collect::>().len() == 0 + fn move_to(&mut self, index: usize) -> Result<(), Box> { + let mut index = index; + let empty = self.is_empty(); + let ind = self.current_index(); + + if !empty { + index += ind as usize; + }else { + return Err("Nothing in the queue to move to!".into()); + } + + dbg!(1); + if !empty && index < self.items.len() -1 { + // TODO: make this check for player position + let pos = self.player.position(); + if pos.is_some_and(|dur| !dur.is_zero() ) { + self.items[ind as usize].state = QueueState::Played + } + dbg!(2); + + let to_item = self.items[index].clone(); + let new_ind = self.current_index() as usize; + dbg!(3); + + // dbg!(&self.items, &new_ind, &to_item.item, &self.items[new_ind + 1].item, &self.items.len()); + loop { + dbg!(4); + + if self.items[new_ind + 1].item != to_item.item { + self.remove_item(0); + dbg!(&self.items, &new_ind, &to_item.item, &self.items[new_ind + 1].item, &self.items.len()); + sleep(Duration::from_millis(1000)); + }else { + break; + } + } + }else { + return Err("index out of bounds!".into()); + } + Ok(()) + } + + pub fn swap(&mut self, index1: usize, index2: usize) {} + + pub fn move_item(&mut self, item: usize, to_index: usize) {} + + pub fn next() {} + + pub fn prev() {} + + pub fn enqueue_item(&mut self, item: QueueItem, lib: Arc>) -> Result<(), Box> { + use QueueItemType::*; + + if let Some(uri) = item.item.get_uri(lib) { + self.player.enqueue_next(&uri)?; + }else { + return Err("this item does not exist!".into()); + } + Ok(()) } } @@ -185,14 +307,48 @@ fn item_add_test() { q.items.push(QueueItem { item: QueueItemType::Song(Uuid::new_v4()), state: QueueState::Played, source: QueueSource::Queue, by_human: false }); } q.clear(); - for _ in 0..5 { + for _ in 0..1 { q.add_item(QueueItemType::Song(Uuid::new_v4()), QueueSource::Library, true).unwrap(); } // q.clear_played(); - for _ in 0..3 { - q.remove_item(0).inspect_err(|e| println!("{e:?}")); + // for _ in 0..3 { + // q.remove_item(0).inspect_err(|e| println!("{e:?}")); + // } + for _ in 0..2 { + q.items.push(QueueItem { item: QueueItemType::Test, state: QueueState::None, source: QueueSource::Queue, by_human: false }); } - q.clear_except(4).inspect_err(|e| println!("{e:?}")); + q.add_item_next(QueueItemType::Test, QueueSource::File); + dbg!(&q.items, &q.items.len()); +} + +#[test] +fn test_() { + let mut q = Queue::new().unwrap(); + for _ in 0..100 { + q.items.push(QueueItem { item: QueueItemType::Song(Uuid::new_v4()), state: QueueState::Played, source: QueueSource::Queue, by_human: false }); + } + for _ in 0..2 { + q.add_item(QueueItemType::Song(Uuid::new_v4()), QueueSource::Library, true).unwrap(); + } + q.add_item_next(QueueItemType::Test, QueueSource::Queue); + + dbg!(&q.items, &q.items.len()); + +} + +#[test] +fn move_test() { + let mut q = Queue::new().unwrap(); + // for _ in 0..1 { + // q.items.push(QueueItem { item: QueueItemType::Song(Uuid::new_v4()), state: QueueState::Played, source: QueueSource::Queue, by_human: false }); + // } + for _ in 0..5 { + q.add_item(QueueItemType::Song(Uuid::new_v4()), QueueSource::Library, true).unwrap(); + } + q.add_item(QueueItemType::Test, QueueSource::Library, true).unwrap(); + dbg!(&q.items, &q.items.len()); + + q.move_to(3).inspect_err(|e| {dbg!(e);}); dbg!(&q.items, &q.items.len()); } \ No newline at end of file diff --git a/src/music_player.rs b/src/music_player.rs index 9893088..e310403 100644 --- a/src/music_player.rs +++ b/src/music_player.rs @@ -180,7 +180,7 @@ impl Player { *position_update.write().unwrap() = None; break }, - PlaybackStats::Idle | PlaybackStats::Switching => println!("waiting!"), + PlaybackStats::Idle | PlaybackStats::Switching => {}, _ => () }