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",
"stream-download",
"symphonia",
"thiserror",
"url",
]

View File

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

View File

@ -15,6 +15,8 @@ use player_engine::{PlayerEngine, PlayerEngineCommand};
// * Emit buffering
// * Emit errors
pub enum PlayerError {}
pub struct Player {
pub messages: Receiver<PlayerMessage>,
tx_engine: Sender<PlayerEngineCommand>,
@ -32,8 +34,9 @@ impl Default for Player {
let mut player = PlayerEngine::new(tx_decoder, tx_player);
loop {
match rx_engine.recv() {
Ok(PlayerEngineCommand::Play(source_str)) => {
player.play(&source_str);
Ok(PlayerEngineCommand::Play(source_str, tx)) => {
let res = player.play(&source_str);
tx.send(res);
}
Ok(PlayerEngineCommand::Pause) => {
player.pause();
@ -67,9 +70,34 @@ impl Default for Player {
impl Player {
// FIXME: this could check if the player started playing using a channel
// 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
.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(())
}
@ -92,4 +120,9 @@ impl Player {
self.tx_engine.send(PlayerEngineCommand::Stop);
Ok(())
}
pub async fn restart(&self) -> Result<()> {
// FIXME: implement
Ok(())
}
}

View File

@ -17,7 +17,7 @@ use symphonia::core::io::{
};
pub enum PlayerEngineCommand {
Play(String),
Play(String, Sender<Result<MediaInfo>>),
Pause,
Unpause,
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 mut sink = Sink::try_new(&handle)?;
let (source, hint) = self.get_source(source_str)?;
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 media_info = decoder.media_info();
tx_player.send(PlayerMessage::Duration(
media_info.duration.unwrap_or_default(),
));
// tx_player.send(PlayerEngineMessage::MediaInfo(media_info));
let decoder = decoder.periodic_access(Duration::from_millis(250), move |src| {
tx_player.send(PlayerMessage::Elapsed(src.elapsed()));
});
sink.append(decoder);
// 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);
Ok(())
Ok(media_info)
}
pub fn pause(&mut self) {