api.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. from collections import namedtuple
  2. from pydrk import Api, HostApi, PropertyType, PropertySubType, Property, serial
  3. import zmq
  4. api = Api()
  5. host = HostApi(api)
  6. print("Node status:", api.hello())
  7. def make_sub_socket():
  8. context = zmq.Context()
  9. socket = context.socket(zmq.SUB)
  10. socket.setsockopt(zmq.SUBSCRIBE, b'')
  11. socket.connect("tcp://localhost:9485")
  12. return socket
  13. def rename_node(node, name):
  14. node_id = lookup_node(node)
  15. api.rename_node(node_id, name)
  16. def remove_all_slots(node_path, sig):
  17. node_id = api.lookup_node_id(node_path)
  18. for slot_id, slot in api.get_slots(node_id, sig):
  19. print(f"{node_path}:{sig}(): Unregistering slot '{slot}':{slot_id}")
  20. api.unregister_slot(node_id, sig, slot_id)
  21. def register_slot(node_path, sig, tag):
  22. #remove_all_slots(node_path, sig)
  23. node_id = api.lookup_node_id(node_path)
  24. api.register_slot(node_id, sig, "", tag)
  25. def get_property(node_id, prop):
  26. node_id = lookup_node(node_id)
  27. return api.get_property_value(node_id, prop)
  28. def set_property(node_id, prop, val):
  29. node_id = lookup_node(node_id)
  30. match val:
  31. case float():
  32. api.set_property_f32(node_id, prop, val)
  33. case int():
  34. api.set_property_u32(node_id, prop, val)
  35. def set_property_bool(node_id, prop, val):
  36. node_id = lookup_node(node_id)
  37. api.set_property_bool(node_id, prop, val)
  38. def set_property_f32(node_id, prop, val):
  39. node_id = lookup_node(node_id)
  40. api.set_property_f32(node_id, prop, float(val))
  41. def set_property_u32(node_id, prop, val):
  42. node_id = lookup_node(node_id)
  43. api.set_property_u32(node_id, prop, int(val))
  44. def add_property_bool(node_id, prop, val=None):
  45. api.add_property(node_id, prop, PropertyType.BOOL)
  46. if val is not None:
  47. api.set_property_bool(node_id, prop, val)
  48. def add_property_f32(node_id, prop, val=None):
  49. api.add_property(node_id, prop, PropertyType.FLOAT32)
  50. if val is not None:
  51. api.set_property_f32(node_id, prop, val)
  52. def add_property_u32(node_id, prop, val=None):
  53. api.add_property(node_id, prop, PropertyType.UINT32)
  54. if val is not None:
  55. api.set_property_u32(node_id, prop, val)
  56. def lookup_node(node_id):
  57. if isinstance(node_id, str):
  58. node_id = api.lookup_node_id(node_id)
  59. return node_id
  60. def link_node(child_id, parent_id):
  61. child_id = lookup_node(child_id)
  62. parent_id = lookup_node(parent_id)
  63. api.link_node(child_id, parent_id)
  64. def unlink_node(child_id, parent_id):
  65. child_id = lookup_node(child_id)
  66. parent_id = lookup_node(parent_id)
  67. api.unlink_node(child_id, parent_id)
  68. def unlink_from_parents(node_id):
  69. node_id = lookup_node(node_id)
  70. for (_, parent_id, _) in api.get_parents(node_id):
  71. api.unlink_node(node_id, parent_id)
  72. def remove_node_recursive(node_id):
  73. node_id = lookup_node(node_id)
  74. for (_, child_id, _) in api.get_children(node_id):
  75. # Unlink the child
  76. api.unlink_node(child_id, node_id)
  77. # Remove the node
  78. remove_node_recursive(child_id)
  79. # Garbage collection
  80. if not api.get_parents(node_id):
  81. api.remove_node(node_id)
  82. def garbage_collect():
  83. dangling = api.scan_dangling()
  84. for node_id in dangling:
  85. remove_node_recursive(node_id)
  86. print(f"Garbage collect: removed {len(dangling)} nodes")
  87. KeyMods = namedtuple("KeyMods", ["shift", "ctrl", "alt", "logo"])
  88. class EventLoop:
  89. def __init__(self):
  90. self.subsock = make_sub_socket()
  91. #register_slot("/window", "resize", b"rs")
  92. #register_slot("/window/input/mouse", "button_down", b"ck")
  93. #register_slot("/window/input/mouse", "wheel", b"wh")
  94. #register_slot("/window/input/mouse", "move", b"mm")
  95. register_slot("/window/input/keyboard", "key_down", b"kd")
  96. def run(self):
  97. while True:
  98. signal_data, user_data = self.subsock.recv_multipart()
  99. cur = serial.Cursor(signal_data)
  100. match user_data:
  101. #case b"rs":
  102. # w = get_property("/window", "width")
  103. # h = get_property("/window", "height")
  104. # self.resize_event(w, h)
  105. #case b"ck":
  106. # x = get_property("/window/input/mouse", "click_x")
  107. # y = get_property("/window/input/mouse", "click_y")
  108. # self.mouse_click(x, y)
  109. #case b"wh":
  110. # y = get_property("/window/input/mouse", "wheel_y")
  111. # self.mouse_wheel(y)
  112. #case b"mm":
  113. # pass
  114. case b"kd":
  115. shift = bool(serial.read_u8(cur))
  116. ctrl = bool(serial.read_u8(cur))
  117. alt = bool(serial.read_u8(cur))
  118. logo = bool(serial.read_u8(cur))
  119. repeat = bool(serial.read_u8(cur))
  120. keycode = serial.decode_str(cur)
  121. keymods = KeyMods(shift, ctrl, alt, logo)
  122. # Sometimes these get stuck when exiting the window.
  123. # We don't need these anyway
  124. if keycode in ("LeftShift", "LeftSuper"):
  125. continue
  126. self.key_down(keycode, keymods, repeat)
  127. def resize_event(self, w, h):
  128. pass
  129. def mouse_click(self, x, y):
  130. pass
  131. def mouse_wheel(self, y):
  132. pass
  133. def key_down(self, keycode, keymods, repeat):
  134. pass