143 lines
4.1 KiB
Rust
143 lines
4.1 KiB
Rust
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<PlayerMessage>,
|
|
tx_engine: Sender<PlayerEngineCommand>,
|
|
}
|
|
|
|
impl Default for Player {
|
|
fn default() -> Self {
|
|
let (tx_engine, rx_engine) = flume::bounded(16);
|
|
let (tx_player, messages): (Sender<PlayerMessage>, Receiver<PlayerMessage>) =
|
|
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<MediaInfo> {
|
|
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<MediaInfo> {
|
|
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<Duration> {
|
|
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<Duration> {
|
|
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<Duration> {
|
|
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<f32> {
|
|
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<bool> {
|
|
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<f32> {
|
|
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<bool> {
|
|
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?
|
|
}
|
|
}
|