# Platform-Specific Audio Device Discovery in Meetily: Windows, macOS, and Linux

> Discover platform-specific audio device implementations in Meetily for Windows WASAPI, macOS ScreenCaptureKit, and Linux ALSA/PulseAudio. Detect microphones and speakers efficiently.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: internals
- Published: 2026-07-25

---

**Meetily abstracts audio hardware enumeration behind a modular `audio::devices` layer that leverages WASAPI on Windows, ScreenCaptureKit on macOS, and ALSA/PulseAudio on Linux to detect microphones and speakers.**

The open-source Meetily project handles cross-platform audio capture through dedicated platform modules written in Rust. Each implementation resides in `frontend/src-tauri/src/audio/devices/platform/` and uses the host operating system's native audio APIs to enumerate capture and playback devices, exposed via a unified interface that insulates the UI from OS-level complexity.

## Platform-Specific Implementation Overview

Meetily organizes its audio device discovery logic into three platform-specific modules, each targeting the native API stack of its respective operating system:

| Platform | Implementation File | Native API |
|----------|---------------------|------------|
| **Windows** | [`frontend/src-tauri/src/audio/devices/platform/windows.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/windows.rs) | **WASAPI** (Windows Audio Session API) |
| **macOS** | [`frontend/src-tauri/src/audio/devices/platform/macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/macos.rs) | **ScreenCaptureKit** and **CoreAudio** |
| **Linux** | [`frontend/src-tauri/src/audio/devices/platform/linux.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/linux.rs) | **ALSA** and **PulseAudio** |

Each module implements a `discover_devices()` function that returns a vector of `AudioDevice` structs containing the device name, unique ID, and type (microphone or system audio).

## Windows Audio Device Discovery via WASAPI

On Windows, Meetily uses the **Windows Audio Session API (WASAPI)** to enumerate audio endpoints. The implementation in [`frontend/src-tauri/src/audio/devices/platform/windows.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/windows.rs) handles device enumeration and supports exclusive-mode handling for low-latency capture.

The WASAPI implementation queries the `IMMDeviceEnumerator` interface to list active capture and render devices, converting the retrieved endpoint data into Meetily's internal `AudioDevice` representation.

## macOS Audio Device Discovery via ScreenCaptureKit

For macOS, the [`macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/macos.rs) module utilizes **ScreenCaptureKit** for system audio discovery alongside **CoreAudio** for microphone enumeration. This dual-framework approach allows Meetily to capture both application audio streams and physical input devices.

ScreenCaptureKit provides modern APIs for capturing system audio without requiring kernel extensions, while CoreAudio handles traditional audio hardware enumeration for microphones and external audio interfaces.

## Linux Audio Device Discovery via ALSA and PulseAudio

The Linux implementation in [`linux.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/linux.rs) probes both **ALSA** and **PulseAudio** backends to maximize compatibility across distributions. The module first attempts to enumerate devices via PulseAudio's asynchronous API, falling back to ALSA hardware enumeration when PulseAudio is unavailable.

This dual-backend strategy ensures Meetily functions on both modern desktop environments running PipeWire/PulseAudio and minimal systems using direct ALSA access.

## Unified API Architecture and Conditional Compilation

The platform-specific modules are abstracted behind a common interface defined in [`frontend/src-tauri/src/audio/devices/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/mod.rs). This module uses Rust's conditional compilation attributes (`#[cfg(target_os = "...")]`) to re-export the appropriate `discover_devices()` function for the target platform.

The [`frontend/src-tauri/src/audio/devices/discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/discovery.rs) file provides the high-level `list_audio_devices()` API that the rest of the codebase consumes. When the UI requests available devices, the backend executes the following flow:

1. The Tauri command invokes `audio::devices::list_audio_devices()`
2. Conditional compilation routes the call to the platform-specific `discover_devices()`
3. The native API queries hardware and returns a `Vec<AudioDevice>`
4. The UI receives structured data to populate device selection dropdowns

```rust
use crate::audio::devices::list_audio_devices;

pub async fn show_device_picker() -> Result<(), anyhow::Error> {
    // Retrieve all devices for the current platform
    let devices = list_audio_devices()?;

    // Filter for microphone and system audio devices
    let microphones = devices.iter()
        .filter(|d| d.kind == AudioDeviceKind::Microphone)
        .collect::<Vec<_>>();

    let systems = devices.iter()
        .filter(|d| d.kind == AudioDeviceKind::System)
        .collect::<Vec<_>>();

    // Example: pick the first available device on each side
    let mic = microphones.first()
        .ok_or_else(|| anyhow!("No microphone found"))?
        .clone();
    let sys = systems.first()
        .ok_or_else(|| anyhow!("No system audio device found"))?
        .clone();

    // Pass the selections to the recording manager
    crate::audio::recording_manager::start(mic, sys).await?;
    Ok(())
}

```

For direct platform testing, you can import the specific implementation using conditional compilation:

```rust
#[cfg(target_os = "windows")]
fn dump_windows_devices() -> Result<(), anyhow::Error> {
    use crate::audio::devices::platform::windows::discover_devices;
    let devs = discover_devices()?;
    println!("Windows audio devices: {:#?}", devs);
    Ok(())
}

```

## Frontend Integration with TypeScript

The React frontend retrieves device lists by invoking the Tauri command, which returns typed data for populating UI selectors:

```typescript
import { invoke } from '@tauri-apps/api/tauri';

// Ask the Rust backend for the list of devices
async function populateDeviceSelectors() {
  const devices: AudioDevice[] = await invoke('list_audio_devices');
  // `AudioDevice` contains `{ id: string, name: string, kind: 'microphone' | 'system' }`
  setMicOptions(devices.filter(d => d.kind === 'microphone'));
  setSystemOptions(devices.filter(d => d.kind === 'system'));
}

```

When the user initiates recording via `start_recording`, the selected device IDs are passed to [`frontend/src-tauri/src/audio/recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/recording_manager.rs), which coordinates the audio pipeline and Whisper transcription services.

## Summary

- **Windows** implementation uses **WASAPI** for device enumeration in [`frontend/src-tauri/src/audio/devices/platform/windows.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/windows.rs)
- **macOS** implementation combines **ScreenCaptureKit** and **CoreAudio** in [`frontend/src-tauri/src/audio/devices/platform/macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/macos.rs)
- **Linux** implementation supports both **ALSA** and **PulseAudio** in [`frontend/src-tauri/src/audio/devices/platform/linux.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/linux.rs)
- The `audio::devices` module abstracts platform differences through `#[cfg]` conditional compilation and the public `list_audio_devices()` API
- Device discovery integrates with [`recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_manager.rs) to orchestrate audio capture and transcription workflows

## Frequently Asked Questions

### How does Meetily handle audio device discovery across different operating systems?

Meetily uses a platform abstraction layer where each OS has a dedicated implementation file that calls native APIs—WASAPI for Windows, ScreenCaptureKit/CoreAudio for macOS, and ALSA/PulseAudio for Linux. These are compiled conditionally using Rust's `#[cfg(target_os = "...")]` attributes, exposing a uniform `list_audio_devices()` function to the rest of the application.

### What Rust pattern does Meetily use to select the correct platform implementation?

The project uses conditional compilation via the `cfg` attribute in [`frontend/src-tauri/src/audio/devices/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/mod.rs) to re-export the appropriate `discover_devices()` function based on the target OS. At compile time, only the relevant platform module is included, ensuring efficient binaries without unused code.

### Can Meetily's audio device discovery be extended to support additional platforms?

Yes, adding a new platform requires creating a new file under `frontend/src-tauri/src/audio/devices/platform/`, implementing the `discover_devices()` function using that OS's native audio API, and adding the corresponding `#[cfg(target_os = "...")]` export to [`mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/mod.rs). This modular structure keeps platform-specific code isolated and maintainable.

### How does the frontend retrieve and display available audio devices?

The TypeScript frontend calls `invoke('list_audio_devices')` from `@tauri-apps/api/tauri`, which triggers the Rust backend to execute the platform-specific discovery logic. The returned array of `AudioDevice` objects contains `id`, `name`, and `kind` fields, allowing the React UI to filter and populate dropdown menus for microphone and system audio selection.