import logging from typing import Set from PyQt6.QtCore import QObject, QTimer, QThread, pyqtSignal from ipod_device import IPodDevice logger = logging.getLogger(__name__) class _DetectWorker(QThread): finished = pyqtSignal(object) def __init__(self, parent=None): super().__init__(parent) def run(self): try: devices = IPodDevice().detect_devices() self.finished.emit(devices) except Exception: logger.exception("Device detection failed") self.finished.emit([]) class DeviceMonitor(QObject): state_changed = pyqtSignal(list) def __init__(self, parent=None): super().__init__(parent) self.timer = QTimer(self) self.timer.timeout.connect(self._poll) self._device_ids: Set[str] = set() self._poll_worker = None def start(self, interval_ms: int = 3000): self._device_ids.clear() self._poll() self.timer.start(interval_ms) def stop(self): self.timer.stop() if self._poll_worker: self._poll_worker.quit() self._poll_worker.wait() self._poll_worker = None self._device_ids.clear() def _poll(self): if self._poll_worker: try: if self._poll_worker.isRunning(): return except RuntimeError: self._poll_worker = None worker = _DetectWorker() worker.finished.connect(self._on_devices_detected) worker.start() self._poll_worker = worker def _on_devices_detected(self, devices): if self._poll_worker: self._poll_worker.quit() self._poll_worker.wait() self._poll_worker = None current_ids = {d["id"] for d in devices} if current_ids != self._device_ids: self._device_ids = current_ids self.state_changed.emit(devices)