# How Meetily Handles Audio Device Connect/Disconnect Events: Device Detection and Monitoring Explained

> Discover how Meetily handles audio device connect/disconnect events using its async monitor, shared registry, and Tauri events for seamless React frontend synchronization.

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

---

**Meetily's audio subsystem uses a dedicated async monitor to watch for OS-level device changes, updates a shared registry, and emits Tauri events to keep the React frontend synchronized when microphones or speakers are added or removed.**

The device detection and monitoring system in [Zackriya-Solutions/meetily](https://github.com/Zackriya-Solutions/meetily) provides real-time tracking of audio hardware across macOS, Windows, and Linux. Built with Rust and Tauri, the architecture separates enumeration logic from continuous monitoring to ensure low-latency detection of connect and disconnect events without blocking the main recording pipeline.

## Core Architecture Components

The system relies on two tightly-coupled modules that handle distinct responsibilities in the audio stack.

### Device Detection Module ([`device_detection.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/device_detection.rs))

Located at [`frontend/src-tauri/src/audio/device_detection.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/device_detection.rs), this module performs the initial enumeration of audio devices and provides helper functions to retrieve default microphones or speakers. It queries platform-specific backends found in `audio/devices/platform/*.rs` to build a list of `AudioDevice` structs, each describing the device name, ID, and capabilities.

### Device Monitor Module ([`device_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/device_monitor.rs))

The [`frontend/src-tauri/src/audio/device_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/device_monitor.rs) file spawns a background async task that registers OS-level listeners. On macOS it uses CoreAudio callbacks, on Windows it leverages WASAPI notifications, and on Linux it listens for PulseAudio or ALSA events. When the OS reports a device addition or removal, the monitor updates the shared device registry and emits a Tauri event to the frontend.

## Event Handling Flow

The detection pipeline follows a four-stage lifecycle from startup enumeration through runtime monitoring.

### Startup Enumeration

When the Tauri application launches, `audio::mod.rs` calls `device_detection::list_audio_devices()` to gather the current snapshot of available hardware. This initial list populates the frontend device selectors before monitoring begins.

### OS-Level Monitoring

The `device_monitor::start()` function creates a Tokio-based watcher that registers with the platform module (`audio/devices/platform/{macos,windows,linux}.rs`). Each platform implementation provides a `register_device_change_callback` that forwards OS events to a `mpsc::UnboundedSender<DeviceChange>` channel. When the callback triggers, it translates native notifications into `DeviceChange::Added` or `DeviceChange::Removed` messages.

### Frontend Synchronization

Upon receiving device change messages, the monitor updates an `Arc<RwLock<Vec<AudioDevice>>>` shared state and calls `app.emit("device-updated", ...)` to broadcast the new device list. The React UI listens for this event to refresh selectors in real time, ensuring users always see current hardware availability.

## Stream Recovery and Graceful Degradation

The [`frontend/src-tauri/src/audio/recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/recording_manager.rs) coordinates the recording lifecycle and reacts to missing devices via the shared state. If an active recording loses its selected input device, the manager detects the absence through the registry and gracefully stops the capture stream, notifying the user through a toast notification. When new devices appear, the UI can automatically select them or preserve the previous selection if still available.

Because the monitor uses a lock-free `Arc<AtomicBool>` flag for the "recording-in-progress" state, device-change handling remains lightweight and does not interfere with the real-time audio mixing pipeline.

## Implementation Examples

The following code demonstrates how to initialize the monitoring system and handle events in both the Rust backend and TypeScript frontend.

Initialize the monitor and emit initial device list:

```rust
#[tauri::command]
async fn init_audio(app: tauri::AppHandle) -> Result<(), String> {
    // Enumerate devices once
    let devices = audio::device_detection::list_audio_devices()?;
    app.emit("device-updated", devices).map_err(|e| e.to_string())?;

    // Begin background monitoring
    audio::device_monitor::start(app.clone());
    Ok(())
}

```

Platform-specific registration for macOS using CoreAudio:

```rust
#[cfg(target_os = "macos")]
pub fn register_device_change_callback(tx: UnboundedSender<DeviceChange>) {
    // Use CoreAudio AudioObjectAddPropertyListener to watch
    // AudioObjectPropertyAddress for device list changes
    // On callback, translate to DeviceChange::Added/Removed and send via tx
}

```

Frontend subscription to device updates:

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

listen('device-updated', (event) => {
  const devices = event.payload as AudioDevice[];
  setAvailableDevices(devices);
});

```

## Summary

- **Separation of concerns**: [`device_detection.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/device_detection.rs) handles static enumeration while [`device_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/device_monitor.rs) manages dynamic OS events
- **Cross-platform abstraction**: Platform-specific modules in `audio/devices/platform/` normalize CoreAudio, WASAPI, and PulseAudio notifications into uniform `DeviceChange` events
- **Thread-safe state**: The system uses `Arc<RwLock<Vec<AudioDevice>>>` for shared device registry and `Arc<AtomicBool>` for recording state to prevent race conditions
- **Tauri integration**: Device changes propagate to the React frontend via the `device-updated` event, enabling real-time UI updates
- **Graceful degradation**: [`recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_manager.rs) detects missing devices during active recordings and stops streams safely rather than crashing

## Frequently Asked Questions

### How does Meetily detect audio device changes on macOS?

On macOS, the platform module in [`audio/devices/platform/macos.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/audio/devices/platform/macos.rs) registers a CoreAudio property listener using `AudioObjectAddPropertyListener` on the default audio object. When the system broadcasts device list changes, the callback translates the native event into a `DeviceChange` enum variant and sends it through an unbounded channel to the async monitor task.

### What happens to active recordings when a device is disconnected?

The [`recording_manager.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/recording_manager.rs) module continuously checks the shared device registry against the currently selected recording input. If the selected device disappears from the registry, the manager triggers a graceful shutdown of the capture stream, releases the audio resources, and emits a notification event to the frontend to alert the user of the hardware change.

### Can the frontend automatically switch to a newly connected microphone?

Yes. When [`device_monitor.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/device_monitor.rs) detects a `DeviceChange::Added` event, it emits the full updated device list via the `device-updated` Tauri event. The React frontend can implement logic to automatically select the new device if no current selection exists, or prioritize it based on device properties, by handling this event in the component state management.

### Which file handles the platform-specific Windows audio notifications?

Windows-specific device notifications are implemented 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). This file registers for WASAPI endpoint change notifications using the `IMMNotificationClient` interface, converting Windows `OnDeviceAdded` and `OnDeviceRemoved` callbacks into the internal `DeviceChange` message types consumed by the monitor.