From eed00bc336e77b1095adceb785f0c2082a1a4cbf Mon Sep 17 00:00:00 2001 From: MrDulfin Date: Tue, 31 Dec 2024 01:16:27 -0500 Subject: [PATCH] Changed command input system to send in senders with commands. This prevents race conditions casing incorrect responses to be recieved --- dmp-core/src/music_controller/controller.rs | 193 ++++++++++-------- .../src/music_controller/controller_handle.rs | 140 ++++++++++--- src-tauri/src/lib.rs | 5 +- 3 files changed, 215 insertions(+), 123 deletions(-) diff --git a/dmp-core/src/music_controller/controller.rs b/dmp-core/src/music_controller/controller.rs index 315c7db..c45c6e7 100644 --- a/dmp-core/src/music_controller/controller.rs +++ b/dmp-core/src/music_controller/controller.rs @@ -28,6 +28,7 @@ use crate::music_storage::playlist::{ExternalPlaylist, Playlist, PlaylistFolderI use crate::{config::Config, music_storage::library::MusicLibrary}; use super::connections::{ConnectionsInput, ConnectionsNotification, ControllerConnections}; +use super::controller_handle::{LibraryCommandInput, PlayerCommandInput, QueueCommandInput}; use super::queue::{QueueAlbum, QueueSong}; pub struct Controller(); @@ -151,16 +152,16 @@ pub enum QueueResponse { pub struct ControllerInput { player_mail: ( - MailMan, - MailMan, + async_channel::Sender, + async_channel::Receiver ), lib_mail: ( - MailMan, - MailMan + async_channel::Sender, + async_channel::Receiver ), queue_mail: ( - MailMan, - MailMan + async_channel::Sender, + async_channel::Receiver ), library: MusicLibrary, config: Arc>, @@ -170,28 +171,28 @@ pub struct ControllerInput { } pub struct ControllerHandle { - pub lib_mail: MailMan, - pub player_mail: MailMan, - pub queue_mail: MailMan, + pub(super) lib_mail_rx: async_channel::Sender, + pub(super) player_mail_rx: async_channel::Sender, + pub(super) queue_mail_rx: async_channel::Sender, } impl ControllerHandle { pub fn new(library: MusicLibrary, config: Arc>, connections: Option) -> (Self, ControllerInput, Arc>, Receiver) { - let lib_mail = MailMan::double(); - let player_mail = MailMan::double(); - let queue_mail = MailMan::double(); + let (lib_mail_rx, lib_mail_tx) = async_channel::unbounded(); + let (player_mail_rx, player_mail_tx) = async_channel::unbounded(); + let (queue_mail_rx, queue_mail_tx)= async_channel::unbounded(); let playback_info = Arc::new(AtomicCell::new(PlaybackInfo::default())); let notify_next_song = crossbeam::channel::unbounded::(); ( ControllerHandle { - lib_mail: lib_mail.0.clone(), - player_mail: player_mail.0.clone(), - queue_mail: queue_mail.0.clone() + lib_mail_rx: lib_mail_rx.clone(), + player_mail_rx: player_mail_rx.clone(), + queue_mail_rx: queue_mail_rx.clone() }, ControllerInput { - player_mail, - lib_mail, - queue_mail, + player_mail: (player_mail_rx, player_mail_tx), + lib_mail: (lib_mail_rx, lib_mail_tx), + queue_mail: (queue_mail_rx, queue_mail_tx), library, config, playback_info: Arc::clone(&playback_info), @@ -351,40 +352,40 @@ impl Controller { async fn player_command_loop( mut player: Prismriver, - player_mail: MailMan, - queue_mail: MailMan, - lib_mail: MailMan, + player_mail: async_channel::Receiver, + queue_mail: async_channel::Sender, + lib_mail: async_channel::Sender, notify_connections_: Sender, mut state: ControllerState, ) -> Result<(), ()> { player.set_volume(Volume::new(state.volume)); 'outer: while true { let _mail = player_mail.recv().await; - if let Ok(mail) = _mail { - match mail { + if let Ok(PlayerCommandInput {res_rx, command}) = _mail { + match command { PlayerCommand::Play => { player.play(); - player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); + res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); } PlayerCommand::Pause => { player.pause(); - player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); + res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); } PlayerCommand::Stop => { player.stop(); - player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); + res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); } PlayerCommand::Seek(time) => { let res = player.seek_to(TimeDelta::milliseconds(time)); - player_mail.send(PlayerResponse::Empty(res.map_err(|e| e.into()))).await.unwrap(); + res_rx.send(PlayerResponse::Empty(res.map_err(|e| e.into()))).await.unwrap(); } PlayerCommand::SetVolume(volume) => { player.set_volume(Volume::new(volume)); - player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); + res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); // make this async or something state.volume = volume; @@ -392,9 +393,10 @@ impl Controller { } PlayerCommand::NextSong => { - queue_mail.send(QueueCommand::Next).await.unwrap(); + let (command, tx) = QueueCommandInput::command(QueueCommand::Next); + queue_mail.send(command).await.unwrap(); - match queue_mail.recv().await.unwrap() { + match tx.recv().await.unwrap() { QueueResponse::Item(Ok(item)) => { let uri = match &item.item { QueueItemType::Single(song) => song.song.primary_uri().unwrap().0, @@ -410,17 +412,20 @@ impl Controller { let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")}; + let (command, tx) = LibraryCommandInput::command(LibraryCommand::AllSongs); // Append next song in library - lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); - let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else { + lib_mail.send(command).await.unwrap(); + let LibraryResponse::AllSongs(songs) = tx.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 { + + let (command, tx) = LibraryCommandInput::command(LibraryCommand::Song(np_song.song.uuid)); + lib_mail.send(command).await.unwrap(); + let LibraryResponse::Song(_, i) = tx.recv().await.unwrap() else { unreachable!() }; if let Some(song) = songs.get(i + 49) { - queue_mail.send( + let (command, tx) = QueueCommandInput::command( QueueCommand::Append( QueueItem::from_item_type( QueueItemType::Single( @@ -432,30 +437,32 @@ impl Controller { ), false ) - ).await + ); + queue_mail.send(command).await .unwrap(); - let QueueResponse::Empty(Ok(())) = queue_mail.recv().await.unwrap() else { + let QueueResponse::Empty(Ok(())) = tx.recv().await.unwrap() else { unreachable!() }; } else { println!("Library Empty"); } - player_mail.send(PlayerResponse::NowPlaying(Ok(np_song.song.clone()))).await.unwrap(); + res_rx.send(PlayerResponse::NowPlaying(Ok(np_song.song.clone()))).await.unwrap(); state.now_playing = np_song.song.uuid; _ = state.write_file(); notify_connections_.send(ConnectionsNotification::SongChange(np_song.song)).unwrap(); } QueueResponse::Item(Err(e)) => { - player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + res_rx.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); } _ => continue } } PlayerCommand::PrevSong => { - queue_mail.send(QueueCommand::Prev).await.unwrap(); - match queue_mail.recv().await.unwrap() { + let (command, tx) = QueueCommandInput::command(QueueCommand::Prev); + queue_mail.send(command).await.unwrap(); + match tx.recv().await.unwrap() { QueueResponse::Item(Ok(item)) => { let uri = match &item.item { QueueItemType::Single(song) => song.song.primary_uri().unwrap().0, @@ -467,25 +474,26 @@ impl Controller { player.play(); 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(); + res_rx.send(PlayerResponse::NowPlaying(Ok(np_song.song.clone()))).await.unwrap(); state.now_playing = np_song.song.uuid; _ = state.write_file(); notify_connections_.send(ConnectionsNotification::SongChange(np_song.song)).unwrap(); } QueueResponse::Item(Err(e)) => { - player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + res_rx.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); } _ => continue } } PlayerCommand::Enqueue(index) => { + let (command, tx) = QueueCommandInput::command(QueueCommand::GetIndex(index)); queue_mail - .send(QueueCommand::GetIndex(index)) + .send(command) .await .unwrap(); - match queue_mail.recv().await.unwrap() { + match tx.recv().await.unwrap() { QueueResponse::Item(Ok(item)) => { match item.item { QueueItemType::Single(np_song) => { @@ -499,10 +507,10 @@ impl Controller { } _ => unimplemented!(), } - player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); + res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); } QueueResponse::Item(Err(e)) => { - player_mail.send(PlayerResponse::Empty(Err(e.into()))).await.unwrap(); + res_rx.send(PlayerResponse::Empty(Err(e.into()))).await.unwrap(); } _ => continue } @@ -510,24 +518,31 @@ impl Controller { 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(); - let LibraryResponse::Song(np_song, index) = lib_mail.recv().await.unwrap() else { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::Song(uuid)); + lib_mail.send(command).await.unwrap(); + let LibraryResponse::Song(np_song, index) = tx.recv().await.unwrap() else { unreachable!() }; - queue_mail.send(QueueCommand::Clear).await.unwrap(); - match queue_mail.recv().await.unwrap() { + + let (command, tx) = QueueCommandInput::command(QueueCommand::Clear); + queue_mail.send(command).await.unwrap(); + match tx.recv().await.unwrap() { QueueResponse::Empty(Ok(())) => (), QueueResponse::Empty(Err(e)) => { - player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + res_rx.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); continue; } _ => unreachable!() } - queue_mail.send(QueueCommand::Append(QueueItem::from_item_type(QueueItemType::Single(QueueSong { song: np_song.clone(), location })), true)).await.unwrap(); - match queue_mail.recv().await.unwrap() { + + let (command, tx) = QueueCommandInput::command( + QueueCommand::Append(QueueItem::from_item_type(QueueItemType::Single(QueueSong { song: np_song.clone(), location })), true) + ); + queue_mail.send(command).await.unwrap(); + match tx.recv().await.unwrap() { QueueResponse::Empty(Ok(())) => (), QueueResponse::Empty(Err(e)) => { - player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + res_rx.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); continue; } _ => unreachable!() @@ -544,15 +559,17 @@ impl Controller { let (songs, index) = match location { PlayerLocation::Library => { - lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); - let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::AllSongs); + lib_mail.send(command).await.unwrap(); + let LibraryResponse::AllSongs(songs) = tx.recv().await.unwrap() else { unreachable!() }; (songs, index) } PlayerLocation::Playlist(uuid) => { - lib_mail.send(LibraryCommand::ExternalPlaylist(uuid)).await.unwrap(); - let LibraryResponse::ExternalPlaylist(list) = lib_mail.recv().await.unwrap() else { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::ExternalPlaylist(uuid)); + lib_mail.send(command).await.unwrap(); + let LibraryResponse::ExternalPlaylist(list) = tx.recv().await.unwrap() else { unreachable!() }; let index = list.get_index(np_song.uuid).unwrap(); @@ -564,11 +581,14 @@ 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(); - match queue_mail.recv().await.unwrap() { + let (command, tx) = QueueCommandInput::command( + QueueCommand::Append(QueueItem::from_item_type(QueueItemType::Single(QueueSong { song: song.clone(), location })), false) + ); + queue_mail.send(command).await.unwrap(); + match tx.recv().await.unwrap() { QueueResponse::Empty(Ok(())) => (), QueueResponse::Empty(Err(e)) => { - player_mail.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); + res_rx.send(PlayerResponse::NowPlaying(Err(e.into()))).await.unwrap(); continue 'outer; } _ => unreachable!() @@ -579,7 +599,7 @@ impl Controller { } } // ^ This be my solution for now ^ - player_mail.send(PlayerResponse::NowPlaying(Ok(np_song.clone()))).await.unwrap(); + res_rx.send(PlayerResponse::NowPlaying(Ok(np_song.clone()))).await.unwrap(); state.now_playing = np_song.uuid; _ = state.write_file(); @@ -597,8 +617,8 @@ impl Controller { playback_state: Arc>, playback_time_tx: Receiver<(Option, Option)>, finished_recv: Receiver<()>, - player_mail: MailMan, - queue_mail: MailMan, + player_mail: async_channel::Sender, + queue_mail: async_channel::Sender, notify_next_song: Sender, notify_connections_: Sender, playback_info: Arc> @@ -625,8 +645,9 @@ impl Controller { let _ = finished_recv.recv(); println!("End of song"); - player_mail.send(PlayerCommand::NextSong).await.unwrap(); - let PlayerResponse::NowPlaying(res) = player_mail.recv().await.unwrap() else { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::NextSong); + player_mail.send(command).await.unwrap(); + let PlayerResponse::NowPlaying(res) = tx.recv().await.unwrap() else { unreachable!() }; if let Ok(song) = res { @@ -660,22 +681,23 @@ impl Controller { async fn library_loop( - lib_mail: MailMan, + lib_mail: async_channel::Receiver, library: &mut MusicLibrary, config: Arc>, ) -> Result<(), ()> { while true { - match lib_mail.recv().await.unwrap() { + let LibraryCommandInput { res_rx, command } = lib_mail.recv().await.unwrap(); + match command { LibraryCommand::Song(uuid) => { let (song, i) = library.query_uuid(&uuid).unwrap(); - lib_mail.send(LibraryResponse::Song(song.clone(), i)).await.unwrap(); + res_rx.send(LibraryResponse::Song(song.clone(), i)).await.unwrap(); } LibraryCommand::AllSongs => { - lib_mail.send(LibraryResponse::AllSongs(library.library.clone())).await.unwrap(); + res_rx.send(LibraryResponse::AllSongs(library.library.clone())).await.unwrap(); }, LibraryCommand::ExternalPlaylist(uuid) => { let playlist = library.query_playlist_uuid(&uuid).unwrap(); - lib_mail.send(LibraryResponse::ExternalPlaylist(ExternalPlaylist::from_playlist(playlist, library))).await.unwrap(); + res_rx.send(LibraryResponse::ExternalPlaylist(ExternalPlaylist::from_playlist(playlist, library))).await.unwrap(); } LibraryCommand::ImportM3UPlayList(path) => { let playlist = Playlist::from_m3u(path, library).unwrap(); @@ -683,17 +705,17 @@ impl Controller { let name = playlist.title.clone(); library.playlists.items.push(PlaylistFolderItem::List(playlist)); - lib_mail.send(LibraryResponse::ImportM3UPlayList(uuid, name)).await.unwrap(); + res_rx.send(LibraryResponse::ImportM3UPlayList(uuid, name)).await.unwrap(); } LibraryCommand::Save => { library.save(config.read().libraries.get_library(&library.uuid).unwrap().path.clone()).unwrap(); - lib_mail.send(LibraryResponse::Ok).await.unwrap(); + res_rx.send(LibraryResponse::Ok).await.unwrap(); } LibraryCommand::Playlists => { let mut lists = vec![]; library.playlists.lists_recursive().into_par_iter().map(|list| (list.uuid, list.title.clone())).collect_into_vec(&mut lists); - lib_mail.send(LibraryResponse::Playlists(lists)).await.unwrap(); + res_rx.send(LibraryResponse::Playlists(lists)).await.unwrap(); } _ => { todo!() } } @@ -703,54 +725,55 @@ impl Controller { async fn queue_loop( mut queue: Queue, - queue_mail: MailMan, + queue_mail: async_channel::Receiver, ) { while true { - match queue_mail.recv().await.unwrap() { + let QueueCommandInput { res_rx, command } = queue_mail.recv().await.unwrap(); + match command { QueueCommand::Append(item, by_human) => { match item.item { QueueItemType::Single(song) => queue.add_item(song, by_human), _ => unimplemented!(), } - queue_mail + res_rx .send(QueueResponse::Empty(Ok(()))) .await .unwrap(); }, QueueCommand::Next => { let next = queue.next().map_or( Err(QueueError::NoNext), |s| Ok(s.clone())); - queue_mail + res_rx .send(QueueResponse::Item(next.clone())) .await .unwrap(); } QueueCommand::Prev => { let prev = queue.prev().map_or( Err(QueueError::EmptyPlayed), |s| Ok(s.clone())); - queue_mail + res_rx .send(QueueResponse::Item(prev.clone())) .await .unwrap(); } QueueCommand::GetIndex(index) => { 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(); + res_rx.send(QueueResponse::Item(item)).await.unwrap(); } QueueCommand::NowPlaying => { let item = queue.current().map(|t| t.clone()); - queue_mail + res_rx .send(QueueResponse::Item(item)) .await .unwrap(); } QueueCommand::Get => { - queue_mail.send(QueueResponse::GetAll(queue.items.clone())).await.unwrap(); + res_rx.send(QueueResponse::GetAll(queue.items.clone())).await.unwrap(); } QueueCommand::Clear => { queue.clear(); - queue_mail.send(QueueResponse::Empty(Ok(()))).await.unwrap(); + res_rx.send(QueueResponse::Empty(Ok(()))).await.unwrap(); } QueueCommand::Remove(index) => { - queue_mail.send(QueueResponse::Item(queue.remove_item(index))).await.unwrap(); + res_rx.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 index b60cb11..ad3796a 100644 --- a/dmp-core/src/music_controller/controller_handle.rs +++ b/dmp-core/src/music_controller/controller_handle.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +use async_channel::{Receiver, Sender}; use kushi::{QueueError, QueueItem}; use uuid::Uuid; @@ -10,32 +11,36 @@ use super::{controller::{ControllerHandle, LibraryCommand, LibraryResponse, Play 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 { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::Song(uuid)); + self.lib_mail_rx.send(command).await.unwrap(); + let LibraryResponse::Song(song, index) = tx.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 { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::AllSongs); + self.lib_mail_rx.send(command).await.unwrap(); + let LibraryResponse::AllSongs(songs) = tx.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 { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::Save); + self.lib_mail_rx.send(command).await.unwrap(); + let LibraryResponse::Ok = tx.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 { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::ExternalPlaylist(uuid)); + self.lib_mail_rx.send(command).await.unwrap(); + let LibraryResponse::ExternalPlaylist(playlist) = tx.recv().await.unwrap() else { unreachable!() }; Ok(playlist) @@ -43,39 +48,44 @@ impl ControllerHandle { /// 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 { + let (command, tx) = LibraryCommandInput::command(LibraryCommand::Playlists); + self.lib_mail_rx.send(command).await.unwrap(); + let LibraryResponse::Playlists(lists) = tx.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") }; + let (command, tx) = LibraryCommandInput::command(LibraryCommand::ImportM3UPlayList(path)); + self.lib_mail_rx.send(command).await.unwrap(); + let LibraryResponse::ImportM3UPlayList(uuid, name) = tx.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 { + let (command, tx) = QueueCommandInput::command(QueueCommand::Append(item, true)); + self.queue_mail_rx.send(command).await.unwrap(); + let QueueResponse::Empty(res) = tx.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 { + let (command, tx) = QueueCommandInput::command(QueueCommand::Remove(index)); + self.queue_mail_rx.send(command).await.unwrap(); + let QueueResponse::Item(res) = tx.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 { + let (command, tx) = QueueCommandInput::command(QueueCommand::Get); + self.queue_mail_rx.send(command).await.unwrap(); + let QueueResponse::GetAll(queue) = tx.recv().await.unwrap() else { unreachable!() }; queue @@ -83,65 +93,127 @@ impl ControllerHandle { // 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 { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::PlayNow(uuid, location)); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::NowPlaying(res) = tx.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 { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::Play); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::Empty(res) = tx.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 { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::Pause); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::Empty(res) = tx.recv().await.unwrap() else { unreachable!() }; res } pub async fn stop(&self) -> Result<(), PlayerError> { - self.player_mail.send(PlayerCommand::Stop).await.unwrap(); - let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::Stop); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::Empty(res) = tx.recv().await.unwrap() else { unreachable!() }; res } pub async fn seek(&self, time: i64) -> Result<(), PlayerError> { - self.player_mail.send(PlayerCommand::Seek(time)).await.unwrap(); - let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::Seek(time)); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::Empty(res) = tx.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 { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::SetVolume(volume)); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::Empty(Ok(())) = tx.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 { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::NextSong); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::NowPlaying(res) = tx.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 { + let (command, tx) = PlayerCommandInput::command(PlayerCommand::PrevSong); + self.player_mail_rx.send(command).await.unwrap(); + let PlayerResponse::NowPlaying(res) = tx.recv().await.unwrap() else { unreachable!() }; res } } + +pub(super) struct LibraryCommandInput { + pub res_rx: Sender, + pub command: LibraryCommand +} + +impl LibraryCommandInput { + pub fn command(command: LibraryCommand) -> (Self, Receiver) { + let (rx, tx) = async_channel::bounded(1); + ( + Self { + res_rx: rx, + command + }, + tx + ) + } +} + +pub(super) struct QueueCommandInput { + pub res_rx: Sender, + pub command: QueueCommand +} + +impl QueueCommandInput { + pub fn command(command: QueueCommand) -> (Self, Receiver) { + let (rx, tx) = async_channel::bounded(1); + ( + Self { + res_rx: rx, + command + }, + tx + ) + } +} + +pub(super) struct PlayerCommandInput { + pub res_rx: Sender, + pub command: PlayerCommand +} + +impl PlayerCommandInput { + pub fn command(command: PlayerCommand) -> (Self, Receiver) { + let (rx, tx) = async_channel::bounded(1); + ( + Self { + res_rx: rx, + command + }, + tx + ) + } +} diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 6c9a3c1..f9a4db0 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -174,10 +174,7 @@ pub fn run() { Some(DEFAULT_IMAGE.to_vec()) } else {futures::executor::block_on(async move { let controller = ctx.app_handle().state::(); - controller.lib_mail.send(dmp_core::music_controller::controller::LibraryCommand::Song(Uuid::parse_str(query.as_str()).unwrap())).await.unwrap(); - let LibraryResponse::Song(song, _) = controller.lib_mail.recv().await.unwrap() else { - return None - }; + let song = controller.lib_get_song(Uuid::parse_str(query.as_str()).unwrap()).await.0; Some(song.album_art(0).unwrap_or_else(|_| None).unwrap_or(DEFAULT_IMAGE.to_vec())) })};