feat(daemon): implementet get full-state command

This commit is contained in:
2026-01-28 02:41:33 +03:00
parent ca85d4c369
commit 5ea9b3b0ba
6 changed files with 74 additions and 74 deletions
+3
View File
@@ -92,6 +92,8 @@ enum GetCommands {
Input, Input,
/// All audio inputs /// All audio inputs
Inputs, Inputs,
/// Full player state
FullState,
} }
#[derive(Subcommand, Debug)] #[derive(Subcommand, Debug)]
@@ -146,6 +148,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
GetCommands::Tracks => Request::get_tracks(), GetCommands::Tracks => Request::get_tracks(),
GetCommands::Input => Request::get_input(), GetCommands::Input => Request::get_input(),
GetCommands::Inputs => Request::get_inputs(), GetCommands::Inputs => Request::get_inputs(),
GetCommands::FullState => Request::get_full_state(),
}, },
Commands::Set { parameter } => match parameter { Commands::Set { parameter } => match parameter {
SetCommands::Volume { volume, id } => Request::set_volume(volume, id), SetCommands::Volume { volume, id } => Request::set_volume(volume, id),
+9
View File
@@ -34,6 +34,15 @@ pub struct TrackInfo {
pub paused: bool, pub paused: bool,
} }
#[derive(Default, Debug, Clone, Serialize, Deserialize)]
pub struct FullState {
pub state: PlayerState,
pub tracks: Vec<TrackInfo>,
pub volume: f32,
pub current_input: String,
pub all_inputs: HashMap<String, String>,
}
pub struct PlayingSound { pub struct PlayingSound {
pub id: u32, pub id: u32,
pub sink: Sink, pub sink: Sink,
+41 -2
View File
@@ -1,12 +1,15 @@
use crate::{ use crate::{
types::{audio_player::PlayerState, socket::Response}, types::{
audio_player::{FullState, PlayerState},
socket::Response,
},
utils::{ utils::{
daemon::get_audio_player, daemon::get_audio_player,
pipewire::{get_all_devices, get_device}, pipewire::{get_all_devices, get_device},
}, },
}; };
use async_trait::async_trait; use async_trait::async_trait;
use std::path::PathBuf; use std::{collections::HashMap, path::PathBuf};
#[async_trait] #[async_trait]
pub trait Executable { pub trait Executable {
@@ -79,6 +82,8 @@ pub struct ToggleLoopCommand {
pub id: Option<u32>, pub id: Option<u32>,
} }
pub struct GetFullStateCommand {}
#[async_trait] #[async_trait]
impl Executable for PingCommand { impl Executable for PingCommand {
async fn execute(&self) -> Response { 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())
}
}
+4
View File
@@ -155,6 +155,10 @@ impl Request {
} }
Request::new("toggle_loop", args) Request::new("toggle_loop", args)
} }
pub fn get_full_state() -> Self {
Request::new("get_full_state", vec![])
}
} }
#[derive(Default, Debug, Clone, Serialize, Deserialize)] #[derive(Default, Debug, Clone, Serialize, Deserialize)]
+1
View File
@@ -69,6 +69,7 @@ pub fn parse_command(request: &Request) -> Option<Box<dyn Executable + Send>> {
Some(Box::new(SetLoopCommand { enabled, id })) Some(Box::new(SetLoopCommand { enabled, id }))
} }
"toggle_loop" => Some(Box::new(ToggleLoopCommand { id })), "toggle_loop" => Some(Box::new(ToggleLoopCommand { id })),
"get_full_state" => Some(Box::new(GetFullStateCommand {})),
_ => None, _ => None,
} }
} }
+16 -72
View File
@@ -1,6 +1,6 @@
use crate::{ use crate::{
types::{ types::{
audio_player::{PlayerState, TrackInfo}, audio_player::FullState,
config::GuiConfig, config::GuiConfig,
gui::AudioPlayerState, gui::AudioPlayerState,
socket::{Request, Response}, socket::{Request, Response},
@@ -8,7 +8,6 @@ use crate::{
utils::daemon::{is_daemon_running, make_request}, utils::daemon::{is_daemon_running, make_request},
}; };
use std::{ use std::{
collections::HashMap,
error::Error, error::Error,
sync::{Arc, Mutex}, sync::{Arc, Mutex},
}; };
@@ -63,73 +62,13 @@ pub fn start_app_state_thread(audio_player_state_shared: Arc<Mutex<AudioPlayerSt
continue; continue;
} }
let state_req = Request::get_state(); let full_state_req = Request::get_full_state();
let tracks_req = Request::get_tracks(); let full_state_res = make_request(full_state_req).await.unwrap_or_default();
let volume_req = Request::get_volume();
let current_input_req = Request::get_input();
let all_inputs_req = Request::get_inputs();
let (state_res, tracks_res, volume_res, current_input_res, all_inputs_res) = tokio::join!( if full_state_res.status {
make_request(state_req), let full_state: FullState =
make_request(tracks_req), serde_json::from_str(&full_state_res.message).unwrap_or_default();
make_request(volume_req),
make_request(current_input_req),
make_request(all_inputs_req),
);
let state_res = state_res.unwrap_or_default();
let tracks_res = tracks_res.unwrap_or_default();
let volume_res = volume_res.unwrap_or_default();
let current_input_res = current_input_res.unwrap_or_default();
let all_inputs_res = all_inputs_res.unwrap_or_default();
let state = match state_res.status {
true => serde_json::from_str::<PlayerState>(&state_res.message).unwrap(),
false => PlayerState::default(),
};
let tracks = match tracks_res.status {
true => {
serde_json::from_str::<Vec<TrackInfo>>(&tracks_res.message).unwrap_or_default()
}
false => vec![],
};
let volume = match volume_res.status {
true => volume_res.message.parse::<f32>().unwrap(),
false => 0.0,
};
let current_input = match current_input_res.status {
true => current_input_res
.message
.as_str()
.split(" - ")
.collect::<Vec<&str>>()
.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::<HashMap<String, String>>(),
false => HashMap::new(),
};
{
let mut guard = audio_player_state_shared.lock().unwrap(); let mut guard = audio_player_state_shared.lock().unwrap();
guard.state = match guard.new_state.clone() { guard.state = match guard.new_state.clone() {
@@ -137,12 +76,17 @@ pub fn start_app_state_thread(audio_player_state_shared: Arc<Mutex<AudioPlayerSt
guard.new_state = None; guard.new_state = None;
new_state new_state
} }
None => state, None => full_state.state,
}; };
guard.tracks = tracks.clone(); guard.tracks = full_state.tracks;
guard.volume = volume; guard.volume = full_state.volume;
guard.current_input = current_input; guard.current_input = full_state
guard.all_inputs = all_inputs; .current_input
.split(" - ")
.next()
.unwrap_or_default()
.to_string();
guard.all_inputs = full_state.all_inputs;
guard.is_daemon_running = true; guard.is_daemon_running = true;
} }