breadbar/src/bar/media.rs
Breadway 275c4aef2b
Some checks failed
Mirror to GitHub / mirror (push) Successful in 1m2s
Build and publish package / package (push) Failing after 1m24s
Release 0.2.0: media widget, wifi popover, control panel
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01PxgMEoa2PWNkKnW88pbMBM
2026-06-24 06:43:52 +08:00

85 lines
2.1 KiB
Rust

use crate::{App, AppInput};
use relm4::ComponentSender;
use std::time::Duration;
#[derive(Debug, Clone)]
pub struct MediaState {
pub title: String,
pub artist: String,
pub playing: bool,
pub has_player: bool,
}
async fn fetch() -> MediaState {
let none = || MediaState {
title: String::new(),
artist: String::new(),
playing: false,
has_player: false,
};
let status_out = tokio::time::timeout(
Duration::from_secs(2),
tokio::process::Command::new("playerctl")
.args(["status"])
.output(),
)
.await;
let status = match status_out {
Ok(Ok(out)) if out.status.success() => {
String::from_utf8_lossy(&out.stdout).trim().to_string()
}
_ => return none(),
};
if status == "Stopped" {
return none();
}
let playing = status == "Playing";
let meta_out = tokio::time::timeout(
Duration::from_secs(2),
tokio::process::Command::new("playerctl")
.args(["metadata", "--format", "{{artist}}\t{{title}}"])
.output(),
)
.await;
let (artist, title) = match meta_out {
Ok(Ok(out)) if out.status.success() => {
let s = String::from_utf8_lossy(&out.stdout).trim().to_string();
let mut parts = s.splitn(2, '\t');
let a = parts.next().unwrap_or("").to_string();
let t = parts.next().unwrap_or("").to_string();
(a, t)
}
_ => (String::new(), String::new()),
};
MediaState {
title,
artist,
playing,
has_player: true,
}
}
pub fn spawn_poller(sender: ComponentSender<App>) {
relm4::spawn(async move {
loop {
sender.input(AppInput::MediaUpdate(fetch().await));
tokio::time::sleep(Duration::from_secs(2)).await;
}
});
}
pub fn spawn_cmd(cmd: &'static str) {
relm4::spawn(async move {
let _ = tokio::process::Command::new("playerctl")
.arg(cmd)
.output()
.await;
});
}