Device Management

Unified device enumeration, caching, and matching

Device Management

Unified device enumeration, caching, and matching for audio and video hardware. All device access goes through DeviceManager in libmediacore.


Location

src/libs/libmediacore/mediacore/devices/
  DeviceManager.hpp / .cpp
  DeviceCache.hpp / .cpp
  DeviceMatcher.hpp / .cpp

DeviceManager

Singleton providing cached access to all audio and video devices.

Key methods

Method Description
instance() Returns the singleton instance
initializeAudio() Initializes audio device enumeration (deferred)
initializeVideo() Initializes video device enumeration (deferred)
audioInputs() Returns cached list of audio input devices
audioOutputs() Returns cached list of audio output devices
videoInputs() Returns cached list of video input devices

Signals

Signal Emitted when
audioDevicesChanged() Audio devices added or removed
videoDevicesChanged() Video devices added or removed

Deferred initialization

DeviceManager does not enumerate devices at construction time. Calling QMediaDevices::audioOutputs() too early on Linux causes PipeWire to reconfigure the system audio graph, disrupting other applications. Instead:

  • initializeAudio() is called when the user first enters an audio-consuming context
  • initializeVideo() is called when the user first enters a video-consuming context

This split initialization prevents audio enumeration from interfering with video and vice versa.

Warning: Never call QMediaDevices::audioOutputs() or QMediaDevices::videoInputs() directly. Always go through DeviceManager to benefit from caching and deferred initialization.


DeviceCache

TTL-based cache that wraps Qt's QMediaDevices enumeration.

Behavior

  • First call enumerates hardware and caches the result
  • Subsequent calls within the TTL window return the cached list
  • After TTL expiry, the next call re-enumerates
  • Hot-plug signals from QMediaDevices invalidate the cache immediately

Configuration

Property Default Description
TTL 5000 ms Cache validity duration

DeviceMatcher

Finds devices by name, USB vendor:product ID, or fuzzy string similarity.

Match strategies

Strategy Description Use case
Exact Exact string match on device description Known device name
UsbId Match by USB vendor:product ID (e.g., 1234:5678) Hardware-specific matching
Fuzzy String similarity with threshold (default 0.5) Approximate matching
Smart Try exact, then USB ID, then fuzzy General-purpose lookup

USB ID extraction

DeviceMatcher extracts USB vendor:product IDs from device description strings using the pattern (xxxx:xxxx):

// Example: "HD Pro Webcam C920 (046d:082d)"
// Extracts: "046d:082d"
auto usbId = DeviceMatcher::extractUsbId(device.description());

Audio-video pairing

DeviceMatcher pairs webcam video inputs with their built-in microphones by matching USB IDs:

auto matcher = DeviceMatcher::usbId(
    DeviceMatcher::extractUsbId(videoDevice.description())
);
QAudioDevice pairedMic = matcher.findBest(audioInputList);

Usage examples

Basic device enumeration

auto& dm = media::devices::DeviceManager::instance();
dm.initializeAudio();

for (const auto& device : dm.audioOutputs().devices()) {
    qDebug() << device.description();
}

Finding a specific device

auto& dm = media::devices::DeviceManager::instance();
auto matcher = media::devices::DeviceMatcher::smart("USB Webcam");
QCameraDevice camera = matcher.findBest(dm.videoInputs().devices());

Responding to hot-plug

auto& dm = media::devices::DeviceManager::instance();
connect(&dm, &DeviceManager::audioDevicesChanged, this, [&]() {
    // Refresh device list in UI
    updateDeviceDropdown(dm.audioOutputs().devices());
});

See Also

In this section
Topics
reference media devices audio video
See also