streamdeck-workspace/streamdeck-daemon/src/dbus/deck.rs

167 lines
4.4 KiB
Rust

use crate::{
dbus::{button::Button, button_path, deck_path},
store::Store,
};
use std::collections::BTreeSet;
use streamdeck_common::Input;
use zbus::{Connection, SignalContext};
pub(super) struct Deck {
connection: Connection,
serial_number: String,
name: String,
product_name: String,
port_name: String,
store: Store,
buttons: BTreeSet<String>,
}
impl Deck {
#[tracing::instrument(skip(connection))]
pub(crate) async fn hydrate(
connection: Connection,
serial_number: String,
product_name: String,
port_name: String,
store: Store,
) -> anyhow::Result<()> {
let commands = store.get_commands(&serial_number).await?;
let name = store.deck_name(&serial_number).await?;
let path = deck_path(&serial_number);
let deck = Deck {
connection: connection.clone(),
serial_number,
name: name.unwrap_or_else(|| String::from("Streamdeck")),
product_name,
port_name,
store,
buttons: BTreeSet::new(),
};
let _ = connection.object_server().at(path.clone(), deck).await?;
let iface_ref = connection
.object_server()
.interface::<_, Deck>(path)
.await?;
let mut iface = iface_ref.get_mut().await;
for (input, command) in commands {
let command = serde_json::to_string(&command)?;
iface.create_button(input, command).await?;
}
Ok(())
}
}
#[zbus::dbus_interface(name = "dog.asonix.git.asonix.StreamdeckDaemon.Deck")]
impl Deck {
#[dbus_interface(property)]
async fn name(&self) -> &str {
tracing::debug!("name");
&self.name
}
#[dbus_interface(property)]
async fn set_name(&mut self, name: String) {
tracing::debug!("set name");
if self
.store
.set_deck_name(&self.serial_number, &name)
.await
.is_ok()
{
self.name = name;
}
}
#[dbus_interface(property)]
async fn product_name(&self) -> &str {
tracing::debug!("product_name");
&self.product_name
}
#[dbus_interface(property)]
async fn port_name(&self) -> &str {
tracing::debug!("port_name");
&self.port_name
}
async fn get_buttons(&self) -> Vec<String> {
tracing::debug!("get buttons");
self.buttons.iter().cloned().collect()
}
async fn create_button(&mut self, input: Input, command: String) -> zbus::fdo::Result<String> {
tracing::debug!("create button");
let path = button_path(&self.serial_number, &input);
self.buttons.insert(path.clone());
Button::hydrate(
self.connection.clone(),
self.serial_number.clone(),
input.clone(),
self.store.clone(),
)
.await
.map_err(crate::dbus::fail)?;
let iface = self
.connection
.object_server()
.interface::<_, Button>(path.clone())
.await?;
let mut iface_ref = iface.get_mut().await;
iface_ref.set_command(command).await;
let ctx = iface.signal_context();
Self::button_added(ctx, input).await?;
Ok(path)
}
async fn remove_button(&mut self, input: Input) -> zbus::fdo::Result<()> {
tracing::debug!("remove button");
let path = button_path(&self.serial_number, &input);
self.buttons.remove(&path);
let _ = self
.connection
.object_server()
.remove::<Button, _>(path.clone())
.await?;
self.store
.unset(&self.serial_number, input.clone())
.await
.map_err(crate::dbus::fail)?;
let iface = self
.connection
.object_server()
.interface::<_, Self>(path)
.await?;
let ctx = iface.signal_context();
Self::button_removed(ctx, input).await?;
Ok(())
}
#[dbus_interface(signal)]
pub(super) async fn button_pushed(ctx: &SignalContext<'_>, input: Input) -> zbus::Result<()>;
#[dbus_interface(signal)]
async fn button_added(ctx: &SignalContext<'_>, input: Input) -> zbus::Result<()>;
#[dbus_interface(signal)]
async fn button_removed(ctx: &SignalContext<'_>, input: Input) -> zbus::Result<()>;
}