api.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143
  1. from collections import namedtuple
  2. from pydrk import Api, HostApi, PropertyType
  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 remove_all_slots(node_path, sig):
  14. node_id = api.lookup_node_id(node_path)
  15. for slot_id, slot in api.get_slots(node_id, sig):
  16. print(f"{node_path}:{sig}(): Unregistering slot '{slot}':{slot_id}")
  17. api.unregister_slot(node_id, sig, slot_id)
  18. def register_slot(node_path, sig, tag):
  19. remove_all_slots(node_path, sig)
  20. node_id = api.lookup_node_id(node_path)
  21. api.register_slot(node_id, sig, "", tag)
  22. def get_property(node_path, prop):
  23. node_id = api.lookup_node_id(node_path)
  24. return api.get_property(node_id, prop)
  25. def set_property(node_id, prop, val):
  26. node_id = _lookup_node(node_id)
  27. match val:
  28. case float():
  29. api.set_property_f32(node_id, prop, val)
  30. case int():
  31. api.set_property_u32(node_id, prop, val)
  32. def set_property_f32(node_id, prop, val):
  33. node_id = _lookup_node(node_id)
  34. api.set_property_f32(node_id, prop, float(val))
  35. def set_property_u32(node_id, prop, val):
  36. node_id = _lookup_node(node_id)
  37. api.set_property_u32(node_id, prop, int(val))
  38. def add_property_bool(node_id, prop, val=None):
  39. api.add_property(node_id, prop, PropertyType.BOOL)
  40. if val is not None:
  41. api.set_property_bool(node_id, prop, val)
  42. def add_property_f32(node_id, prop, val=None):
  43. api.add_property(node_id, prop, PropertyType.FLOAT32)
  44. if val is not None:
  45. api.set_property_f32(node_id, prop, val)
  46. def add_property_u32(node_id, prop, val=None):
  47. api.add_property(node_id, prop, PropertyType.UINT32)
  48. if val is not None:
  49. api.set_property_u32(node_id, prop, val)
  50. def _lookup_node(node_id):
  51. if isinstance(node_id, str):
  52. node_id = api.lookup_node_id(node_id)
  53. return node_id
  54. def link_node(child_id, parent_id):
  55. child_id = _lookup_node(child_id)
  56. parent_id = _lookup_node(parent_id)
  57. api.link_node(child_id, parent_id)
  58. def unlink_node(child_id, parent_id):
  59. child_id = _lookup_node(child_id)
  60. parent_id = _lookup_node(parent_id)
  61. api.unlink_node(child_id, parent_id)
  62. def remove_node_recursive(node_id):
  63. for (_, child_id, _) in api.get_children(node_id):
  64. # Unlink the child
  65. api.unlink_node(child_id, node_id)
  66. # Remove the node
  67. remove_node_recursive(child_id)
  68. # Garbage collection
  69. if not api.get_parents(node_id):
  70. api.remove_node(node_id)
  71. def garbage_collect():
  72. dangling = api.scan_dangling()
  73. for node_id in dangling:
  74. remove_node_recursive(node_id)
  75. print(f"Garbage collect: removed {len(dangling)} nodes")
  76. KeyMods = namedtuple("KeyMods", ["shift", "ctrl", "alt", "logo"])
  77. class EventLoop:
  78. def __init__(self):
  79. self.subsock = make_sub_socket()
  80. register_slot("/window", "resize", b"rs")
  81. register_slot("/window/input/mouse", "button_down", b"ck")
  82. register_slot("/window/input/mouse", "wheel", b"wh")
  83. register_slot("/window/input/mouse", "move", b"mm")
  84. register_slot("/window/input/keyboard", "key_down", b"kd")
  85. def run(self):
  86. while True:
  87. data = self.subsock.recv()
  88. match data:
  89. case b"rs":
  90. w = get_property("/window", "width")
  91. h = get_property("/window", "height")
  92. self.resize_event(w, h)
  93. case b"ck":
  94. x = get_property("/window/input/mouse", "click_x")
  95. y = get_property("/window/input/mouse", "click_y")
  96. self.mouse_click(x, y)
  97. case b"wh":
  98. y = get_property("/window/input/mouse", "wheel_y")
  99. self.mouse_wheel(y)
  100. case b"mm":
  101. pass
  102. case b"kd":
  103. shift = get_property("/window/input/keyboard", "shift")
  104. ctrl = get_property("/window/input/keyboard", "ctrl")
  105. alt = get_property("/window/input/keyboard", "alt")
  106. logo = get_property("/window/input/keyboard", "logo")
  107. keycode = get_property("/window/input/keyboard", "keycode")
  108. repeat = get_property("/window/input/keyboard", "repeat")
  109. keymods = KeyMods(shift, ctrl, alt, logo)
  110. # Sometimes these get stuck when exiting the window.
  111. # We don't need these anyway
  112. if keycode in ("LeftShift", "LeftSuper"):
  113. continue
  114. self.key_down(keycode, keymods, repeat)
  115. def resize_event(self, w, h):
  116. pass
  117. def mouse_click(self, x, y):
  118. pass
  119. def mouse_wheel(self, y):
  120. pass
  121. def key_down(self, keycode, keymods, repeat):
  122. pass