| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762 |
- /* This file is part of DarkFi (https://dark.fi)
- *
- * Copyright (C) 2020-2026 Dyne.org foundation
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Affero General Public License as
- * published by the Free Software Foundation, either version 3 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Affero General Public License for more details.
- *
- * You should have received a copy of the GNU Affero General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
- use async_lock::Mutex;
- use darkfi_serial::{async_trait, deserialize, Decodable, Encodable, SerialDecodable, VarInt};
- use std::{io::Cursor, sync::Arc};
- use zeromq::{Socket, SocketRecv, SocketSend};
- use crate::{
- app::node::{create_layer, create_vector_art},
- error::{Error, Result},
- expr::{decompile, Compiler, MachineGlobals, SExprCode, SExprMachine, SExprVal},
- gfx::{gfxtag, Renderer},
- prop::{PropertyPermission, PropertyType, Role},
- scene::{Pimpl, SceneNodeId, SceneNodePtr, SceneNodeType, ScenePath, Slot},
- ui::{
- get_ui_object3, get_ui_object_ptr, Layer, RedrawTrigger, ShapeVertex, VectorArt,
- VectorShape,
- },
- ExecutorPtr,
- };
- /// Stop the UI tasks and clear the buffers of a subtree about to be
- /// removed at runtime, mirroring Window::stop(). Only pimpl types with a
- /// UIObject mapping are touched; others (Window, Setting, plugins, Null)
- /// keep their tasks until process exit.
- fn stop_ui_subtree(node: &SceneNodePtr) {
- if matches!(
- node.pimpl(),
- Pimpl::Layer(_) |
- Pimpl::ScrollLayer(_) |
- Pimpl::VectorArt(_) |
- Pimpl::Text(_) |
- Pimpl::TextScramble(_) |
- Pimpl::Edit(_) |
- Pimpl::Image(_) |
- Pimpl::Video(_) |
- Pimpl::Button(_) |
- Pimpl::EmojiPicker(_) |
- Pimpl::Shortcut(_) |
- Pimpl::Menu(_) |
- Pimpl::TokenTable(_) |
- Pimpl::Slider(_) |
- Pimpl::Dropdown(_)
- ) {
- get_ui_object3(node).stop();
- }
- for child in node.get_children() {
- stop_ui_subtree(&child);
- }
- }
- /// Run a freshly compiled expr on a throwaway machine so unknown
- /// variables (typos) reject the set request instead of failing silently
- /// on every eval afterwards. The dummy values are irrelevant; only name
- /// resolution matters and the globals are discarded. `global_names` are
- /// the variable names the property's real eval can provide.
- fn check_expr(code: &SExprCode, global_names: &[String]) -> Result<()> {
- let mut globals: MachineGlobals = vec![];
- for name in global_names {
- globals.push((name.clone(), SExprVal::Float32(1.)));
- }
- let mut machine = SExprMachine { globals, stmts: code };
- machine.call()?;
- Ok(())
- }
- const USE_IPV6: bool = true;
- #[derive(Debug, SerialDecodable)]
- #[repr(u8)]
- enum Command {
- Hello = 0,
- AddNode = 1,
- RemoveNode = 9,
- RenameNode = 23,
- ScanDangling = 24,
- LookupNodeId = 12,
- AddProperty = 11,
- LinkNode = 2,
- UnlinkNode = 8,
- GetInfo = 19,
- GetChildren = 4,
- GetParents = 5,
- GetProperties = 3,
- GetPropertyValue = 6,
- SetPropertyValue = 7,
- GetSignals = 14,
- RegisterSlot = 15,
- UnregisterSlot = 16,
- LookupSlotId = 17,
- GetSlots = 18,
- GetMethods = 20,
- GetMethod = 21,
- CallMethod = 22,
- }
- // Missing calls todo:
- // GetPropLen
- // UnsetProperty
- // SetPropertyNull
- // PropertyPushNull
- // PropertyPush
- // PropertyIsUnset
- pub struct ZeroMQAdapter {
- /*
- // req-reply commands
- req_socket: zmq::Socket,
- // We cannot share zmq sockets across threads, and we cannot quickly spawn
- // pub sockets due to address reuse errors.
- slot_sender: mpsc::SyncSender<(Vec<u8>, Vec<u8>)>,
- slot_recvr: Option<mpsc::Receiver<(Vec<u8>, Vec<u8>)>>,
- */
- sg_root: SceneNodePtr,
- renderer: Renderer,
- redraw: RedrawTrigger,
- ex: ExecutorPtr,
- zmq_rep: Mutex<zeromq::RepSocket>,
- zmq_pub: Mutex<zeromq::PubSocket>,
- }
- impl ZeroMQAdapter {
- pub async fn new(
- sg_root: SceneNodePtr,
- renderer: Renderer,
- redraw: RedrawTrigger,
- ex: ExecutorPtr,
- ) -> Arc<Self> {
- let mut zmq_rep = zeromq::RepSocket::new();
- if USE_IPV6 {
- zmq_rep.bind("tcp://[::]:9484").await.unwrap();
- } else {
- zmq_rep.bind("tcp://0.0.0.0:9484").await.unwrap();
- }
- let mut zmq_pub = zeromq::PubSocket::new();
- if USE_IPV6 {
- zmq_pub.bind("tcp://[::]:9485").await.unwrap();
- } else {
- zmq_pub.bind("tcp://0.0.0.0:9485").await.unwrap();
- }
- Arc::new(Self {
- sg_root,
- renderer,
- redraw,
- ex,
- zmq_rep: Mutex::new(zmq_rep),
- zmq_pub: Mutex::new(zmq_pub),
- })
- }
- pub async fn run(self: Arc<Self>) {
- loop {
- let req = self.zmq_rep.lock().await.recv().await.unwrap();
- assert_eq!(req.len(), 2);
- let cmd = req.get(0).unwrap().to_vec();
- assert_eq!(cmd.len(), 1);
- let payload = req.get(1).unwrap().to_vec();
- let cmd = deserialize(&cmd).unwrap();
- debug!(target: "req", "zmq: {:?} {:?}", cmd, payload);
- let self2 = self.clone();
- match self2.process_request(cmd, payload).await {
- Ok(reply) => {
- let mut m = zeromq::ZmqMessage::from(vec![0u8]);
- m.push_back(reply.into());
- // [errc:1] [reply]
- self.zmq_rep.lock().await.send(m).await.unwrap();
- }
- Err(err) => {
- let errc = err as u8;
- warn!(target: "req", "errc {}: {}", errc, err);
- let mut m = zeromq::ZmqMessage::from(vec![errc]);
- m.push_back(vec![].into());
- // [errc:1] [reply]
- self.zmq_rep.lock().await.send(m).await.unwrap();
- }
- }
- }
- }
- async fn process_request(self: Arc<Self>, cmd: Command, payload: Vec<u8>) -> Result<Vec<u8>> {
- let mut cur = Cursor::new(&payload);
- let mut reply = vec![];
- match cmd {
- Command::Hello => {
- debug!(target: "req", "hello()");
- assert_eq!(payload.len(), 0);
- "hello".encode(&mut reply).unwrap();
- }
- Command::GetInfo => {
- /*
- let node_id = SceneNodeId::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({})", cmd, node_id);
- let node = scene_graph.get_node(node_id).ok_or(Error::NodeNotFound)?;
- node.name.encode(&mut reply).unwrap();
- node.typ.encode(&mut reply).unwrap();
- */
- }
- Command::GetChildren => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- debug!(target: "req", "{cmd:?}({node_path})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let children: Vec<_> = node
- .get_children()
- .iter()
- .map(|node| (node.name.clone(), node.id, node.typ))
- .collect();
- children.encode(&mut reply).unwrap();
- }
- Command::GetParents => {
- /*
- let node_id = SceneNodeId::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({})", cmd, node_id);
- let node = scene_graph.get_node(node_id).ok_or(Error::NodeNotFound)?;
- let parents: Vec<_> = node
- .parents
- .iter()
- .map(|node_inf| (node_inf.name.clone(), node_inf.id, node_inf.typ))
- .collect();
- parents.encode(&mut reply).unwrap();
- */
- }
- Command::GetProperties => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- debug!(target: "req", "{cmd:?}({node_path})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- VarInt(node.props.len() as u64).encode(&mut reply).unwrap();
- for prop in &node.props {
- prop.name.encode(&mut reply).unwrap();
- prop.typ.encode(&mut reply).unwrap();
- prop.subtype.encode(&mut reply).unwrap();
- //prop.defaults.encode(&mut reply).unwrap();
- prop.ui_name.encode(&mut reply).unwrap();
- prop.desc.encode(&mut reply).unwrap();
- prop.is_null_allowed.encode(&mut reply).unwrap();
- prop.is_expr_allowed.encode(&mut reply).unwrap();
- (prop.array_len as u32).encode(&mut reply).unwrap();
- prop.min_val.encode(&mut reply).unwrap();
- prop.max_val.encode(&mut reply).unwrap();
- prop.enum_items.encode(&mut reply).unwrap();
- let depends: Vec<_> = prop
- .get_depends()
- .into_iter()
- .map(|d| (d.i as u32, d.local_name))
- .collect();
- depends.encode(&mut reply).unwrap();
- }
- }
- Command::GetPropertyValue => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- let prop_name = String::decode(&mut cur).unwrap();
- debug!(target: "req", "{cmd:?}({node_path}, {prop_name})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let prop = node.get_property(&prop_name).ok_or(Error::PropertyNotFound)?;
- prop.typ.encode(&mut reply).unwrap();
- VarInt(prop.get_len() as u64).encode(&mut reply).unwrap();
- for i in 0..prop.get_len() {
- // Check the raw stored value, since get_value() resolves
- // exprs to their cached/default value and would never
- // report the EXPR status.
- let val = prop.get_raw_value(i)?;
- if val.is_expr() {
- 3u8.encode(&mut reply).unwrap();
- let expr = prop.get_expr(i)?;
- decompile(&expr).encode(&mut reply).unwrap();
- } else if val.is_unset() {
- // A null default encodes zero payload bytes, so it
- // is reported as the NULL status instead of UNSET.
- // This mirrors the old get_value() semantics, where
- // an unset index with a null default resolved to
- // null.
- let default = prop.defaults.lock().unwrap()[i].clone();
- if default.is_null() {
- 2u8.encode(&mut reply).unwrap();
- } else if default.is_expr() {
- // An unset index resolving through a default
- // expr reports the decompiled expr source under
- // the EXPR status. Encoding the SExprCode bytes
- // as the payload would desync the client, which
- // expects a payload matching the property type
- // on the UNSET path.
- 3u8.encode(&mut reply).unwrap();
- let expr = default.as_sexpr().unwrap();
- decompile(&expr).encode(&mut reply).unwrap();
- } else {
- 1u8.encode(&mut reply).unwrap();
- // Shapes are not serialized on the get path;
- // the python client shows a "<...>" placeholder.
- if prop.typ != PropertyType::VectorShape {
- default.encode(&mut reply).unwrap();
- }
- }
- } else if val.is_null() {
- 2u8.encode(&mut reply).unwrap();
- } else {
- 0u8.encode(&mut reply).unwrap();
- if prop.typ != PropertyType::VectorShape {
- val.encode(&mut reply).unwrap();
- }
- }
- }
- }
- Command::SetPropertyValue => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- let prop_name = String::decode(&mut cur).unwrap();
- let prop_i = u32::decode(&mut cur).unwrap() as usize;
- let prop_type = PropertyType::decode(&mut cur).unwrap();
- debug!(target: "req", "{cmd:?}({node_path}, {prop_name}, {prop_i}, {prop_type:?})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let prop = node.get_property(&prop_name).ok_or(Error::PropertyNotFound)?;
- let atom = &mut self.redraw.make_guard(gfxtag!("ZeroMQAdapter::SetPropertyValue"));
- match prop_type {
- PropertyType::Null => {
- prop.set_null(atom, Role::Root, prop_i)?;
- }
- PropertyType::Bool => {
- let val = bool::decode(&mut cur).unwrap();
- prop.set_bool(atom, Role::Root, prop_i, val)?;
- }
- PropertyType::Uint32 => {
- let val = u32::decode(&mut cur).unwrap();
- prop.set_u32(atom, Role::Root, prop_i, val)?;
- }
- PropertyType::Float32 => {
- let val = f32::decode(&mut cur).unwrap();
- prop.set_f32(atom, Role::Root, prop_i, val)?;
- }
- PropertyType::Str => {
- let val = String::decode(&mut cur).unwrap();
- prop.set_str(atom, Role::Root, prop_i, val)?;
- }
- PropertyType::Enum => {
- let val = String::decode(&mut cur).unwrap();
- prop.set_enum(atom, Role::Root, prop_i, val)?;
- }
- PropertyType::SceneNodeId => {
- let val = SceneNodeId::decode(&mut cur).unwrap();
- prop.set_node_id(atom, Role::Root, prop_i, val)?;
- }
- PropertyType::SExpr => {
- // Exprs are sent as source strings and compiled here.
- // The netdebug compiler is const-free: only machine
- // globals (w, h, ...) are available as variables.
- let expr_str = String::decode(&mut cur).unwrap();
- debug!(target: "req", " compiling expr \"{expr_str}\"");
- let code = Compiler::new().compile(&expr_str)?;
- // The property's eval site provides its depends
- // names plus one of the machine global sets in
- // use (w, h for most rects, parent_*/rect_* for
- // edit behaves), so accept the union and treat
- // anything else as a typo.
- let mut names: Vec<String> =
- prop.get_depends().into_iter().map(|d| d.local_name).collect();
- names.extend(
- ["w", "h", "parent_w", "parent_h", "rect_w", "rect_h"]
- .iter()
- .map(|s| s.to_string()),
- );
- check_expr(&code, &names)?;
- prop.set_expr(atom, Role::Root, prop_i, code)?;
- }
- PropertyType::VectorShape => {
- // Vertices carry coordinate exprs as source strings,
- // compiled with the same const-free compiler. The
- // payload is: vert count varint; per vert: x expr
- // string, y expr string, 4x f32 color; index count
- // varint; u16 indices.
- let cc = Compiler::new();
- // Shape verts eval with only the w/h globals.
- let shape_globals: Vec<String> =
- ["w", "h"].iter().map(|s| s.to_string()).collect();
- let vert_count = VarInt::decode(&mut cur)?.0 as usize;
- let mut verts = vec![];
- for _ in 0..vert_count {
- let x_src = String::decode(&mut cur)?;
- let y_src = String::decode(&mut cur)?;
- let color = [
- f32::decode(&mut cur)?,
- f32::decode(&mut cur)?,
- f32::decode(&mut cur)?,
- f32::decode(&mut cur)?,
- ];
- let x = cc.compile(&x_src)?;
- let y = cc.compile(&y_src)?;
- check_expr(&x, &shape_globals)?;
- check_expr(&y, &shape_globals)?;
- verts.push(ShapeVertex::new(x, y, color));
- }
- let index_count = VarInt::decode(&mut cur)?.0 as usize;
- let mut indices = vec![];
- for _ in 0..index_count {
- let index = u16::decode(&mut cur)?;
- if index as usize >= verts.len() {
- return Err(Error::PropertyWrongIndex)
- }
- indices.push(index);
- }
- let shape = VectorShape { verts, indices };
- prop.set_shape(atom, Role::Root, prop_i, shape)?;
- }
- }
- }
- Command::AddNode => {
- let parent_path: ScenePath = String::decode(&mut cur)?.parse()?;
- let node_name = String::decode(&mut cur)?;
- let node_type = SceneNodeType::decode(&mut cur)?;
- debug!(target: "req", "{cmd:?}({parent_path}, {node_name}, {node_type:?})");
- let parent = self.sg_root.lookup_node(parent_path).ok_or(Error::NodeNotFound)?;
- if parent.get_children().iter().any(|c| c.name == node_name) {
- return Err(Error::NodeSiblingNameConflict)
- }
- let renderer = self.renderer.clone();
- let redraw = self.redraw.clone();
- let node = match node_type {
- SceneNodeType::Layer => {
- create_layer(&node_name)
- .setup(|me| Layer::new(me, renderer.clone(), redraw.clone()))
- .await
- }
- SceneNodeType::VectorArt => {
- create_vector_art(&node_name)
- .setup(|me| VectorArt::new(me, renderer.clone(), redraw.clone()))
- .await
- }
- _ => return Err(Error::UnsupportedNodeType),
- };
- // Hold the guard over the link so the triggered pass sees
- // the attached node.
- let _atom = self.redraw.make_guard(gfxtag!("ZeroMQAdapter::AddNode"));
- parent.link(node.clone());
- node.id.encode(&mut reply).unwrap();
- // Arm the pimpl's OnModify handlers (redraw on property
- // change) exactly like window-owned nodes. The task keeps a
- // strong ref so an immediate RemoveNode cannot drop the node
- // out from under start().
- let node2 = node.clone();
- let ex2 = self.ex.clone();
- self.ex
- .spawn(async move {
- let obj = get_ui_object_ptr(&node2);
- obj.start(ex2).await
- })
- .detach();
- }
- Command::RemoveNode => {
- let node_path: ScenePath = String::decode(&mut cur)?.parse()?;
- debug!(target: "req", "{cmd:?}({node_path})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- // The scene root has no parent, removal is meaningless.
- if Arc::ptr_eq(&node, &self.sg_root) {
- return Err(Error::NodeNotRemovable)
- }
- // Tear down the subtree's UI tasks and buffers before
- // unlinking, mirroring Window::stop(). Pimpl types without
- // a UIObject mapping (Window, Setting, plugins, ...) keep
- // their tasks until process exit.
- stop_ui_subtree(&node);
- node.unlink();
- self.redraw.trigger();
- }
- Command::RenameNode => {
- /*
- let node_id = SceneNodeId::decode(&mut cur).unwrap();
- let node_name = String::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({}, {})", cmd, node_id, node_name);
- scene_graph.rename_node(node_id, node_name)?;
- */
- }
- Command::ScanDangling => {
- /*
- let dangling = scene_graph.scan_dangling();
- dangling.encode(&mut reply).unwrap();
- */
- }
- Command::LookupNodeId => {
- /*
- let node_path: String = deserialize(&payload).unwrap();
- debug!(target: "req", "{:?}({})", cmd, node_path);
- let node_id = scene_graph.lookup_node_id(&node_path).ok_or(Error::NodeNotFound)?;
- node_id.encode(&mut reply).unwrap();
- */
- }
- Command::AddProperty => {
- /*
- let node_id = SceneNodeId::decode(&mut cur).unwrap();
- let prop_name = String::decode(&mut cur).unwrap();
- let prop_type = PropertyType::decode(&mut cur).unwrap();
- let prop_subtype = PropertySubType::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({}, {}, {:?}, {:?}, ...)", cmd, node_id, prop_name, prop_type, prop_subtype);
- let mut prop = Property::new(prop_name, prop_type, prop_subtype, PropertyPermission::default());
- let prop_array_len = u32::decode(&mut cur).unwrap();
- prop.set_array_len(prop_array_len as usize);
- let prop_defaults_is_some = bool::decode(&mut cur).unwrap();
- if prop_defaults_is_some {
- let prop_defaults_len = VarInt::decode(&mut cur).unwrap();
- match prop_type {
- PropertyType::Uint32 => {
- let mut prop_defaults = vec![];
- for _ in 0..prop_defaults_len.0 {
- prop_defaults.push(u32::decode(&mut cur).unwrap());
- }
- prop.set_defaults_u32(prop_defaults)?;
- }
- PropertyType::Float32 => {
- let mut prop_defaults = vec![];
- for _ in 0..prop_defaults_len.0 {
- prop_defaults.push(f32::decode(&mut cur).unwrap());
- }
- prop.set_defaults_f32(prop_defaults)?;
- }
- PropertyType::Str => {
- let mut prop_defaults = vec![];
- for _ in 0..prop_defaults_len.0 {
- prop_defaults.push(String::decode(&mut cur).unwrap());
- }
- prop.set_defaults_str(prop_defaults)?;
- }
- _ => return Err(Error::PropertyWrongType),
- }
- }
- let prop_ui_name = String::decode(&mut cur).unwrap();
- let prop_desc = String::decode(&mut cur).unwrap();
- let prop_is_null_allowed = bool::decode(&mut cur).unwrap();
- let prop_is_expr_allowed = bool::decode(&mut cur).unwrap();
- match prop_type {
- PropertyType::Uint32 => {
- let min_is_some = bool::decode(&mut cur).unwrap();
- let min = if min_is_some {
- let min = u32::decode(&mut cur).unwrap();
- Some(PropertyValue::Uint32(min))
- } else {
- None
- };
- let max_is_some = bool::decode(&mut cur).unwrap();
- let max = if max_is_some {
- let max = u32::decode(&mut cur).unwrap();
- Some(PropertyValue::Uint32(max))
- } else {
- None
- };
- prop.min_val = min;
- prop.max_val = max;
- }
- PropertyType::Float32 => {
- let min_is_some = bool::decode(&mut cur).unwrap();
- let min = if min_is_some {
- let min = f32::decode(&mut cur).unwrap();
- Some(PropertyValue::Float32(min))
- } else {
- None
- };
- let max_is_some = bool::decode(&mut cur).unwrap();
- let max = if max_is_some {
- let max = f32::decode(&mut cur).unwrap();
- Some(PropertyValue::Float32(max))
- } else {
- None
- };
- prop.min_val = min;
- prop.max_val = max;
- }
- _ => {
- let min_is_some = bool::decode(&mut cur).unwrap();
- if min_is_some {
- return Err(Error::PropertyWrongType)
- }
- let max_is_some = bool::decode(&mut cur).unwrap();
- if max_is_some {
- return Err(Error::PropertyWrongType)
- }
- }
- }
- let prop_enum_items = Vec::<String>::decode(&mut cur).unwrap();
- let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
- prop.set_ui_text(prop_ui_name, prop_desc);
- prop.is_null_allowed = prop_is_null_allowed;
- prop.is_expr_allowed = prop_is_expr_allowed;
- if !prop_enum_items.is_empty() {
- prop.set_enum_items(prop_enum_items)?;
- }
- node.add_property(prop)?;
- */
- }
- Command::LinkNode => {
- /*
- let child_id = SceneNodeId::decode(&mut cur).unwrap();
- let parent_id = SceneNodeId::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({}, {})", cmd, child_id, parent_id);
- scene_graph.link(child_id, parent_id)?;
- */
- }
- Command::UnlinkNode => {
- /*
- let child_id = SceneNodeId::decode(&mut cur).unwrap();
- let parent_id = SceneNodeId::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({}, {})", cmd, child_id, parent_id);
- scene_graph.unlink(child_id, parent_id)?;
- */
- }
- Command::GetSignals => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- debug!(target: "req", "{cmd:?}({node_path})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let sigs = node.sigs.read().unwrap();
- let sig_names: Vec<_> = sigs.iter().map(|sig| sig.name.clone()).collect();
- sig_names.encode(&mut reply).unwrap();
- }
- Command::RegisterSlot => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- let sig_name = String::decode(&mut cur).unwrap();
- let slot_name = String::decode(&mut cur).unwrap();
- let user_data = Vec::<u8>::decode(&mut cur).unwrap();
- debug!(target: "req", "{cmd:?}({node_path}, {sig_name}, {slot_name}, {user_data:?})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let (sendr, recvr) = async_channel::unbounded();
- let slot = Slot { name: slot_name, notify: sendr };
- // This task will auto-die when the slot is unregistered
- let self2 = self.clone();
- self.ex
- .spawn(async move {
- loop {
- let Ok(signal_data) = recvr.recv().await else {
- // Die
- break
- };
- let mut m = zeromq::ZmqMessage::from(signal_data);
- m.push_back(user_data.clone().into());
- self2.zmq_pub.lock().await.send(m).await.unwrap();
- }
- })
- .detach();
- let slot_id = node.register(&sig_name, slot)?;
- slot_id.encode(&mut reply).unwrap();
- }
- Command::UnregisterSlot => {
- /*
- let node_id = SceneNodeId::decode(&mut cur).unwrap();
- let sig_name = String::decode(&mut cur).unwrap();
- let slot_id = SlotId::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({}, {}, {})", cmd, node_id, sig_name, slot_id);
- let node = scene_graph.get_node_mut(node_id).ok_or(Error::NodeNotFound)?;
- node.unregister(&sig_name, slot_id)?;
- */
- }
- Command::LookupSlotId => {
- /*
- let node_id = SceneNodeId::decode(&mut cur).unwrap();
- let sig_name = String::decode(&mut cur).unwrap();
- let slot_name = String::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({}, {}, {})", cmd, node_id, sig_name, slot_name);
- let node = scene_graph.get_node(node_id).ok_or(Error::NodeNotFound)?;
- let signal = node.get_signal(&sig_name).ok_or(Error::SignalNotFound)?;
- let slot_id = signal.lookup_slot_id(&slot_name).ok_or(Error::SlotNotFound)?;
- slot_id.encode(&mut reply).unwrap();
- */
- }
- Command::GetSlots => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- let sig_name = String::decode(&mut cur).unwrap();
- debug!(target: "req", "{cmd:?}({node_path}, {sig_name})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let signal = node.get_signal(&sig_name).ok_or(Error::SignalNotFound)?;
- let slots = signal.get_slots();
- let slot_names: Vec<_> =
- slots.iter().map(|(slot_id, slot)| (slot.name.clone(), *slot_id)).collect();
- slot_names.encode(&mut reply).unwrap();
- }
- Command::GetMethods => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- debug!(target: "req", "{cmd:?}({node_path})");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let method_names: Vec<_> = node.methods.iter().map(|m| m.name.clone()).collect();
- method_names.encode(&mut reply).unwrap();
- }
- Command::GetMethod => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- let method_name = String::decode(&mut cur).unwrap();
- debug!(target: "req", "{:?}({}, {})", cmd, node_path, method_name);
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let method = node.get_method(&method_name).ok_or(Error::MethodNotFound)?;
- method.args.encode(&mut reply).unwrap();
- method.result.encode(&mut reply).unwrap();
- }
- Command::CallMethod => {
- let node_path: ScenePath = String::decode(&mut cur).unwrap().parse()?;
- let method_name = String::decode(&mut cur).unwrap();
- let arg_data = Vec::<u8>::decode(&mut cur).unwrap();
- debug!(target: "req", "{cmd:?}({node_path}, {method_name}, ...)");
- let node = self.sg_root.lookup_node(node_path).ok_or(Error::NodeNotFound)?;
- let result = node.call_method(&method_name, arg_data).await?;
- result.encode(&mut reply).unwrap();
- }
- }
- Ok(reply)
- }
- }
|