|
19 | 19 | logger = logging.getLogger(__name__) |
20 | 20 |
|
21 | 21 |
|
22 | | -# Windows volume control |
23 | | -try: |
24 | | - from pycaw.pycaw import AudioUtilities |
25 | | - PYCAW_AVAILABLE = True |
26 | | -except ImportError: |
27 | | - PYCAW_AVAILABLE = False |
28 | | - logger.warning("pycaw not available, duck/unduck will be disabled") |
| 22 | +# pycaw availability flag (lazy import to avoid COM conflicts) |
| 23 | +PYCAW_AVAILABLE = None # Will be set on first use |
| 24 | + |
| 25 | + |
| 26 | +def _check_pycaw(): |
| 27 | + """Check pycaw availability (lazy import)""" |
| 28 | + global PYCAW_AVAILABLE |
| 29 | + if PYCAW_AVAILABLE is None: |
| 30 | + try: |
| 31 | + from pycaw.pycaw import AudioUtilities # noqa: F401 |
| 32 | + PYCAW_AVAILABLE = True |
| 33 | + except (ImportError, OSError): |
| 34 | + PYCAW_AVAILABLE = False |
| 35 | + logger.warning("pycaw not available, duck/unduck will be disabled") |
| 36 | + return PYCAW_AVAILABLE |
29 | 37 |
|
30 | 38 |
|
31 | 39 | class WakeWordType(str, Enum): |
@@ -101,11 +109,12 @@ def __init__(self): |
101 | 109 |
|
102 | 110 | def _init_volume_interface(self) -> None: |
103 | 111 | """Initialize volume interface""" |
104 | | - if not PYCAW_AVAILABLE: |
| 112 | + if not _check_pycaw(): |
105 | 113 | logger.warning("pycaw not available, volume control disabled") |
106 | 114 | return |
107 | 115 |
|
108 | 116 | try: |
| 117 | + from pycaw.pycaw import AudioUtilities |
109 | 118 | devices = AudioUtilities.GetSpeakers() |
110 | 119 | # New pycaw uses EndpointVolume property |
111 | 120 | self._volume_interface = devices.EndpointVolume |
|
0 commit comments