mainloopのスレッド管理を改善し、マルチワーカー化を実装。デバイス管理の初期化を遅延させ、エラーハンドリングを強化。ドキュメントを更新し、設定の変更点を明示化。

This commit is contained in:
misyaguziya
2025-10-13 08:28:27 +09:00
parent 0130792682
commit 914789c9cb
10 changed files with 328 additions and 86 deletions

View File

@@ -60,7 +60,20 @@ class DeviceManager:
if cls._instance is None:
cls._instance = super(DeviceManager, cls).__new__(cls)
# do NOT auto-init monitoring-heavy resources on import; require explicit init
# Still perform a light-weight init so that callers observing the singleton
# do not see uninitialized internal structures (which caused NoDevice to
# be seen when import order differed).
cls._instance._initialized = False
try:
# Call init() to populate internal containers. This will NOT start
# the monitoring thread (startMonitoring must be called explicitly).
cls._instance.init()
except Exception:
# Avoid import-time crashes; log and continue.
try:
errorLogging()
except Exception:
pass
return cls._instance
def init(self) -> None:
@@ -108,6 +121,22 @@ class DeviceManager:
self._initialized = True
# Best-effort single update: if PyAudio is available, attempt to populate
# real device lists. Keep this short and ignore errors to avoid import-time
# failures.
try:
if PyAudio is not None:
try:
# update() is robust and will fall back to defaults if audio libs
# are missing or fail; do not let exceptions bubble up.
self.update()
except Exception:
errorLogging()
except Exception:
# defensive: if errorLogging isn't available or other issues occur,
# swallow to avoid breaking initialization
pass
def update(self):
buffer_mic_devices: Dict[str, List[Dict[str, Any]]] = {}
buffer_default_mic_device: Dict[str, Any] = {"host": {"index": -1, "name": "NoHost"}, "device": {"index": -1, "name": "NoDevice"}}
@@ -428,16 +457,52 @@ class DeviceManager:
errorLogging()
def getMicDevices(self):
return self.mic_devices
# Ensure initialized and return devices (safe default if still not populated)
if not getattr(self, '_initialized', False):
try:
self.init()
except Exception:
try:
errorLogging()
except Exception:
pass
return getattr(self, 'mic_devices', {"NoHost": [{"index": -1, "name": "NoDevice"}]})
def getDefaultMicDevice(self):
return self.default_mic_device
# Ensure initialized and return default mic device (safe default if still not populated)
if not getattr(self, '_initialized', False):
try:
self.init()
except Exception:
try:
errorLogging()
except Exception:
pass
return getattr(self, 'default_mic_device', {"host": {"index": -1, "name": "NoHost"}, "device": {"index": -1, "name": "NoDevice"}})
def getSpeakerDevices(self):
return self.speaker_devices
# Ensure initialized and return speaker devices (safe default if still not populated)
if not getattr(self, '_initialized', False):
try:
self.init()
except Exception:
try:
errorLogging()
except Exception:
pass
return getattr(self, 'speaker_devices', [{"index": -1, "name": "NoDevice"}])
def getDefaultSpeakerDevice(self):
return self.default_speaker_device
# Ensure initialized and return default speaker device (safe default if still not populated)
if not getattr(self, '_initialized', False):
try:
self.init()
except Exception:
try:
errorLogging()
except Exception:
pass
return getattr(self, 'default_speaker_device', {"device": {"index": -1, "name": "NoDevice"}})
def forceUpdateAndSetMicDevices(self):
self.update()