Commit 400e3c9a authored by David Reid's avatar David Reid

API CHANGE: Pass the log callback to mal_context_init().

parent 57e872fe
...@@ -76,7 +76,7 @@ ...@@ -76,7 +76,7 @@
// ... // ...
// //
// mal_context context; // mal_context context;
// if (mal_context_init(NULL, 0, &context) != MAL_SUCCESS) { // if (mal_context_init(NULL, 0, NULL, &context) != MAL_SUCCESS) {
// printf("Failed to initialize context."); // printf("Failed to initialize context.");
// return -3; // return -3;
// } // }
...@@ -364,12 +364,13 @@ typedef int mal_result; ...@@ -364,12 +364,13 @@ typedef int mal_result;
#define MAL_WINMM_FAILED_TO_GET_DEVICE_CAPS -4096 #define MAL_WINMM_FAILED_TO_GET_DEVICE_CAPS -4096
#define MAL_WINMM_FAILED_TO_GET_SUPPORTED_FORMATS -4097 #define MAL_WINMM_FAILED_TO_GET_SUPPORTED_FORMATS -4097
typedef struct mal_context mal_context;
typedef struct mal_device mal_device; typedef struct mal_device mal_device;
typedef void (* mal_log_proc) (mal_context* pContext, mal_device* pDevice, const char* message);
typedef void (* mal_recv_proc)(mal_device* pDevice, mal_uint32 frameCount, const void* pSamples); 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 mal_uint32 (* mal_send_proc)(mal_device* pDevice, mal_uint32 frameCount, void* pSamples);
typedef void (* mal_stop_proc)(mal_device* pDevice); typedef void (* mal_stop_proc)(mal_device* pDevice);
typedef void (* mal_log_proc) (mal_device* pDevice, const char* message);
typedef enum typedef enum
{ {
...@@ -539,12 +540,12 @@ typedef struct ...@@ -539,12 +540,12 @@ typedef struct
mal_recv_proc onRecvCallback; mal_recv_proc onRecvCallback;
mal_send_proc onSendCallback; mal_send_proc onSendCallback;
mal_stop_proc onStopCallback; mal_stop_proc onStopCallback;
mal_log_proc onLogCallback;
} mal_device_config; } mal_device_config;
typedef struct struct mal_context
{ {
mal_backend backend; // DirectSound, ALSA, etc. mal_backend backend; // DirectSound, ALSA, etc.
mal_log_proc onLog;
union union
{ {
...@@ -718,7 +719,7 @@ typedef struct ...@@ -718,7 +719,7 @@ typedef struct
#endif #endif
int _unused; int _unused;
}; };
} mal_context; };
struct mal_device struct mal_device
{ {
...@@ -734,7 +735,6 @@ struct mal_device ...@@ -734,7 +735,6 @@ struct mal_device
mal_recv_proc onRecv; mal_recv_proc onRecv;
mal_send_proc onSend; mal_send_proc onSend;
mal_stop_proc onStop; mal_stop_proc onStop;
mal_log_proc onLog;
void* pUserData; // Application defined data. void* pUserData; // Application defined data.
mal_mutex lock; mal_mutex lock;
mal_event wakeupEvent; mal_event wakeupEvent;
...@@ -882,29 +882,24 @@ struct mal_device ...@@ -882,29 +882,24 @@ struct mal_device
// - OpenAL // - OpenAL
// - Null // - Null
// //
// The onLog callback is used for posting log messages back to the client for diagnostics, debugging,
// etc. You can pass NULL for this if you do not need it.
//
// Return Value: // Return Value:
// - MAL_SUCCESS if successful. // MAL_SUCCESS if successful; any other error code otherwise.
// - MAL_INVALID_ARGS
// One or more of the input arguments is invalid.
// - MAL_NO_BACKEND
// There is no supported backend, or there was an error loading it (such as a missing dll/so).
// //
// Thread Safety: UNSAFE // Thread Safety: UNSAFE
// //
// Effeciency: LOW // Effeciency: LOW
// This will dynamically load backends DLLs/SOs (such as dsound.dll). // This will dynamically load backends DLLs/SOs (such as dsound.dll).
mal_result mal_context_init(mal_backend backends[], mal_uint32 backendCount, mal_context* pContext); mal_result mal_context_init(mal_backend backends[], mal_uint32 backendCount, mal_log_proc onLog, mal_context* pContext);
// Uninitializes a context. // Uninitializes a context.
// //
// Results are undefined if you call this while any device created by this context is still active. // Results are undefined if you call this while any device created by this context is still active.
// //
// Return Value: // Return Value:
// - MAL_SUCCESS if successful. // MAL_SUCCESS if successful; any other error code otherwise.
// - MAL_INVALID_ARGS
// One or more of the input arguments is invalid.
// - MAL_NO_BACKEND
// The device has an unknown backend. This probably means the context of <pContext> has been trashed.
// //
// Thread Safety: UNSAFE // Thread Safety: UNSAFE
// //
...@@ -1951,23 +1946,35 @@ mal_bool32 mal_event_signal(mal_event* pEvent) ...@@ -1951,23 +1946,35 @@ mal_bool32 mal_event_signal(mal_event* pEvent)
// Posts a log message. // Posts a log message.
static void mal_log(mal_device* pDevice, const char* message) static void mal_log(mal_context* pContext, mal_device* pDevice, const char* message)
{ {
if (pDevice == NULL) return; if (pContext == NULL) return;
mal_log_proc onLog = pDevice->onLog; mal_log_proc onLog = pContext->onLog;
if (onLog) { if (onLog) {
onLog(pDevice, message); onLog(pContext, pDevice, message);
} }
} }
// Posts an error. Throw a breakpoint in here if you're needing to debug. The return value is always "resultCode". // Posts an error. Throw a breakpoint in here if you're needing to debug. The return value is always "resultCode".
static mal_result mal_post_error(mal_device* pDevice, const char* message, mal_result resultCode) static mal_result mal_context_post_error(mal_context* pContext, mal_device* pDevice, const char* message, mal_result resultCode)
{ {
mal_log(pDevice, message); // Derive the context from the device if necessary.
if (pContext == NULL) {
if (pDevice != NULL) {
pContext = pDevice->pContext;
}
}
mal_log(pContext, pDevice, message);
return resultCode; return resultCode;
} }
static mal_result mal_post_error(mal_device* pDevice, const char* message, mal_result resultCode)
{
return mal_context_post_error(NULL, pDevice, message, resultCode);
}
static void mal_get_default_channel_mapping(mal_backend backend, mal_uint32 channels, mal_channel channelMap[MAL_MAX_CHANNELS]) static void mal_get_default_channel_mapping(mal_backend backend, mal_uint32 channels, mal_channel channelMap[MAL_MAX_CHANNELS])
{ {
...@@ -7319,10 +7326,11 @@ mal_result mal_context_uninit_backend_apis(mal_context* pContext) ...@@ -7319,10 +7326,11 @@ mal_result mal_context_uninit_backend_apis(mal_context* pContext)
return result; return result;
} }
mal_result mal_context_init(mal_backend backends[], mal_uint32 backendCount, mal_context* pContext) mal_result mal_context_init(mal_backend backends[], mal_uint32 backendCount, mal_log_proc onLog, mal_context* pContext)
{ {
if (pContext == NULL) return MAL_INVALID_ARGS; if (pContext == NULL) return MAL_INVALID_ARGS;
mal_zero_object(pContext); mal_zero_object(pContext);
pContext->onLog = onLog; // <-- Set this at the top to ensure the application has access to every log message.
// Backend APIs need to be initialized first. This is where external libraries will be loaded and linked. // Backend APIs need to be initialized first. This is where external libraries will be loaded and linked.
mal_result result = mal_context_init_backend_apis(pContext); mal_result result = mal_context_init_backend_apis(pContext);
...@@ -7576,14 +7584,13 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi ...@@ -7576,14 +7584,13 @@ mal_result mal_device_init(mal_context* pContext, mal_device_type type, mal_devi
// Set the user data and log callback ASAP to ensure it is available for the entire initialization process. // Set the user data and log callback ASAP to ensure it is available for the entire initialization process.
pDevice->pUserData = pUserData; pDevice->pUserData = pUserData;
pDevice->onLog = pConfig->onLogCallback;
pDevice->onStop = pConfig->onStopCallback; pDevice->onStop = pConfig->onStopCallback;
pDevice->onSend = pConfig->onSendCallback; pDevice->onSend = pConfig->onSendCallback;
pDevice->onRecv = pConfig->onRecvCallback; pDevice->onRecv = pConfig->onRecvCallback;
if (((mal_uint64)pDevice % sizeof(pDevice)) != 0) { if (((mal_uint64)pDevice % sizeof(pDevice)) != 0) {
if (pDevice->onLog) { if (pContext->onLog) {
pDevice->onLog(pDevice, "WARNING: mal_device_init() called for a device that is not properly aligned. Thread safety is not supported."); pContext->onLog(pContext, pDevice, "WARNING: mal_device_init() called for a device that is not properly aligned. Thread safety is not supported.");
} }
} }
...@@ -9176,6 +9183,9 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count) ...@@ -9176,6 +9183,9 @@ void mal_pcm_f32_to_s32(int* pOut, const float* pIn, unsigned int count)
// ================ // ================
// //
// v0.4 - TBD // v0.4 - TBD
// - API CHANGE: The log callback is now per-context rather than per-device and as is thus now passed to
// mal_context_init(). The rationale for this change is that it allows applications to capture diagnostic
// messages at the context level. Previously this was only available at the device level.
// - Added support for OSS which enables support on BSD platforms. // - Added support for OSS which enables support on BSD platforms.
// - Added support for WinMM (waveOut/waveIn). // - Added support for WinMM (waveOut/waveIn).
// - Added support for UWP (Universal Windows Platform) applications. Currently C++ only. // - Added support for UWP (Universal Windows Platform) applications. Currently C++ only.
......
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