mirror of
https://github.com/arabianq/pipewire-soundpad.git
synced 2026-04-28 06:21:23 +00:00
feat(daemon): implementet get full-state command
This commit is contained in:
@@ -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),
|
||||||
|
|||||||
@@ -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
@@ -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())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user