api.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. import zmq
  2. from collections import namedtuple
  3. from . import serial, exc, expr
  4. Property = namedtuple("Property", [
  5. "name",
  6. "type",
  7. "subtype",
  8. #"defaults",
  9. "ui_name",
  10. "desc",
  11. "is_null_allowed",
  12. "is_expr_allowed",
  13. "array_len",
  14. "min_val",
  15. "max_val",
  16. "enum_items"
  17. ])
  18. class Command:
  19. HELLO = 0
  20. ADD_NODE = 1
  21. REMOVE_NODE = 9
  22. RENAME_NODE = 23
  23. SCAN_DANGLING = 24
  24. LOOKUP_NODE_ID = 12
  25. ADD_PROPERTY = 11
  26. LINK_NODE = 2
  27. UNLINK_NODE = 8
  28. GET_INFO = 19
  29. GET_CHILDREN = 4
  30. GET_PARENTS = 5
  31. GET_PROPERTIES = 3
  32. GET_PROPERTY_VALUE = 6
  33. SET_PROPERTY_VALUE = 7
  34. GET_SIGNALS = 14
  35. REGISTER_SLOT = 15
  36. UNREGISTER_SLOT = 16
  37. LOOKUP_SLOT_ID = 17
  38. GET_SLOTS = 18
  39. GET_METHODS = 20
  40. GET_METHOD = 21
  41. CALL_METHOD = 22
  42. class SceneNodeType:
  43. NULL = 0
  44. ROOT = 1
  45. WINDOW = 2
  46. WINDOW_INPUT = 6
  47. KEYBOARD = 7
  48. MOUSE = 8
  49. LAYER = 3
  50. OBJECT = 4
  51. VECTOR_ART = 5
  52. TEXT = 9
  53. TEXTURE = 13
  54. FONTS = 10
  55. FONT = 11
  56. PLUGINS = 14
  57. PLUGIN = 15
  58. CHAT_VIEW = 16
  59. EDIT_BOX = 17
  60. CHAT_EDIT = 18
  61. IMAGE = 18
  62. BUTTON = 19
  63. class PropertyType:
  64. NULL = 0
  65. BOOL = 1
  66. UINT32 = 2
  67. FLOAT32 = 3
  68. STR = 4
  69. ENUM = 5
  70. BUFFER = 6
  71. SCENE_NODE_ID = 7
  72. SEXPR = 8
  73. @staticmethod
  74. def to_str(prop_type):
  75. match prop_type:
  76. case PropertyType.NULL:
  77. return "null"
  78. case PropertyType.BOOL:
  79. return "bool"
  80. case PropertyType.UINT32:
  81. return "uint32"
  82. case PropertyType.FLOAT32:
  83. return "float32"
  84. case PropertyType.STR:
  85. return "str"
  86. case PropertyType.ENUM:
  87. return "enum"
  88. case PropertyType.BUFFER:
  89. return "buffer"
  90. case PropertyType.SCENE_NODE_ID:
  91. return "scene_node_id"
  92. case PropertyType.SEXPR:
  93. return "sexpr"
  94. class PropertySubType:
  95. NULL = 0
  96. COLOR = 1
  97. PIXEL = 2
  98. RESOURCE_ID = 3
  99. @staticmethod
  100. def to_str(prop_type):
  101. match prop_type:
  102. case PropertySubType.NULL:
  103. return "null"
  104. case PropertySubType.Color:
  105. return "color"
  106. case PropertySubType.PIXEL:
  107. return "pixel"
  108. case PropertySubType.RESOURCE_ID:
  109. return "resource_id"
  110. class PropertyStatus:
  111. OK = 0
  112. UNSET = 1
  113. NULL = 2
  114. EXPR = 3
  115. class ErrorCode:
  116. INVALID_SCENE_PATH = 1
  117. NODE_NOT_FOUND = 2
  118. CHILD_NODE_NOT_FOUND = 3
  119. PARENT_NODE_NOT_FOUND = 4
  120. PROPERTY_ALREADY_EXISTS = 5
  121. PROPERTY_NOT_FOUND = 6
  122. PROPERTY_WRONG_TYPE = 7
  123. PROPERTY_WRONG_SUB_TYPE = 8
  124. PROPERTY_WRONG_LEN = 9
  125. PROPERTY_WRONG_INDEX = 10
  126. PROPERTY_OUT_OF_RANGE = 11
  127. PROPERTY_NULL_NOT_ALLOWED = 12
  128. PROPERTY_SEXPR_NOT_ALLOWED = 13
  129. PROPERTY_IS_BOUNDED = 14
  130. PROPERTY_WRONG_ENUM_ITEM = 15
  131. SIGNAL_ALREADY_EXISTS = 16
  132. SIGNAL_NOT_FOUND = 17
  133. SLOT_NOT_FOUND = 18
  134. METHOD_ALREADY_EXISTS = 19
  135. METHOD_NOT_FOUND = 20
  136. NODES_ARE_LINKED = 21
  137. NODES_NOT_LINKED = 22
  138. NODE_HAS_PARENTS = 23
  139. NODE_HAS_CHILDREN = 24
  140. NODE_PARENT_NAME_CONFLICT = 25
  141. NODE_CHILD_NAME_CONFLICT = 26
  142. NODE_SIBLING_NAME_CONFLICT = 27
  143. FILE_NOT_FOUND = 28
  144. RESOURCE_NOT_FOUND = 29
  145. PY_EVAL_ERR = 30
  146. SEXPR_EMPTY = 31
  147. SEXPR_GLOBAL_NOT_FOUND = 32
  148. CHANNEL_CLOSED = 36
  149. @staticmethod
  150. def to_str(errc):
  151. match errc:
  152. case ErrorCode.INVALID_SCENE_PATH:
  153. return "invalid_scene_path"
  154. case ErrorCode.NODE_NOT_FOUND:
  155. return "node_not_found"
  156. case ErrorCode.CHILD_NODE_NOT_FOUND:
  157. return "child_node_not_found"
  158. case ErrorCode.PARENT_NODE_NOT_FOUND:
  159. return "parent_node_not_found"
  160. case ErrorCode.PROPERTY_ALREADY_EXISTS:
  161. return "property_already_exists"
  162. case ErrorCode.PROPERTY_NOT_FOUND:
  163. return "property_not_found"
  164. case ErrorCode.PROPERTY_WRONG_TYPE:
  165. return "property_wrong_type"
  166. case ErrorCode.PROPERTY_WRONG_LEN:
  167. return "property_wrong_len"
  168. case ErrorCode.PROPERTY_WRONG_INDEX:
  169. return "property_wrong_index"
  170. case ErrorCode.PROPERTY_OUT_OF_RANGE:
  171. return "property_out_of_range"
  172. case ErrorCode.PROPERTY_NULL_NOT_ALLOWED:
  173. return "property_null_not_allowed"
  174. case ErrorCode.PROPERTY_SEXPR_NOT_ALLOWED:
  175. return "property_sexpr_not_allowed"
  176. case ErrorCode.PROPERTY_IS_BOUNDED:
  177. return "property_is_bounded"
  178. case ErrorCode.PROPERTY_WRONG_ENUM_ITEM:
  179. return "property_wrong_enum_item"
  180. case ErrorCode.SIGNAL_ALREADY_EXISTS:
  181. return "signal_already_exists"
  182. case ErrorCode.SIGNAL_NOT_FOUND:
  183. return "signal_not_found"
  184. case ErrorCode.SLOT_NOT_FOUND:
  185. return "slot_not_found"
  186. case ErrorCode.METHOD_ALREADY_EXISTS:
  187. return "method_already_exists"
  188. case ErrorCode.METHOD_NOT_FOUND:
  189. return "method_not_found"
  190. case ErrorCode.NODES_ARE_LINKED:
  191. return "nodes_are_linked"
  192. case ErrorCode.NODES_NOT_LINKED:
  193. return "nodes_not_linked"
  194. case ErrorCode.NODE_HAS_PARENTS:
  195. return "node_has_parents"
  196. case ErrorCode.NODE_HAS_CHILDREN:
  197. return "node_has_children"
  198. case ErrorCode.NODE_PARENT_NAME_CONFLICT:
  199. return "node_parent_name_conflict"
  200. case ErrorCode.NODE_CHILD_NAME_CONFLICT:
  201. return "node_child_name_conflict"
  202. case ErrorCode.NODE_SIBLING_NAME_CONFLICT:
  203. return "node_sibling_name_conflict"
  204. case ErrorCode.FILE_NOT_FOUND:
  205. return "file_not_found"
  206. case ErrorCode.RESOURCE_NOT_FOUND:
  207. return "resource_not_found"
  208. case ErrorCode.PY_EVAL_ERR:
  209. return "py_eval_err"
  210. case ErrorCode.SEXPR_EMPTY:
  211. return "sexpr_empty"
  212. case ErrorCode.SEXPR_GLOBAL_NOT_FOUND:
  213. return "sexpr_global_not_found"
  214. case ErrorCode.CHANNEL_CLOSED:
  215. return "channel_closed"
  216. def vertex(x, y, r, g, b, a, u, v):
  217. buf = bytearray()
  218. serial.write_f32(buf, x)
  219. serial.write_f32(buf, y)
  220. serial.write_f32(buf, r)
  221. serial.write_f32(buf, g)
  222. serial.write_f32(buf, b)
  223. serial.write_f32(buf, a)
  224. serial.write_f32(buf, u)
  225. serial.write_f32(buf, v)
  226. return buf
  227. def face(idx1, idx2, idx3):
  228. buf = bytearray()
  229. serial.write_u32(buf, idx1)
  230. serial.write_u32(buf, idx2)
  231. serial.write_u32(buf, idx3)
  232. return buf
  233. class Api:
  234. def __init__(self, addr="127.0.0.1", port=9484):
  235. context = zmq.Context()
  236. self.socket = context.socket(zmq.REQ)
  237. #self.socket.setsockopt(zmq.IPV6, True)
  238. self.socket.connect(f"tcp://{addr}:{port}")
  239. def _make_request(self, cmd, payload):
  240. req_cmd = bytearray()
  241. serial.write_u8(req_cmd, cmd)
  242. self.socket.send_multipart([req_cmd, payload])
  243. errc, reply = self.socket.recv_multipart()
  244. errc = int.from_bytes(errc, "little")
  245. cursor = serial.Cursor(reply)
  246. match errc:
  247. case 1:
  248. raise exc.InvalidScenePath
  249. case 2:
  250. raise exc.NodeNotFound
  251. case 3:
  252. raise exc.ChildNodeNotFound
  253. case 4:
  254. raise exc.ParentNodeNotFound
  255. case 5:
  256. raise exc.PropertyAlreadyExists
  257. case 6:
  258. raise exc.PropertyNotFound
  259. case 7:
  260. raise exc.PropertyWrongType
  261. case 8:
  262. raise exc.PropertyWrongSubType
  263. case 9:
  264. raise exc.PropertyWrongLen
  265. case 10:
  266. raise exc.PropertyWrongIndex
  267. case 11:
  268. raise exc.PropertyOutOfRange
  269. case 12:
  270. raise exc.PropertyNullNotAllowed
  271. case 12:
  272. raise exc.PropertySExprNotAllowed
  273. case 14:
  274. raise exc.PropertyIsBounded
  275. case 15:
  276. raise exc.PropertyWrongEnumItem
  277. case 16:
  278. raise exc.SignalAlreadyExists
  279. case 17:
  280. raise exc.SignalNotFound
  281. case 18:
  282. raise exc.SlotNotFound
  283. case 19:
  284. raise exc.MethodAlreadyExists
  285. case 20:
  286. raise exc.MethodNotFound
  287. case 21:
  288. raise exc.NodesAreLinked
  289. case 22:
  290. raise exc.NodesNotLinked
  291. case 23:
  292. raise exc.NodeHasParents
  293. case 24:
  294. raise exc.NodeHasChildren
  295. case 25:
  296. raise exc.NodeParentNameConflict
  297. case 26:
  298. raise exc.NodeChildNameConflict
  299. case 27:
  300. raise exc.NodeSiblingNameConflict
  301. case 28:
  302. raise exc.FileNotFound
  303. case 29:
  304. raise exc.ResourceNotFound
  305. case 30:
  306. raise exc.PyEvalErr
  307. case 31:
  308. raise exc.SExprEmpty
  309. case 32:
  310. raise exc.SExprGlobalNotFound
  311. case 36:
  312. raise exc.ChannelClosed
  313. return cursor
  314. def hello(self):
  315. response = self._make_request(Command.HELLO, bytearray())
  316. return serial.decode_str(response)
  317. def get_info(self, node_id):
  318. req = bytearray()
  319. serial.write_u32(req, node_id)
  320. cur = self._make_request(Command.GET_INFO, req)
  321. name = serial.decode_str(cur)
  322. type = serial.read_u8(cur)
  323. return (name, type)
  324. def get_children(self, node_path):
  325. req = bytearray()
  326. serial.encode_str(req, node_path)
  327. cur = self._make_request(Command.GET_CHILDREN, req)
  328. children_len = serial.decode_varint(cur)
  329. children = []
  330. for _ in range(children_len):
  331. child_name = serial.decode_str(cur)
  332. child_id = serial.read_u32(cur)
  333. child_type = serial.read_u8(cur)
  334. children.append((child_name, child_id, child_type))
  335. return children
  336. def get_parents(self, node_id):
  337. req = bytearray()
  338. serial.write_u32(req, node_id)
  339. cur = self._make_request(Command.GET_PARENTS, req)
  340. parents_len = serial.decode_varint(cur)
  341. parents = []
  342. for _ in range(parents_len):
  343. parent_name = serial.decode_str(cur)
  344. parent_id = serial.read_u32(cur)
  345. parent_type = serial.read_u8(cur)
  346. parents.append((parent_name, parent_id, parent_type))
  347. return parents
  348. def get_properties(self, node_path):
  349. req = bytearray()
  350. serial.encode_str(req, node_path)
  351. cur = self._make_request(Command.GET_PROPERTIES, req)
  352. props_len = serial.decode_varint(cur)
  353. props = []
  354. enum_read_fn = lambda cur: serial.decode_arr(cur, serial.decode_str)
  355. for _ in range(props_len):
  356. prop_name = serial.decode_str(cur)
  357. # We need prop_type below
  358. prop_type = serial.read_u8(cur)
  359. prop_read_fn = lambda cur: Api.read_prop_val(cur, prop_type)
  360. prop = Property(
  361. prop_name,
  362. prop_type,
  363. # subtype
  364. serial.read_u8(cur),
  365. # defaults
  366. #serial.decode_arr(cur, prop_read_fn),
  367. # ui_name
  368. serial.decode_str(cur),
  369. # desc
  370. serial.decode_str(cur),
  371. # is_null_allowed
  372. bool(serial.read_u8(cur)),
  373. # is_expr_allowed
  374. bool(serial.read_u8(cur)),
  375. # array_len
  376. serial.read_u32(cur),
  377. # min_val
  378. serial.decode_opt(cur, prop_read_fn),
  379. # max_val
  380. serial.decode_opt(cur, prop_read_fn),
  381. # enum_items
  382. serial.decode_opt(cur, enum_read_fn)
  383. )
  384. props.append(prop)
  385. return props
  386. @staticmethod
  387. def read_prop_val(cur, prop_type):
  388. match prop_type:
  389. case PropertyType.NULL:
  390. return None
  391. case PropertyType.BOOL:
  392. return bool(serial.read_u8(cur))
  393. case PropertyType.UINT32:
  394. return serial.read_u32(cur)
  395. case PropertyType.FLOAT32:
  396. return serial.read_f32(cur)
  397. case PropertyType.STR:
  398. return serial.decode_str(cur)
  399. case PropertyType.ENUM:
  400. return serial.decode_str(cur)
  401. case PropertyType.BUFFER:
  402. pass
  403. case PropertyType.SCENE_NODE_ID:
  404. return serial.read_u32(cur)
  405. case _:
  406. raise Exception("unknown property type returned")
  407. def get_property_value(self, node_path, prop_name):
  408. req = bytearray()
  409. serial.encode_str(req, node_path)
  410. serial.encode_str(req, prop_name)
  411. cur = self._make_request(Command.GET_PROPERTY_VALUE, req)
  412. prop_type = serial.read_u8(cur)
  413. def prop_read_fn(cur):
  414. prop_status = serial.read_u8(cur)
  415. match prop_status:
  416. case PropertyStatus.NULL:
  417. return None
  418. case PropertyStatus.EXPR:
  419. return None
  420. case PropertyStatus.UNSET | PropertyStatus.OK:
  421. return Api.read_prop_val(cur, prop_type)
  422. vals = serial.decode_arr(cur, prop_read_fn)
  423. return vals
  424. def add_node(self, node_name, node_type):
  425. req = bytearray()
  426. serial.encode_str(req, node_name)
  427. serial.write_u8(req, int(node_type))
  428. cur = self._make_request(Command.ADD_NODE, req)
  429. node_id = serial.read_u32(cur)
  430. return node_id
  431. def remove_node(self, node_id):
  432. req = bytearray()
  433. serial.write_u32(req, node_id)
  434. self._make_request(Command.REMOVE_NODE, req)
  435. def rename_node(self, node_id, node_name):
  436. req = bytearray()
  437. serial.write_u32(req, node_id)
  438. serial.encode_str(req, node_name)
  439. self._make_request(Command.RENAME_NODE, req)
  440. def scan_dangling(self):
  441. cur = self._make_request(Command.SCAN_DANGLING, bytearray())
  442. dangling_len = serial.decode_varint(cur)
  443. dangling = []
  444. for _ in range(dangling_len):
  445. node_id = serial.read_u32(cur)
  446. dangling.append(node_id)
  447. return dangling
  448. def lookup_node_id(self, node_path):
  449. req = bytearray()
  450. serial.encode_str(req, node_path)
  451. try:
  452. cur = self._make_request(Command.LOOKUP_NODE_ID, req)
  453. except exc.NodeNotFound:
  454. return None
  455. return serial.read_u32(cur)
  456. def add_property(self, node_id, prop):
  457. req = bytearray()
  458. serial.write_u32(req, node_id)
  459. serial.encode_str(req, prop.name)
  460. serial.write_u8(req, int(prop.type))
  461. serial.write_u8(req, int(prop.subtype))
  462. serial.write_u32(req, int(prop.array_len))
  463. def write_defaults(by):
  464. assert prop.defaults is not None
  465. defaults_len = len(prop.defaults)
  466. serial.encode_varint(req, defaults_len)
  467. for default in prop.defaults:
  468. match prop.type:
  469. case PropertyType.UINT32:
  470. serial.write_u32(req, default)
  471. case PropertyType.FLOAT32:
  472. serial.write_f32(req, default)
  473. case PropertyType.STR:
  474. serial.encode_str(req, default)
  475. case _:
  476. raise exc.PropertyWrongType
  477. serial.encode_opt(req, prop.defaults, write_defaults)
  478. serial.encode_str(req, prop.ui_name)
  479. serial.encode_str(req, prop.desc)
  480. serial.write_u8(req, int(prop.is_null_allowed))
  481. serial.write_u8(req, int(prop.is_expr_allowed))
  482. def write_mxx(v, by):
  483. assert v is not None
  484. match prop.type:
  485. case PropertyType.UINT32:
  486. serial.write_u32(req, v)
  487. case PropertyType.FLOAT32:
  488. serial.write_f32(req, v)
  489. case _:
  490. raise exc.PropertyWrongType
  491. write_min = lambda by: write_mxx(prop.min_val, by)
  492. write_max = lambda by: write_mxx(prop.max_val, by)
  493. serial.encode_opt(req, prop.min_val, write_min)
  494. serial.encode_opt(req, prop.max_val, write_max)
  495. serial.encode_varint(req, len(prop.enum_items))
  496. for enum_item in prop.enum_items:
  497. if prop.type != PropertyType.ENUM:
  498. raise exc.PropertyWrongType
  499. serial.encode_str(req, enum_item)
  500. self._make_request(Command.ADD_PROPERTY, req)
  501. def link_node(self, child_id, parent_id):
  502. req = bytearray()
  503. serial.write_u32(req, child_id)
  504. serial.write_u32(req, parent_id)
  505. self._make_request(Command.LINK_NODE, req)
  506. def unlink_node(self, child_id, parent_id):
  507. req = bytearray()
  508. serial.write_u32(req, child_id)
  509. serial.write_u32(req, parent_id)
  510. self._make_request(Command.UNLINK_NODE, req)
  511. def set_property_null(self, node_path, prop_name, i):
  512. req = bytearray()
  513. serial.encode_str(req, node_path)
  514. serial.encode_str(req, prop_name)
  515. serial.write_u32(req, i)
  516. serial.write_u8(req, PropertyType.NULL)
  517. self._make_request(Command.SET_PROPERTY_VALUE, req)
  518. def set_property_bool(self, node_path, prop_name, i, val):
  519. req = bytearray()
  520. serial.encode_str(req, node_path)
  521. serial.encode_str(req, prop_name)
  522. serial.write_u32(req, i)
  523. serial.write_u8(req, PropertyType.BOOL)
  524. serial.write_u8(req, int(val))
  525. self._make_request(Command.SET_PROPERTY_VALUE, req)
  526. def set_property_u32(self, node_path, prop_name, i, val):
  527. req = bytearray()
  528. serial.encode_str(req, node_path)
  529. serial.encode_str(req, prop_name)
  530. serial.write_u32(req, i)
  531. serial.write_u8(req, PropertyType.UINT32)
  532. serial.write_u32(req, val)
  533. self._make_request(Command.SET_PROPERTY_VALUE, req)
  534. def set_property_f32(self, node_path, prop_name, i, val):
  535. req = bytearray()
  536. serial.encode_str(req, node_path)
  537. serial.encode_str(req, prop_name)
  538. serial.write_u32(req, i)
  539. serial.write_u8(req, PropertyType.FLOAT32)
  540. serial.write_f32(req, val)
  541. self._make_request(Command.SET_PROPERTY_VALUE, req)
  542. def set_property_str(self, node_path, prop_name, i, val):
  543. req = bytearray()
  544. serial.encode_str(req, node_path)
  545. serial.encode_str(req, prop_name)
  546. serial.write_u32(req, i)
  547. serial.write_u8(req, PropertyType.STR)
  548. serial.encode_str(req, val)
  549. self._make_request(Command.SET_PROPERTY_VALUE, req)
  550. def set_property_enum(self, node_path, prop_name, i, val):
  551. req = bytearray()
  552. serial.encode_str(req, node_path)
  553. serial.encode_str(req, prop_name)
  554. serial.write_u32(req, i)
  555. serial.write_u8(req, PropertyType.ENUM)
  556. serial.encode_str(req, val)
  557. self._make_request(Command.SET_PROPERTY_VALUE, req)
  558. def set_property_buf(self, node_path, prop_name, i, buf):
  559. req = bytearray()
  560. serial.encode_str(req, node_path)
  561. serial.encode_str(req, prop_name)
  562. serial.write_u32(req, i)
  563. serial.write_u8(req, PropertyType.BUFFER)
  564. serial.encode_buf(req, buf)
  565. self._make_request(Command.SET_PROPERTY_VALUE, req)
  566. def set_property_expr(self, node_path, prop_name, i, code):
  567. req = bytearray()
  568. serial.encode_str(req, node_path)
  569. serial.encode_str(req, prop_name)
  570. serial.write_u32(req, i)
  571. serial.write_u8(req, PropertyType.SEXPR)
  572. serial.encode_varint(req, len(code))
  573. for sexpr in code:
  574. expr.encode_expr(req, sexpr)
  575. self._make_request(Command.SET_PROPERTY_VALUE, req)
  576. def get_signals(self, node_id):
  577. req = bytearray()
  578. serial.write_u32(req, node_id)
  579. cur = self._make_request(Command.GET_SIGNALS, req)
  580. sigs_len = serial.decode_varint(cur)
  581. sigs = []
  582. for _ in range(sigs_len):
  583. sigs.append(serial.decode_str(cur))
  584. return sigs
  585. def register_slot(self, node_id, sig_name, slot_name, user_data):
  586. req = bytearray()
  587. serial.write_u32(req, node_id)
  588. serial.encode_str(req, sig_name)
  589. serial.encode_str(req, slot_name)
  590. serial.encode_varint(req, len(user_data))
  591. req += user_data
  592. cur = self._make_request(Command.REGISTER_SLOT, req)
  593. slot_id = serial.read_u32(cur)
  594. return slot_id
  595. def unregister_slot(self, node_id, sig_name, slot_id):
  596. req = bytearray()
  597. serial.write_u32(req, node_id)
  598. serial.encode_str(req, sig_name)
  599. serial.write_u32(req, slot_id)
  600. self._make_request(Command.UNREGISTER_SLOT, req)
  601. def lookup_slot_id(self, node_id, sig_name, slot_name):
  602. req = bytearray()
  603. serial.write_u32(req, node_id)
  604. serial.encode_str(req, sig_name)
  605. serial.encode_str(req, slot_name)
  606. try:
  607. cur = self._make_request(Command.LOOKUP_SLOT_ID, req)
  608. except exc.RequestSlotNotFound:
  609. return None
  610. return serial.read_u32(cur)
  611. def get_slots(self, node_id, sig_name):
  612. req = bytearray()
  613. serial.write_u32(req, node_id)
  614. serial.encode_str(req, sig_name)
  615. cur = self._make_request(Command.GET_SLOTS, req)
  616. def read_slot(cur):
  617. slot_name = serial.decode_str(cur)
  618. slot_id = serial.read_u32(cur)
  619. return (slot_name, slot_id)
  620. slots = serial.decode_arr(cur, read_slot)
  621. return slots
  622. def get_methods(self, node_id):
  623. req = bytearray()
  624. serial.write_u32(req, node_id)
  625. cur = self._make_request(Command.GET_METHODS, req)
  626. def read_method(cur):
  627. method_name = serial.decode_str(cur)
  628. return method_name
  629. methods = serial.decode_arr(cur, read_method)
  630. return methods
  631. def get_method(self, node_id, method_name):
  632. req = bytearray()
  633. serial.write_u32(req, node_id)
  634. serial.encode_str(req, method_name)
  635. cur = self._make_request(Command.GET_METHOD, req)
  636. def read_arg(cur):
  637. arg_name = serial.decode_str(cur)
  638. arg_desc = serial.decode_str(cur)
  639. arg_type = serial.read_u8(cur)
  640. return (arg_name, arg_desc, arg_type)
  641. args = serial.decode_arr(cur, read_arg)
  642. results = serial.decode_arr(cur, read_arg)
  643. return (args, results)
  644. def call_method(self, node_path, method_name, arg_data):
  645. req = bytearray()
  646. serial.encode_str(req, node_path)
  647. serial.encode_str(req, method_name)
  648. serial.encode_buf(req, arg_data)
  649. cur = self._make_request(Command.CALL_METHOD, req)
  650. result = serial.decode_opt(cur, serial.decode_buf)
  651. return result