Skip to content

Commit c1ed384

Browse files
committed
Working input recorder
1 parent 6841f63 commit c1ed384

File tree

4 files changed

+64
-21
lines changed

4 files changed

+64
-21
lines changed

config/input_recorder.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
input_recorder:
2-
enabled: false
2+
enabled: true
33
path: modules.input_recorder.InputRecorder
44
config:
55
animations_dir: animations/recorded

modules/controller.py

Lines changed: 32 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -58,30 +58,31 @@ def listen(self):
5858
except FileNotFoundError:
5959
self.log(f"No gamepad found at {self.device}. Waiting for connection...", level='warning')
6060
time.sleep(1)
61-
except Exception as e:
62-
self.log(f"Error: {e}", level='error')
63-
time.sleep(1)
6461

6562
def _handle_js_event(self, time_ms, value, type_, number):
6663
"""Route joystick events to appropriate handlers."""
6764
is_init = (type_ & self.JS_EVENT_INIT) != 0
6865
event_type = type_ & ~self.JS_EVENT_INIT
6966

70-
topic = None
71-
args = {}
72-
67+
topics_args = []
7368
if event_type == self.JS_EVENT_BUTTON:
74-
topic, args = self._handle_button_event(value, number)
69+
topics_args = self._handle_button_event(value, number, collect_topics_args=True)
7570
elif event_type == self.JS_EVENT_AXIS:
76-
topic, args = self._handle_axis_event(value, number)
77-
78-
self.publish('controller/event', event=(time_ms, value, type_, number, topic, args))
79-
80-
def _handle_button_event(self, value, number):
71+
topics_args = self._handle_axis_event(value, number, collect_topics_args=True)
72+
self.publish('controller/event', event={
73+
'time_ms': time_ms,
74+
'value': value,
75+
'type': type_,
76+
'number': number,
77+
'topics_args': topics_args
78+
})
79+
80+
def _handle_button_event(self, value, number, collect_topics_args=False):
8181
"""Handle button press/release events."""
8282
button = self.button_names.get(number, f'BTN_{number}')
8383
topic = None
8484
args = {}
85+
topics_args = []
8586

8687
if value == 1:
8788
self.pressed_buttons.add(button)
@@ -98,17 +99,29 @@ def _handle_button_event(self, value, number):
9899
args = mapping.get('args', {})
99100
self.publish(topic, **args)
100101
self.log(f"Published to topic {topic} with args {args} (jsdev)")
102+
topics_args.append({'topic': topic, 'args': args})
101103

104+
# If collect_topics_args is set, return the list, else preserve old behavior
105+
import inspect
106+
frame = inspect.currentframe().f_back
107+
if frame and 'collect_topics_args' in frame.f_locals and frame.f_locals['collect_topics_args']:
108+
return topics_args
102109
return topic, args
103110

104-
def _handle_axis_event(self, value, number):
111+
def _handle_axis_event(self, value, number, collect_topics_args=False):
105112
"""Handle axis movement events."""
106113
axis = self.axis_names.get(number, f'AXIS_{number}')
107114
topic = None
108115
args = {}
116+
topics_args = []
109117

110118
button_map = self._get_active_mapping()
111119
if axis not in button_map:
120+
# If collecting, return empty list
121+
import inspect
122+
frame = inspect.currentframe().f_back
123+
if frame and 'collect_topics_args' in frame.f_locals and frame.f_locals['collect_topics_args']:
124+
return topics_args
112125
return topic, args
113126

114127
for mapping in button_map[axis]:
@@ -141,7 +154,13 @@ def _handle_axis_event(self, value, number):
141154

142155
self.publish(topic, **args)
143156
self.log(f"Published to topic {topic} with args {args} (jsdev)")
157+
topics_args.append({'topic': topic, 'args': args})
144158

159+
# If collect_topics_args is set, return the list, else preserve old behavior
160+
import inspect
161+
frame = inspect.currentframe().f_back
162+
if frame and 'collect_topics_args' in frame.f_locals and frame.f_locals['collect_topics_args']:
163+
return topics_args
145164
return topic, args
146165

147166
# Keep public method for backwards compatibility with tests

modules/input_recorder.py

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,16 @@ def __init__(self, **kwargs):
1313
self.filename = None
1414

1515
def setup_messaging(self):
16-
self.subscribe('record/start', self.toggle_recording(enable=True))
17-
self.subscribe('record/stop', lambda: self.toggle_recording(enable=False))
16+
self.subscribe('record/start', self.start_recording )
17+
self.subscribe('record/stop', self.stop_recording )
1818
self.subscribe('controller/event', self.handle_event)
1919

20+
def start_recording(self):
21+
self.toggle_recording(enable=True)
22+
23+
def stop_recording(self):
24+
self.toggle_recording(enable=False)
25+
2026
def toggle_recording(self, enable=True, filename=None):
2127
if enable and not self.recording:
2228
self.recording = True
@@ -28,7 +34,7 @@ def toggle_recording(self, enable=True, filename=None):
2834
self.save_events()
2935
self.log(f"Recording stopped and saved: {self.filename}")
3036

31-
def handle_event(self, **event):
37+
def handle_event(self, event):
3238
if self.recording:
3339
event['timestamp'] = time.time()
3440
self.events.append(event)

tests/test_input_recorder.py

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,17 +13,35 @@ def test_recording_toggle_and_event(self):
1313
self.recorder.toggle_recording(enable=True, filename='test.json')
1414
self.assertTrue(self.recorder.recording)
1515
self.assertEqual(self.recorder.filename, 'test.json')
16-
event = {'ev_type': 'Key', 'code': 'BTN_A', 'state': 1}
17-
self.recorder.handle_event(**event)
16+
# Simulate a controller event as per new format
17+
event = {
18+
'time_ms': 123456,
19+
'value': 1,
20+
'type': 1,
21+
'number': 7,
22+
'topics_args': [
23+
{'topic': 'tts', 'args': {'msg': 'Test Default'}}
24+
]
25+
}
26+
self.recorder.handle_event(event)
1827
self.assertEqual(len(self.recorder.events), 1)
28+
self.assertIn('timestamp', self.recorder.events[0])
1929
self.recorder.toggle_recording(enable=False)
2030
self.assertFalse(self.recorder.recording)
2131
self.recorder.save_events.assert_called()
2232

2333
def test_event_timestamp(self):
2434
self.recorder.toggle_recording(enable=True, filename='test2.json')
25-
event = {'ev_type': 'Key', 'code': 'BTN_B', 'state': 1}
26-
self.recorder.handle_event(**event)
35+
event = {
36+
'time_ms': 654321,
37+
'value': 0,
38+
'type': 1,
39+
'number': 7,
40+
'topics_args': [
41+
{'topic': 'tts', 'args': {'msg': 'Test Default'}}
42+
]
43+
}
44+
self.recorder.handle_event(event)
2745
self.assertIn('timestamp', self.recorder.events[0])
2846
self.recorder.toggle_recording(enable=False)
2947

0 commit comments

Comments
 (0)