diff --git a/dmp-core/src/music_controller/controller.rs b/dmp-core/src/music_controller/controller.rs index 203a48c..b7bfe40 100644 --- a/dmp-core/src/music_controller/controller.rs +++ b/dmp-core/src/music_controller/controller.rs @@ -24,7 +24,7 @@ use thiserror::Error; use uuid::Uuid; use crate::config::ConfigError; -use crate::music_storage::library::Song; +use crate::music_storage::library::{self, Song, Tag}; use crate::music_storage::playlist::{ExternalPlaylist, Playlist, PlaylistFolderItem}; use crate::{config::Config, music_storage::library::MusicLibrary}; @@ -80,6 +80,8 @@ impl MailMan { #[derive(Debug, PartialEq, PartialOrd, Clone)] pub enum PlayerCommand { + AllSongsInOrder, + SongInOrder(Uuid), NextSong, PrevSong, Pause, @@ -94,7 +96,9 @@ pub enum PlayerCommand { #[derive(Debug, PartialEq, Clone)] pub enum PlayerResponse { Empty(Result<(), PlayerError>), - NowPlaying(Result) + NowPlaying(Result), + AllSongsInOrder(Vec), + SongInOrder(Song, usize), } #[derive(Error, Debug, PartialEq, Clone)] @@ -107,8 +111,8 @@ pub enum PlayerError { #[derive(Debug, PartialEq, PartialOrd, Clone)] pub enum LibraryCommand { - Song(Uuid), - AllSongs, + Song(Uuid, Vec), + AllSongs(Vec), GetLibrary, ExternalPlaylist(Uuid), Playlist(Uuid), @@ -207,6 +211,7 @@ pub struct ControllerState { path: PathBuf, volume: f32, now_playing: Uuid, + sort_order: Vec, } impl ControllerState { @@ -214,6 +219,12 @@ impl ControllerState { ControllerState { path, volume: 0.35, + sort_order: vec![ + Tag::Field("location".to_string()), + Tag::Album, + Tag::Disk, + Tag::Track, + ], ..Default::default() } } @@ -342,6 +353,22 @@ impl Controller { let _mail = player_mail.recv().await; if let Ok(mail) = _mail { match mail { + PlayerCommand::AllSongsInOrder => { + lib_mail.send(LibraryCommand::AllSongs(state.sort_order.clone())).await.unwrap(); + let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else { + continue; + }; + player_mail.send(PlayerResponse::AllSongsInOrder(songs)).await.unwrap(); + } + + PlayerCommand::SongInOrder(uuid) => { + lib_mail.send(LibraryCommand::Song(uuid, state.sort_order.clone())).await.unwrap(); + let LibraryResponse::Song(song, index) = lib_mail.recv().await.unwrap() else { + continue; + }; + player_mail.send(PlayerResponse::SongInOrder(song, index)).await.unwrap(); + } + PlayerCommand::Play => { player.write().unwrap().play(); player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap(); @@ -390,11 +417,12 @@ impl Controller { let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")}; // Append next song in library - lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); + dbg!(&state.sort_order); + lib_mail.send(LibraryCommand::AllSongs(state.sort_order.clone())).await.unwrap(); let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else { continue; }; - lib_mail.send(LibraryCommand::Song(np_song.song.uuid)).await.unwrap(); + lib_mail.send(LibraryCommand::Song(np_song.song.uuid, state.sort_order.clone())).await.unwrap(); let LibraryResponse::Song(_, i) = lib_mail.recv().await.unwrap() else { unreachable!() }; @@ -483,7 +511,7 @@ 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(); + lib_mail.send(LibraryCommand::Song(uuid, state.sort_order.clone())).await.unwrap(); let LibraryResponse::Song(song, index) = lib_mail.recv().await.unwrap() else { unreachable!() }; @@ -517,7 +545,7 @@ impl Controller { let (songs, index) = match location { PlayerLocation::Library => { - lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); + lib_mail.send(LibraryCommand::AllSongs(state.sort_order.clone())).await.unwrap(); let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else { unreachable!() }; @@ -623,12 +651,19 @@ impl Controller { ) -> Result<(), ()> { while true { match lib_mail.recv().await.unwrap() { - LibraryCommand::Song(uuid) => { - let (song, i) = library.query_uuid(&uuid).unwrap(); + LibraryCommand::Song(uuid, sort_order) => { + let (song, _) = library.query_uuid(&uuid).unwrap(); + let i = library.uuid_index(&uuid, &sort_order).unwrap(); lib_mail.send(LibraryResponse::Song(song.clone(), i)).await.unwrap(); } - LibraryCommand::AllSongs => { - lib_mail.send(LibraryResponse::AllSongs(library.library.clone())).await.unwrap(); + LibraryCommand::AllSongs(sort_order) => { + let songs = library.query_tracks( + &String::from(""), + &vec![Tag::Title], + &sort_order, + ).unwrap().iter().map(|s| (*s).clone()).collect(); + + lib_mail.send(LibraryResponse::AllSongs(songs)).await.unwrap(); }, LibraryCommand::ExternalPlaylist(uuid) => { let playlist = library.query_playlist_uuid(&uuid).unwrap(); diff --git a/dmp-core/src/music_controller/controller_handle.rs b/dmp-core/src/music_controller/controller_handle.rs index b60cb11..a44b8cb 100644 --- a/dmp-core/src/music_controller/controller_handle.rs +++ b/dmp-core/src/music_controller/controller_handle.rs @@ -10,16 +10,16 @@ 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 { + self.player_mail.send(PlayerCommand::SongInOrder(uuid)).await.unwrap(); + let PlayerResponse::SongInOrder(song, index) = self.player_mail.recv().await.unwrap() else { unreachable!() }; (song, index) } pub async fn lib_get_all(&self) -> Vec { - self.lib_mail.send(LibraryCommand::AllSongs).await.unwrap(); - let LibraryResponse::AllSongs(songs) = self.lib_mail.recv().await.unwrap() else { + self.player_mail.send(PlayerCommand::AllSongsInOrder).await.unwrap(); + let PlayerResponse::AllSongsInOrder(songs) = self.player_mail.recv().await.unwrap() else { unreachable!("It has been reached") }; songs diff --git a/dmp-core/src/music_storage/library.rs b/dmp-core/src/music_storage/library.rs index 89f37d5..ac192e7 100644 --- a/dmp-core/src/music_storage/library.rs +++ b/dmp-core/src/music_storage/library.rs @@ -818,6 +818,28 @@ impl MusicLibrary { } } + pub fn uuid_index(&self, uuid: &Uuid, sort_order: &Vec) -> Option { + let result = self.query_tracks( + &String::from(""), + &vec![Tag::Title], + sort_order, + )?; + + let result = result.par_iter() + .enumerate() + .try_for_each(|(i, track)| { + if uuid == &track.uuid { + return std::ops::ControlFlow::Break(i); + } + Continue(()) + }); + + match result { + Break(i) => Some(i), + Continue(_) => None, + } + } + /// Queries for a [Song] by its [PathBuf], returning a `Vec<&Song>` /// with matching `PathBuf`s fn query_path(&self, path: PathBuf) -> Option> { diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 7478ef3..8693907 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -4,7 +4,7 @@ use std::{borrow::BorrowMut, fs, ops::Deref, path::PathBuf, sync::{atomic::Order use crossbeam::channel::{bounded, unbounded, Receiver, Sender}; use discord_presence::{models::{Activity, ActivityButton, ActivityTimestamps, ActivityType}, Event}; -use dmp_core::{config::{Config, ConfigLibrary}, music_controller::controller::{Controller, ControllerHandle, LibraryResponse, PlaybackInfo}, music_storage::library::{MusicLibrary, Song}}; +use dmp_core::{config::{Config, ConfigLibrary}, music_controller::controller::{Controller, ControllerHandle, LibraryCommand, LibraryResponse, PlaybackInfo, PlayerCommand, PlayerResponse}, music_storage::library::{MusicLibrary, Song}}; use futures::channel::oneshot; use parking_lot::RwLock; use rfd::FileHandle; @@ -176,8 +176,8 @@ 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 { + controller.player_mail.send(PlayerCommand::SongInOrder(Uuid::parse_str(query.as_str()).unwrap())).await.unwrap(); + let PlayerResponse::SongInOrder(song, _) = controller.player_mail.recv().await.unwrap() else { return None }; Some(song.album_art(0).unwrap_or_else(|_| None).unwrap_or(DEFAULT_IMAGE.to_vec()))