Commit 596a3ef9 authored by David Reid's avatar David Reid

Add onStop callback which is called when a device is stopped either explicitly...

Add onStop callback which is called when a device is stopped either explicitly or internally as a result of an error.
parent 26ccabc8
......@@ -244,6 +244,7 @@ typedef struct mal_device mal_device;
typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples);
typedef mal_uint32 (* mal_send_proc)(mal_device* pDevice, mal_uint32 frameCount, void* pSamples);
typedef void (* mal_stop_proc)(mal_device* pDevice);
typedef void (* mal_log_proc) (mal_device* pDevice, const char* message);
typedef enum
......@@ -303,6 +304,7 @@ struct mal_device
mal_uint32 state;
mal_recv_proc onRecv;
mal_send_proc onSend;
mal_stop_proc onStop;
mal_log_proc onLog;
void* pUserData; // Application defined data.
mal_mutex lock;
......@@ -443,6 +445,15 @@ void mal_device_uninit(mal_device* pDevice);
// This is just an atomic assignment.
void mal_device_set_recv_callback(mal_device* pDevice, mal_recv_proc proc);
// Sets the callback to use when the device has stopped, either explicitly or as a result of an error.
//
// Thread Safety: SAFE
// This API is implemented as a simple atomic assignment.
//
// Efficiency: HIGH
// This is just an atomic assignment.
void mal_device_set_stop_callback(mal_device* pDevice, mal_stop_proc proc);
// Sets the callback to use when the application needs to send data to the device for playback.
//
// Note that the implementation of this callback must copy over as many samples as is available. The
......@@ -2831,11 +2842,24 @@ mal_thread_result MAL_THREADCALL mal_worker_thread(void* pData)
{
mal_device* pDevice = (mal_device*)pData;
mal_assert(pDevice != NULL);
// This is only used to prevent posting onStop() when the device is first initialized.
mal_bool32 skipNextStopEvent = MAL_TRUE;
for (;;) {
// At the start of iteration the device is stopped - we must explicitly mark it as such.
mal_device__stop_backend(pDevice);
if (!skipNextStopEvent) {
mal_stop_proc onStop = pDevice->onStop;
if (onStop) {
onStop(pDevice);
}
} else {
skipNextStopEvent = MAL_FALSE;
}
// Let the other threads know that the device has stopped.
mal_device__set_state(pDevice, MAL_STATE_STOPPED);
mal_event_signal(&pDevice->stopEvent);
......@@ -3051,6 +3075,12 @@ void mal_device_set_send_callback(mal_device* pDevice, mal_send_proc proc)
mal_atomic_exchange_ptr(&pDevice->onSend, proc);
}
void mal_device_set_stop_callback(mal_device* pDevice, mal_stop_proc proc)
{
if (pDevice == NULL) return;
mal_atomic_exchange_ptr(&pDevice->onStop, proc);
}
mal_result mal_device_start(mal_device* pDevice)
{
if (pDevice == NULL) return mal_post_error(pDevice, "mal_device_start() called with invalid arguments.", MAL_INVALID_ARGS);
......@@ -3244,7 +3274,6 @@ mal_uint32 mal_get_sample_size_in_bytes(mal_format format)
// TODO
// ====
// - Examples.
//
// ALSA
// ----
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment