# How Meetily Handles Device Hotplug Detection and Monitoring: A Technical Deep Dive

> Discover how Meetily handles device hotplug detection and monitoring using a three-layer pipeline. Learn how it seamlessly swaps audio devices in real time.

- Repository: [Zackriya Solutions/meetily](https://github.com/Zackriya-Solutions/meetily)
- Tags: deep-dive
- Published: 2026-07-14

---

**Meetily implements a three-layer detection pipeline that combines platform-native APIs, name heuristics, and buffer-size analysis to classify audio devices as wired, Bluetooth, or virtual, then uses OS-specific listeners to swap devices in real time without restarting the application.**

Meetily, an open-source meeting transcription app by Zackriya-Solutions, automatically adapts its audio pipeline when users plug in headsets or microphones. The `device hotplug detection and monitoring` system runs inside the Tauri-based Rust backend, ensuring the Whisper transcription engine and VAD (Voice Activity Detection) mixer instantly switch to new hardware while applying the correct latency buffers.

## The Three-Layer Device Classification Strategy

Meetily’s detection logic prioritizes accuracy through a cascading fallback mechanism. If a platform-native query fails, the system falls back to faster heuristic methods.

### Platform-Native Queries

The most reliable layer uses operating-system-specific APIs. On macOS, the code leverages Core Audio’s `transport_type()` via the `cidre` crate to identify Bluetooth transport. Windows queries WASAPI naming conventions and property stores, while Linux inspects PulseAudio and BlueZ hints to detect Bluetooth headsets.

### Cross-Platform Name Heuristics

When native APIs return ambiguous results, Meetily applies pattern matching against device names. The `InputDeviceKind::detect()` function in [`frontend/src-tauri/src/audio/device_detection.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/device_detection.rs) searches for substrings like "AirPods", "bluetooth", "blackhole", or "virtual" to classify the hardware without expensive system calls.

### Buffer-Size Analysis

If the device name yields no clues, the system examines the reported buffer size and sample rate. According to the source code, buffers larger than 50 ms are treated as Bluetooth-style latency, while buffers under 20 ms indicate a wired connection. This fallback ensures robust detection even for devices with generic USB descriptors.

## Core Detection Logic in device_detection.rs

The [`frontend/src-tauri/src/audio/device_detection.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/device_detection.rs) file contains the central classification engine. The `InputDeviceKind` enum defines three variants: `Wired`, `Bluetooth`, and `Unknown`.

The `detect()` method orchestrates the three layers and returns the appropriate enum value. Once classified, `buffer_timeout()` supplies device-specific ranges (Wired = 20‑50 ms, Bluetooth = 80‑200 ms, Unknown ≈ Bluetooth). The `calculate_buffer_timeout()` function then computes an adaptive timeout from the reported buffer size, applying a 2× head-room factor and clamping to the device-specific range.

```rust
use crate::audio::device_detection::{InputDeviceKind, calculate_buffer_timeout};

let kind = InputDeviceKind::detect("AirPods Pro", 3840, 48_000);
let timeout = calculate_buffer_timeout(kind, 3840, 48_000);
// timeout = 160 ms (within Bluetooth range of 80-200 ms)

```

## Real-Time Hotplug Monitoring with system_detector.rs

Hot-plug monitoring lives in [`frontend/src-tauri/src/audio/system_detector.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/system_detector.rs). This module registers OS-specific listeners: a Core Audio property listener on macOS or a Windows event callback that fires when the default output device changes.

When a hotplug event occurs, the listener retrieves the new device via `ca::System::default_output_device()`, invokes `InputDeviceKind::detect()` on the device name and buffer info, and updates the shared `Arc<Mutex<Option<ca::Device>>>`. The rest of the audio pipeline—mixing, VAD, and Whisper transcription—reads this mutex to adapt instantly without restarting the app.

```rust
extern "C-unwind" fn device_listener(_: *mut std::ffi::c_void, _: ca::Device) {
    // Acquire lock, replace the stored device, and broadcast a Tauri event
    // with the new name and detected InputDeviceKind.
}

```

## Frontend Reactivity

The detection result propagates to the React frontend via Tauri’s event system. The [`frontend/src/app/page.tsx`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src/app/page.tsx) component listens for the `device-changed` event to update the sidebar and display current device type and latency settings.

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

await listen<{ name: string; kind: string }>('device-changed', ev => {
  console.log(`New audio device: ${ev.payload.name} (${ev.payload.kind})`);
  // Update UI or re-configure buffers here
});

```

## Summary

- **Three-layer detection** combines native APIs, name heuristics, and buffer-size analysis to classify devices as wired, Bluetooth, or virtual.
- **`InputDeviceKind`** enum in [`device_detection.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/device_detection.rs) provides the core classification logic with adaptive timeout calculations.
- **[`system_detector.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/system_detector.rs)** handles OS-specific hotplug events using Core Audio listeners or Windows callbacks.
- **Shared state** via `Arc<Mutex<Option<ca::Device>>>` allows the pipeline to switch devices without application restarts.
- **Tauri bridge** ensures the frontend React components receive instant notifications via the `device-changed` event.

## Frequently Asked Questions

### How does Meetily distinguish between Bluetooth and wired microphones?

Meetily first checks platform-native APIs—such as Core Audio’s `transport_type()` on macOS or WASAPI properties on Windows. If these return ambiguous results, the system falls back to name pattern matching (e.g., "AirPods", "bluetooth") and finally examines buffer sizes, treating buffers over 50 ms as Bluetooth and under 20 ms as wired.

### What happens when a device is unplugged during a meeting?

The OS-specific listener in [`system_detector.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/system_detector.rs) triggers immediately upon device removal. It acquires the lock on the shared `Arc<Mutex<Option<ca::Device>>>`, updates the stored device reference, and emits a `device-changed` event. The audio pipeline automatically reroutes to the remaining default device without requiring a restart.

### Which file contains the timeout calculation logic?

The `calculate_buffer_timeout()` function resides in [`frontend/src-tauri/src/audio/device_detection.rs`](https://github.com/Zackriya-Solutions/meetily/blob/main/frontend/src-tauri/src/audio/device_detection.rs). It computes adaptive timeouts based on the detected `InputDeviceKind` and clamps values to device-specific ranges—specifically 20‑50 ms for wired devices and 80‑200 ms for Bluetooth.

### Does Meetily support hotplug detection on all operating systems?

Yes. The repository includes platform-specific implementations in `frontend/src-tauri/src/audio/devices/` for macOS (Core Audio), Windows (WASAPI), and Linux (PulseAudio/BlueZ). Each implementation provides consistent hotplug detection and monitoring across all supported platforms.