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
This commit is contained in:
parent
570d4224a0
commit
275c4aef2b
8 changed files with 1157 additions and 81 deletions
85
src/bar/media.rs
Normal file
85
src/bar/media.rs
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
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;
|
||||
});
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue