ran cargo fmt

This commit is contained in:
MrDulfin 2025-03-23 23:40:36 -04:00
parent d88c6e07d5
commit 8f30c38c4c
10 changed files with 211 additions and 108 deletions

View file

@ -1,9 +1,9 @@
#![allow(while_true)]
pub mod music_storage {
pub mod library;
pub mod queue;
pub mod music_collection;
pub mod playlist;
pub mod queue;
mod utils;
#[allow(dead_code)]

View file

@ -2,7 +2,9 @@ use std::{
sync::{
atomic::{AtomicBool, Ordering},
Arc,
}, thread::sleep, time::{Duration, Instant, SystemTime, UNIX_EPOCH}
},
thread::sleep,
time::{Duration, Instant, SystemTime, UNIX_EPOCH},
};
use chrono::TimeDelta;
@ -20,7 +22,6 @@ use crate::{
music_storage::library::{Song, Tag},
};
#[derive(Debug, Clone)]
pub(super) enum ConnectionsNotification {
Playback {
@ -31,7 +32,7 @@ pub(super) enum ConnectionsNotification {
SongChange(Song),
AboutToFinish,
EOS,
TryEnableConnection(TryConnectionType)
TryEnableConnection(TryConnectionType),
}
#[non_exhaustive]
@ -41,7 +42,7 @@ pub(super) enum TryConnectionType {
LastFM {
api_key: String,
api_secret: String,
auth: LastFMAuth
auth: LastFMAuth,
},
ListenBrainz(String),
}
@ -49,10 +50,7 @@ pub(super) enum TryConnectionType {
#[derive(Debug, Clone)]
pub enum LastFMAuth {
Session(Option<String>),
UserPass {
username: String,
password: String
}
UserPass { username: String, password: String },
}
pub(super) struct ControllerConnections {
@ -92,15 +90,26 @@ pub(super) fn handle_connections(
use ConnectionsNotification::*;
while true {
match notifications_tx.recv().unwrap() {
Playback { position: _position, duration: _duration } => {
Playback {
position: _position,
duration: _duration,
} => {
_ = dc_position_rx.send_timeout(_position.clone(), Duration::from_millis(0));
if song_scrobbled { continue }
if song_scrobbled {
continue;
}
let Some(position) = _position.map(|t| t.num_milliseconds()) else { continue };
let Some(duration) = _duration.map(|t| t.num_milliseconds()) else { continue };
let Some(position) = _position.map(|t| t.num_milliseconds()) else {
continue;
};
let Some(duration) = _duration.map(|t| t.num_milliseconds()) else {
continue;
};
// Scrobble at 50% or at 4 minutes
if duration < 30000 || position == 0 { continue }
if duration < 30000 || position == 0 {
continue;
}
let percent_played = position as f32 / duration as f32;
if percent_played != 0.0 && (percent_played > 0.5 || position >= 240000) {
@ -130,11 +139,16 @@ pub(super) fn handle_connections(
last_now_playing_rx.send(song.clone()).unwrap();
}
}
EOS => { continue }
AboutToFinish => { continue }
TryEnableConnection(c) => { match c {
EOS => continue,
AboutToFinish => continue,
TryEnableConnection(c) => {
match c {
TryConnectionType::Discord(client_id) => {
let (dc_song_tx, dc_state_tx, dc_position_tx) = (dc_now_playing_tx.clone(), dc_state_tx.clone(), dc_position_tx.clone());
let (dc_song_tx, dc_state_tx, dc_position_tx) = (
dc_now_playing_tx.clone(),
dc_state_tx.clone(),
dc_position_tx.clone(),
);
std::thread::Builder::new()
.name("Discord RPC Handler".to_string())
.spawn(move || {
@ -142,9 +156,10 @@ pub(super) fn handle_connections(
discord_rpc(client_id, dc_song_tx, dc_state_tx, dc_position_tx);
})
.unwrap();
},
}
TryConnectionType::ListenBrainz(token) => {
let (lb_now_playing_tx, lb_scrobble_tx) = (lb_now_playing_tx.clone(), lb_scrobble_tx.clone());
let (lb_now_playing_tx, lb_scrobble_tx) =
(lb_now_playing_tx.clone(), lb_scrobble_tx.clone());
std::thread::Builder::new()
.name("ListenBrainz Handler".to_string())
.spawn(move || {
@ -152,25 +167,36 @@ pub(super) fn handle_connections(
})
.unwrap();
}
TryConnectionType::LastFM { api_key, api_secret, auth } => {
TryConnectionType::LastFM {
api_key,
api_secret,
auth,
} => {
let (config, notifications_rx) = (config.clone(), notifications_rx.clone());
let (last_now_playing_tx, last_scrobble_tx) = (last_now_playing_tx.clone(), last_scrobble_tx.clone());
let (last_now_playing_tx, last_scrobble_tx) =
(last_now_playing_tx.clone(), last_scrobble_tx.clone());
std::thread::Builder::new()
.name("last.fm Handler".to_string())
.spawn(move || {
let scrobbler = match auth {
LastFMAuth::Session(key) => {
if let Some(session) = key {
LastFMAuth::Session(key) => if let Some(session) = key {
let mut scrobbler = Scrobbler::new(&api_key, &api_secret);
scrobbler.authenticate_with_session_key(&session);
Ok(scrobbler)
} else {
last_fm_auth(config, notifications_rx, &api_key, &api_secret)
}.unwrap()
},
last_fm_auth(
config,
notifications_rx,
&api_key,
&api_secret,
)
}
.unwrap(),
LastFMAuth::UserPass { username, password } => {
let mut scrobbler = Scrobbler::new(&api_key, &api_secret);
scrobbler.authenticate_with_password(&username, &password).unwrap();
scrobbler
.authenticate_with_password(&username, &password)
.unwrap();
scrobbler
}
};
@ -178,12 +204,18 @@ pub(super) fn handle_connections(
})
.unwrap();
}
}}
}
}
}
}
}
fn discord_rpc(client_id: u64, song_tx: Receiver<Song>, state_tx: Receiver<PrismState>, position_tx: Receiver<Option<TimeDelta>>) {
fn discord_rpc(
client_id: u64,
song_tx: Receiver<Song>,
state_tx: Receiver<PrismState>,
position_tx: Receiver<Option<TimeDelta>>,
) {
let mut client =
discord_presence::Client::with_error_config(client_id, Duration::from_secs(5), None);
client.start();
@ -225,7 +257,8 @@ fn discord_rpc(client_id: u64, song_tx: Receiver<Song>, state_tx: Receiver<Prism
now = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards?")
.as_secs() - u64::try_from(pos.num_seconds()).unwrap();
.as_secs()
- u64::try_from(pos.num_seconds()).unwrap();
}
client
@ -236,8 +269,7 @@ fn discord_rpc(client_id: u64, song_tx: Receiver<Song>, state_tx: Receiver<Prism
"{}{}{}",
s.get_tag(&Tag::Artist)
.map_or(String::new(), |album| album.clone()),
if s.get_tag(&Tag::Album).is_some()
&& s.get_tag(&Tag::Artist).is_some()
if s.get_tag(&Tag::Album).is_some() && s.get_tag(&Tag::Artist).is_some()
{
" - "
} else {
@ -265,13 +297,15 @@ fn discord_rpc(client_id: u64, song_tx: Receiver<Song>, state_tx: Receiver<Prism
} else {
activity
}
.assets(|a| a.large_text(match state {
.assets(|a| {
a.large_text(match state {
Some(PrismState::Playing) => "Playing",
Some(PrismState::Paused) => "Paused",
Some(PrismState::Stopped) => "Stopped",
None => "Started",
_ => "I'm Scared, Boss"
}))
_ => "I'm Scared, Boss",
})
})
.instance(true)
})
.unwrap();
@ -340,7 +374,7 @@ fn last_fm_auth(
config: Arc<RwLock<Config>>,
notifications_rx: Sender<ConnectionsNotification>,
api_key: &str,
api_secret: &str
api_secret: &str,
) -> Result<Scrobbler, Box<dyn std::error::Error>> {
let token = {
tokio::runtime::Builder::new_current_thread()
@ -361,7 +395,11 @@ fn last_fm_auth(
};
let mut scrobbler = Scrobbler::new(api_key, api_secret);
println!("Token: {}", token.token);
opener::open_browser(format!("http://www.last.fm/api/auth/?api_key={api_key}&token={}", token.token)).unwrap();
opener::open_browser(format!(
"http://www.last.fm/api/auth/?api_key={api_key}&token={}",
token.token
))
.unwrap();
let session = loop {
if let Ok(session) = scrobbler.authenticate_with_token(&token.token) {
@ -378,7 +416,11 @@ fn last_fm_auth(
Ok(scrobbler)
}
fn last_fm_scrobble(scrobbler: Scrobbler, now_playing_tx: Receiver<Song>, scrobble_tx: Receiver<()>) {
fn last_fm_scrobble(
scrobbler: Scrobbler,
now_playing_tx: Receiver<Song>,
scrobble_tx: Receiver<()>,
) {
// TODO: Add support for scrobble storage for later
let mut song: Option<Song> = None;
@ -446,8 +488,6 @@ fn last_fm_scrobble(scrobbler: Scrobbler, now_playing_tx: Receiver<Song>, scrobb
LAST_FM_ACTIVE.store(false, Ordering::Relaxed);
}
#[derive(Deserialize)]
pub struct Token {
token: String,

View file

@ -161,7 +161,7 @@ pub struct ControllerInput {
),
connections_mail: (
crossbeam_channel::Sender<ConnectionsNotification>,
crossbeam_channel::Receiver<ConnectionsNotification>
crossbeam_channel::Receiver<ConnectionsNotification>,
),
library: MusicLibrary,
config: Arc<RwLock<Config>>,

View file

@ -3,7 +3,11 @@ use std::path::PathBuf;
use async_channel::{Receiver, Sender};
use uuid::Uuid;
use crate::music_storage::{library::Song, playlist::ExternalPlaylist, queue::{QueueError, QueueItem}};
use crate::music_storage::{
library::Song,
playlist::ExternalPlaylist,
queue::{QueueError, QueueItem},
};
use super::{
controller::{
@ -178,18 +182,43 @@ impl ControllerHandle {
// The Connections Section
pub fn discord_rpc(&self, client_id: u64) {
self.connections_rx.send(super::connections::ConnectionsNotification::TryEnableConnection(super::connections::TryConnectionType::Discord(client_id))).unwrap();
self.connections_rx
.send(
super::connections::ConnectionsNotification::TryEnableConnection(
super::connections::TryConnectionType::Discord(client_id),
),
)
.unwrap();
}
pub fn listenbrainz_scrobble_auth(&self, token: String) {
self.connections_rx.send(super::connections::ConnectionsNotification::TryEnableConnection(super::connections::TryConnectionType::ListenBrainz(token))).unwrap();
self.connections_rx
.send(
super::connections::ConnectionsNotification::TryEnableConnection(
super::connections::TryConnectionType::ListenBrainz(token),
),
)
.unwrap();
}
pub fn last_fm_scrobble_auth(&self, api_key: String, api_secret: String, auth: super::connections::LastFMAuth) {
self.connections_rx.send(super::connections::ConnectionsNotification::TryEnableConnection(super::connections::TryConnectionType::LastFM { api_key, api_secret, auth })).unwrap();
pub fn last_fm_scrobble_auth(
&self,
api_key: String,
api_secret: String,
auth: super::connections::LastFMAuth,
) {
self.connections_rx
.send(
super::connections::ConnectionsNotification::TryEnableConnection(
super::connections::TryConnectionType::LastFM {
api_key,
api_secret,
auth,
},
),
)
.unwrap();
}
}
pub(super) struct LibraryCommandInput {

View file

@ -2,10 +2,13 @@ use chrono::TimeDelta;
use crossbeam_channel::Sender;
use prismriver::{Prismriver, Volume};
use crate::{music_controller::{
use crate::{
music_controller::{
controller::{LibraryCommand, LibraryResponse},
queue::QueueSong,
}, music_storage::queue::{QueueItem, QueueItemType}};
},
music_storage::queue::{QueueItem, QueueItemType},
};
use super::{
connections::ConnectionsNotification,

View file

@ -52,7 +52,9 @@ impl Controller {
futures::executor::block_on(async {
while true {
_ = about_to_finish_tx.recv();
notify_connections.send(ConnectionsNotification::AboutToFinish).unwrap();
notify_connections
.send(ConnectionsNotification::AboutToFinish)
.unwrap();
println!("About to Finish");
}
})

View file

@ -1,8 +1,13 @@
use std::{fs::OpenOptions, io::Write};
use dmp_core::{music_controller::{
connections::LastFMAuth, controller::{ControllerHandle, PlayerLocation}, queue::QueueSong
}, music_storage::queue::{QueueItem, QueueItemType}};
use dmp_core::{
music_controller::{
connections::LastFMAuth,
controller::{ControllerHandle, PlayerLocation},
queue::QueueSong,
},
music_storage::queue::{QueueItem, QueueItemType},
};
use tauri::{AppHandle, Emitter, State, Wry};
use tempfile::TempDir;
use uuid::Uuid;
@ -81,6 +86,10 @@ pub async fn display_album_art(
#[tauri::command]
pub async fn last_fm_init_auth(ctrl_handle: State<'_, ControllerHandle>) -> Result<(), String> {
ctrl_handle.last_fm_scrobble_auth(LAST_FM_API_KEY.to_string(), LAST_FM_API_SECRET.to_string(), LastFMAuth::Session(None));
ctrl_handle.last_fm_scrobble_auth(
LAST_FM_API_KEY.to_string(),
LAST_FM_API_SECRET.to_string(),
LastFMAuth::Session(None),
);
Ok(())
}

View file

@ -5,7 +5,11 @@ use tauri::{State, WebviewWindowBuilder, Window, Wry};
#[tauri::command]
pub async fn open_config_window(app: tauri::AppHandle<Wry>) -> Result<(), String> {
WebviewWindowBuilder::new(&app, "config", tauri::WebviewUrl::App(PathBuf::from("src/config/index.html")))
WebviewWindowBuilder::new(
&app,
"config",
tauri::WebviewUrl::App(PathBuf::from("src/config/index.html")),
)
.title("Edit Dango Music Player")
.build()
.unwrap();
@ -18,10 +22,18 @@ pub async fn get_config(ctrl_handle: State<'_, ControllerHandle>) -> Result<Conf
}
#[tauri::command]
pub async fn save_config(ctrl_handle: State<'_, ControllerHandle>, config: Config) -> Result<(), String> {
pub async fn save_config(
ctrl_handle: State<'_, ControllerHandle>,
config: Config,
) -> Result<(), String> {
let config_original = ctrl_handle.config.read().clone();
if config.connections.listenbrainz_token.as_ref().is_some_and(|t| Some(t) != config_original.connections.listenbrainz_token.as_ref()) {
if config
.connections
.listenbrainz_token
.as_ref()
.is_some_and(|t| Some(t) != config_original.connections.listenbrainz_token.as_ref())
{
let token = config.connections.listenbrainz_token.clone().unwrap();
ctrl_handle.listenbrainz_scrobble_auth(dbg!(token));
}

View file

@ -12,7 +12,10 @@ use config::{close_window, get_config, open_config_window, save_config};
use crossbeam::channel::{bounded, unbounded, Receiver, Sender};
use dmp_core::{
config::{Config, ConfigLibrary},
music_controller::{connections::LastFMAuth, controller::{Controller, ControllerHandle, PlaybackInfo}},
music_controller::{
connections::LastFMAuth,
controller::{Controller, ControllerHandle, PlaybackInfo},
},
music_storage::library::{MusicLibrary, Song},
};
use parking_lot::RwLock;
@ -27,8 +30,8 @@ use crate::wrappers::{
use commands::{add_song_to_queue, display_album_art, last_fm_init_auth, play_now};
pub mod commands;
pub mod wrappers;
pub mod config;
pub mod wrappers;
const DEFAULT_IMAGE: &[u8] = include_bytes!("../icons/icon.png");
@ -102,10 +105,8 @@ pub fn run() {
let last_fm_session = config.connections.last_fm_session.clone();
let listenbrainz_token = config.connections.listenbrainz_token.clone();
let (handle, input, playback_info, next_song_notification) = ControllerHandle::new(
library,
std::sync::Arc::new(RwLock::new(config))
);
let (handle, input, playback_info, next_song_notification) =
ControllerHandle::new(library, std::sync::Arc::new(RwLock::new(config)));
handle.discord_rpc(DISCORD_CLIENT_ID);
if let Some(token) = listenbrainz_token {
@ -114,7 +115,11 @@ pub fn run() {
println!("No ListenBrainz token found");
}
if let Some(session) = last_fm_session {
handle.last_fm_scrobble_auth(LAST_FM_API_KEY.to_string(), LAST_FM_API_SECRET.to_string(), LastFMAuth::Session(Some(session)));
handle.last_fm_scrobble_auth(
LAST_FM_API_KEY.to_string(),
LAST_FM_API_SECRET.to_string(),
LastFMAuth::Session(Some(session)),
);
}
handle_rx.send(handle).unwrap();

View file

@ -4,7 +4,10 @@ use chrono::{serde::ts_milliseconds_option, DateTime, Utc};
use crossbeam::channel::Sender;
use dmp_core::{
music_controller::controller::{ControllerHandle, PlayerLocation},
music_storage::{library::{Song, Tag, URI}, queue::QueueItemType},
music_storage::{
library::{Song, Tag, URI},
queue::QueueItemType,
},
};
use itertools::Itertools;
use serde::Serialize;