mirror of
https://github.com/Dangoware/dango-music-player.git
synced 2025-04-19 01:52:53 -05:00
Updated Prismriver and fixed scrobbling timing
This commit is contained in:
parent
2ac3acdf5a
commit
b8f942feb1
4 changed files with 57 additions and 52 deletions
|
@ -9,7 +9,7 @@ use std::{
|
||||||
|
|
||||||
use chrono::TimeDelta;
|
use chrono::TimeDelta;
|
||||||
use crossbeam::{scope, select};
|
use crossbeam::{scope, select};
|
||||||
use crossbeam_channel::{bounded, Receiver};
|
use crossbeam_channel::{unbounded, Receiver};
|
||||||
use discord_presence::Client;
|
use discord_presence::Client;
|
||||||
use listenbrainz::ListenBrainz;
|
use listenbrainz::ListenBrainz;
|
||||||
use parking_lot::RwLock;
|
use parking_lot::RwLock;
|
||||||
|
@ -30,6 +30,7 @@ pub(super) enum ConnectionsNotification {
|
||||||
},
|
},
|
||||||
StateChange(PrismState),
|
StateChange(PrismState),
|
||||||
SongChange(Song),
|
SongChange(Song),
|
||||||
|
AboutToFinish,
|
||||||
EOS,
|
EOS,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,10 +57,11 @@ impl Controller {
|
||||||
},
|
},
|
||||||
}: ControllerConnections,
|
}: ControllerConnections,
|
||||||
) {
|
) {
|
||||||
let (dc_state_rx, dc_state_tx) = bounded::<PrismState>(1);
|
let (dc_state_rx, dc_state_tx) = unbounded::<PrismState>();
|
||||||
let (dc_song_rx, dc_song_tx) = bounded::<Song>(1);
|
let (dc_song_rx, dc_song_tx) = unbounded::<Song>();
|
||||||
let (lb_song_rx, lb_song_tx) = bounded::<Song>(1);
|
let (lb_song_rx, lb_song_tx) = unbounded::<Song>();
|
||||||
let (lb_eos_rx, lb_eos_tx) = bounded::<()>(1);
|
let (lb_abt_fin_rx, lb_abt_fn_tx) = unbounded::<()>();
|
||||||
|
let (lb_eos_rx, lb_eos_tx) = unbounded::<()>();
|
||||||
|
|
||||||
scope(|s| {
|
scope(|s| {
|
||||||
s.builder()
|
s.builder()
|
||||||
|
@ -87,6 +89,11 @@ impl Controller {
|
||||||
lb_eos_rx.send(()).unwrap();
|
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()
|
s.builder()
|
||||||
.name("ListenBrainz Handler".to_string())
|
.name("ListenBrainz Handler".to_string())
|
||||||
.spawn(move |_| {
|
.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();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
@ -199,7 +206,7 @@ impl Controller {
|
||||||
DC_ACTIVE.store(false, Ordering::Relaxed);
|
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();
|
let mut client = ListenBrainz::new();
|
||||||
client.authenticate(token).unwrap();
|
client.authenticate(token).unwrap();
|
||||||
if !client.is_authenticated() {
|
if !client.is_authenticated() {
|
||||||
|
@ -207,10 +214,14 @@ impl Controller {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut song: Option<Song> = None;
|
let mut song: Option<Song> = None;
|
||||||
|
let mut last_song: Option<Song> = None;
|
||||||
LB_ACTIVE.store(true, Ordering::Relaxed);
|
LB_ACTIVE.store(true, Ordering::Relaxed);
|
||||||
|
println!("ListenBrainz connected");
|
||||||
|
|
||||||
while true {
|
while true {
|
||||||
let song = &mut song;
|
let song = &mut song;
|
||||||
|
let last_song = &mut last_song;
|
||||||
|
|
||||||
let client = &client;
|
let client = &client;
|
||||||
select! {
|
select! {
|
||||||
recv(song_tx) -> res => {
|
recv(song_tx) -> res => {
|
||||||
|
@ -225,13 +236,19 @@ impl Controller {
|
||||||
} else {
|
} else {
|
||||||
continue
|
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);
|
*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) -> _ => {
|
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) {
|
let artist = if let Some(tag) = song.get_tag(&Tag::Artist) {
|
||||||
tag.as_str()
|
tag.as_str()
|
||||||
} else {
|
} else {
|
||||||
|
@ -242,7 +259,9 @@ impl Controller {
|
||||||
} else {
|
} else {
|
||||||
continue
|
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");
|
println!("Song Scrobbled");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -250,34 +269,4 @@ impl Controller {
|
||||||
}
|
}
|
||||||
LB_ACTIVE.store(false, Ordering::Relaxed);
|
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));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -277,6 +277,7 @@ impl Controller {
|
||||||
let player = Prismriver::new();
|
let player = Prismriver::new();
|
||||||
let player_state = player.state.clone();
|
let player_state = player.state.clone();
|
||||||
let player_timing = player.get_timing_recv();
|
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 finished_tx = player.get_finished_recv();
|
||||||
let (notifications_rx, notifications_tx) =
|
let (notifications_rx, notifications_tx) =
|
||||||
crossbeam_channel::unbounded::<ConnectionsNotification>();
|
crossbeam_channel::unbounded::<ConnectionsNotification>();
|
||||||
|
@ -325,6 +326,7 @@ impl Controller {
|
||||||
Controller::player_monitor_loop(
|
Controller::player_monitor_loop(
|
||||||
player_state,
|
player_state,
|
||||||
player_timing,
|
player_timing,
|
||||||
|
about_to_finish_tx,
|
||||||
finished_tx,
|
finished_tx,
|
||||||
player_mail.0,
|
player_mail.0,
|
||||||
notify_next_song,
|
notify_next_song,
|
||||||
|
|
|
@ -20,7 +20,8 @@ impl Controller {
|
||||||
pub(super) fn player_monitor_loop(
|
pub(super) fn player_monitor_loop(
|
||||||
playback_state: Arc<std::sync::RwLock<PrismState>>,
|
playback_state: Arc<std::sync::RwLock<PrismState>>,
|
||||||
playback_time_tx: Receiver<(Option<TimeDelta>, Option<TimeDelta>)>,
|
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>,
|
player_mail: async_channel::Sender<PlayerCommandInput>,
|
||||||
notify_next_song: Sender<Song>,
|
notify_next_song: Sender<Song>,
|
||||||
notify_connections_: Sender<ConnectionsNotification>,
|
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
|
// Thread for End of Track
|
||||||
let notify_connections = notify_connections_.clone();
|
let notify_connections = notify_connections_.clone();
|
||||||
s.spawn(move || {
|
s.spawn(move || {
|
||||||
|
println!("EOS monitor started");
|
||||||
futures::executor::block_on(async {
|
futures::executor::block_on(async {
|
||||||
println!("EOS monitor started");
|
|
||||||
while true {
|
while true {
|
||||||
let _ = finished_recv.recv();
|
_ = finished_tx.recv();
|
||||||
println!("End of song");
|
|
||||||
|
|
||||||
let (command, tx) = PlayerCommandInput::command(PlayerCommand::NextSong);
|
let (command, tx) = PlayerCommandInput::command(PlayerCommand::NextSong);
|
||||||
player_mail.send(command).await.unwrap();
|
player_mail.send(command).await.unwrap();
|
||||||
|
@ -64,12 +76,13 @@ impl Controller {
|
||||||
notify_connections
|
notify_connections
|
||||||
.send(ConnectionsNotification::SongChange(song))
|
.send(ConnectionsNotification::SongChange(song))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
notify_connections
|
}
|
||||||
|
|
||||||
|
notify_connections
|
||||||
.send(ConnectionsNotification::EOS)
|
.send(ConnectionsNotification::EOS)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
println!("End of song");
|
||||||
}
|
}
|
||||||
std::thread::sleep(Duration::from_millis(100));
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
"$schema": "https://schema.tauri.app/config/2",
|
"$schema": "https://schema.tauri.app/config/2",
|
||||||
"productName": "Dango Music Player",
|
"productName": "Dango Music Player",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"identifier": "com.dango-music-player.app",
|
"identifier": "com.dmp.app",
|
||||||
"build": {
|
"build": {
|
||||||
"beforeDevCommand": "npm run dev",
|
"beforeDevCommand": "npm run dev",
|
||||||
"devUrl": "http://localhost:1420",
|
"devUrl": "http://localhost:1420",
|
||||||
|
@ -14,13 +14,14 @@
|
||||||
{
|
{
|
||||||
"title": "Dango Music Player",
|
"title": "Dango Music Player",
|
||||||
"width": 800,
|
"width": 800,
|
||||||
"height": 600
|
"height": 600,
|
||||||
|
"decorations": true
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"security": {
|
"security": {
|
||||||
"assetProtocol": {
|
"assetProtocol": {
|
||||||
"enable": true,
|
"enable": true,
|
||||||
"scope": { "allow": ["asset://localhost*", "http://localhost*"] }
|
"scope": { "allow": ["asset://localhost*"] }
|
||||||
},
|
},
|
||||||
"csp": {
|
"csp": {
|
||||||
"default-src": "'self' customprotocol: asset:",
|
"default-src": "'self' customprotocol: asset:",
|
||||||
|
|
Loading…
Reference in a new issue