mirror of
https://github.com/Dangoware/dango-music-player.git
synced 2025-04-19 10:02:53 -05:00
Changed command input system to send in senders with commands. This prevents race conditions casing incorrect responses to be recieved
This commit is contained in:
parent
5be0df4dc2
commit
eed00bc336
3 changed files with 215 additions and 123 deletions
|
@ -28,6 +28,7 @@ use crate::music_storage::playlist::{ExternalPlaylist, Playlist, PlaylistFolderI
|
||||||
use crate::{config::Config, music_storage::library::MusicLibrary};
|
use crate::{config::Config, music_storage::library::MusicLibrary};
|
||||||
|
|
||||||
use super::connections::{ConnectionsInput, ConnectionsNotification, ControllerConnections};
|
use super::connections::{ConnectionsInput, ConnectionsNotification, ControllerConnections};
|
||||||
|
use super::controller_handle::{LibraryCommandInput, PlayerCommandInput, QueueCommandInput};
|
||||||
use super::queue::{QueueAlbum, QueueSong};
|
use super::queue::{QueueAlbum, QueueSong};
|
||||||
|
|
||||||
pub struct Controller();
|
pub struct Controller();
|
||||||
|
@ -151,16 +152,16 @@ pub enum QueueResponse {
|
||||||
|
|
||||||
pub struct ControllerInput {
|
pub struct ControllerInput {
|
||||||
player_mail: (
|
player_mail: (
|
||||||
MailMan<PlayerCommand, PlayerResponse>,
|
async_channel::Sender<PlayerCommandInput>,
|
||||||
MailMan<PlayerResponse, PlayerCommand>,
|
async_channel::Receiver<PlayerCommandInput>
|
||||||
),
|
),
|
||||||
lib_mail: (
|
lib_mail: (
|
||||||
MailMan<LibraryCommand, LibraryResponse>,
|
async_channel::Sender<LibraryCommandInput>,
|
||||||
MailMan<LibraryResponse, LibraryCommand>
|
async_channel::Receiver<LibraryCommandInput>
|
||||||
),
|
),
|
||||||
queue_mail: (
|
queue_mail: (
|
||||||
MailMan<QueueCommand, QueueResponse>,
|
async_channel::Sender<QueueCommandInput>,
|
||||||
MailMan<QueueResponse, QueueCommand>
|
async_channel::Receiver<QueueCommandInput>
|
||||||
),
|
),
|
||||||
library: MusicLibrary,
|
library: MusicLibrary,
|
||||||
config: Arc<RwLock<Config>>,
|
config: Arc<RwLock<Config>>,
|
||||||
|
@ -170,28 +171,28 @@ pub struct ControllerInput {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ControllerHandle {
|
pub struct ControllerHandle {
|
||||||
pub lib_mail: MailMan<LibraryCommand, LibraryResponse>,
|
pub(super) lib_mail_rx: async_channel::Sender<LibraryCommandInput>,
|
||||||
pub player_mail: MailMan<PlayerCommand, PlayerResponse>,
|
pub(super) player_mail_rx: async_channel::Sender<PlayerCommandInput>,
|
||||||
pub queue_mail: MailMan<QueueCommand, QueueResponse>,
|
pub(super) queue_mail_rx: async_channel::Sender<QueueCommandInput>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ControllerHandle {
|
impl ControllerHandle {
|
||||||
pub fn new(library: MusicLibrary, config: Arc<RwLock<Config>>, connections: Option<ConnectionsInput>) -> (Self, ControllerInput, Arc<AtomicCell<PlaybackInfo>>, Receiver<Song>) {
|
pub fn new(library: MusicLibrary, config: Arc<RwLock<Config>>, connections: Option<ConnectionsInput>) -> (Self, ControllerInput, Arc<AtomicCell<PlaybackInfo>>, Receiver<Song>) {
|
||||||
let lib_mail = MailMan::double();
|
let (lib_mail_rx, lib_mail_tx) = async_channel::unbounded();
|
||||||
let player_mail = MailMan::double();
|
let (player_mail_rx, player_mail_tx) = async_channel::unbounded();
|
||||||
let queue_mail = MailMan::double();
|
let (queue_mail_rx, queue_mail_tx)= async_channel::unbounded();
|
||||||
let playback_info = Arc::new(AtomicCell::new(PlaybackInfo::default()));
|
let playback_info = Arc::new(AtomicCell::new(PlaybackInfo::default()));
|
||||||
let notify_next_song = crossbeam::channel::unbounded::<Song>();
|
let notify_next_song = crossbeam::channel::unbounded::<Song>();
|
||||||
(
|
(
|
||||||
ControllerHandle {
|
ControllerHandle {
|
||||||
lib_mail: lib_mail.0.clone(),
|
lib_mail_rx: lib_mail_rx.clone(),
|
||||||
player_mail: player_mail.0.clone(),
|
player_mail_rx: player_mail_rx.clone(),
|
||||||
queue_mail: queue_mail.0.clone()
|
queue_mail_rx: queue_mail_rx.clone()
|
||||||
},
|
},
|
||||||
ControllerInput {
|
ControllerInput {
|
||||||
player_mail,
|
player_mail: (player_mail_rx, player_mail_tx),
|
||||||
lib_mail,
|
lib_mail: (lib_mail_rx, lib_mail_tx),
|
||||||
queue_mail,
|
queue_mail: (queue_mail_rx, queue_mail_tx),
|
||||||
library,
|
library,
|
||||||
config,
|
config,
|
||||||
playback_info: Arc::clone(&playback_info),
|
playback_info: Arc::clone(&playback_info),
|
||||||
|
@ -351,40 +352,40 @@ impl Controller {
|
||||||
|
|
||||||
async fn player_command_loop(
|
async fn player_command_loop(
|
||||||
mut player: Prismriver,
|
mut player: Prismriver,
|
||||||
player_mail: MailMan<PlayerResponse, PlayerCommand>,
|
player_mail: async_channel::Receiver<PlayerCommandInput>,
|
||||||
queue_mail: MailMan<QueueCommand, QueueResponse>,
|
queue_mail: async_channel::Sender<QueueCommandInput>,
|
||||||
lib_mail: MailMan<LibraryCommand, LibraryResponse>,
|
lib_mail: async_channel::Sender<LibraryCommandInput>,
|
||||||
notify_connections_: Sender<ConnectionsNotification>,
|
notify_connections_: Sender<ConnectionsNotification>,
|
||||||
mut state: ControllerState,
|
mut state: ControllerState,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
player.set_volume(Volume::new(state.volume));
|
player.set_volume(Volume::new(state.volume));
|
||||||
'outer: while true {
|
'outer: while true {
|
||||||
let _mail = player_mail.recv().await;
|
let _mail = player_mail.recv().await;
|
||||||
if let Ok(mail) = _mail {
|
if let Ok(PlayerCommandInput {res_rx, command}) = _mail {
|
||||||
match mail {
|
match command {
|
||||||
PlayerCommand::Play => {
|
PlayerCommand::Play => {
|
||||||
player.play();
|
player.play();
|
||||||
player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCommand::Pause => {
|
PlayerCommand::Pause => {
|
||||||
player.pause();
|
player.pause();
|
||||||
player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCommand::Stop => {
|
PlayerCommand::Stop => {
|
||||||
player.stop();
|
player.stop();
|
||||||
player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCommand::Seek(time) => {
|
PlayerCommand::Seek(time) => {
|
||||||
let res = player.seek_to(TimeDelta::milliseconds(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) => {
|
PlayerCommand::SetVolume(volume) => {
|
||||||
player.set_volume(Volume::new(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
|
// make this async or something
|
||||||
state.volume = volume;
|
state.volume = volume;
|
||||||
|
@ -392,9 +393,10 @@ impl Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCommand::NextSong => {
|
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)) => {
|
QueueResponse::Item(Ok(item)) => {
|
||||||
let uri = match &item.item {
|
let uri = match &item.item {
|
||||||
QueueItemType::Single(song) => song.song.primary_uri().unwrap().0,
|
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 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
|
// Append next song in library
|
||||||
lib_mail.send(LibraryCommand::AllSongs).await.unwrap();
|
lib_mail.send(command).await.unwrap();
|
||||||
let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else {
|
let LibraryResponse::AllSongs(songs) = tx.recv().await.unwrap() else {
|
||||||
continue;
|
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!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
if let Some(song) = songs.get(i + 49) {
|
if let Some(song) = songs.get(i + 49) {
|
||||||
queue_mail.send(
|
let (command, tx) = QueueCommandInput::command(
|
||||||
QueueCommand::Append(
|
QueueCommand::Append(
|
||||||
QueueItem::from_item_type(
|
QueueItem::from_item_type(
|
||||||
QueueItemType::Single(
|
QueueItemType::Single(
|
||||||
|
@ -432,30 +437,32 @@ impl Controller {
|
||||||
),
|
),
|
||||||
false
|
false
|
||||||
)
|
)
|
||||||
).await
|
);
|
||||||
|
queue_mail.send(command).await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
let QueueResponse::Empty(Ok(())) = queue_mail.recv().await.unwrap() else {
|
let QueueResponse::Empty(Ok(())) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
println!("Library Empty");
|
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.now_playing = np_song.song.uuid;
|
||||||
_ = state.write_file();
|
_ = state.write_file();
|
||||||
notify_connections_.send(ConnectionsNotification::SongChange(np_song.song)).unwrap();
|
notify_connections_.send(ConnectionsNotification::SongChange(np_song.song)).unwrap();
|
||||||
} QueueResponse::Item(Err(e)) => {
|
} 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
|
_ => continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCommand::PrevSong => {
|
PlayerCommand::PrevSong => {
|
||||||
queue_mail.send(QueueCommand::Prev).await.unwrap();
|
let (command, tx) = QueueCommandInput::command(QueueCommand::Prev);
|
||||||
match queue_mail.recv().await.unwrap() {
|
queue_mail.send(command).await.unwrap();
|
||||||
|
match tx.recv().await.unwrap() {
|
||||||
QueueResponse::Item(Ok(item)) => {
|
QueueResponse::Item(Ok(item)) => {
|
||||||
let uri = match &item.item {
|
let uri = match &item.item {
|
||||||
QueueItemType::Single(song) => song.song.primary_uri().unwrap().0,
|
QueueItemType::Single(song) => song.song.primary_uri().unwrap().0,
|
||||||
|
@ -467,25 +474,26 @@ impl Controller {
|
||||||
player.play();
|
player.play();
|
||||||
|
|
||||||
let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")};
|
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.now_playing = np_song.song.uuid;
|
||||||
_ = state.write_file();
|
_ = state.write_file();
|
||||||
notify_connections_.send(ConnectionsNotification::SongChange(np_song.song)).unwrap();
|
notify_connections_.send(ConnectionsNotification::SongChange(np_song.song)).unwrap();
|
||||||
}
|
}
|
||||||
QueueResponse::Item(Err(e)) => {
|
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
|
_ => continue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PlayerCommand::Enqueue(index) => {
|
PlayerCommand::Enqueue(index) => {
|
||||||
|
let (command, tx) = QueueCommandInput::command(QueueCommand::GetIndex(index));
|
||||||
queue_mail
|
queue_mail
|
||||||
.send(QueueCommand::GetIndex(index))
|
.send(command)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
match queue_mail.recv().await.unwrap() {
|
match tx.recv().await.unwrap() {
|
||||||
QueueResponse::Item(Ok(item)) => {
|
QueueResponse::Item(Ok(item)) => {
|
||||||
match item.item {
|
match item.item {
|
||||||
QueueItemType::Single(np_song) => {
|
QueueItemType::Single(np_song) => {
|
||||||
|
@ -499,10 +507,10 @@ impl Controller {
|
||||||
}
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
res_rx.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
||||||
}
|
}
|
||||||
QueueResponse::Item(Err(e)) => {
|
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
|
_ => continue
|
||||||
}
|
}
|
||||||
|
@ -510,24 +518,31 @@ impl Controller {
|
||||||
|
|
||||||
PlayerCommand::PlayNow(uuid, location) => {
|
PlayerCommand::PlayNow(uuid, location) => {
|
||||||
// TODO: This assumes the uuid doesn't point to an album. we've been over this.
|
// 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 (command, tx) = LibraryCommandInput::command(LibraryCommand::Song(uuid));
|
||||||
let LibraryResponse::Song(np_song, index) = lib_mail.recv().await.unwrap() else {
|
lib_mail.send(command).await.unwrap();
|
||||||
|
let LibraryResponse::Song(np_song, index) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
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(Ok(())) => (),
|
||||||
QueueResponse::Empty(Err(e)) => {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => 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(Ok(())) => (),
|
||||||
QueueResponse::Empty(Err(e)) => {
|
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;
|
continue;
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
|
@ -544,15 +559,17 @@ impl Controller {
|
||||||
|
|
||||||
let (songs, index) = match location {
|
let (songs, index) = match location {
|
||||||
PlayerLocation::Library => {
|
PlayerLocation::Library => {
|
||||||
lib_mail.send(LibraryCommand::AllSongs).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::AllSongs);
|
||||||
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 {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
(songs, index)
|
(songs, index)
|
||||||
}
|
}
|
||||||
PlayerLocation::Playlist(uuid) => {
|
PlayerLocation::Playlist(uuid) => {
|
||||||
lib_mail.send(LibraryCommand::ExternalPlaylist(uuid)).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::ExternalPlaylist(uuid));
|
||||||
let LibraryResponse::ExternalPlaylist(list) = lib_mail.recv().await.unwrap() else {
|
lib_mail.send(command).await.unwrap();
|
||||||
|
let LibraryResponse::ExternalPlaylist(list) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
let index = list.get_index(np_song.uuid).unwrap();
|
let index = list.get_index(np_song.uuid).unwrap();
|
||||||
|
@ -564,11 +581,14 @@ impl Controller {
|
||||||
|
|
||||||
for i in index+1..(index+50) {
|
for i in index+1..(index+50) {
|
||||||
if let Some(song) = songs.get(i) {
|
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 (command, tx) = QueueCommandInput::command(
|
||||||
match queue_mail.recv().await.unwrap() {
|
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(Ok(())) => (),
|
||||||
QueueResponse::Empty(Err(e)) => {
|
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;
|
continue 'outer;
|
||||||
}
|
}
|
||||||
_ => unreachable!()
|
_ => unreachable!()
|
||||||
|
@ -579,7 +599,7 @@ impl Controller {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ^ This be my solution for now ^
|
// ^ 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.now_playing = np_song.uuid;
|
||||||
_ = state.write_file();
|
_ = state.write_file();
|
||||||
|
@ -597,8 +617,8 @@ impl Controller {
|
||||||
playback_state: Arc<std::sync::RwLock<PrismState>>,
|
playback_state: Arc<std::sync::RwLock<PrismState>>,
|
||||||
playback_time_tx: Receiver<(Option<TimeDelta>, Option<TimeDelta>)>,
|
playback_time_tx: Receiver<(Option<TimeDelta>, Option<TimeDelta>)>,
|
||||||
finished_recv: Receiver<()>,
|
finished_recv: Receiver<()>,
|
||||||
player_mail: MailMan<PlayerCommand, PlayerResponse>,
|
player_mail: async_channel::Sender<PlayerCommandInput>,
|
||||||
queue_mail: MailMan<QueueCommand, QueueResponse>,
|
queue_mail: async_channel::Sender<QueueCommandInput>,
|
||||||
notify_next_song: Sender<Song>,
|
notify_next_song: Sender<Song>,
|
||||||
notify_connections_: Sender<ConnectionsNotification>,
|
notify_connections_: Sender<ConnectionsNotification>,
|
||||||
playback_info: Arc<AtomicCell<PlaybackInfo>>
|
playback_info: Arc<AtomicCell<PlaybackInfo>>
|
||||||
|
@ -625,8 +645,9 @@ impl Controller {
|
||||||
let _ = finished_recv.recv();
|
let _ = finished_recv.recv();
|
||||||
println!("End of song");
|
println!("End of song");
|
||||||
|
|
||||||
player_mail.send(PlayerCommand::NextSong).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::NextSong);
|
||||||
let PlayerResponse::NowPlaying(res) = player_mail.recv().await.unwrap() else {
|
player_mail.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::NowPlaying(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
if let Ok(song) = res {
|
if let Ok(song) = res {
|
||||||
|
@ -660,22 +681,23 @@ impl Controller {
|
||||||
|
|
||||||
|
|
||||||
async fn library_loop(
|
async fn library_loop(
|
||||||
lib_mail: MailMan<LibraryResponse, LibraryCommand>,
|
lib_mail: async_channel::Receiver<LibraryCommandInput>,
|
||||||
library: &mut MusicLibrary,
|
library: &mut MusicLibrary,
|
||||||
config: Arc<RwLock<Config>>,
|
config: Arc<RwLock<Config>>,
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
while true {
|
while true {
|
||||||
match lib_mail.recv().await.unwrap() {
|
let LibraryCommandInput { res_rx, command } = lib_mail.recv().await.unwrap();
|
||||||
|
match command {
|
||||||
LibraryCommand::Song(uuid) => {
|
LibraryCommand::Song(uuid) => {
|
||||||
let (song, i) = library.query_uuid(&uuid).unwrap();
|
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 => {
|
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) => {
|
LibraryCommand::ExternalPlaylist(uuid) => {
|
||||||
let playlist = library.query_playlist_uuid(&uuid).unwrap();
|
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) => {
|
LibraryCommand::ImportM3UPlayList(path) => {
|
||||||
let playlist = Playlist::from_m3u(path, library).unwrap();
|
let playlist = Playlist::from_m3u(path, library).unwrap();
|
||||||
|
@ -683,17 +705,17 @@ impl Controller {
|
||||||
let name = playlist.title.clone();
|
let name = playlist.title.clone();
|
||||||
library.playlists.items.push(PlaylistFolderItem::List(playlist));
|
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 => {
|
LibraryCommand::Save => {
|
||||||
library.save(config.read().libraries.get_library(&library.uuid).unwrap().path.clone()).unwrap();
|
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 => {
|
LibraryCommand::Playlists => {
|
||||||
let mut lists = vec![];
|
let mut lists = vec![];
|
||||||
library.playlists.lists_recursive().into_par_iter().map(|list| (list.uuid, list.title.clone())).collect_into_vec(&mut lists);
|
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!() }
|
_ => { todo!() }
|
||||||
}
|
}
|
||||||
|
@ -703,54 +725,55 @@ impl Controller {
|
||||||
|
|
||||||
async fn queue_loop(
|
async fn queue_loop(
|
||||||
mut queue: Queue<QueueSong, QueueAlbum>,
|
mut queue: Queue<QueueSong, QueueAlbum>,
|
||||||
queue_mail: MailMan<QueueResponse, QueueCommand>,
|
queue_mail: async_channel::Receiver<QueueCommandInput>,
|
||||||
) {
|
) {
|
||||||
while true {
|
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) => {
|
QueueCommand::Append(item, by_human) => {
|
||||||
match item.item {
|
match item.item {
|
||||||
QueueItemType::Single(song) => queue.add_item(song, by_human),
|
QueueItemType::Single(song) => queue.add_item(song, by_human),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
queue_mail
|
res_rx
|
||||||
.send(QueueResponse::Empty(Ok(())))
|
.send(QueueResponse::Empty(Ok(())))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
},
|
},
|
||||||
QueueCommand::Next => {
|
QueueCommand::Next => {
|
||||||
let next = queue.next().map_or( Err(QueueError::NoNext), |s| Ok(s.clone()));
|
let next = queue.next().map_or( Err(QueueError::NoNext), |s| Ok(s.clone()));
|
||||||
queue_mail
|
res_rx
|
||||||
.send(QueueResponse::Item(next.clone()))
|
.send(QueueResponse::Item(next.clone()))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
QueueCommand::Prev => {
|
QueueCommand::Prev => {
|
||||||
let prev = queue.prev().map_or( Err(QueueError::EmptyPlayed), |s| Ok(s.clone()));
|
let prev = queue.prev().map_or( Err(QueueError::EmptyPlayed), |s| Ok(s.clone()));
|
||||||
queue_mail
|
res_rx
|
||||||
.send(QueueResponse::Item(prev.clone()))
|
.send(QueueResponse::Item(prev.clone()))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
QueueCommand::GetIndex(index) => {
|
QueueCommand::GetIndex(index) => {
|
||||||
let item = queue.items.get(index).map_or( Err(QueueError::OutOfBounds { index, len: queue.items.len() }), |s| Ok(s.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();
|
res_rx.send(QueueResponse::Item(item)).await.unwrap();
|
||||||
}
|
}
|
||||||
QueueCommand::NowPlaying => {
|
QueueCommand::NowPlaying => {
|
||||||
let item = queue.current().map(|t| t.clone());
|
let item = queue.current().map(|t| t.clone());
|
||||||
queue_mail
|
res_rx
|
||||||
.send(QueueResponse::Item(item))
|
.send(QueueResponse::Item(item))
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
QueueCommand::Get => {
|
QueueCommand::Get => {
|
||||||
queue_mail.send(QueueResponse::GetAll(queue.items.clone())).await.unwrap();
|
res_rx.send(QueueResponse::GetAll(queue.items.clone())).await.unwrap();
|
||||||
}
|
}
|
||||||
QueueCommand::Clear => {
|
QueueCommand::Clear => {
|
||||||
queue.clear();
|
queue.clear();
|
||||||
queue_mail.send(QueueResponse::Empty(Ok(()))).await.unwrap();
|
res_rx.send(QueueResponse::Empty(Ok(()))).await.unwrap();
|
||||||
}
|
}
|
||||||
QueueCommand::Remove(index) => {
|
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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
use async_channel::{Receiver, Sender};
|
||||||
use kushi::{QueueError, QueueItem};
|
use kushi::{QueueError, QueueItem};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
|
@ -10,32 +11,36 @@ use super::{controller::{ControllerHandle, LibraryCommand, LibraryResponse, Play
|
||||||
impl ControllerHandle {
|
impl ControllerHandle {
|
||||||
// The Library Section
|
// The Library Section
|
||||||
pub async fn lib_get_song(&self, uuid: Uuid) -> (Song, usize) {
|
pub async fn lib_get_song(&self, uuid: Uuid) -> (Song, usize) {
|
||||||
self.lib_mail.send(LibraryCommand::Song(uuid)).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::Song(uuid));
|
||||||
let LibraryResponse::Song(song, index) = self.lib_mail.recv().await.unwrap() else {
|
self.lib_mail_rx.send(command).await.unwrap();
|
||||||
|
let LibraryResponse::Song(song, index) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
(song, index)
|
(song, index)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn lib_get_all(&self) -> Vec<Song> {
|
pub async fn lib_get_all(&self) -> Vec<Song> {
|
||||||
self.lib_mail.send(LibraryCommand::AllSongs).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::AllSongs);
|
||||||
let LibraryResponse::AllSongs(songs) = self.lib_mail.recv().await.unwrap() else {
|
self.lib_mail_rx.send(command).await.unwrap();
|
||||||
|
let LibraryResponse::AllSongs(songs) = tx.recv().await.unwrap() else {
|
||||||
unreachable!("It has been reached")
|
unreachable!("It has been reached")
|
||||||
};
|
};
|
||||||
songs
|
songs
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn lib_save(&self) {
|
pub async fn lib_save(&self) {
|
||||||
self.lib_mail.send(LibraryCommand::Save).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::Save);
|
||||||
let LibraryResponse::Ok = self.lib_mail.recv().await.unwrap() else {
|
self.lib_mail_rx.send(command).await.unwrap();
|
||||||
|
let LibraryResponse::Ok = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Playlist Section
|
// The Playlist Section
|
||||||
pub async fn playlist_get(&self, uuid: Uuid) -> Result<ExternalPlaylist, ()> {
|
pub async fn playlist_get(&self, uuid: Uuid) -> Result<ExternalPlaylist, ()> {
|
||||||
self.lib_mail.send(LibraryCommand::ExternalPlaylist(uuid)).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::ExternalPlaylist(uuid));
|
||||||
let LibraryResponse::ExternalPlaylist(playlist) = self.lib_mail.recv().await.unwrap() else {
|
self.lib_mail_rx.send(command).await.unwrap();
|
||||||
|
let LibraryResponse::ExternalPlaylist(playlist) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
Ok(playlist)
|
Ok(playlist)
|
||||||
|
@ -43,39 +48,44 @@ impl ControllerHandle {
|
||||||
|
|
||||||
/// Returns a `Vec<(Uuid, String)>` containing the Uuid of the playlist and the name after
|
/// 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)> {
|
pub async fn playlist_get_all(&self) -> Vec<(Uuid, String)> {
|
||||||
self.lib_mail.send(LibraryCommand::Playlists).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::Playlists);
|
||||||
let LibraryResponse::Playlists(lists) = self.lib_mail.recv().await.unwrap() else {
|
self.lib_mail_rx.send(command).await.unwrap();
|
||||||
|
let LibraryResponse::Playlists(lists) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
lists
|
lists
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn playlist_import_m3u(&self, path: PathBuf) -> Result<(Uuid, String), ()> {
|
pub async fn playlist_import_m3u(&self, path: PathBuf) -> Result<(Uuid, String), ()> {
|
||||||
self.lib_mail.send(LibraryCommand::ImportM3UPlayList(path)).await.unwrap();
|
let (command, tx) = LibraryCommandInput::command(LibraryCommand::ImportM3UPlayList(path));
|
||||||
let LibraryResponse::ImportM3UPlayList(uuid, name) = self.lib_mail.recv().await.unwrap() else { unreachable!("It has been reached") };
|
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))
|
Ok((uuid, name))
|
||||||
}
|
}
|
||||||
|
|
||||||
// The Queue Section
|
// The Queue Section
|
||||||
pub async fn queue_append(&self, item: QueueItem<QueueSong, QueueAlbum>) -> Result<(), QueueError> {
|
pub async fn queue_append(&self, item: QueueItem<QueueSong, QueueAlbum>) -> Result<(), QueueError> {
|
||||||
self.queue_mail.send(QueueCommand::Append(item, true)).await.unwrap();
|
let (command, tx) = QueueCommandInput::command(QueueCommand::Append(item, true));
|
||||||
let QueueResponse::Empty(res) = self.queue_mail.recv().await.unwrap() else {
|
self.queue_mail_rx.send(command).await.unwrap();
|
||||||
|
let QueueResponse::Empty(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn queue_remove(&self, index: usize) -> Result<QueueItem<QueueSong, QueueAlbum>, QueueError> {
|
pub async fn queue_remove(&self, index: usize) -> Result<QueueItem<QueueSong, QueueAlbum>, QueueError> {
|
||||||
self.queue_mail.send(QueueCommand::Remove(index)).await.unwrap();
|
let (command, tx) = QueueCommandInput::command(QueueCommand::Remove(index));
|
||||||
let QueueResponse::Item(res) = self.queue_mail.recv().await.unwrap() else {
|
self.queue_mail_rx.send(command).await.unwrap();
|
||||||
|
let QueueResponse::Item(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn queue_get_all(&self) -> Vec<QueueItem<QueueSong, QueueAlbum>> {
|
pub async fn queue_get_all(&self) -> Vec<QueueItem<QueueSong, QueueAlbum>> {
|
||||||
self.queue_mail.send(QueueCommand::Get).await.unwrap();
|
let (command, tx) = QueueCommandInput::command(QueueCommand::Get);
|
||||||
let QueueResponse::GetAll(queue) = self.queue_mail.recv().await.unwrap() else {
|
self.queue_mail_rx.send(command).await.unwrap();
|
||||||
|
let QueueResponse::GetAll(queue) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
queue
|
queue
|
||||||
|
@ -83,65 +93,127 @@ impl ControllerHandle {
|
||||||
|
|
||||||
// The Player Section
|
// The Player Section
|
||||||
pub async fn play_now(&self, uuid: Uuid, location: PlayerLocation) -> Result<Song, QueueError> {
|
pub async fn play_now(&self, uuid: Uuid, location: PlayerLocation) -> Result<Song, QueueError> {
|
||||||
self.player_mail.send(PlayerCommand::PlayNow(uuid, location)).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::PlayNow(uuid, location));
|
||||||
let PlayerResponse::NowPlaying(res) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::NowPlaying(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn play(&self) -> Result<(), PlayerError> {
|
pub async fn play(&self) -> Result<(), PlayerError> {
|
||||||
self.player_mail.send(PlayerCommand::Play).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::Play);
|
||||||
let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::Empty(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn pause(&self) -> Result<(), PlayerError> {
|
pub async fn pause(&self) -> Result<(), PlayerError> {
|
||||||
self.player_mail.send(PlayerCommand::Pause).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::Pause);
|
||||||
let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::Empty(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn stop(&self) -> Result<(), PlayerError> {
|
pub async fn stop(&self) -> Result<(), PlayerError> {
|
||||||
self.player_mail.send(PlayerCommand::Stop).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::Stop);
|
||||||
let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::Empty(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn seek(&self, time: i64) -> Result<(), PlayerError> {
|
pub async fn seek(&self, time: i64) -> Result<(), PlayerError> {
|
||||||
self.player_mail.send(PlayerCommand::Seek(time)).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::Seek(time));
|
||||||
let PlayerResponse::Empty(res) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::Empty(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_volume(&self, volume: f32) -> () {
|
pub async fn set_volume(&self, volume: f32) -> () {
|
||||||
self.player_mail.send(PlayerCommand::SetVolume(volume)).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::SetVolume(volume));
|
||||||
let PlayerResponse::Empty(Ok(())) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::Empty(Ok(())) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn next(&self) -> Result<Song, QueueError> {
|
pub async fn next(&self) -> Result<Song, QueueError> {
|
||||||
self.player_mail.send(PlayerCommand::NextSong).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::NextSong);
|
||||||
let PlayerResponse::NowPlaying(res) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::NowPlaying(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn prev(&self) -> Result<Song, QueueError> {
|
pub async fn prev(&self) -> Result<Song, QueueError> {
|
||||||
self.player_mail.send(PlayerCommand::PrevSong).await.unwrap();
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::PrevSong);
|
||||||
let PlayerResponse::NowPlaying(res) = self.player_mail.recv().await.unwrap() else {
|
self.player_mail_rx.send(command).await.unwrap();
|
||||||
|
let PlayerResponse::NowPlaying(res) = tx.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(super) struct LibraryCommandInput {
|
||||||
|
pub res_rx: Sender<LibraryResponse>,
|
||||||
|
pub command: LibraryCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LibraryCommandInput {
|
||||||
|
pub fn command(command: LibraryCommand) -> (Self, Receiver<LibraryResponse>) {
|
||||||
|
let (rx, tx) = async_channel::bounded(1);
|
||||||
|
(
|
||||||
|
Self {
|
||||||
|
res_rx: rx,
|
||||||
|
command
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct QueueCommandInput {
|
||||||
|
pub res_rx: Sender<QueueResponse>,
|
||||||
|
pub command: QueueCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
impl QueueCommandInput {
|
||||||
|
pub fn command(command: QueueCommand) -> (Self, Receiver<QueueResponse>) {
|
||||||
|
let (rx, tx) = async_channel::bounded(1);
|
||||||
|
(
|
||||||
|
Self {
|
||||||
|
res_rx: rx,
|
||||||
|
command
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) struct PlayerCommandInput {
|
||||||
|
pub res_rx: Sender<PlayerResponse>,
|
||||||
|
pub command: PlayerCommand
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlayerCommandInput {
|
||||||
|
pub fn command(command: PlayerCommand) -> (Self, Receiver<PlayerResponse>) {
|
||||||
|
let (rx, tx) = async_channel::bounded(1);
|
||||||
|
(
|
||||||
|
Self {
|
||||||
|
res_rx: rx,
|
||||||
|
command
|
||||||
|
},
|
||||||
|
tx
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -174,10 +174,7 @@ pub fn run() {
|
||||||
Some(DEFAULT_IMAGE.to_vec())
|
Some(DEFAULT_IMAGE.to_vec())
|
||||||
} else {futures::executor::block_on(async move {
|
} else {futures::executor::block_on(async move {
|
||||||
let controller = ctx.app_handle().state::<ControllerHandle>();
|
let controller = ctx.app_handle().state::<ControllerHandle>();
|
||||||
controller.lib_mail.send(dmp_core::music_controller::controller::LibraryCommand::Song(Uuid::parse_str(query.as_str()).unwrap())).await.unwrap();
|
let song = controller.lib_get_song(Uuid::parse_str(query.as_str()).unwrap()).await.0;
|
||||||
let LibraryResponse::Song(song, _) = controller.lib_mail.recv().await.unwrap() else {
|
|
||||||
return None
|
|
||||||
};
|
|
||||||
Some(song.album_art(0).unwrap_or_else(|_| None).unwrap_or(DEFAULT_IMAGE.to_vec()))
|
Some(song.album_art(0).unwrap_or_else(|_| None).unwrap_or(DEFAULT_IMAGE.to_vec()))
|
||||||
})};
|
})};
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue