2023-09-18 22:39:11 +02:00

108 lines
2.4 KiB
Rust

use librespot::{
connect::spirc::Spirc,
core::{
config::{ConnectConfig, SessionConfig},
session::Session,
},
discovery::Credentials,
playback::{
config::{Bitrate, PlayerConfig, VolumeCtrl},
mixer::{self, MixerConfig},
player::{Player as SpotifyPlayer, PlayerEvent},
},
};
use tokio::sync::mpsc::UnboundedReceiver;
use crate::{
audio::{stream::Stream, SinkEvent, StreamSink},
librespot_ext::discovery::CredentialsExt,
utils,
};
pub struct Player {
stream: Stream,
session: Option<Session>,
}
impl Player {
pub fn create() -> Self {
Self {
stream: Stream::new(),
session: None,
}
}
pub async fn start(
&mut self,
token: &str,
device_name: &str,
) -> Result<
(
Spirc,
(UnboundedReceiver<PlayerEvent>, UnboundedReceiver<SinkEvent>),
),
Box<dyn std::error::Error>,
> {
let username = utils::spotify::get_username(token).await?;
let player_config = PlayerConfig {
bitrate: Bitrate::Bitrate96,
..Default::default()
};
let credentials = Credentials::with_token(username, token);
// Shutdown old session (cannot be done in the stop function)
if let Some(session) = self.session.take() {
session.shutdown()
}
// Connect the session
let (session, _) = Session::connect(
SessionConfig {
ap_port: Some(9999), // Force the use of ap.spotify.com, which has the lowest latency
..Default::default()
},
credentials,
None,
false,
)
.await?;
self.session = Some(session.clone());
let mixer = (mixer::find(Some("softvol")).expect("to exist"))(MixerConfig {
volume_ctrl: VolumeCtrl::Linear,
..Default::default()
});
let stream = self.get_stream();
let (tx, rx) = tokio::sync::mpsc::unbounded_channel();
let (player, receiver) = SpotifyPlayer::new(
player_config,
session.clone(),
mixer.get_soft_volume(),
move || Box::new(StreamSink::new(stream, tx)),
);
let (spirc, spirc_task) = Spirc::new(
ConnectConfig {
name: device_name.into(),
// 50%
initial_volume: Some(65535 / 2),
..Default::default()
},
session.clone(),
player,
mixer,
);
tokio::spawn(spirc_task);
Ok((spirc, (receiver, rx)))
}
pub fn get_stream(&self) -> Stream {
self.stream.clone()
}
}