api.py 24 KB

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