Added Error Handling for Queue and abstractions over the ControllerHandle

This commit is contained in:
MrDulfin 2024-12-27 22:45:59 -05:00
parent f51650f4d2
commit d18f980fa0
6 changed files with 344 additions and 162 deletions

View file

@ -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"]}

View file

@ -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;
}

View file

@ -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<QueueSong, QueueAlbum>;
#[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<Song, QueueError>)
}
#[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<QueueSong, QueueAlbum>, bool),
Append(QueueItem_, bool),
Next,
Prev,
GetIndex(usize),
NowPlaying,
Get,
Clear
Clear,
Remove(usize),
}
#[derive(Debug, PartialEq, Clone)]
pub enum QueueResponse {
Ok,
Item(QueueItem<QueueSong, QueueAlbum>),
GetAll(Vec<QueueItem<QueueSong, QueueAlbum>>),
Err(QueueError),
Empty(Result<(), QueueError>),
Item(Result<QueueItem_, QueueError>),
GetAll(Vec<QueueItem_>),
}
@ -302,116 +312,136 @@ impl Controller {
lib_mail: MailMan<LibraryCommand, LibraryResponse>,
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();
}
}
}

View file

@ -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<Song> {
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<ExternalPlaylist, ()> {
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<QueueSong, QueueAlbum>) -> 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<QueueItem<QueueSong, QueueAlbum>, 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<QueueItem<QueueSong, QueueAlbum>> {
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<Song, QueueError> {
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<Song, QueueError> {
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<Song, QueueError> {
self.player_mail.send(PlayerCommand::PrevSong).await.unwrap();
let PlayerResponse::NowPlaying(res) = self.player_mail.recv().await.unwrap() else {
unreachable!()
};
res
}
}

View file

@ -10,23 +10,20 @@ use crate::wrappers::_Song;
#[tauri::command]
pub async fn add_song_to_queue(app: AppHandle<Wry>, 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<Wry>, 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();

View file

@ -13,35 +13,31 @@ pub struct ArtworkRx(pub Sender<Vec<u8>>);
#[tauri::command]
pub async fn play(app: AppHandle<Wry>, 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<Wry>, 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::<f32>().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<Wry>, 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<Wry>, ctrl_handle: State<'_, ControllerHandle>)
#[tauri::command]
pub async fn prev(app: AppHandle<Wry>, 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<Vec<_Song>, 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<Wry>, 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<Vec<_Song>, 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::<Vec<_>>();
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<Vec<_Song>, 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::<Vec<_>>();
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<Wry>, 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))
}