diff --git a/dmp-core/Cargo.toml b/dmp-core/Cargo.toml index afbcf56..0f1c647 100644 --- a/dmp-core/Cargo.toml +++ b/dmp-core/Cargo.toml @@ -37,4 +37,4 @@ futures = "0.3.30" async-channel = "2.3.1" ciborium = "0.2.2" itertools = "0.13.0" -prismriver = { git = "https://github.com/Dangoware/prismriver.git" } +prismriver = { git = "https://github.com/Dangoware/prismriver.git", features = ["ffmpeg"]} diff --git a/dmp-core/src/lib.rs b/dmp-core/src/lib.rs index cc2779c..eea4dd5 100644 --- a/dmp-core/src/lib.rs +++ b/dmp-core/src/lib.rs @@ -11,6 +11,7 @@ pub mod music_storage { pub mod music_controller { pub mod connections; pub mod controller; + pub mod controller_handle; pub mod queue; } diff --git a/dmp-core/src/music_controller/controller.rs b/dmp-core/src/music_controller/controller.rs index 9bbee83..2b7ad7b 100644 --- a/dmp-core/src/music_controller/controller.rs +++ b/dmp-core/src/music_controller/controller.rs @@ -5,7 +5,7 @@ use kushi::{Queue, QueueItemType}; use kushi::{QueueError, QueueItem}; -use prismriver::{Prismriver, Volume}; +use prismriver::{Prismriver, Volume, Error as PrismError}; use rayon::iter::{IndexedParallelIterator, IntoParallelIterator, ParallelIterator}; use serde::{Deserialize, Serialize}; use serde_json::to_string_pretty; @@ -26,6 +26,8 @@ use super::queue::{QueueAlbum, QueueSong}; pub struct Controller(); +type QueueItem_ = QueueItem; + #[derive(Error, Debug)] pub enum ControllerError { #[error("{0:?}")] @@ -83,8 +85,16 @@ pub enum PlayerCommand { #[derive(Debug, PartialEq, Clone)] pub enum PlayerResponse { - Empty, - NowPlaying(Song) + Empty(Result<(), PlayerError>), + NowPlaying(Result) +} + +#[derive(Error, Debug, PartialEq, Clone)] +pub enum PlayerError { + #[error("{0}")] + QueueError(#[from] QueueError), + #[error("{0}")] + Prismriver(#[from] PrismError), } #[derive(Debug, PartialEq, PartialOrd, Clone)] @@ -113,21 +123,21 @@ pub enum LibraryResponse { #[derive(Debug, PartialEq, Clone)] pub enum QueueCommand { - Append(QueueItem, bool), + Append(QueueItem_, bool), Next, Prev, GetIndex(usize), NowPlaying, Get, - Clear + Clear, + Remove(usize), } #[derive(Debug, PartialEq, Clone)] pub enum QueueResponse { - Ok, - Item(QueueItem), - GetAll(Vec>), - Err(QueueError), + Empty(Result<(), QueueError>), + Item(Result), + GetAll(Vec), } @@ -149,9 +159,9 @@ pub struct ControllerInput { } pub struct ControllerHandle { - pub lib_mail: MailMan, - pub player_mail: MailMan, - pub queue_mail: MailMan, + lib_mail: MailMan, + player_mail: MailMan, + queue_mail: MailMan, } impl ControllerHandle { @@ -302,116 +312,136 @@ impl Controller { lib_mail: MailMan, mut state: ControllerState, ) -> Result<(), ()> { - let mut first = true; - { - player.write().unwrap().set_volume(Volume::new(state.volume)); - println!("volume set to {}", state.volume); - } - while true { + player.write().unwrap().set_volume(Volume::new(state.volume)); + println!("volume set to {}", state.volume); + 'outer: while true { let _mail = player_mail.recv().await; if let Ok(mail) = _mail { match mail { PlayerCommand::Play => { player.write().unwrap().play(); - player_mail.send(PlayerResponse::Empty).await.unwrap(); + player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); } + PlayerCommand::Pause => { player.write().unwrap().pause(); - player_mail.send(PlayerResponse::Empty).await.unwrap(); + player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); } + PlayerCommand::SetVolume(volume) => { player.write().unwrap().set_volume(Volume::new(volume)); println!("volume set to {volume}"); - player_mail.send(PlayerResponse::Empty).await.unwrap(); + player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); state.volume = volume; _ = state.write_file() } + PlayerCommand::NextSong => { queue_mail.send(QueueCommand::Next).await.unwrap(); - if let QueueResponse::Item(item) = queue_mail.recv().await.unwrap() { - let uri = match &item.item { - QueueItemType::Single(song) => song.song.primary_uri().unwrap().0, - _ => unimplemented!(), - }; + match queue_mail.recv().await.unwrap() { + QueueResponse::Item(Ok(item)) => { + let uri = match &item.item { + QueueItemType::Single(song) => song.song.primary_uri().unwrap().0, + _ => unimplemented!(), + }; - let prism_uri = prismriver::utils::path_to_uri(&uri.as_path().unwrap()).unwrap(); - println!("Playing song at path: {:?}", prism_uri); - player.write().unwrap().load_new(&prism_uri).unwrap(); - player.write().unwrap().play(); + let prism_uri = prismriver::utils::path_to_uri(&uri.as_path().unwrap()).unwrap(); + println!("Playing song at path: {:?}", prism_uri); - let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")}; + // handle error here for unknown formats + player.write().unwrap().load_new(&prism_uri).unwrap(); + player.write().unwrap().play(); - // Append next song in library - lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); + let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")}; - let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else { - continue; - }; - lib_mail.send(LibraryCommand::Song(np_song.song.uuid)).await.unwrap(); - let LibraryResponse::Song(_, i) = lib_mail.recv().await.unwrap() else { - unreachable!() - }; - if let Some(song) = songs.get(i + 49) { - queue_mail.send( - QueueCommand::Append( - QueueItem::from_item_type( - QueueItemType::Single( - QueueSong { - song: song.clone(), - location: np_song.location - } - ) - ), - false - ) - ).await - .unwrap(); - let QueueResponse::Ok = queue_mail.recv().await.unwrap() else { + // Append next song in library + lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); + let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else { + continue; + }; + lib_mail.send(LibraryCommand::Song(np_song.song.uuid)).await.unwrap(); + let LibraryResponse::Song(_, i) = lib_mail.recv().await.unwrap() else { unreachable!() }; - } else { - println!("Library Empty"); - } + if let Some(song) = songs.get(i + 49) { + queue_mail.send( + QueueCommand::Append( + QueueItem::from_item_type( + QueueItemType::Single( + QueueSong { + song: song.clone(), + location: np_song.location + } + ) + ), + false + ) + ).await + .unwrap(); + let QueueResponse::Empty(Ok(())) = queue_mail.recv().await.unwrap() else { + unreachable!() + }; + } else { + println!("Library Empty"); + } - player_mail.send(PlayerResponse::NowPlaying(np_song.song.clone())).await.unwrap(); + player_mail.send(PlayerResponse::NowPlaying(Ok(np_song.song.clone()))).await.unwrap(); + } QueueResponse::Item(Err(e)) => { + player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + } + _ => continue } } + PlayerCommand::PrevSong => { queue_mail.send(QueueCommand::Prev).await.unwrap(); + match queue_mail.recv().await.unwrap() { + QueueResponse::Item(Ok(item)) => { + let uri = match &item.item { + QueueItemType::Single(song) => song.song.primary_uri().unwrap().0, + _ => unimplemented!(), + }; - if let QueueResponse::Item(item) = queue_mail.recv().await.unwrap() { - let uri = match &item.item { - QueueItemType::Single(song) => song.song.primary_uri().unwrap().0, - _ => unimplemented!(), - }; + let prism_uri = prismriver::utils::path_to_uri(&uri.as_path().unwrap()).unwrap(); + player.write().unwrap().load_new(&prism_uri).unwrap(); + player.write().unwrap().play(); - let prism_uri = prismriver::utils::path_to_uri(&uri.as_path().unwrap()).unwrap(); - player.write().unwrap().load_new(&prism_uri).unwrap(); - player.write().unwrap().play(); - - let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")}; - player_mail.send(PlayerResponse::NowPlaying(np_song.song.clone())).await.unwrap(); + let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")}; + player_mail.send(PlayerResponse::NowPlaying(Ok(np_song.song.clone()))).await.unwrap(); + } + QueueResponse::Item(Err(e)) => { + player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + } + _ => continue } } + PlayerCommand::Enqueue(index) => { queue_mail .send(QueueCommand::GetIndex(index)) .await .unwrap(); - if let QueueResponse::Item(item) = queue_mail.recv().await.unwrap() { - match item.item { - QueueItemType::Single(song) => { - let prism_uri = prismriver::utils::path_to_uri(&song.song.primary_uri().unwrap().0.as_path().unwrap()).unwrap(); - player.write().unwrap().load_new(&prism_uri).unwrap(); - player.write().unwrap().play(); + match queue_mail.recv().await.unwrap() { + QueueResponse::Item(Ok(item)) => { + match item.item { + QueueItemType::Single(song) => { + let prism_uri = prismriver::utils::path_to_uri(&song.song.primary_uri().unwrap().0.as_path().unwrap()).unwrap(); + player.write().unwrap().load_new(&prism_uri).unwrap(); + player.write().unwrap().play(); + } + _ => unimplemented!(), } - _ => unimplemented!(), + player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); } - player_mail.send(PlayerResponse::Empty).await.unwrap(); + QueueResponse::Item(Err(e)) => { + player_mail.send(PlayerResponse::Empty(Err(e.into()))).await.unwrap(); + } + _ => continue } } + PlayerCommand::PlayNow(uuid, location) => { // TODO: This assumes the uuid doesn't point to an album. we've been over this. lib_mail.send(LibraryCommand::Song(uuid)).await.unwrap(); @@ -419,13 +449,23 @@ impl Controller { unreachable!() }; queue_mail.send(QueueCommand::Clear).await.unwrap(); - let QueueResponse::Ok = queue_mail.recv().await.unwrap() else { - unreachable!() - }; + match queue_mail.recv().await.unwrap() { + QueueResponse::Empty(Ok(())) => (), + QueueResponse::Empty(Err(e)) => { + player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + continue; + } + _ => unreachable!() + } queue_mail.send(QueueCommand::Append(QueueItem::from_item_type(QueueItemType::Single(QueueSong { song: song.clone(), location })), true)).await.unwrap(); - let QueueResponse::Ok = queue_mail.recv().await.unwrap() else { - unreachable!() - }; + match queue_mail.recv().await.unwrap() { + QueueResponse::Empty(Ok(())) => (), + QueueResponse::Empty(Err(e)) => { + player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + continue; + } + _ => unreachable!() + } // TODO: Handle non Local URIs here, and whenever `load_new()` or `load_gapless()` is called let prism_uri = prismriver::utils::path_to_uri(&song.primary_uri().unwrap().0.as_path().unwrap()).unwrap(); @@ -459,16 +499,21 @@ impl Controller { for i in index+1..(index+50) { if let Some(song) = songs.get(i) { queue_mail.send(QueueCommand::Append(QueueItem::from_item_type(QueueItemType::Single(QueueSong { song: song.clone(), location })), false)).await.unwrap(); - let QueueResponse::Ok = queue_mail.recv().await.unwrap() else { - unreachable!() - }; + match queue_mail.recv().await.unwrap() { + QueueResponse::Empty(Ok(())) => (), + QueueResponse::Empty(Err(e)) => { + player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + continue 'outer; + } + _ => unreachable!() + } } else { println!("End of Library / Playlist"); break; } } // ^ This be my solution for now ^ - player_mail.send(PlayerResponse::NowPlaying(song.clone())).await.unwrap(); + player_mail.send(PlayerResponse::NowPlaying(Ok(song.clone()))).await.unwrap(); } } } else { @@ -540,32 +585,32 @@ impl Controller { _ => unimplemented!(), } queue_mail - .send(QueueResponse::Ok) + .send(QueueResponse::Empty(Ok(()))) .await .unwrap(); }, QueueCommand::Next => { - let next = queue.next().unwrap(); + let next = queue.next().map_or( Err(QueueError::NoNext), |s| Ok(s.clone())); queue_mail .send(QueueResponse::Item(next.clone())) .await .unwrap(); } QueueCommand::Prev => { - let next = queue.prev().unwrap(); + let prev = queue.prev().map_or( Err(QueueError::EmptyPlayed), |s| Ok(s.clone())); queue_mail - .send(QueueResponse::Item(next.clone())) + .send(QueueResponse::Item(prev.clone())) .await .unwrap(); } QueueCommand::GetIndex(index) => { - let item = queue.items.get(index).expect("No item in the queue at index {index}").clone(); + let item = queue.items.get(index).map_or( Err(QueueError::OutOfBounds { index, len: queue.items.len() }), |s| Ok(s.clone())); queue_mail.send(QueueResponse::Item(item)).await.unwrap(); } QueueCommand::NowPlaying => { - let item = queue.current().unwrap(); + let item = queue.current().map(|t| t.clone()); queue_mail - .send(QueueResponse::Item(item.clone())) + .send(QueueResponse::Item(item)) .await .unwrap(); } @@ -574,7 +619,10 @@ impl Controller { } QueueCommand::Clear => { queue.clear(); - queue_mail.send(QueueResponse::Ok).await.unwrap(); + queue_mail.send(QueueResponse::Empty(Ok(()))).await.unwrap(); + } + QueueCommand::Remove(index) => { + queue_mail.send(QueueResponse::Item(queue.remove_item(index))).await.unwrap(); } } } diff --git a/dmp-core/src/music_controller/controller_handle.rs b/dmp-core/src/music_controller/controller_handle.rs new file mode 100644 index 0000000..fcb289e --- /dev/null +++ b/dmp-core/src/music_controller/controller_handle.rs @@ -0,0 +1,131 @@ +use std::path::PathBuf; + +use kushi::{QueueError, QueueItem}; +use uuid::Uuid; + +use crate::music_storage::{library::Song, playlist::ExternalPlaylist}; + +use super::{controller::{ControllerHandle, LibraryCommand, LibraryResponse, PlayerCommand, PlayerError, PlayerLocation, PlayerResponse, QueueCommand, QueueResponse}, queue::{QueueAlbum, QueueSong}}; + +impl ControllerHandle { + // The Library Section + pub async fn lib_get_song(&self, uuid: Uuid) -> (Song, usize) { + self.lib_mail.send(LibraryCommand::Song(uuid)).await.unwrap(); + let LibraryResponse::Song(song, index) = self.lib_mail.recv().await.unwrap() else { + unreachable!() + }; + (song, index) + } + + pub async fn lib_get_all(&self) -> Vec { + self.lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); + let LibraryResponse::AllSongs(songs) = self.lib_mail.recv().await.unwrap() else { + unreachable!("It has been reached") + }; + songs + } + + pub async fn lib_save(&self) { + self.lib_mail.send(LibraryCommand::Save).await.unwrap(); + let LibraryResponse::Ok = self.lib_mail.recv().await.unwrap() else { + unreachable!() + }; + } + + // The Playlist Section + pub async fn playlist_get(&self, uuid: Uuid) -> Result { + self.lib_mail.send(LibraryCommand::ExternalPlaylist(uuid)).await.unwrap(); + let LibraryResponse::ExternalPlaylist(playlist) = self.lib_mail.recv().await.unwrap() else { + unreachable!() + }; + Ok(playlist) + } + + /// Returns a `Vec<(Uuid, String)>` containing the Uuid of the playlist and the name after + pub async fn playlist_get_all(&self) -> Vec<(Uuid, String)> { + self.lib_mail.send(LibraryCommand::Playlists).await.unwrap(); + let LibraryResponse::Playlists(lists) = self.lib_mail.recv().await.unwrap() else { + unreachable!() + }; + lists + } + + pub async fn playlist_import_m3u(&self, path: PathBuf) -> Result<(Uuid, String), ()> { + self.lib_mail.send(LibraryCommand::ImportM3UPlayList(path)).await.unwrap(); + let LibraryResponse::ImportM3UPlayList(uuid, name) = self.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") }; + Ok((uuid, name)) + } + + // The Queue Section + pub async fn queue_append(&self, item: QueueItem) -> Result<(), QueueError> { + self.queue_mail.send(QueueCommand::Append(item, true)).await.unwrap(); + let QueueResponse::Empty(res) = self.queue_mail.recv().await.unwrap() else { + unreachable!() + }; + res + } + + pub async fn queue_remove(&self, index: usize) -> Result, QueueError> { + self.queue_mail.send(QueueCommand::Remove(index)).await.unwrap(); + let QueueResponse::Item(res) = self.queue_mail.recv().await.unwrap() else { + unreachable!() + }; + res + } + + pub async fn queue_get_all(&self) -> Vec> { + self.queue_mail.send(QueueCommand::Get).await.unwrap(); + let QueueResponse::GetAll(queue) = self.queue_mail.recv().await.unwrap() else { + unreachable!() + }; + queue + } + + // The Player Section + pub async fn play_now(&self, uuid: Uuid, location: PlayerLocation) -> Result { + self.player_mail.send(PlayerCommand::PlayNow(uuid, location)).await.unwrap(); + let PlayerResponse::NowPlaying(res) = self.player_mail.recv().await.unwrap() else { + unreachable!() + }; + res + } + + pub async fn play(&self) -> Result<(), PlayerError> { + self.player_mail.send(PlayerCommand::Play).await.unwrap(); + let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else { + unreachable!() + }; + res + } + + pub async fn pause(&self) -> Result<(), PlayerError> { + self.player_mail.send(PlayerCommand::Pause).await.unwrap(); + let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else { + unreachable!() + }; + res + } + + pub async fn set_volume(&self, volume: f32) -> () { + self.player_mail.send(PlayerCommand::SetVolume(volume)).await.unwrap(); + let PlayerResponse::Empty(Ok(())) = self.player_mail.recv().await.unwrap() else { + unreachable!() + }; + } + + pub async fn next(&self) -> Result { + self.player_mail.send(PlayerCommand::NextSong).await.unwrap(); + let PlayerResponse::NowPlaying(res) = self.player_mail.recv().await.unwrap() else { + unreachable!() + }; + res + } + + pub async fn prev(&self) -> Result { + self.player_mail.send(PlayerCommand::PrevSong).await.unwrap(); + let PlayerResponse::NowPlaying(res) = self.player_mail.recv().await.unwrap() else { + unreachable!() + }; + res + } +} \ No newline at end of file diff --git a/src-tauri/src/commands.rs b/src-tauri/src/commands.rs index 4e57ed1..08fd437 100644 --- a/src-tauri/src/commands.rs +++ b/src-tauri/src/commands.rs @@ -10,23 +10,20 @@ use crate::wrappers::_Song; #[tauri::command] pub async fn add_song_to_queue(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>, uuid: Uuid, location: PlayerLocation) -> Result<(), String> { dbg!(&location); - ctrl_handle.lib_mail.send(dmp_core::music_controller::controller::LibraryCommand::Song(uuid)).await.unwrap(); - let LibraryResponse::Song(song, _) = ctrl_handle.lib_mail.recv().await.unwrap() else { - unreachable!() - }; - ctrl_handle.queue_mail.send(dmp_core::music_controller::controller::QueueCommand::Append(QueueItem::from_item_type(kushi::QueueItemType::Single(QueueSong { song, location })), true)).await.unwrap(); - let QueueResponse::Ok = ctrl_handle.queue_mail.recv().await.unwrap() else { - panic!() - }; + let (song, _) = ctrl_handle.lib_get_song(uuid).await; + match ctrl_handle.queue_append(QueueItem::from_item_type(kushi::QueueItemType::Single(QueueSong { song, location }))).await { + Ok(()) => (), + Err(e) => return Err(e.to_string()) + } app.emit("queue_updated", ()).unwrap(); Ok(()) } #[tauri::command] pub async fn play_now(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>, uuid: Uuid, location: PlayerLocation) -> Result<(), String> { - ctrl_handle.player_mail.send(PlayerCommand::PlayNow(uuid, location)).await.unwrap(); - let PlayerResponse::NowPlaying(song) = ctrl_handle.player_mail.recv().await.unwrap() else { - unreachable!() + let song = match ctrl_handle.play_now(uuid, location).await { + Ok(song) => song, + Err(e) => return Err(e.to_string()) }; app.emit("queue_updated", ()).unwrap(); app.emit("now_playing_change", _Song::from(&song)).unwrap(); diff --git a/src-tauri/src/wrappers.rs b/src-tauri/src/wrappers.rs index 0218634..c982e73 100644 --- a/src-tauri/src/wrappers.rs +++ b/src-tauri/src/wrappers.rs @@ -13,35 +13,31 @@ pub struct ArtworkRx(pub Sender>); #[tauri::command] pub async fn play(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>) -> Result<(), String> { - ctrl_handle.player_mail.send(dmp_core::music_controller::controller::PlayerCommand::Play).await.unwrap(); - let res = ctrl_handle.player_mail.recv().await.unwrap(); - if let PlayerResponse::Empty = res {} - else if let PlayerResponse::NowPlaying(song) = res { - app.emit("now_playing_change", _Song::from(&song)).unwrap(); - } else { - unreachable!() - }; - app.emit("playing", ()).unwrap(); - Ok(()) + match ctrl_handle.play().await { + Ok(()) => { + app.emit("playing", ()).unwrap(); + Ok(()) + }, + Err(e) => Err(e.to_string()) + } } #[tauri::command] pub async fn pause(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>) -> Result<(), String> { - ctrl_handle.player_mail.send(dmp_core::music_controller::controller::PlayerCommand::Pause).await.unwrap(); - let PlayerResponse::Empty = ctrl_handle.player_mail.recv().await.unwrap() else { - unreachable!() - }; - app.emit("paused", ()).unwrap(); - Ok(()) + match ctrl_handle.pause().await { + Ok(()) => { + app.emit("paused", ()).unwrap(); + Ok(()) + } + Err(e) => Err(e.to_string()) + } + } #[tauri::command] pub async fn set_volume(ctrl_handle: State<'_, ControllerHandle>, volume: String) -> Result<(), String> { let volume = volume.parse::().unwrap() / 100.0; - ctrl_handle.player_mail.send(dmp_core::music_controller::controller::PlayerCommand::SetVolume(volume)).await.unwrap(); - let PlayerResponse::Empty = ctrl_handle.player_mail.recv().await.unwrap() else { - unreachable!() - }; + ctrl_handle.set_volume(volume).await; Ok(()) } @@ -53,11 +49,10 @@ pub async fn get_volume(ctrl_handle: State<'_, ControllerHandle>) -> Result<(), #[tauri::command] pub async fn next(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>) -> Result<(), String> { - ctrl_handle.player_mail.send(dmp_core::music_controller::controller::PlayerCommand::NextSong).await.unwrap(); - let PlayerResponse::NowPlaying(song) = ctrl_handle.player_mail.recv().await.unwrap() else { - return Ok(()) + let song = match ctrl_handle.next().await { + Ok(s) => s, + Err(e) => return Err(e.to_string()) }; - println!("next"); app.emit("now_playing_change", _Song::from(&song)).unwrap(); app.emit("queue_updated", ()).unwrap(); app.emit("playing", ()).unwrap(); @@ -66,9 +61,9 @@ pub async fn next(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>) #[tauri::command] pub async fn prev(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>) -> Result<(), String> { - ctrl_handle.player_mail.send(dmp_core::music_controller::controller::PlayerCommand::PrevSong).await.unwrap(); - let PlayerResponse::NowPlaying(song) = ctrl_handle.player_mail.recv().await.unwrap() else { - unreachable!() + let song = match ctrl_handle.prev().await { + Ok(s) => s, + Err(e) => return Err(e.to_string()) }; println!("prev"); app.emit("now_playing_change", _Song::from(&song)).unwrap(); @@ -84,14 +79,28 @@ pub async fn now_playing(ctrl_handle: State<'_, ControllerHandle>) -> Result<(), #[tauri::command] pub async fn get_queue(ctrl_handle: State<'_, ControllerHandle>) -> Result, String> { - ctrl_handle.queue_mail.send(QueueCommand::Get).await.unwrap(); - let QueueResponse::GetAll(queue) = ctrl_handle.queue_mail.recv().await.unwrap() else { - unreachable!() - }; - Ok(queue.into_iter().map(|item| { - let QueueItemType::Single(song) = item.item else { unreachable!("There should be no albums in the queue right now") }; - _Song::from(&song.song) - }).collect_vec()) + Ok( + ctrl_handle + .queue_get_all() + .await + .into_iter() + .map(|item| { + let QueueItemType::Single(song) = item.item else { unreachable!("There should be no albums in the queue right now") }; + _Song::from(&song.song) + } + ).collect_vec() + ) +} + +#[tauri::command] +pub async fn remove_from_queue(app: AppHandle, ctrl_handle: ControllerHandle, index: usize) -> Result<(), String> { + match ctrl_handle.queue_remove(index).await { + Ok(_) => { + app.emit("queue_updated", ()).unwrap(); + Ok(()) + } + Err(e) => Err(e.to_string()) + } } //Grab Album art from custom protocol @@ -129,19 +138,21 @@ impl From<&Song> for _Song { #[tauri::command] pub async fn get_library(ctrl_handle: State<'_, ControllerHandle>) -> Result, String> { - ctrl_handle.lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); - println!("getting library"); - let LibraryResponse::AllSongs(songs) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") }; - - let _songs = songs.iter().map(|song| _Song::from(song)).collect::>(); - - Ok(_songs) + let songs = ctrl_handle + .lib_get_all() + .await + .iter() + .map(|song| _Song::from(song)) + .collect_vec(); + Ok(songs) } #[tauri::command] pub async fn get_playlist(ctrl_handle: State<'_, ControllerHandle>, uuid: Uuid) -> Result, String> { - ctrl_handle.lib_mail.send(LibraryCommand::ExternalPlaylist(uuid)).await.unwrap(); - let LibraryResponse::ExternalPlaylist(playlist) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") }; + let playlist = match ctrl_handle.playlist_get(uuid).await { + Ok(list) => list, + Err(_) => todo!() + }; let songs = playlist.tracks.iter().map(|song| _Song::from(song)).collect::>(); println!("Got Playlist {}, len {}", playlist.title, playlist.tracks.len()); @@ -150,11 +161,7 @@ pub async fn get_playlist(ctrl_handle: State<'_, ControllerHandle>, uuid: Uuid) #[tauri::command] pub async fn get_playlists(app: AppHandle, ctrl_handle: State<'_, ControllerHandle>) -> Result<(), String> { - println!("getting Playlists"); - ctrl_handle.lib_mail.send(LibraryCommand::Playlists).await.unwrap(); - let LibraryResponse::Playlists(lists) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!() }; - println!("gotten playlists"); - + let lists = ctrl_handle.playlist_get_all().await; app.emit("playlists_gotten", lists.into_iter().map(|(uuid, name)| PlaylistPayload { uuid, name }).collect_vec()).unwrap(); Ok(()) } @@ -168,10 +175,9 @@ pub async fn import_playlist(ctrl_handle: State<'_, ControllerHandle>) -> Result .await .unwrap(); - ctrl_handle.lib_mail.send(LibraryCommand::ImportM3UPlayList(PathBuf::from(file.path()))).await.unwrap(); - let LibraryResponse::ImportM3UPlayList(uuid, name) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") }; - ctrl_handle.lib_mail.send(LibraryCommand::Save).await.unwrap(); - let LibraryResponse::Ok = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!() }; + let (uuid, name) = ctrl_handle.playlist_import_m3u(PathBuf::from(file.path())).await.unwrap(); + ctrl_handle.lib_save().await; + println!("Imported Playlist {name}"); Ok(PlaylistPayload {uuid, name}) } @@ -183,9 +189,8 @@ pub struct PlaylistPayload { } #[tauri::command] -pub async fn get_song(ctrl_handle: State<'_, ControllerHandle>) -> Result<_Song, String> { - ctrl_handle.lib_mail.send(LibraryCommand::Song(Uuid::default())).await.unwrap(); - let LibraryResponse::Song(song, _) = ctrl_handle.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") }; +pub async fn get_song(ctrl_handle: State<'_, ControllerHandle>, uuid: Uuid) -> Result<_Song, String> { + let song = ctrl_handle.lib_get_song(uuid).await.0; println!("got song {}", &song.tags.get(&Tag::Title).unwrap_or(&String::new())); Ok(_Song::from(&song)) }