Repository: ErikBjare/gptme
File: gptme/tools/tts.py (Python)

Code before:
            if device_info["max_output_channels"] > 0 and device_name in [
                "pulse",
                "pipewire",
            ]:
                log.debug(f"Using virtual audio device: {device_info['name']}")
                return default_output, int(device_info["default_samplerate"])
            else:
                log.debug(f"Skipping non-virtual default device: {device_info['name']}")
    except Exception as e:
        log.debug(f"Could not use default device: {e}")

    # Second try: platform-specific defaults
    # - On macOS: prefer CoreAudio (hostapi == 2)
    # - On Linux: prefer PulseAudio/PipeWire virtual devices
    output_device = next(
        (
            i
            for i, d in enumerate(devices)
            if d["max_output_channels"] > 0
            and (
                # macOS: CoreAudio devices
                (d["hostapi"] == 2)
                or
                # Linux: PulseAudio/PipeWire virtual devices
                d["name"].lower() in ["pulse", "pipewire"]
            )
        ),
        None,
    )

    # Third try: any device with output channels
    if output_device is None:
        output_device = next(
            (i for i, d in enumerate(devices) if d["max_output_channels"] > 0),
            None,
        )

    if output_device is None:
        raise RuntimeError(
            "No suitable audio output device found. "
            "Available devices:\n"
            + "\n".join(f"  {i}: {d['name']}" for i, d in enumerate(devices))
        )

    device_info = sd.query_devices(output_device)
    device_sr = int(device_info["default_samplerate"])

    log.debug(f"Selected output device: {output_device} ({device_info['name']})")
    log.debug(f"Sample rate: {device_sr}")

    return output_device, device_sr

Review comment (suggestion):
```suggestion
            if d["max_output_channels"] > 0 and d["hostapi"] == 2
```

Code after:
            if device_info["max_output_channels"] > 0 and device_name in [
                "pulse",
                "pipewire",
            ]:
                log.debug(f"Using virtual audio device: {device_info['name']}")
                return default_output, int(device_info["default_samplerate"])
            else:
                log.debug(f"Skipping non-virtual default device: {device_info['name']}")
    except Exception as e:
        log.debug(f"Could not use default device: {e}")

    # on macOS, prefer CoreAudio (hostapi == 2)
    output_device = next(
        (
            i
            for i, d in enumerate(devices)
            if d["max_output_channels"] > 0 and (d["hostapi"] == 2)
        ),
        None,
    )

    # Third try: any device with output channels
    if output_device is None:
        output_device = next(
            (i for i, d in enumerate(devices) if d["max_output_channels"] > 0),
            None,
        )

    if output_device is None:
        raise RuntimeError(
            "No suitable audio output device found. "
            "Available devices:\n"
            + "\n".join(f"  {i}: {d['name']}" for i, d in enumerate(devices))
        )

    device_info = sd.query_devices(output_device)
    device_sr = int(device_info["default_samplerate"])

    log.debug(f"Selected output device: {output_device} ({device_info['name']})")
    log.debug(f"Sample rate: {device_sr}")

    return output_device, device_sr


def _audio_player_thread_fn() -> None:
    """Background thread for playing audio."""
    log.debug("Audio player thread started")
    while True:
        try:
            # Get audio data from queue
            log.debug("Waiting for audio data...")