From 5c0c2a17b0539aecfd7401ae96ca946a1142418e Mon Sep 17 00:00:00 2001 From: Shane Smiskol Date: Tue, 30 Sep 2025 22:30:45 -0700 Subject: [PATCH] raylib: add mic indicator (#36207) * update lang * mic indicator * clean up * clean up * switch * fix * revert --- selfdrive/ui/layouts/main.py | 3 ++- selfdrive/ui/layouts/settings/toggles.py | 2 +- selfdrive/ui/layouts/sidebar.py | 23 ++++++++++++++++++++++- selfdrive/ui/ui_state.py | 1 + 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/selfdrive/ui/layouts/main.py b/selfdrive/ui/layouts/main.py index 1f5612224..a2401ef8b 100644 --- a/selfdrive/ui/layouts/main.py +++ b/selfdrive/ui/layouts/main.py @@ -47,7 +47,8 @@ class MainLayout(Widget): def _setup_callbacks(self): self._sidebar.set_callbacks(on_settings=self._on_settings_clicked, - on_flag=self._on_bookmark_clicked) + on_flag=self._on_bookmark_clicked, + open_settings=lambda: self.open_settings(PanelType.TOGGLES)) self._layouts[MainState.HOME]._setup_widget.set_open_settings_callback(lambda: self.open_settings(PanelType.FIREHOSE)) self._layouts[MainState.SETTINGS].set_callbacks(on_close=self._set_mode_for_state) self._layouts[MainState.ONROAD].set_click_callback(self._on_onroad_clicked) diff --git a/selfdrive/ui/layouts/settings/toggles.py b/selfdrive/ui/layouts/settings/toggles.py index 58afcec5e..1e0e7bfd5 100644 --- a/selfdrive/ui/layouts/settings/toggles.py +++ b/selfdrive/ui/layouts/settings/toggles.py @@ -76,7 +76,7 @@ class TogglesLayout(Widget): icon="monitoring.png", ), toggle_item( - "Record Microphone Audio", + "Record and Upload Microphone Audio", DESCRIPTIONS["RecordAudio"], self._params.get_bool("RecordAudio"), icon="microphone.png", diff --git a/selfdrive/ui/layouts/sidebar.py b/selfdrive/ui/layouts/sidebar.py index 4d47a9878..5987d062f 100644 --- a/selfdrive/ui/layouts/sidebar.py +++ b/selfdrive/ui/layouts/sidebar.py @@ -71,20 +71,26 @@ class Sidebar(Widget): self._temp_status = MetricData("TEMP", "GOOD", Colors.GOOD) self._panda_status = MetricData("VEHICLE", "ONLINE", Colors.GOOD) self._connect_status = MetricData("CONNECT", "OFFLINE", Colors.WARNING) + self._recording_audio = False self._home_img = gui_app.texture("images/button_home.png", HOME_BTN.width, HOME_BTN.height) self._flag_img = gui_app.texture("images/button_flag.png", HOME_BTN.width, HOME_BTN.height) self._settings_img = gui_app.texture("images/button_settings.png", SETTINGS_BTN.width, SETTINGS_BTN.height) + self._mic_img = gui_app.texture("icons/microphone.png", 30, 30) + self._mic_indicator_rect = rl.Rectangle(0, 0, 0, 0) self._font_regular = gui_app.font(FontWeight.NORMAL) self._font_bold = gui_app.font(FontWeight.SEMI_BOLD) # Callbacks self._on_settings_click: Callable | None = None self._on_flag_click: Callable | None = None + self._open_settings_callback: Callable | None = None - def set_callbacks(self, on_settings: Callable | None = None, on_flag: Callable | None = None): + def set_callbacks(self, on_settings: Callable | None = None, on_flag: Callable | None = None, + open_settings: Callable | None = None): self._on_settings_click = on_settings self._on_flag_click = on_flag + self._open_settings_callback = open_settings def _render(self, rect: rl.Rectangle): # Background @@ -101,6 +107,7 @@ class Sidebar(Widget): device_state = sm['deviceState'] + self._recording_audio = sm.alive['rawAudioData'] self._update_network_status(device_state) self._update_temperature_status(device_state) self._update_connection_status(device_state) @@ -143,6 +150,9 @@ class Sidebar(Widget): elif rl.check_collision_point_rec(mouse_pos, HOME_BTN) and ui_state.started: if self._on_flag_click: self._on_flag_click() + elif self._recording_audio and rl.check_collision_point_rec(mouse_pos, self._mic_indicator_rect): + if self._open_settings_callback: + self._open_settings_callback() def _draw_buttons(self, rect: rl.Rectangle): mouse_pos = rl.get_mouse_position() @@ -160,6 +170,17 @@ class Sidebar(Widget): tint = Colors.BUTTON_PRESSED if (ui_state.started and flag_pressed) else Colors.BUTTON_NORMAL rl.draw_texture(button_img, int(HOME_BTN.x), int(HOME_BTN.y), tint) + # Microphone button + if self._recording_audio: + self._mic_indicator_rect = rl.Rectangle(rect.x + rect.width - 138, rect.y + 245, 75, 40) + + mic_pressed = mouse_down and rl.check_collision_point_rec(mouse_pos, self._mic_indicator_rect) + bg_color = rl.Color(Colors.DANGER.r, Colors.DANGER.g, Colors.DANGER.b, int(255 * 0.65)) if mic_pressed else Colors.DANGER + + rl.draw_rectangle_rounded(self._mic_indicator_rect, 1, 10, bg_color) + rl.draw_texture(self._mic_img, int(self._mic_indicator_rect.x + (self._mic_indicator_rect.width - self._mic_img.width) / 2), + int(self._mic_indicator_rect.y + (self._mic_indicator_rect.height - self._mic_img.height) / 2), Colors.WHITE) + def _draw_network_indicator(self, rect: rl.Rectangle): # Signal strength dots x_start = rect.x + 58 diff --git a/selfdrive/ui/ui_state.py b/selfdrive/ui/ui_state.py index bb3abcddb..9c45519b4 100644 --- a/selfdrive/ui/ui_state.py +++ b/selfdrive/ui/ui_state.py @@ -50,6 +50,7 @@ class UIState: "managerState", "selfdriveState", "longitudinalPlan", + "rawAudioData", ] )