# How to Add Support for a New Audio Device Platform in Meetily

> Learn to add new audio device platform support in Meetily. Implement Rust functions, register them with cfg guards, and leverage existing discovery logic for seamless integration.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: how-to-guide
- Published: 2026-07-20

---

**To add support for a new audio device platform in Meetily, implement two standard Rust functions—`configure_<platform>_audio` and `get_<platform>_device`—in a platform-specific module, register them behind `#[cfg(target_os)]` guards in the platform gate, and the existing discovery logic will automatically enumerate devices for your target OS.**

Meetily's audio subsystem is built around a portable, platform-agnostic core that delegates OS-specific device enumeration to modular backend implementations. Whether you are targeting a new Linux distribution, a BSD variant, or an embedded audio stack, you can add support for a new audio device platform in Meetily by placing your implementation in `frontend/src-tauri/src/audio/devices/platform/` and exposing two public symbols that the generic discovery layer consumes.

## Architecture Overview

Meetily isolates platform-specific code in `frontend/src-tauri/src/audio/devices/platform/`, where each operating system lives in its own source file. Every platform module exposes two public symbols:

- **`configure_<platform>_audio(&cpal::Host) -> Result<Vec<AudioDevice>>`** – Enumerates available input and output devices that Meetily can present to the user.
- **`get_<platform>_device(&AudioDevice) -> Result<(cpal::Device, cpal::SupportedStreamConfig)>]`** – Returns a concrete CPAL device and a usable stream configuration for recording.

These functions are re-exported from [`frontend/src-tauri/src/audio/devices/platform/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/mod.rs) via `#[cfg(target_os = "...")]` guards. The generic discovery logic in [`frontend/src-tauri/src/audio/devices/discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/discovery.rs) calls the appropriate implementation based on the compile-time target triple, ensuring only relevant code is linked into the final binary.

## Step 1: Create the Platform Implementation File

Create a new Rust source file at `frontend/src-tauri/src/audio/devices/platform/<your_os>.rs`. You must implement at least the device enumeration function, and optionally the device retrieval function if your platform requires special handling (e.g., loop-back modes or specific audio APIs).

### Implement Device Enumeration

Define `configure_<your_os>_audio` to return a vector of `AudioDevice` structs using CPAL's `HostTrait` and `DeviceTrait`. The following skeleton mirrors the pattern used in the Windows ([`windows.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/windows.rs)) and macOS ([`macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/macos.rs)) implementations:

```rust
use anyhow::Result;
use cpal::traits::{DeviceTrait, HostTrait};
use crate::audio::devices::configuration::{AudioDevice, DeviceType};

/// Configure MyOS audio devices using the native API (e.g., PipeWire, ALSA)
pub fn configure_myos_audio(host: &cpal::Host) -> Result<Vec<AudioDevice>> {
    let mut devices = Vec::new();

    // Enumerate input devices (microphones)
    for device in host.input_devices()? {
        if let Ok(name) = device.name() {
            devices.push(AudioDevice::new(name, DeviceType::Input));
        }
    }

    // Enumerate output devices (system audio)
    for device in host.output_devices()? {
        if let Ok(name) = device.name() {
            devices.push(AudioDevice::new(name, DeviceType::Output));
        }
    }

    Ok(devices)
}

```

### Implement Device Retrieval

Implement `get_<your_os>_device` to resolve an `AudioDevice` back to a concrete CPAL device and its default configuration:

```rust
/// Retrieve a specific MyOS device and a compatible stream config.
pub fn get_myos_device(
    audio_device: &AudioDevice
) -> Result<(cpal::Device, cpal::SupportedStreamConfig)> {
    let host = cpal::default_host();
    let target_name = &audio_device.name;

    match audio_device.device_type {
        DeviceType::Input => {
            for dev in host.input_devices()? {
                if let Ok(name) = dev.name() {
                    if name == *target_name {
                        return Ok((dev, dev.default_input_config()?));
                    }
                }
            }
        }
        DeviceType::Output => {
            for dev in host.output_devices()? {
                if let Ok(name) = dev.name() {
                    if name == *target_name {
                        return Ok((dev, dev.default_output_config()?));
                    }
                }
            }
        }
    }

    Err(anyhow::anyhow!("Device not found: {}", target_name))
}

```

## Step 2: Register the Platform Module

Edit [`frontend/src-tauri/src/audio/devices/platform/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/platform/mod.rs) to conditionally expose your new symbols. Use `#[cfg(target_os = "...")]` attributes to ensure the code is only compiled for the relevant target, following the existing pattern for Windows, macOS, and Linux:

```rust
#[cfg(target_os = "myos")]
pub mod myos;

#[cfg(target_os = "myos")]
pub use myos::configure_myos_audio;
#[cfg(target_os = "myos")]
pub use myos::get_myos_device;

```

This registration step is critical: it allows the rest of the codebase to call `platform::configure_myos_audio` without knowing the specific target OS at the call site.

## Step 3: Verify Integration with the Discovery Flow

The `list_audio_devices` function in [`frontend/src-tauri/src/audio/devices/discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/discovery.rs) automatically invokes your platform's configuration function based on compile-time target detection. No further code changes are required; once your module is compiled, `list_audio_devices` will include the devices returned by your implementation in the results returned to the frontend.

From the TypeScript UI layer, you consume the new platform support exactly like existing platforms:

```typescript
// Automatically uses the platform-specific configure_* function
const devices: AudioDevice[] = await invoke('list_audio_devices');

// Start recording with discovered devices
await invoke('start_recording', {
  mic_device_name: devices.find(d => d.type === 'input')?.name,
  system_device_name: devices.find(d => d.type === 'output')?.name,
  meeting_name: 'Demo Meeting',
});

```

## Optional: Handle Platform-Specific Permissions

If your platform requires runtime permissions (e.g., microphone access or screen recording), extend `trigger_audio_permission` in [`discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/discovery.rs) or add a platform-specific helper. Invoke this from the UI layer before calling `list_audio_devices` to ensure the user has granted necessary access, mirroring the macOS permission flow pattern found in the source code.

## Summary

- **Create** a new Rust file in `frontend/src-tauri/src/audio/devices/platform/` implementing `configure_<platform>_audio` for device enumeration and `get_<platform>_device` for stream configuration.
- **Register** the module in [`platform/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/platform/mod.rs) using `#[cfg(target_os = "...")]` guards to enable conditional compilation.
- **Verify** that `list_audio_devices` in [`discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/discovery.rs) automatically includes your platform's devices without additional changes to the discovery logic.
- **Leverage** CPAL's `HostTrait` and `DeviceTrait` abstractions to maintain portability across audio backends.
- **Handle** platform-specific permissions separately from device enumeration to keep the modular architecture clean.

## Frequently Asked Questions

### What functions must I implement to add a new audio platform in Meetily?

You must implement `configure_<platform>_audio` to return a `Vec<AudioDevice>` containing available input and output devices, and `get_<platform>_device` to return a tuple of `(cpal::Device, cpal::SupportedStreamConfig)` for a given `AudioDevice`. These signatures integrate directly with the existing discovery pipeline in [`discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/discovery.rs).

### Where does Meetily store platform-specific audio device code?

Platform-specific implementations reside in `frontend/src-tauri/src/audio/devices/platform/`, with reference implementations for Windows ([`windows.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/windows.rs)), macOS ([`macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/macos.rs)), and Linux ([`linux.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/linux.rs)). The module gate at [`platform/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/platform/mod.rs) re-exports these implementations using `#[cfg(target_os)]` conditional compilation.

### How does Meetily automatically detect my new platform implementation?

The `list_audio_devices` function in [`frontend/src-tauri/src/audio/devices/discovery.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/devices/discovery.rs) uses compile-time target detection to call the appropriate `configure_<platform>_audio` function. When you register your module in [`platform/mod.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/platform/mod.rs) with the correct `#[cfg(target_os = "...")]` attribute, the Rust compiler includes your code only for that target, and the discovery logic automatically invokes it.

### Do I need to modify the UI code when adding a new audio platform?

No. The TypeScript frontend calls generic commands like `list_audio_devices` and `start_recording` through Tauri's invoke API. Because the Rust backend abstracts platform differences behind the `AudioDevice` and `DeviceType` structures, the UI remains agnostic to the underlying operating system or audio API.