mirror of
https://github.com/Dangoware/dango-music-player.git
synced 2025-04-19 10:02:53 -05:00
Made library sorting work
This commit is contained in:
parent
2130af1e4a
commit
92fa9c566f
4 changed files with 76 additions and 19 deletions
|
@ -24,7 +24,7 @@ use thiserror::Error;
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::config::ConfigError;
|
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::music_storage::playlist::{ExternalPlaylist, Playlist, PlaylistFolderItem};
|
||||||
use crate::{config::Config, music_storage::library::MusicLibrary};
|
use crate::{config::Config, music_storage::library::MusicLibrary};
|
||||||
|
|
||||||
|
@ -80,6 +80,8 @@ impl<Tx: Send, Rx: Send> MailMan<Tx, Rx> {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
||||||
pub enum PlayerCommand {
|
pub enum PlayerCommand {
|
||||||
|
AllSongsInOrder,
|
||||||
|
SongInOrder(Uuid),
|
||||||
NextSong,
|
NextSong,
|
||||||
PrevSong,
|
PrevSong,
|
||||||
Pause,
|
Pause,
|
||||||
|
@ -94,7 +96,9 @@ pub enum PlayerCommand {
|
||||||
#[derive(Debug, PartialEq, Clone)]
|
#[derive(Debug, PartialEq, Clone)]
|
||||||
pub enum PlayerResponse {
|
pub enum PlayerResponse {
|
||||||
Empty(Result<(), PlayerError>),
|
Empty(Result<(), PlayerError>),
|
||||||
NowPlaying(Result<Song, QueueError>)
|
NowPlaying(Result<Song, QueueError>),
|
||||||
|
AllSongsInOrder(Vec<Song>),
|
||||||
|
SongInOrder(Song, usize),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Error, Debug, PartialEq, Clone)]
|
#[derive(Error, Debug, PartialEq, Clone)]
|
||||||
|
@ -107,8 +111,8 @@ pub enum PlayerError {
|
||||||
|
|
||||||
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
#[derive(Debug, PartialEq, PartialOrd, Clone)]
|
||||||
pub enum LibraryCommand {
|
pub enum LibraryCommand {
|
||||||
Song(Uuid),
|
Song(Uuid, Vec<library::Tag>),
|
||||||
AllSongs,
|
AllSongs(Vec<library::Tag>),
|
||||||
GetLibrary,
|
GetLibrary,
|
||||||
ExternalPlaylist(Uuid),
|
ExternalPlaylist(Uuid),
|
||||||
Playlist(Uuid),
|
Playlist(Uuid),
|
||||||
|
@ -207,6 +211,7 @@ pub struct ControllerState {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
volume: f32,
|
volume: f32,
|
||||||
now_playing: Uuid,
|
now_playing: Uuid,
|
||||||
|
sort_order: Vec<Tag>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ControllerState {
|
impl ControllerState {
|
||||||
|
@ -214,6 +219,12 @@ impl ControllerState {
|
||||||
ControllerState {
|
ControllerState {
|
||||||
path,
|
path,
|
||||||
volume: 0.35,
|
volume: 0.35,
|
||||||
|
sort_order: vec![
|
||||||
|
Tag::Field("location".to_string()),
|
||||||
|
Tag::Album,
|
||||||
|
Tag::Disk,
|
||||||
|
Tag::Track,
|
||||||
|
],
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -342,6 +353,22 @@ impl Controller {
|
||||||
let _mail = player_mail.recv().await;
|
let _mail = player_mail.recv().await;
|
||||||
if let Ok(mail) = _mail {
|
if let Ok(mail) = _mail {
|
||||||
match 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 => {
|
PlayerCommand::Play => {
|
||||||
player.write().unwrap().play();
|
player.write().unwrap().play();
|
||||||
player_mail.send(PlayerResponse::Empty(Ok(()))).await.unwrap();
|
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")};
|
let QueueItemType::Single(np_song) = item.item else { panic!("This is temporary, handle queueItemTypes at some point")};
|
||||||
|
|
||||||
// Append next song in library
|
// 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 {
|
let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else {
|
||||||
continue;
|
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 {
|
let LibraryResponse::Song(_, i) = lib_mail.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -483,7 +511,7 @@ 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();
|
lib_mail.send(LibraryCommand::Song(uuid, state.sort_order.clone())).await.unwrap();
|
||||||
let LibraryResponse::Song(song, index) = lib_mail.recv().await.unwrap() else {
|
let LibraryResponse::Song(song, index) = lib_mail.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -517,7 +545,7 @@ impl Controller {
|
||||||
|
|
||||||
let (songs, index) = match location {
|
let (songs, index) = match location {
|
||||||
PlayerLocation::Library => {
|
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 {
|
let LibraryResponse::AllSongs(songs) = lib_mail.recv().await.unwrap() else {
|
||||||
unreachable!()
|
unreachable!()
|
||||||
};
|
};
|
||||||
|
@ -623,12 +651,19 @@ impl Controller {
|
||||||
) -> Result<(), ()> {
|
) -> Result<(), ()> {
|
||||||
while true {
|
while true {
|
||||||
match lib_mail.recv().await.unwrap() {
|
match lib_mail.recv().await.unwrap() {
|
||||||
LibraryCommand::Song(uuid) => {
|
LibraryCommand::Song(uuid, sort_order) => {
|
||||||
let (song, i) = library.query_uuid(&uuid).unwrap();
|
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();
|
lib_mail.send(LibraryResponse::Song(song.clone(), i)).await.unwrap();
|
||||||
}
|
}
|
||||||
LibraryCommand::AllSongs => {
|
LibraryCommand::AllSongs(sort_order) => {
|
||||||
lib_mail.send(LibraryResponse::AllSongs(library.library.clone())).await.unwrap();
|
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) => {
|
LibraryCommand::ExternalPlaylist(uuid) => {
|
||||||
let playlist = library.query_playlist_uuid(&uuid).unwrap();
|
let playlist = library.query_playlist_uuid(&uuid).unwrap();
|
||||||
|
|
|
@ -10,16 +10,16 @@ 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();
|
self.player_mail.send(PlayerCommand::SongInOrder(uuid)).await.unwrap();
|
||||||
let LibraryResponse::Song(song, index) = self.lib_mail.recv().await.unwrap() else {
|
let PlayerResponse::SongInOrder(song, index) = self.player_mail.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();
|
self.player_mail.send(PlayerCommand::AllSongsInOrder).await.unwrap();
|
||||||
let LibraryResponse::AllSongs(songs) = self.lib_mail.recv().await.unwrap() else {
|
let PlayerResponse::AllSongsInOrder(songs) = self.player_mail.recv().await.unwrap() else {
|
||||||
unreachable!("It has been reached")
|
unreachable!("It has been reached")
|
||||||
};
|
};
|
||||||
songs
|
songs
|
||||||
|
|
|
@ -818,6 +818,28 @@ impl MusicLibrary {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn uuid_index(&self, uuid: &Uuid, sort_order: &Vec<Tag>) -> Option<usize> {
|
||||||
|
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>`
|
/// Queries for a [Song] by its [PathBuf], returning a `Vec<&Song>`
|
||||||
/// with matching `PathBuf`s
|
/// with matching `PathBuf`s
|
||||||
fn query_path(&self, path: PathBuf) -> Option<Vec<&Song>> {
|
fn query_path(&self, path: PathBuf) -> Option<Vec<&Song>> {
|
||||||
|
|
|
@ -4,7 +4,7 @@ use std::{borrow::BorrowMut, fs, ops::Deref, path::PathBuf, sync::{atomic::Order
|
||||||
|
|
||||||
use crossbeam::channel::{bounded, unbounded, Receiver, Sender};
|
use crossbeam::channel::{bounded, unbounded, Receiver, Sender};
|
||||||
use discord_presence::{models::{Activity, ActivityButton, ActivityTimestamps, ActivityType}, Event};
|
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 futures::channel::oneshot;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
use rfd::FileHandle;
|
use rfd::FileHandle;
|
||||||
|
@ -176,8 +176,8 @@ 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();
|
controller.player_mail.send(PlayerCommand::SongInOrder(Uuid::parse_str(query.as_str()).unwrap())).await.unwrap();
|
||||||
let LibraryResponse::Song(song, _) = controller.lib_mail.recv().await.unwrap() else {
|
let PlayerResponse::SongInOrder(song, _) = controller.player_mail.recv().await.unwrap() else {
|
||||||
return None
|
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