ma_backend_callbacks class final

These are the callbacks required to be implemented for a backend. These callbacks are grouped into two parts: context and device. There is one context to many devices. A device is created from a context.

The general flow goes like this:

  1. A context is created with onContextInit() 1a) Available devices can be enumerated with onContextEnumerateDevices() if required. 1b) Detailed information about a device can be queried with onContextGetDeviceInfo() if required.
  2. A device is created from the context that was created in the first step using onDeviceInit(), and optionally a device ID that was selected from device enumeration via onContextEnumerateDevices().
  3. A device is started or stopped with onDeviceStart() / onDeviceStop()
  4. Data is delivered to and from the device by the backend. This is always done based on the native format returned by the prior call to onDeviceInit(). Conversion between the device's native format and the format requested by the application will be handled by miniaudio internally.

Initialization of the context is quite simple. You need to do any necessary initialization of internal objects and then output the callbacks defined in this structure.

Once the context has been initialized you can initialize a device. Before doing so, however, the application may want to know which physical devices are available. This is where onContextEnumerateDevices() comes in. This is fairly simple. For each device, fire the given callback with, at a minimum, the basic information filled out in ma_device_info. When the callback returns MA_FALSE, enumeration needs to stop and the onContextEnumerateDevices() function returns with a success code.

Detailed device information can be retrieved from a device ID using onContextGetDeviceInfo(). This takes as input the device type and ID, and on output returns detailed information about the device in ma_device_info. The onContextGetDeviceInfo() callback must handle the case when the device ID is NULL, in which case information about the default device needs to be retrieved.

Once the context has been created and the device ID retrieved (if using anything other than the default device), the device can be created. This is a little bit more complicated than initialization of the context due to it's more complicated configuration. When initializing a device, a duplex device may be requested. This means a separate data format needs to be specified for both playback and capture. On input, the data format is set to what the application wants. On output it's set to the native format which should match as closely as possible to the requested format. The conversion between the format requested by the application and the device's native format will be handled internally by miniaudio.

On input, if the sample format is set to ma_format_unknown, the backend is free to use whatever sample format it desires, so long as it's supported by miniaudio. When the channel count is set to 0, the backend should use the device's native channel count. The same applies for sample rate. For the channel map, the default should be used when ma_channel_map_is_blank() returns true (all channels set to MA_CHANNEL_NONE). On input, the periodSizeInFrames or periodSizeInMilliseconds option should always be set. The backend should inspect both of these variables. If periodSizeInFrames is set, it should take priority, otherwise it needs to be derived from the period size in milliseconds (periodSizeInMilliseconds) and the sample rate, keeping in mind that the sample rate may be 0, in which case the sample rate will need to be determined before calculating the period size in frames. On output, all members of the ma_device_descriptor object should be set to a valid value, except for periodSizeInMilliseconds which is optional (periodSizeInFrames must be set).

Starting and stopping of the device is done with onDeviceStart() and onDeviceStop() and should be self-explanatory. If the backend uses asynchronous reading and writing, onDeviceStart() and onDeviceStop() should always be implemented.

The handling of data delivery between the application and the device is the most complicated part of the process. To make this a bit easier, some helper callbacks are available. If the backend uses a blocking read/write style of API, the onDeviceRead() and onDeviceWrite() callbacks can optionally be implemented. These are blocking and work just like reading and writing from a file. If the backend uses a callback for data delivery, that callback must call ma_device_handle_backend_data_callback() from within it's callback. This allows miniaudio to then process any necessary data conversion and then pass it to the miniaudio data callback.

If the backend requires absolute flexibility with it's data delivery, it can optionally implement the onDeviceDataLoop() callback which will allow it to implement the logic that will run on the audio thread. This is much more advanced and is completely optional.

The audio thread should run data delivery logic in a loop while ma_device_get_state() == ma_device_state_started and no errors have been encountered. Do not start or stop the device here. That will be handled from outside the onDeviceDataLoop() callback.

The invocation of the onDeviceDataLoop() callback will be handled by miniaudio. When you start the device, miniaudio will fire this callback. When the device is stopped, the ma_device_get_state() == ma_device_state_started condition will fail and the loop will be terminated which will then fall through to the part that stops the device. For an example on how to implement the onDeviceDataLoop() callback, look at ma_device_audio_thread__default_read_write(). Implement the onDeviceDataLoopWakeup() callback if you need a mechanism to wake up the audio thread.

If the backend supports an optimized retrieval of device information from an initialized ma_device object, it should implement the onDeviceGetInfo() callback. This is optional, in which case it will fall back to onContextGetDeviceInfo() which is less efficient.

Inheritance
Implemented types
Available extensions

Constructors

ma_backend_callbacks()

Properties

address Pointer<T>

Available on T, provided by the StructAddress extension

The memory address of the underlying data.
no setter
hashCode int
The hash code for this object.
no setterinherited
onContextEnumerateDevices Pointer<NativeFunction<Int Function(Pointer<ma_context> pContext, ma_enum_devices_callback_proc callback, Pointer<Void> pUserData)>>
getter/setter pair
onContextGetDeviceInfo Pointer<NativeFunction<Int Function(Pointer<ma_context> pContext, UnsignedInt deviceType, Pointer<ma_device_id> pDeviceID, Pointer<ma_device_info> pDeviceInfo)>>
getter/setter pair
onContextInit Pointer<NativeFunction<Int Function(Pointer<ma_context> pContext, Pointer<ma_context_config> pConfig, Pointer<ma_backend_callbacks> pCallbacks)>>
getter/setter pair
onContextUninit Pointer<NativeFunction<Int Function(Pointer<ma_context> pContext)>>
getter/setter pair
onDeviceDataLoop Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice)>>
getter/setter pair
onDeviceDataLoopWakeup Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice)>>
getter/setter pair
onDeviceGetInfo Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice, UnsignedInt type, Pointer<ma_device_info> pDeviceInfo)>>
getter/setter pair
onDeviceInit Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice, Pointer<ma_device_config> pConfig, Pointer<ma_device_descriptor> pDescriptorPlayback, Pointer<ma_device_descriptor> pDescriptorCapture)>>
getter/setter pair
onDeviceRead Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice, Pointer<Void> pFrames, ma_uint32 frameCount, Pointer<ma_uint32> pFramesRead)>>
getter/setter pair
onDeviceStart Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice)>>
getter/setter pair
onDeviceStop Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice)>>
getter/setter pair
onDeviceUninit Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice)>>
getter/setter pair
onDeviceWrite Pointer<NativeFunction<Int Function(Pointer<ma_device> pDevice, Pointer<Void> pFrames, ma_uint32 frameCount, Pointer<ma_uint32> pFramesWritten)>>
getter/setter pair
runtimeType Type
A representation of the runtime type of the object.
no setterinherited

Methods

noSuchMethod(Invocation invocation) → dynamic
Invoked when a nonexistent method or property is accessed.
inherited
toString() String
A string representation of this object.
inherited

Operators

operator ==(Object other) bool
The equality operator.
inherited