87 lines
2.5 KiB
Rust
87 lines
2.5 KiB
Rust
use super::App;
|
|
use crate::radio::station::StationInfo;
|
|
use std::io;
|
|
use tokio::process::Child;
|
|
use tokio::sync::mpsc;
|
|
|
|
#[allow(clippy::type_complexity)]
|
|
pub(super) struct SpawnFn(Box<dyn Fn(&str) -> io::Result<Child> + Send + Sync>);
|
|
|
|
impl std::fmt::Debug for SpawnFn {
|
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
|
f.write_str("SpawnFn")
|
|
}
|
|
}
|
|
|
|
pub(super) fn new_mpv_spawn() -> SpawnFn {
|
|
SpawnFn(Box::new(mpv_spawn))
|
|
}
|
|
|
|
fn mpv_spawn(url: &str) -> io::Result<Child> {
|
|
tokio::process::Command::new("mpv")
|
|
.arg(url)
|
|
.arg("--no-video")
|
|
.arg("--quiet")
|
|
.arg("--term-playing-msg=${media-title}")
|
|
.stdout(std::process::Stdio::piped())
|
|
.stderr(std::process::Stdio::null())
|
|
.spawn()
|
|
}
|
|
|
|
impl App {
|
|
pub(super) async fn play_station(&mut self, station: StationInfo) {
|
|
if let Some(mut child) = self.player.take() {
|
|
let _ = child.kill().await;
|
|
}
|
|
|
|
self.error_message = None;
|
|
self.current_song = None;
|
|
self.current_station = Some(station.clone());
|
|
|
|
let Some(SpawnFn(ref spawn)) = self.spawn_player else {
|
|
return;
|
|
};
|
|
|
|
let (tx, rx) = mpsc::unbounded_channel();
|
|
self.song_rx = Some(rx);
|
|
|
|
match spawn(&station.url) {
|
|
Err(e) => {
|
|
self.error_message = Some(format!("Failed to start mpv: {e}"));
|
|
self.current_station = None;
|
|
}
|
|
Ok(mut child) => {
|
|
let mut stdout = child.stdout.take().expect("mpv stdout");
|
|
tokio::spawn(async move {
|
|
use tokio::io::{AsyncBufReadExt, BufReader};
|
|
let mut reader = BufReader::new(&mut stdout).lines();
|
|
while let Ok(Some(line)) = reader.next_line().await {
|
|
let title = line.trim().to_string();
|
|
if !title.is_empty() {
|
|
let _ = tx.send(title);
|
|
}
|
|
}
|
|
});
|
|
self.player = Some(child);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub(super) async fn stop_playback(&mut self) {
|
|
if let Some(mut child) = self.player.take() {
|
|
let _ = child.kill().await;
|
|
}
|
|
self.current_station = None;
|
|
self.current_song = None;
|
|
self.song_rx = None;
|
|
self.error_message = None;
|
|
}
|
|
|
|
pub(super) async fn exit(&mut self) {
|
|
if let Some(mut child) = self.player.take() {
|
|
let _ = child.kill().await;
|
|
}
|
|
self.exit = true;
|
|
}
|
|
}
|