use std::thread; use std::time::Duration; use anyhow::Result; use flume::{Receiver, Sender}; use tracing::error; use crate::player_engine::{MediaInfo, PlayerEngine, PlayerEngineCommand, PlayerMessage}; pub enum PlayerError {} pub struct Player { pub messages: Receiver, tx_engine: Sender, } impl Default for Player { fn default() -> Self { let (tx_engine, rx_engine) = flume::bounded(16); let (tx_player, messages): (Sender, Receiver) = flume::bounded(16); let tx_callbacks = tx_engine.clone(); // Capture the runtime handle here: the engine thread itself is not a // tokio context but needs one to create http streams. let runtime = tokio::runtime::Handle::try_current().ok(); thread::spawn(move || { let engine = match PlayerEngine::init(tx_callbacks, tx_player, runtime) { Err(e) => { error!("Could not initialize player: {}", e); return; } Ok(engine) => engine, }; engine.run(rx_engine); }); Self { messages, tx_engine, } } } impl Player { pub async fn play(&self, source_str: &str) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::Play(source_str.to_string(), tx)) .await?; rx.recv_async().await? } pub async fn restart(&self) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::Restart(tx)) .await?; rx.recv_async().await? } pub async fn elapsed(&self) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::GetElapsed(tx)) .await?; rx.recv_async().await? } pub async fn duration(&self) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::GetDuration(tx)) .await?; rx.recv_async().await? } pub async fn seek_to(&self, time: Duration) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::SeekTo(time, tx)) .await?; rx.recv_async().await? } pub async fn volume(&self) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::GetVolume(tx)) .await?; Ok(rx.recv_async().await?) } pub async fn is_paused(&self) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::GetPaused(tx)) .await?; rx.recv_async().await? } pub async fn set_volume(&self, volume: f32) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::SetVolume(volume, tx)) .await?; Ok(rx.recv_async().await?) } pub async fn pause(&self) -> Result<()> { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::Pause(tx)) .await?; rx.recv_async().await? } pub async fn unpause(&self) -> Result<()> { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::Unpause(tx)) .await?; rx.recv_async().await? } pub async fn toggle_play(&self) -> Result { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::TogglePlay(tx)) .await?; rx.recv_async().await? } pub async fn stop(&self) -> Result<()> { let (tx, rx) = flume::bounded(1); self.tx_engine .send_async(PlayerEngineCommand::Stop(tx)) .await?; rx.recv_async().await? } }