while (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
while (ma_device_get_state(pDevice) == ma_device_state_started) {
ma_result result;
ma_result result;
/* The first thing to do is wait for space to become available for writing. This will return an error code if the device has been stopped. */
/* The first thing to do is wait for space to become available for writing. This will return an error code if the device has been stopped. */
...
@@ -24693,7 +24696,7 @@ that point (it may still need to load files or whatnot). Instead, this callback
...
@@ -24693,7 +24696,7 @@ that point (it may still need to load files or whatnot). Instead, this callback
stream be started which is how it works with literally *every* other callback-based audio API. Since miniaudio forbids firing of the data
stream be started which is how it works with literally *every* other callback-based audio API. Since miniaudio forbids firing of the data
callback until the device has been started (as it should be with *all* callback based APIs), logic needs to be added to ensure miniaudio
callback until the device has been started (as it should be with *all* callback based APIs), logic needs to be added to ensure miniaudio
doesn't just blindly fire the application-defined data callback from within the PulseAudio callback before the stream has actually been
doesn't just blindly fire the application-defined data callback from within the PulseAudio callback before the stream has actually been
started. The device state is used for this - if the state is anything other than `MA_STATE_STARTING` or `MA_STATE_STARTED`, the main data
started. The device state is used for this - if the state is anything other than `ma_device_state_starting` or `ma_device_state_started`, the main data
callback is not fired.
callback is not fired.
This, unfortunately, is not the end of the problems with the PulseAudio write callback. Any normal callback based audio API will
This, unfortunately, is not the end of the problems with the PulseAudio write callback. Any normal callback based audio API will
if (deviceState == MA_STATE_STARTED || deviceState == MA_STATE_STARTING) { /* Check for starting state just in case this is being used to do the initial fill. */
if (deviceState == ma_device_state_started || deviceState == ma_device_state_starting) { /* Check for starting state just in case this is being used to do the initial fill. */
if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
if (ma_device_get_state(pDevice) == ma_device_state_uninitialized) {
return MA_INVALID_OPERATION; /* Not initialized. */
return MA_INVALID_OPERATION; /* Not initialized. */
}
}
if (ma_device_get_state(pDevice) == MA_STATE_STARTED) {
if (ma_device_get_state(pDevice) == ma_device_state_started) {
return MA_INVALID_OPERATION; /* Already started. Returning an error to let the application know because it probably means they're doing something wrong. */
return MA_INVALID_OPERATION; /* Already started. Returning an error to let the application know because it probably means they're doing something wrong. */
}
}
ma_mutex_lock(&pDevice->startStopLock);
ma_mutex_lock(&pDevice->startStopLock);
{
{
/* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
/* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a stopped or paused state. */
if (ma_device_get_state(pDevice) == MA_STATE_UNINITIALIZED) {
if (ma_device_get_state(pDevice) == ma_device_state_uninitialized) {
return MA_INVALID_OPERATION; /* Not initialized. */
return MA_INVALID_OPERATION; /* Not initialized. */
}
}
if (ma_device_get_state(pDevice) == MA_STATE_STOPPED) {
if (ma_device_get_state(pDevice) == ma_device_state_stopped) {
return MA_INVALID_OPERATION; /* Already stopped. Returning an error to let the application know because it probably means they're doing something wrong. */
return MA_INVALID_OPERATION; /* Already stopped. Returning an error to let the application know because it probably means they're doing something wrong. */
}
}
ma_mutex_lock(&pDevice->startStopLock);
ma_mutex_lock(&pDevice->startStopLock);
{
{
/* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a started or paused state. */
/* Starting and stopping are wrapped in a mutex which means we can assert that the device is in a started or paused state. */