Add more player API methods

This commit is contained in:
chmanie 2023-06-08 12:17:11 +02:00
parent 788ac6ba6d
commit 85d6d263e1
4 changed files with 45 additions and 13 deletions

1
Cargo.lock generated
View File

@ -179,6 +179,7 @@ dependencies = [
"rodio", "rodio",
"stream-download", "stream-download",
"symphonia", "symphonia",
"thiserror",
"url", "url",
] ]

View File

@ -10,3 +10,4 @@ stream-download = { git = "https://github.com/aschey/stream-download-rs.git" }
anyhow = "1.0.71" anyhow = "1.0.71"
url = "2.4.0" url = "2.4.0"
flume = "0.10.14" flume = "0.10.14"
thiserror = "1.0.40"

View File

@ -15,6 +15,8 @@ use player_engine::{PlayerEngine, PlayerEngineCommand};
// * Emit buffering // * Emit buffering
// * Emit errors // * Emit errors
pub enum PlayerError {}
pub struct Player { pub struct Player {
pub messages: Receiver<PlayerMessage>, pub messages: Receiver<PlayerMessage>,
tx_engine: Sender<PlayerEngineCommand>, tx_engine: Sender<PlayerEngineCommand>,
@ -32,8 +34,9 @@ impl Default for Player {
let mut player = PlayerEngine::new(tx_decoder, tx_player); let mut player = PlayerEngine::new(tx_decoder, tx_player);
loop { loop {
match rx_engine.recv() { match rx_engine.recv() {
Ok(PlayerEngineCommand::Play(source_str)) => { Ok(PlayerEngineCommand::Play(source_str, tx)) => {
player.play(&source_str); let res = player.play(&source_str);
tx.send(res);
} }
Ok(PlayerEngineCommand::Pause) => { Ok(PlayerEngineCommand::Pause) => {
player.pause(); player.pause();
@ -67,9 +70,34 @@ impl Default for Player {
impl Player { impl Player {
// FIXME: this could check if the player started playing using a channel // FIXME: this could check if the player started playing using a channel
// Then it would be async (wait for Playing for example) // Then it would be async (wait for Playing for example)
pub async fn play(&self, source_str: &str) -> Result<()> { pub async fn play(&self, source_str: &str) -> Result<MediaInfo> {
let (tx, rx) = flume::bounded(1);
self.tx_engine self.tx_engine
.send(PlayerEngineCommand::Play(source_str.to_string())); .send(PlayerEngineCommand::Play(source_str.to_string(), tx));
if let Ok(res) = rx.recv_async().await {
return res;
}
// FIXME: add error type
Err(anyhow!("Player channel error"))
}
pub async fn elpased(&self) -> Duration {
// FIXME: implement
Duration::default()
}
pub async fn duration(&self) -> Duration {
// FIXME: implement
Duration::default()
}
pub async fn volume(&self) -> f32 {
// FIXME: implement
0.0
}
pub async fn set_volume(&self) -> Result<()> {
// FIXME: implement
Ok(()) Ok(())
} }
@ -92,4 +120,9 @@ impl Player {
self.tx_engine.send(PlayerEngineCommand::Stop); self.tx_engine.send(PlayerEngineCommand::Stop);
Ok(()) Ok(())
} }
pub async fn restart(&self) -> Result<()> {
// FIXME: implement
Ok(())
}
} }

View File

@ -17,7 +17,7 @@ use symphonia::core::io::{
}; };
pub enum PlayerEngineCommand { pub enum PlayerEngineCommand {
Play(String), Play(String, Sender<Result<MediaInfo>>),
Pause, Pause,
Unpause, Unpause,
TogglePlay, TogglePlay,
@ -56,26 +56,23 @@ impl PlayerEngine {
} }
} }
pub fn play(&mut self, source_str: &str) -> Result<()> { pub fn play(&mut self, source_str: &str) -> Result<MediaInfo> {
let tx_player = self.tx_player.clone();
let (stream, handle) = OutputStream::try_default()?; let (stream, handle) = OutputStream::try_default()?;
let mut sink = Sink::try_new(&handle)?; let mut sink = Sink::try_new(&handle)?;
let (source, hint) = self.get_source(source_str)?; let (source, hint) = self.get_source(source_str)?;
let mss = MediaSourceStream::new(source, MediaSourceStreamOptions::default()); let mss = MediaSourceStream::new(source, MediaSourceStreamOptions::default());
let tx_player = self.tx_player.clone();
let decoder = SymphoniaDecoder::new(mss, hint, self.tx_engine.clone())?; let decoder = SymphoniaDecoder::new(mss, hint, self.tx_engine.clone())?;
let media_info = decoder.media_info(); let media_info = decoder.media_info();
tx_player.send(PlayerMessage::Duration( tx_player.send(PlayerMessage::Duration(
media_info.duration.unwrap_or_default(), media_info.duration.unwrap_or_default(),
)); ));
// tx_player.send(PlayerEngineMessage::MediaInfo(media_info));
let decoder = decoder.periodic_access(Duration::from_millis(250), move |src| { let decoder = decoder.periodic_access(Duration::from_millis(250), move |src| {
tx_player.send(PlayerMessage::Elapsed(src.elapsed())); tx_player.send(PlayerMessage::Elapsed(src.elapsed()));
}); });
sink.append(decoder); sink.append(decoder);
// We need to keep the stream around, otherwise it gets dropped outside of this scope // We need to keep the stream around, otherwise it gets dropped outside of this scope
@ -85,7 +82,7 @@ impl PlayerEngine {
self.tx_player.send(PlayerMessage::Playing); self.tx_player.send(PlayerMessage::Playing);
Ok(()) Ok(media_info)
} }
pub fn pause(&mut self) { pub fn pause(&mut self) {