MediaDeviceQuery

class NatML.Devices.MediaDeviceQuery : IReadOnlyList<IMediaDevice>

This class is responsible for discovering available media devices and reporting them to the user. It serves as an entry point for using media devices within NatDevice.

Creating a Query

/// <summary>
/// Create a media device query.
/// </summary>
/// <param name="filter">Filter that devices should meet.</param>
MediaDeviceQuery (Predicate<IMediaDevice> filter = null);

The query is created with an optional filter used to filter available devices. The filter is a Predicate<IMediaDevice>. This is useful for filtering for a specific kind of device. For instance, we can filter for camera devices that are front-facing like so:

var query = new MediaDeviceQuery(
    // Filter for front facing camera devices
    device => device is CameraDevice cameraDevice && cameraDevice.frontFacing
);

If the filter is null, the query will acquire all available media devices.

// Find all available media devices
var query = new MediaDeviceQuery();

NatDevice provides a set of commonly-used criteria, so that you don't have to keep defining them.

Inspecting Available Devices

The MediaDeviceQuery implements the IReadOnlyList<IMediaDevice> interface, and as such it doubles as an indexable list:

// Enumerate all devices in the collection
foreach (var device in query)
    ...
// Or get a device at a specific index
var secondDevice = query[1];

Device Count

The query also provides the number of devices that meets its criterion:

/// <summary>
/// Number of devices discovered by the query.
/// </summary>
int count { get; }

Working with Devices

/// <summary>
/// Current device that meets the provided criteria.
/// </summary>
IMediaDevice current { get; }

The query acts both as a device discoverer and as a cursor for enumerating discovered devices. As such, it provides the current property holds a reference to the device at the current cursor position:

// Get the first available audio device
var query = new MediaDeviceQuery(device => device is AudioDevice);
var device = query.current as AudioDevice;

Switching Between Devices

The current property simplifies workflows that might need to enumerate over multiple devices over a long period (e.g., camera applications that support switching cameras). The cursor can be advanced to point to the next device that meets the provided criteria.

/// <summary>
/// Advance the next available device that meets the provided criteria.
/// </summary>
void Advance ();

When the cursor reaches the end of its devices , it will wrap around, looping back to the first device in the query.

Managing Permissions

Access to audio and camera devices requires user authorization on most platforms, given the kind of sensitive data that can be streamed from them. As such, you must always ensure that your app has been granted permission to access these devices:

Checking Permissions

/// <summary>
/// Check the current permission status for a media device type.
/// </summary>
/// <returns>Current permissions status.</returns>
static PermissionStatus CheckPermissions<T> () where T : IMediaDevice;

The media device query can check the current authorization status for a specific media device type:

/// <summary>
/// Permissions status.
/// </summary>
enum PermissionStatus {
    /// <summary>
    /// User has not authorized or denied access to media device.
    /// </summary>
    Unknown = 0,
    /// <summary>
    /// User has denied access to media device.
    /// </summary>
    Denied = 2,
    /// <summary>
    /// User has authorized access to media device.
    /// </summary>
    Authorized = 3
}

Requesting Permissions

/// <summary>
/// Request permissions to use media devices from the user.
/// </summary>
static Task<PermissionStatus> RequestPermissions<T> () where T : IMediaDevice;

This function returns an asynchronous task that completes once the permissions result is available. The task returns the user's chosen permission status.

Before creating a media device query to search for devices, it is highly recommended to request permissions first.

The function can request camera or microphone permissions depending on the generic type T that is provided. If T is AudioDevice, then microphone permissions will be requested:

// Request microphone permissions
MediaDeviceQuery.RequestPermissions<AudioDevice>();

Similarly, if T is CameraDevice, then camera permissions will be requested:

// Request camera permissions
MediaDeviceQuery.RequestPermissions<CameraDevice>();

Preparing Requests

Different platforms have their own sets of added requirements before media devices can be used:

Configuring the iOS Audio Session

/// <summary>
/// Configure the app's global audio session for audio device discovery.
/// The desired value MUST be set before a query is created. It defaults to `true`.
/// </summary>
static bool ConfigureAudioSession { get; set; } = true;

iOS apps use a global audio session object which controls the app-wide audio configuration. In order to discover audio devices, iOS requires a specific configuration, AVAudioSessionCategoryPlayAndRecord. This property specifies whether NatDevice updates the app's audio configuration before discovering audio devices.

Last updated