From e97075401d02e970d0d6ce59523796ccad362a2d Mon Sep 17 00:00:00 2001 From: MrDulfin Date: Sun, 7 Jul 2024 19:27:13 -0400 Subject: [PATCH] updated Kushi, mode changes to the moved location field to wrapper structs rather than as part of the queue --- Cargo.toml | 2 +- src/lib.rs | 2 +- src/music_controller/controller.rs | 23 +- src/music_controller/queue.rs | 412 ++--------------------------- 4 files changed, 28 insertions(+), 411 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index d810a1e..b4ab8d0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -48,4 +48,4 @@ tempfile = "3.10.1" listenbrainz = "0.7.0" discord-rpc-client = "0.4.0" nestify = "0.3.3" -kushi = "0.1.2" +kushi = "0.1.3" diff --git a/src/lib.rs b/src/lib.rs index d25f68f..6f93ec1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,7 @@ pub mod music_storage { pub mod music_controller { pub mod controller; pub mod connections; - // pub mod queue; + pub mod queue; } pub mod music_player { diff --git a/src/music_controller/controller.rs b/src/music_controller/controller.rs index 97af6e1..74c3c62 100644 --- a/src/music_controller/controller.rs +++ b/src/music_controller/controller.rs @@ -4,8 +4,7 @@ use crossbeam_channel; use crossbeam_channel::{Receiver, Sender}; -use kushi::error::QueueError; -use kushi::Location; +use kushi::QueueError; use kushi::{Queue, QueueItemType}; use std::path::PathBuf; use std::sync::{Arc, Mutex, RwLock}; @@ -18,13 +17,15 @@ use uuid::Uuid; use crate::config::ConfigError; use crate::music_player::player::{Player, PlayerCommand, PlayerError}; -use crate::music_storage::library::{Album, Song}; use crate::{ config::Config, music_storage::library::MusicLibrary, }; +use super::queue::{QueueAlbum, QueueSong}; + + pub struct Controller { - pub queue: Arc>>, + pub queue: Arc>>, pub config: Arc>, pub library: MusicLibrary, pub player: Arc>, @@ -51,8 +52,6 @@ pub enum PlayerLocation { Custom, } -impl Location for PlayerLocation {} - #[derive(Debug)] pub(super) struct MailMan { pub tx: Sender, @@ -99,7 +98,7 @@ impl Controller

{ let config_ = Arc::new(RwLock::from(config)); let library = MusicLibrary::init(config_.clone(), uuid)?; - let queue: Queue = Queue { + let queue: Queue = Queue { items: Vec::new(), played: Vec::new(), loop_: false, @@ -135,7 +134,7 @@ impl Controller

{ .unwrap() .enqueue_next(&{ match uri.item { - QueueItemType::Single(song) => song.primary_uri().unwrap().0.clone(), + QueueItemType::Single(song) => song.song.primary_uri().unwrap().0.clone(), _ => unimplemented!() } }) @@ -152,9 +151,9 @@ impl Controller

{ Ok(controller) } - pub fn q_add(&mut self, item: &Uuid, source: Option, by_human: bool) { + pub fn q_add(&mut self, item: &Uuid, source: PlayerLocation, by_human: bool) { let item = self.library.query_uuid(item).unwrap().0.to_owned(); - self.queue.write().unwrap().add_item(item, source, by_human) + self.queue.write().unwrap().add_item(QueueSong { song: item, location: source }, by_human) } } @@ -162,7 +161,7 @@ impl Controller

{ mod test_super { use std::{thread::sleep, time::Duration}; - use crate::{config::tests::read_config_lib, music_controller::controller::PlayerLocation, music_player::{gstreamer::GStreamer, player::Player}}; + use crate::{config::tests::read_config_lib, music_controller::controller::{PlayerLocation, QueueSong}, music_player::{gstreamer::GStreamer, player::Player}}; use super::Controller; @@ -177,7 +176,7 @@ mod test_super { { let mut queue = controller.queue.write().unwrap(); for x in config.1.library { - queue.add_item(x, Some(PlayerLocation::Library), true); + queue.add_item(QueueSong { song: x, location: PlayerLocation::Library }, true); } } { diff --git a/src/music_controller/queue.rs b/src/music_controller/queue.rs index d13ab35..27f8075 100644 --- a/src/music_controller/queue.rs +++ b/src/music_controller/queue.rs @@ -1,407 +1,25 @@ -use crate::music_storage::library::Song; -use uuid::Uuid; - -use thiserror::Error; - -#[derive(Error, Debug)] -pub enum QueueError { - #[error("Index out of bounds! Index {index} is over len {len}")] - OutOfBounds { index: usize, len: usize }, - #[error("The Queue is empty!")] - EmptyQueue, - #[error("There are no past played songs!")] - EmptyPlayed, - #[error("There is no item after this in the Queue")] - NoNext, -} - -#[derive(Debug, PartialEq, Clone, Copy)] -pub enum QueueState { - Played, - First, - AddHere, - NoState, -} +use std::vec::IntoIter; +use crate::music_storage::library::{Album, AlbumTrack, Song}; +use super::controller::PlayerLocation; #[derive(Debug, Clone, PartialEq)] -#[non_exhaustive] -pub struct QueueItem { - pub(super) item: Song, - pub(super) state: QueueState, - pub(super) source: PlayerLocation, - pub(super) by_human: bool, +pub struct QueueSong { + pub song: Song, + pub location: PlayerLocation, } -impl QueueItem { - fn from_song(song: Song, source: PlayerLocation) -> Self { - QueueItem { - item: song, - state: QueueState::NoState, - source, - by_human: false, - } - } +#[derive(Debug, Clone, PartialEq)] +pub struct QueueAlbum { + pub album: Album, + pub location: PlayerLocation, } -#[derive(Debug, Default)] -pub struct Queue { - pub items: Vec, - pub played: Vec, - pub loop_: bool, - pub shuffle: Option>, -} - -// TODO: HAndle the First QueueState[looping] and shuffle -impl Queue { - fn has_addhere(&self) -> bool { - for item in &self.items { - if item.state == QueueState::AddHere { - return true; - } - } - false - } - - #[allow(unused)] - pub(super) fn dbg_items(&self) { - dbg!( - self.items - .iter() - .map(|item| (item.item.uuid, item.state)) - .collect::>(), - self.items.len() - ); - } - - pub fn set_items(&mut self, tracks: Vec) { - let mut tracks = tracks; - self.items.clear(); - self.items.append(&mut tracks); - } - - /// Inserts an item after the AddHere item - pub fn add_item(&mut self, item: Song, source: PlayerLocation, by_human: bool) { - let mut i: usize = 0; - - 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 == QueueState::AddHere { - i = j; - item_.state = QueueState::NoState; - } - item_ - }) - .collect::>(); - - self.items.insert( - i + if self.items.is_empty() { 0 } else { 1 }, - QueueItem { - item, - state: QueueState::AddHere, - source, - by_human, - }, - ); - } - - /// Inserts an item after the currently playing item - pub fn add_item_next(&mut self, item: Song, source: PlayerLocation) { - use QueueState::*; - let empty = self.items.is_empty(); - - self.items.insert( - if empty { 0 } else { 1 }, - QueueItem { - item, - state: if (self.items.get(1).is_none() - || !self.has_addhere() && self.items.get(1).is_some()) - || empty - { - AddHere - } else { - NoState - }, - source, - by_human: true, - }, - ) - } - - pub fn add_multi(&mut self, items: Vec, source: PlayerLocation, by_human: bool) { - let mut i: usize = 0; - - 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 == QueueState::AddHere { - i = j; - item_.state = QueueState::NoState; - } - item_ - }) - .collect::>(); - - let empty = self.items.is_empty(); - - let len = items.len(); - for item in items.into_iter().rev() { - self.items.insert( - i + if empty { 0 } else { 1 }, - QueueItem { - item, - state: QueueState::NoState, - source, - by_human, - }, - ); - } - self.items[i + len - if empty { 1 } else { 0 }].state = QueueState::AddHere; - } - - /// Add multiple Songs after the currently playing Song - pub fn add_multi_next(&mut self, items: Vec, source: PlayerLocation) { - use QueueState::*; - let empty = self.items.is_empty(); - - let add_here = (self.items.get(1).is_none() - || !self.has_addhere() && self.items.get(1).is_some()) - || empty; - - let len = items.len(); - - for item in items { - self.items.insert( - if empty { 0 } else { 1 }, - QueueItem { - item, - state: NoState, - source, - by_human: true, - }, - ) - } - - if add_here { - self.items[len - if empty { 1 } else { 0 }].state = QueueState::AddHere; - } - } - - pub fn remove_item(&mut self, remove_index: usize) -> Result { - // dbg!(/*&remove_index, self.current_index(), &index,*/ &self.items[remove_index]); - - if remove_index < self.items.len() { - // update the state of the next item to replace the item being removed - if self.items.get(remove_index + 1).is_some() { - self.items[remove_index + 1].state = self.items[remove_index].state; - } - Ok(self.items.remove(remove_index)) - } else { - Err(QueueError::EmptyQueue) - } - } - - pub fn insert( - &mut self, - index: usize, - new_item: Song, - source: PlayerLocation, - addhere: bool, - ) -> Result<(), QueueError> { - if self.items.get_mut(index).is_none() - && index > 0 - && self.items.get_mut(index - 1).is_none() - { - return Err(QueueError::OutOfBounds { - index, - len: self.items.len(), - }); - } - if addhere { - let mut new_item = QueueItem::from_song(new_item, source); - for item in &mut self.items { - if item.state == QueueState::AddHere { - item.state = QueueState::NoState - } - } - new_item.state = QueueState::AddHere; - self.items.insert(index, new_item); - } else { - let new_item = QueueItem::from_song(new_item, source); - self.items.insert(index, new_item); - } - Ok(()) - } - - pub fn clear(&mut self) { - self.items.clear(); - } - - pub fn clear_except(&mut self, index: usize) -> Result<(), QueueError> { - use QueueState::*; - let empty = self.items.is_empty(); - - if !empty && index < self.items.len() { - let i = self.items[index].clone(); - self.items.retain(|item| *item == i); - self.items[0].state = AddHere; - } else if empty { - return Err(QueueError::EmptyQueue); - } else { - return Err(QueueError::OutOfBounds { - index, - len: self.items.len(), - }); - } - Ok(()) - } - - pub fn clear_played(&mut self) { - self.played.clear(); - } - - pub fn clear_all(&mut self) { - self.items.clear(); - self.played.clear(); - } - - pub fn move_to(&mut self, index: usize) -> Result<(), QueueError> { - use QueueState::*; - - let empty = self.items.is_empty(); - - let index = if !empty { - index - } else { - return Err(QueueError::EmptyQueue); - }; - - if !empty && dbg!(index < self.items.len()) { - let to_item = self.items[index].clone(); - - loop { - let empty = self.items.is_empty(); - let item = self.items[0].item.to_owned(); - - if item != to_item.item && !empty { - if self.items[0].state == AddHere && self.items.get(1).is_some() { - self.items[1].state = AddHere; - } - let item = self.items.remove(0); - self.played.push(item); - - // dbg!(&to_item.item, &self.items[ind].item); - } else if empty { - return Err(QueueError::EmptyQueue); - } else { - break; - } - } - } else { - return Err(QueueError::EmptyQueue); - } - Ok(()) - } - - pub fn swap(&mut self, a: usize, b: usize) { - self.items.swap(a, b) - } - - pub fn move_item(&mut self, from: usize, to: usize) { - let item = self.items[from].to_owned(); - if from != to { - self.items.remove(from); - } - self.items.insert(to, item); - } - - #[allow(clippy::should_implement_trait)] - pub fn next(&mut self) -> Result<&QueueItem, QueueError> { - if self.items.is_empty() { - if self.loop_ { - unimplemented!() // TODO: add function to loop the queue - } else { - return Err(QueueError::EmptyQueue); - } - } - - if self.items[0].state == QueueState::AddHere || !self.has_addhere() { - self.items[0].state = QueueState::NoState; - if self.items.get_mut(1).is_some() { - self.items[1].state = QueueState::AddHere; - } - } - let item = self.items.remove(0); - self.played.push(item); - - if self.items.is_empty() { - Err(QueueError::NoNext) - } else { - Ok(&self.items[0]) - } - } - - pub fn prev(&mut self) -> Result<&QueueItem, QueueError> { - if let Some(item) = self.played.pop() { - if item.state == QueueState::First && self.loop_ { - todo!() - } - self.items.insert(0, item); - Ok(&self.items[0]) - } else { - Err(QueueError::EmptyPlayed) - } - } - - pub fn now_playing(&self) -> Result<&QueueItem, QueueError> { - if !self.items.is_empty() { - Ok(&self.items[0]) - } else { - Err(QueueError::EmptyQueue) - } - } - - pub fn check_played(&mut self) { - while self.played.len() > 50 { - self.played.remove(0); - } - } -} - -#[cfg(test)] -mod test_super { - #![allow(unused)] - use crate::{ - config::tests::{new_config_lib, read_config_lib}, - music_storage::library, - }; - - use super::*; - - #[test] - fn move_test() { - let (_, library) = read_config_lib(); - let mut q = Queue::default(); - - q.insert(0, library.library[2].to_owned(), PlayerLocation::File, true) - .inspect_err(|e| println!("{e}")); - q.insert(1, library.library[2].to_owned(), PlayerLocation::File, true) - .inspect_err(|e| println!("{e}")); - // q.next(); - // q.clear(); - q.dbg_items(); - dbg!(&q.played.len()); - - // q.dbg_items(); +impl IntoIterator for QueueAlbum { + type Item = AlbumTrack; + type IntoIter = IntoIter; + fn into_iter(self) -> Self::IntoIter { + self.album.into_iter() } }