Add naming support
This commit is contained in:
parent
a6d11a9f1f
commit
381a54a62a
84
src/dbus.rs
84
src/dbus.rs
|
@ -331,6 +331,90 @@ impl Dbus {
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
b.method_with_cr_async(
|
||||||
|
"SetInputName",
|
||||||
|
("serial_number", "input", "name"),
|
||||||
|
(),
|
||||||
|
|mut ctx, cr, (serial_number, key, name): (String, u8, String)| {
|
||||||
|
log::debug!("SetInputName");
|
||||||
|
let state: &mut DbusState = cr.data_mut(ctx.path()).unwrap();
|
||||||
|
|
||||||
|
let store = state.store.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
if store
|
||||||
|
.set_input_name(&serial_number, key, &name)
|
||||||
|
.await
|
||||||
|
.is_ok()
|
||||||
|
{
|
||||||
|
return ctx.reply(Ok(()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reply(Err(MethodErr::failed("Failed to set input name")))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
b.method_with_cr_async(
|
||||||
|
"GetInputNames",
|
||||||
|
("serial_number",),
|
||||||
|
("names",),
|
||||||
|
|mut ctx, cr, (serial_number,): (String,)| {
|
||||||
|
log::debug!("InputNames");
|
||||||
|
let state: &mut DbusState = cr.data_mut(ctx.path()).unwrap();
|
||||||
|
|
||||||
|
let store = state.store.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
if let Ok(names) = store.input_names(&serial_number).await {
|
||||||
|
return ctx.reply(Ok((names.into_iter().collect::<Vec<_>>(),)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reply(Err(MethodErr::failed("Failed to get input names")))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
b.method_with_cr_async(
|
||||||
|
"SetDeckName",
|
||||||
|
("serial_number", "name"),
|
||||||
|
(),
|
||||||
|
|mut ctx, cr, (serial_number, name): (String, String)| {
|
||||||
|
log::debug!("SetDeckName");
|
||||||
|
let state: &mut DbusState = cr.data_mut(ctx.path()).unwrap();
|
||||||
|
|
||||||
|
let store = state.store.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
if store.set_deck_name(&serial_number, &name).await.is_ok() {
|
||||||
|
return ctx.reply(Ok(()));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reply(Err(MethodErr::failed("Failed to set deck name")))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
b.method_with_cr_async(
|
||||||
|
"GetDeckName",
|
||||||
|
("serial_number",),
|
||||||
|
("name",),
|
||||||
|
|mut ctx, cr, (serial_number,): (String,)| {
|
||||||
|
log::debug!("GetDeckName");
|
||||||
|
let state: &mut DbusState = cr.data_mut(ctx.path()).unwrap();
|
||||||
|
|
||||||
|
let store = state.store.clone();
|
||||||
|
|
||||||
|
async move {
|
||||||
|
if let Ok(Some(name)) = store.deck_name(&serial_number).await {
|
||||||
|
return ctx.reply(Ok((name,)));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.reply(Err(MethodErr::failed("Failed to fetch deck name")))
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
cr.insert("/dog/asonix/git/asonix/Streamdeck", &[iface_token], state);
|
cr.insert("/dog/asonix/git/asonix/Streamdeck", &[iface_token], state);
|
||||||
|
|
93
src/store.rs
93
src/store.rs
|
@ -1,10 +1,12 @@
|
||||||
use crate::message::Command;
|
use crate::message::Command;
|
||||||
use sled::{Db, IVec, Tree};
|
use sled::{Db, IVec, Tree};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub(crate) struct Store {
|
pub(crate) struct Store {
|
||||||
commands: Tree,
|
commands: Tree,
|
||||||
settings: Tree,
|
settings: Tree,
|
||||||
|
names: Tree,
|
||||||
db: Db,
|
db: Db,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,12 +16,79 @@ impl Store {
|
||||||
Ok(Store {
|
Ok(Store {
|
||||||
commands: db.open_tree("dog.asonix.git.asonix.streamdeck/commands")?,
|
commands: db.open_tree("dog.asonix.git.asonix.streamdeck/commands")?,
|
||||||
settings: db.open_tree("dog.asonix.git.asonix.streamdeck/settings")?,
|
settings: db.open_tree("dog.asonix.git.asonix.streamdeck/settings")?,
|
||||||
|
names: db.open_tree("dog.asonix.git.asonix.streamdeck/names")?,
|
||||||
db,
|
db,
|
||||||
}) as Result<Store, anyhow::Error>
|
}) as Result<Store, anyhow::Error>
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn set_input_name(
|
||||||
|
&self,
|
||||||
|
deck: &str,
|
||||||
|
input: u8,
|
||||||
|
name: &str,
|
||||||
|
) -> Result<(), anyhow::Error> {
|
||||||
|
let key = self.input_name_key(deck, input);
|
||||||
|
let value = name.as_bytes().to_vec();
|
||||||
|
|
||||||
|
let names = self.names.clone();
|
||||||
|
tokio::task::spawn_blocking(move || names.insert(key, value)).await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn input_names(
|
||||||
|
&self,
|
||||||
|
deck: &str,
|
||||||
|
) -> Result<HashMap<u8, String>, anyhow::Error> {
|
||||||
|
let prefix = self.input_name_prefix(deck);
|
||||||
|
let prefix_len = prefix.len();
|
||||||
|
|
||||||
|
let names = self.names.clone();
|
||||||
|
let vec = tokio::task::spawn_blocking(move || {
|
||||||
|
names
|
||||||
|
.scan_prefix(prefix.clone())
|
||||||
|
.filter_map(|res| {
|
||||||
|
let (key, value) = res.ok()?;
|
||||||
|
|
||||||
|
if key.len() != prefix_len + 1 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let input = key[prefix_len];
|
||||||
|
|
||||||
|
let value = String::from_utf8_lossy(&value).to_string();
|
||||||
|
Some((input, value))
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
|
.await?;
|
||||||
|
|
||||||
|
Ok(vec)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn set_deck_name(&self, deck: &str, name: &str) -> Result<(), anyhow::Error> {
|
||||||
|
let key = self.deck_name_key(deck);
|
||||||
|
let value = name.as_bytes().to_vec();
|
||||||
|
|
||||||
|
let names = self.names.clone();
|
||||||
|
tokio::task::spawn_blocking(move || names.insert(key, value)).await??;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) async fn deck_name(&self, deck: &str) -> Result<Option<String>, anyhow::Error> {
|
||||||
|
let key = self.deck_name_key(deck);
|
||||||
|
|
||||||
|
let names = self.names.clone();
|
||||||
|
let opt = tokio::task::spawn_blocking(move || names.get(key)).await??;
|
||||||
|
|
||||||
|
if let Some(ivec) = opt {
|
||||||
|
return Ok(Some(String::from_utf8_lossy(&ivec).to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(None)
|
||||||
|
}
|
||||||
|
|
||||||
pub(crate) async fn setting<T>(&self, key: &str) -> Result<Option<T>, anyhow::Error>
|
pub(crate) async fn setting<T>(&self, key: &str) -> Result<Option<T>, anyhow::Error>
|
||||||
where
|
where
|
||||||
T: serde::de::DeserializeOwned,
|
T: serde::de::DeserializeOwned,
|
||||||
|
@ -119,6 +188,30 @@ impl Store {
|
||||||
Ok(vec)
|
Ok(vec)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn deck_name_key(&self, deck: &str) -> IVec {
|
||||||
|
let mut key = b"names/".to_vec();
|
||||||
|
key.extend(deck.as_bytes());
|
||||||
|
|
||||||
|
IVec::from(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input_name_prefix(&self, deck: &str) -> IVec {
|
||||||
|
let mut key = b"names/".to_vec();
|
||||||
|
key.extend(deck.as_bytes());
|
||||||
|
key.push(b'/');
|
||||||
|
|
||||||
|
IVec::from(key)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input_name_key(&self, deck: &str, input: u8) -> IVec {
|
||||||
|
let mut key = b"names/".to_vec();
|
||||||
|
key.extend(deck.as_bytes());
|
||||||
|
key.push(b'/');
|
||||||
|
key.push(input);
|
||||||
|
|
||||||
|
IVec::from(key)
|
||||||
|
}
|
||||||
|
|
||||||
fn cmd_prefix(&self, deck: &str) -> IVec {
|
fn cmd_prefix(&self, deck: &str) -> IVec {
|
||||||
let mut prefix = deck.as_bytes().to_vec();
|
let mut prefix = deck.as_bytes().to_vec();
|
||||||
prefix.push(b'/');
|
prefix.push(b'/');
|
||||||
|
|
Loading…
Reference in a new issue