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 contextinitializeVideo()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()orQMediaDevices::videoInputs()directly. Always go throughDeviceManagerto 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
QMediaDevicesinvalidate 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
- Media Architecture - Design rationale
- Graph Framework - Graph-based processing
- Video Streaming - Vision system and streaming