Add microphone picker and device management features
- Implement `list_input_devices` to retrieve and filter input-capable audio devices. - Create `MicPickerDialog` for selecting and saving microphone settings. - Add `set_env_value` function to update .env file with selected microphone index. - Update UI components to integrate microphone selection functionality. - Enhance tests for microphone device handling and environment variable management.
This commit is contained in:
+33
-12
@@ -11,13 +11,14 @@ from __future__ import annotations
|
||||
import sys
|
||||
|
||||
from PySide6.QtCore import QThread
|
||||
from PySide6.QtWidgets import QApplication
|
||||
from PySide6.QtWidgets import QApplication, QMessageBox
|
||||
|
||||
from .. import config, updater
|
||||
from ..controller import PetController
|
||||
from ..hotkey import GlobalHotkey
|
||||
from ..state import PetState
|
||||
from .history_window import HistoryWindow
|
||||
from .mic_picker import MicPickerDialog
|
||||
from .pet_window import PetWindow
|
||||
from .tray import PetTray
|
||||
from .wake_tuner import WakeTunerWindow
|
||||
@@ -57,6 +58,19 @@ def run() -> int:
|
||||
window.publish_monitors()
|
||||
window.copied.connect(lambda text: _log(f"Copied to clipboard: {text[:60]}"))
|
||||
|
||||
# The updater has already moved the checkout by the time this fires; all
|
||||
# that's left is to let Qt tear down cleanly (so the mic and the tray
|
||||
# icon are released) and then exec the new code. Doing the exec after
|
||||
# app.exec() returns, rather than from the controller thread, is what
|
||||
# guarantees the audio device is free before the new process opens it.
|
||||
# Defined early so the mic picker (below) can trigger the same restart
|
||||
# a self-update or self-restart does.
|
||||
pending_restart = {"tag": None}
|
||||
|
||||
def _handle_restart(tag: str) -> None:
|
||||
pending_restart["tag"] = tag
|
||||
app.quit()
|
||||
|
||||
history_window = HistoryWindow(controller.history)
|
||||
tuner_window = WakeTunerWindow(
|
||||
get_threshold=controller.wake_threshold,
|
||||
@@ -65,6 +79,23 @@ def run() -> int:
|
||||
on_reset=controller.reset_wake_stats,
|
||||
)
|
||||
|
||||
def _save_mic_device(value) -> None:
|
||||
config.set_env_value("MIC_DEVICE", str(value) if value is not None else "")
|
||||
_log(f"Microphone set to device #{value}." if value is not None else
|
||||
"Microphone set to system default.")
|
||||
answer = QMessageBox.question(
|
||||
None, "Restart Bolt?",
|
||||
"Restart now so Bolt starts listening on the new microphone?",
|
||||
QMessageBox.Yes | QMessageBox.No,
|
||||
)
|
||||
if answer == QMessageBox.Yes:
|
||||
_handle_restart("microphone change")
|
||||
|
||||
mic_picker = MicPickerDialog(
|
||||
get_current=lambda: config.MIC_DEVICE,
|
||||
on_save=_save_mic_device,
|
||||
)
|
||||
|
||||
def _set_nap(napping: bool) -> None:
|
||||
# Clicking the tray item pins the state; the schedule takes over again
|
||||
# only after a restart or a `petctl nap off`.
|
||||
@@ -82,6 +113,7 @@ def run() -> int:
|
||||
on_set_nap=_set_nap,
|
||||
on_show_history=history_window.show_refreshed,
|
||||
on_show_wake_tuner=tuner_window.show_refreshed,
|
||||
on_show_mic_picker=mic_picker.show_refreshed,
|
||||
on_reset_voice=controller.reset_voice,
|
||||
)
|
||||
|
||||
@@ -104,17 +136,6 @@ def run() -> int:
|
||||
elif hotkey.running:
|
||||
_log(f"Push-to-talk: {config.PUSH_TO_TALK_HOTKEY}")
|
||||
|
||||
# The updater has already moved the checkout by the time this fires; all
|
||||
# that's left is to let Qt tear down cleanly (so the mic and the tray
|
||||
# icon are released) and then exec the new code. Doing the exec after
|
||||
# app.exec() returns, rather than from the controller thread, is what
|
||||
# guarantees the audio device is free before the new process opens it.
|
||||
pending_restart = {"tag": None}
|
||||
|
||||
def _handle_restart(tag: str) -> None:
|
||||
pending_restart["tag"] = tag
|
||||
app.quit()
|
||||
|
||||
controller.restart_requested.connect(_handle_restart)
|
||||
|
||||
def _shutdown() -> None:
|
||||
|
||||
Reference in New Issue
Block a user