Updated Prismriver and fixed scrobbling timing

This commit is contained in:
MrDulfin 2025-01-01 16:38:41 -05:00
parent 2ac3acdf5a
commit b8f942feb1
4 changed files with 57 additions and 52 deletions

View file

@ -9,7 +9,7 @@ use std::{
use chrono::TimeDelta;
use crossbeam::{scope, select};
use crossbeam_channel::{bounded, Receiver};
use crossbeam_channel::{unbounded, Receiver};
use discord_presence::Client;
use listenbrainz::ListenBrainz;
use parking_lot::RwLock;
@ -30,6 +30,7 @@ pub(super) enum ConnectionsNotification {
},
StateChange(PrismState),
SongChange(Song),
AboutToFinish,
EOS,
}
@ -56,10 +57,11 @@ impl Controller {
},
}: ControllerConnections,
) {
let (dc_state_rx, dc_state_tx) = bounded::<PrismState>(1);
let (dc_song_rx, dc_song_tx) = bounded::<Song>(1);
let (lb_song_rx, lb_song_tx) = bounded::<Song>(1);
let (lb_eos_rx, lb_eos_tx) = bounded::<()>(1);
let (dc_state_rx, dc_state_tx) = unbounded::<PrismState>();
let (dc_song_rx, dc_song_tx) = unbounded::<Song>();
let (lb_song_rx, lb_song_tx) = unbounded::<Song>();
let (lb_abt_fin_rx, lb_abt_fn_tx) = unbounded::<()>();
let (lb_eos_rx, lb_eos_tx) = unbounded::<()>();
scope(|s| {
s.builder()
@ -87,6 +89,11 @@ impl Controller {
lb_eos_rx.send(()).unwrap();
}
}
AboutToFinish => {
if LB_ACTIVE.load(Ordering::Relaxed) {
lb_abt_fin_rx.send(()).unwrap();
}
}
}
}
})
@ -105,7 +112,7 @@ impl Controller {
s.builder()
.name("ListenBrainz Handler".to_string())
.spawn(move |_| {
Controller::listenbrainz_scrobble(&token, lb_song_tx, lb_eos_tx);
Controller::listenbrainz_scrobble(&token, lb_song_tx, lb_abt_fn_tx, lb_eos_tx);
})
.unwrap();
}
@ -199,7 +206,7 @@ impl Controller {
DC_ACTIVE.store(false, Ordering::Relaxed);
}
fn listenbrainz_scrobble(token: &str, song_tx: Receiver<Song>, eos_tx: Receiver<()>) {
fn listenbrainz_scrobble(token: &str, song_tx: Receiver<Song>, abt_fn_tx: Receiver<()>, eos_tx: Receiver<()>) {
let mut client = ListenBrainz::new();
client.authenticate(token).unwrap();
if !client.is_authenticated() {
@ -207,10 +214,14 @@ impl Controller {
}
let mut song: Option<Song> = None;
let mut last_song: Option<Song> = None;
LB_ACTIVE.store(true, Ordering::Relaxed);
println!("ListenBrainz connected");
while true {
let song = &mut song;
let last_song = &mut last_song;
let client = &client;
select! {
recv(song_tx) -> res => {
@ -225,13 +236,19 @@ impl Controller {
} else {
continue
};
client.playing_now(artist, title, None).unwrap();
let release = _song.get_tag(&Tag::Key(String::from("MusicBrainzReleaseId"))).map(|id| id.as_str());
client.playing_now(artist, title, release).unwrap();
println!("Song Listening = {artist} - {title}");
*song = Some(_song);
println!("Song Listening")
}
},
recv(abt_fn_tx) -> _ => {
*last_song = song.take();
println!("song = {:?}", last_song.as_ref().map(|s| s.get_tag(&Tag::Title).map_or("No Title", |t| t.as_str())));
},
recv(eos_tx) -> _ => {
if let Some(song) = song {
if let Some(song) = last_song {
let artist = if let Some(tag) = song.get_tag(&Tag::Artist) {
tag.as_str()
} else {
@ -242,7 +259,9 @@ impl Controller {
} else {
continue
};
client.listen(artist, title, None).unwrap();
let release = song.get_tag(&Tag::Key(String::from("MusicBrainzReleaseId"))).map(|id| id.as_str());
client.listen(artist, title, release).unwrap();
println!("Song Scrobbled");
}
}
@ -251,33 +270,3 @@ impl Controller {
LB_ACTIVE.store(false, Ordering::Relaxed);
}
}
#[cfg(test)]
mod test_super {
use std::thread::{sleep, spawn};
use crossbeam_channel::unbounded;
use crate::config::tests::read_config_lib;
use super::*;
#[test]
fn lb_test() {
let (song_rx, song_tx) = unbounded();
let (eos_rx, eos_tx) = unbounded();
let (config, lib) = read_config_lib();
song_rx.send(lib.library[0].clone()).unwrap();
spawn(|| {
Controller::listenbrainz_scrobble(
config.connections.listenbrainz_token.unwrap().as_str(),
song_tx,
eos_tx,
);
});
sleep(Duration::from_secs(10));
eos_rx.send(()).unwrap();
sleep(Duration::from_secs(10));
}
}

View file

@ -277,6 +277,7 @@ impl Controller {
let player = Prismriver::new();
let player_state = player.state.clone();
let player_timing = player.get_timing_recv();
let about_to_finish_tx = player.get_about_to_finish_recv();
let finished_tx = player.get_finished_recv();
let (notifications_rx, notifications_tx) =
crossbeam_channel::unbounded::<ConnectionsNotification>();
@ -325,6 +326,7 @@ impl Controller {
Controller::player_monitor_loop(
player_state,
player_timing,
about_to_finish_tx,
finished_tx,
player_mail.0,
notify_next_song,

View file

@ -20,7 +20,8 @@ impl Controller {
pub(super) fn player_monitor_loop(
playback_state: Arc<std::sync::RwLock<PrismState>>,
playback_time_tx: Receiver<(Option<TimeDelta>, Option<TimeDelta>)>,
finished_recv: Receiver<()>,
about_to_finish_tx: Receiver<()>,
finished_tx: Receiver<()>,
player_mail: async_channel::Sender<PlayerCommandInput>,
notify_next_song: Sender<Song>,
notify_connections_: Sender<ConnectionsNotification>,
@ -45,14 +46,25 @@ impl Controller {
}
});
let notify_connections = notify_connections_.clone();
s.spawn(move || {
println!("AboutToFinish monitor started");
futures::executor::block_on(async {
while true {
_ = about_to_finish_tx.recv();
notify_connections.send(ConnectionsNotification::AboutToFinish).unwrap();
println!("About to Finish");
}
})
});
// Thread for End of Track
let notify_connections = notify_connections_.clone();
s.spawn(move || {
futures::executor::block_on(async {
println!("EOS monitor started");
futures::executor::block_on(async {
while true {
let _ = finished_recv.recv();
println!("End of song");
_ = finished_tx.recv();
let (command, tx) = PlayerCommandInput::command(PlayerCommand::NextSong);
player_mail.send(command).await.unwrap();
@ -64,12 +76,13 @@ impl Controller {
notify_connections
.send(ConnectionsNotification::SongChange(song))
.unwrap();
}
notify_connections
.send(ConnectionsNotification::EOS)
.unwrap();
println!("End of song");
}
}
std::thread::sleep(Duration::from_millis(100));
});
});

View file

@ -2,7 +2,7 @@
"$schema": "https://schema.tauri.app/config/2",
"productName": "Dango Music Player",
"version": "0.0.1",
"identifier": "com.dango-music-player.app",
"identifier": "com.dmp.app",
"build": {
"beforeDevCommand": "npm run dev",
"devUrl": "http://localhost:1420",
@ -14,13 +14,14 @@
{
"title": "Dango Music Player",
"width": 800,
"height": 600
"height": 600,
"decorations": true
}
],
"security": {
"assetProtocol": {
"enable": true,
"scope": { "allow": ["asset://localhost*", "http://localhost*"] }
"scope": { "allow": ["asset://localhost*"] }
},
"csp": {
"default-src": "'self' customprotocol: asset:",