From 5ea9b3b0bafbe22d5a0be701b36542b36fed559f Mon Sep 17 00:00:00 2001 From: arabian Date: Wed, 28 Jan 2026 02:41:33 +0300 Subject: [PATCH] feat(daemon): implementet get full-state command --- src/bin/cli.rs | 3 ++ src/types/audio_player.rs | 9 ++++ src/types/commands.rs | 43 ++++++++++++++++++- src/types/socket.rs | 4 ++ src/utils/commands.rs | 1 + src/utils/gui.rs | 88 +++++++-------------------------------- 6 files changed, 74 insertions(+), 74 deletions(-) diff --git a/src/bin/cli.rs b/src/bin/cli.rs index 4037368..c155632 100644 --- a/src/bin/cli.rs +++ b/src/bin/cli.rs @@ -92,6 +92,8 @@ enum GetCommands { Input, /// All audio inputs Inputs, + /// Full player state + FullState, } #[derive(Subcommand, Debug)] @@ -146,6 +148,7 @@ async fn main() -> Result<(), Box> { GetCommands::Tracks => Request::get_tracks(), GetCommands::Input => Request::get_input(), GetCommands::Inputs => Request::get_inputs(), + GetCommands::FullState => Request::get_full_state(), }, Commands::Set { parameter } => match parameter { SetCommands::Volume { volume, id } => Request::set_volume(volume, id), diff --git a/src/types/audio_player.rs b/src/types/audio_player.rs index 40e7337..7169741 100644 --- a/src/types/audio_player.rs +++ b/src/types/audio_player.rs @@ -34,6 +34,15 @@ pub struct TrackInfo { pub paused: bool, } +#[derive(Default, Debug, Clone, Serialize, Deserialize)] +pub struct FullState { + pub state: PlayerState, + pub tracks: Vec, + pub volume: f32, + pub current_input: String, + pub all_inputs: HashMap, +} + pub struct PlayingSound { pub id: u32, pub sink: Sink, diff --git a/src/types/commands.rs b/src/types/commands.rs index c07ddc9..b8f1cba 100644 --- a/src/types/commands.rs +++ b/src/types/commands.rs @@ -1,12 +1,15 @@ use crate::{ - types::{audio_player::PlayerState, socket::Response}, + types::{ + audio_player::{FullState, PlayerState}, + socket::Response, + }, utils::{ daemon::get_audio_player, pipewire::{get_all_devices, get_device}, }, }; use async_trait::async_trait; -use std::path::PathBuf; +use std::{collections::HashMap, path::PathBuf}; #[async_trait] pub trait Executable { @@ -79,6 +82,8 @@ pub struct ToggleLoopCommand { pub id: Option, } +pub struct GetFullStateCommand {} + #[async_trait] impl Executable for PingCommand { async fn execute(&self) -> Response { @@ -341,3 +346,37 @@ impl Executable for ToggleLoopCommand { } } } + +#[async_trait] +impl Executable for GetFullStateCommand { + async fn execute(&self) -> Response { + let (input_devices, _output_devices) = get_all_devices().await.unwrap(); + let mut all_inputs = HashMap::new(); + let mut current_input_nick = String::new(); + + let audio_player = get_audio_player().await.lock().await; + for device in input_devices { + if device.name == "pwsp-virtual-mic" { + continue; + } + + if let Some(current_input_name) = &audio_player.input_device_name { + if device.name == *current_input_name { + current_input_nick = format!("{} - {}", device.name, device.nick); + } + } + + all_inputs.insert(device.name, device.nick); + } + + let full_state = FullState { + state: audio_player.get_state(), + tracks: audio_player.get_tracks(), + volume: audio_player.volume, + current_input: current_input_nick, + all_inputs, + }; + + Response::new(true, serde_json::to_string(&full_state).unwrap()) + } +} diff --git a/src/types/socket.rs b/src/types/socket.rs index 1f35810..d762842 100644 --- a/src/types/socket.rs +++ b/src/types/socket.rs @@ -155,6 +155,10 @@ impl Request { } Request::new("toggle_loop", args) } + + pub fn get_full_state() -> Self { + Request::new("get_full_state", vec![]) + } } #[derive(Default, Debug, Clone, Serialize, Deserialize)] diff --git a/src/utils/commands.rs b/src/utils/commands.rs index 0e6e7c3..911b23a 100644 --- a/src/utils/commands.rs +++ b/src/utils/commands.rs @@ -69,6 +69,7 @@ pub fn parse_command(request: &Request) -> Option> { Some(Box::new(SetLoopCommand { enabled, id })) } "toggle_loop" => Some(Box::new(ToggleLoopCommand { id })), + "get_full_state" => Some(Box::new(GetFullStateCommand {})), _ => None, } } diff --git a/src/utils/gui.rs b/src/utils/gui.rs index 78af6ef..45a3d3d 100644 --- a/src/utils/gui.rs +++ b/src/utils/gui.rs @@ -1,6 +1,6 @@ use crate::{ types::{ - audio_player::{PlayerState, TrackInfo}, + audio_player::FullState, config::GuiConfig, gui::AudioPlayerState, socket::{Request, Response}, @@ -8,7 +8,6 @@ use crate::{ utils::daemon::{is_daemon_running, make_request}, }; use std::{ - collections::HashMap, error::Error, sync::{Arc, Mutex}, }; @@ -63,73 +62,13 @@ pub fn start_app_state_thread(audio_player_state_shared: Arc serde_json::from_str::(&state_res.message).unwrap(), - false => PlayerState::default(), - }; - - let tracks = match tracks_res.status { - true => { - serde_json::from_str::>(&tracks_res.message).unwrap_or_default() - } - false => vec![], - }; - - let volume = match volume_res.status { - true => volume_res.message.parse::().unwrap(), - false => 0.0, - }; - - let current_input = match current_input_res.status { - true => current_input_res - .message - .as_str() - .split(" - ") - .collect::>() - .first() - .unwrap() - .to_string(), - false => String::new(), - }; - let all_inputs = match all_inputs_res.status { - true => all_inputs_res - .message - .as_str() - .split(';') - .filter_map(|entry| { - let entry = entry.trim(); - if entry.is_empty() { - return None; - } - entry - .split_once(" - ") - .map(|(k, v)| (k.trim().to_string(), v.trim().to_string())) - }) - .collect::>(), - false => HashMap::new(), - }; - - { let mut guard = audio_player_state_shared.lock().unwrap(); guard.state = match guard.new_state.clone() { @@ -137,12 +76,17 @@ pub fn start_app_state_thread(audio_player_state_shared: Arc state, + None => full_state.state, }; - guard.tracks = tracks.clone(); - guard.volume = volume; - guard.current_input = current_input; - guard.all_inputs = all_inputs; + guard.tracks = full_state.tracks; + guard.volume = full_state.volume; + guard.current_input = full_state + .current_input + .split(" - ") + .next() + .unwrap_or_default() + .to_string(); + guard.all_inputs = full_state.all_inputs; guard.is_daemon_running = true; }