mirror of
https://github.com/librespot-org/librespot.git
synced 2024-12-18 17:11:53 +00:00
Use single player and mixer instances
This commit is contained in:
parent
c6b62b82d4
commit
e3db0994bc
6 changed files with 48 additions and 39 deletions
|
@ -3,6 +3,7 @@ use std::{
|
||||||
future::Future,
|
future::Future,
|
||||||
pin::Pin,
|
pin::Pin,
|
||||||
sync::atomic::{AtomicUsize, Ordering},
|
sync::atomic::{AtomicUsize, Ordering},
|
||||||
|
sync::Arc,
|
||||||
time::{SystemTime, UNIX_EPOCH},
|
time::{SystemTime, UNIX_EPOCH},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -77,8 +78,8 @@ enum SpircPlayStatus {
|
||||||
type BoxedStream<T> = Pin<Box<dyn FusedStream<Item = T> + Send>>;
|
type BoxedStream<T> = Pin<Box<dyn FusedStream<Item = T> + Send>>;
|
||||||
|
|
||||||
struct SpircTask {
|
struct SpircTask {
|
||||||
player: Player,
|
player: Arc<Player>,
|
||||||
mixer: Box<dyn Mixer>,
|
mixer: Arc<dyn Mixer>,
|
||||||
|
|
||||||
sequence: SeqGenerator<u32>,
|
sequence: SeqGenerator<u32>,
|
||||||
|
|
||||||
|
@ -272,8 +273,8 @@ impl Spirc {
|
||||||
config: ConnectConfig,
|
config: ConnectConfig,
|
||||||
session: Session,
|
session: Session,
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
player: Player,
|
player: Arc<Player>,
|
||||||
mixer: Box<dyn Mixer>,
|
mixer: Arc<dyn Mixer>,
|
||||||
) -> Result<(Spirc, impl Future<Output = ()>), Error> {
|
) -> Result<(Spirc, impl Future<Output = ()>), Error> {
|
||||||
let spirc_id = SPIRC_COUNTER.fetch_add(1, Ordering::AcqRel);
|
let spirc_id = SPIRC_COUNTER.fetch_add(1, Ordering::AcqRel);
|
||||||
debug!("new Spirc[{}]", spirc_id);
|
debug!("new Spirc[{}]", spirc_id);
|
||||||
|
|
|
@ -40,7 +40,7 @@ async fn main() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut player = Player::new(player_config, session, Box::new(NoOpVolume), move || {
|
let player = Player::new(player_config, session, Box::new(NoOpVolume), move || {
|
||||||
backend(None, audio_format)
|
backend(None, audio_format)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -17,6 +17,7 @@ use librespot_metadata::{Album, Metadata};
|
||||||
use librespot_playback::mixer::{softmixer::SoftMixer, Mixer, MixerConfig};
|
use librespot_playback::mixer::{softmixer::SoftMixer, Mixer, MixerConfig};
|
||||||
use librespot_protocol::spirc::TrackRef;
|
use librespot_protocol::spirc::TrackRef;
|
||||||
use std::env;
|
use std::env;
|
||||||
|
use std::sync::Arc;
|
||||||
use tokio::join;
|
use tokio::join;
|
||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
|
@ -54,7 +55,7 @@ async fn main() {
|
||||||
session.clone(),
|
session.clone(),
|
||||||
credentials,
|
credentials,
|
||||||
player,
|
player,
|
||||||
Box::new(SoftMixer::open(MixerConfig::default())),
|
Arc::new(SoftMixer::open(MixerConfig::default())),
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::config::VolumeCtrl;
|
use crate::config::VolumeCtrl;
|
||||||
|
|
||||||
pub mod mappings;
|
pub mod mappings;
|
||||||
|
@ -5,7 +7,7 @@ use self::mappings::MappedCtrl;
|
||||||
|
|
||||||
pub struct NoOpVolume;
|
pub struct NoOpVolume;
|
||||||
|
|
||||||
pub trait Mixer: Send {
|
pub trait Mixer: Send + Sync {
|
||||||
fn open(config: MixerConfig) -> Self
|
fn open(config: MixerConfig) -> Self
|
||||||
where
|
where
|
||||||
Self: Sized;
|
Self: Sized;
|
||||||
|
@ -55,10 +57,10 @@ impl Default for MixerConfig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type MixerFn = fn(MixerConfig) -> Box<dyn Mixer>;
|
pub type MixerFn = fn(MixerConfig) -> Arc<dyn Mixer>;
|
||||||
|
|
||||||
fn mk_sink<M: Mixer + 'static>(config: MixerConfig) -> Box<dyn Mixer> {
|
fn mk_sink<M: Mixer + 'static>(config: MixerConfig) -> Arc<dyn Mixer> {
|
||||||
Box::new(M::open(config))
|
Arc::new(M::open(config))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const MIXERS: &[(&str, MixerFn)] = &[
|
pub const MIXERS: &[(&str, MixerFn)] = &[
|
||||||
|
|
|
@ -420,7 +420,7 @@ impl Player {
|
||||||
session: Session,
|
session: Session,
|
||||||
volume_getter: Box<dyn VolumeGetter + Send>,
|
volume_getter: Box<dyn VolumeGetter + Send>,
|
||||||
sink_builder: F,
|
sink_builder: F,
|
||||||
) -> Self
|
) -> Arc<Self>
|
||||||
where
|
where
|
||||||
F: FnOnce() -> Box<dyn Sink> + Send + 'static,
|
F: FnOnce() -> Box<dyn Sink> + Send + 'static,
|
||||||
{
|
{
|
||||||
|
@ -490,10 +490,10 @@ impl Player {
|
||||||
debug!("PlayerInternal thread finished.");
|
debug!("PlayerInternal thread finished.");
|
||||||
});
|
});
|
||||||
|
|
||||||
Self {
|
Arc::new(Self {
|
||||||
commands: Some(cmd_tx),
|
commands: Some(cmd_tx),
|
||||||
thread_handle: Some(handle),
|
thread_handle: Some(handle),
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_invalid(&self) -> bool {
|
pub fn is_invalid(&self) -> bool {
|
||||||
|
@ -1390,10 +1390,6 @@ impl Future for PlayerInternal {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.session.is_invalid() {
|
|
||||||
return Poll::Ready(());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!self.state.is_playing()) && all_futures_completed_or_not_ready {
|
if (!self.state.is_playing()) && all_futures_completed_or_not_ready {
|
||||||
return Poll::Pending;
|
return Poll::Pending;
|
||||||
}
|
}
|
||||||
|
|
53
src/main.rs
53
src/main.rs
|
@ -1715,6 +1715,31 @@ async fn main() {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mixer_config = setup.mixer_config.clone();
|
||||||
|
let mixer = (setup.mixer)(mixer_config);
|
||||||
|
let player_config = setup.player_config.clone();
|
||||||
|
|
||||||
|
let soft_volume = mixer.get_soft_volume();
|
||||||
|
let format = setup.format;
|
||||||
|
let backend = setup.backend;
|
||||||
|
let device = setup.device.clone();
|
||||||
|
let player = Player::new(player_config, session.clone(), soft_volume, move || {
|
||||||
|
(backend)(device, format)
|
||||||
|
});
|
||||||
|
|
||||||
|
if let Some(player_event_program) = setup.player_event_program.clone() {
|
||||||
|
_event_handler = Some(EventHandler::new(
|
||||||
|
player.get_player_event_channel(),
|
||||||
|
&player_event_program,
|
||||||
|
));
|
||||||
|
|
||||||
|
if setup.emit_sink_events {
|
||||||
|
player.set_sink_event_callback(Some(Box::new(move |sink_status| {
|
||||||
|
run_program_on_sink_events(sink_status, &player_event_program)
|
||||||
|
})));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
tokio::select! {
|
tokio::select! {
|
||||||
credentials = async {
|
credentials = async {
|
||||||
|
@ -1749,32 +1774,16 @@ async fn main() {
|
||||||
_ = async {}, if connecting && last_credentials.is_some() => {
|
_ = async {}, if connecting && last_credentials.is_some() => {
|
||||||
if session.is_invalid() {
|
if session.is_invalid() {
|
||||||
session = Session::new(setup.session_config.clone(), setup.cache.clone());
|
session = Session::new(setup.session_config.clone(), setup.cache.clone());
|
||||||
|
player.set_session(session.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mixer_config = setup.mixer_config.clone();
|
|
||||||
let mixer = (setup.mixer)(mixer_config);
|
|
||||||
let player_config = setup.player_config.clone();
|
|
||||||
let connect_config = setup.connect_config.clone();
|
let connect_config = setup.connect_config.clone();
|
||||||
|
|
||||||
let soft_volume = mixer.get_soft_volume();
|
let (spirc_, spirc_task_) = match Spirc::new(connect_config,
|
||||||
let format = setup.format;
|
session.clone(),
|
||||||
let backend = setup.backend;
|
last_credentials.clone().unwrap_or_default(),
|
||||||
let device = setup.device.clone();
|
player.clone(),
|
||||||
let player = Player::new(player_config, session.clone(), soft_volume, move || {
|
mixer.clone()).await {
|
||||||
(backend)(device, format)
|
|
||||||
});
|
|
||||||
|
|
||||||
if let Some(player_event_program) = setup.player_event_program.clone() {
|
|
||||||
_event_handler = Some(EventHandler::new(player.get_player_event_channel(), &player_event_program));
|
|
||||||
|
|
||||||
if setup.emit_sink_events {
|
|
||||||
player.set_sink_event_callback(Some(Box::new(move |sink_status| {
|
|
||||||
run_program_on_sink_events(sink_status, &player_event_program)
|
|
||||||
})));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let (spirc_, spirc_task_) = match Spirc::new(connect_config, session.clone(), last_credentials.clone().unwrap_or_default(), player, mixer).await {
|
|
||||||
Ok((spirc_, spirc_task_)) => (spirc_, spirc_task_),
|
Ok((spirc_, spirc_task_)) => (spirc_, spirc_task_),
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
error!("could not initialize spirc: {}", e);
|
error!("could not initialize spirc: {}", e);
|
||||||
|
|
Loading…
Reference in a new issue