aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Alc/ALc.c20
-rw-r--r--Alc/backends/alsa.c49
-rw-r--r--Alc/backends/dsound.c53
-rw-r--r--Alc/backends/loopback.c7
-rw-r--r--Alc/backends/mmdevapi.c84
-rw-r--r--Alc/backends/null.c9
-rw-r--r--Alc/backends/opensl.c40
-rw-r--r--Alc/backends/oss.c14
-rw-r--r--Alc/backends/portaudio.c10
-rw-r--r--Alc/backends/pulseaudio.c41
-rw-r--r--Alc/backends/sndio.c10
-rw-r--r--Alc/backends/solaris.c14
-rw-r--r--Alc/backends/wave.c15
-rw-r--r--Alc/backends/winmm.c22
-rw-r--r--OpenAL32/Include/alMain.h2
15 files changed, 273 insertions, 117 deletions
diff --git a/Alc/ALc.c b/Alc/ALc.c
index 024350ae..9ac841b3 100644
--- a/Alc/ALc.c
+++ b/Alc/ALc.c
@@ -40,7 +40,7 @@
#include "alu.h"
-#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
+#define EmptyFuncs { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
static struct BackendInfo BackendList[] = {
#ifdef HAVE_PULSEAUDIO
{ "pulse", alc_pulse_init, alc_pulse_deinit, alc_pulse_probe, EmptyFuncs },
@@ -1197,8 +1197,6 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if((device->Flags&DEVICE_RUNNING))
return ALC_NO_ERROR;
- LockDevice(device);
-
oldFreq = device->Frequency;
oldChans = device->FmtChans;
oldType = device->FmtType;
@@ -1211,12 +1209,9 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
device->Frequency,
(device->Flags&DEVICE_FREQUENCY_REQUEST)?" (requested)":"",
device->UpdateSize, device->NumUpdates);
+
if(ALCdevice_ResetPlayback(device) == ALC_FALSE)
- {
- UnlockDevice(device);
return ALC_INVALID_DEVICE;
- }
- device->Flags |= DEVICE_RUNNING;
if(device->FmtChans != oldChans && (device->Flags&DEVICE_CHANNELS_REQUEST))
{
@@ -1290,6 +1285,7 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
TRACE("Stereo duplication %s\n", (device->Flags&DEVICE_DUPLICATE_STEREO)?"enabled":"disabled");
oldMode = SetMixerFPUMode();
+ LockDevice(device);
context = device->ContextList;
while(context)
{
@@ -1304,10 +1300,8 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
if(ALeffectState_DeviceUpdate(slot->EffectState, device) == AL_FALSE)
{
UnlockUIntMapRead(&context->EffectSlotMap);
- RestoreFPUMode(oldMode);
UnlockDevice(device);
- ALCdevice_StopPlayback(device);
- device->Flags &= ~DEVICE_RUNNING;
+ RestoreFPUMode(oldMode);
return ALC_INVALID_DEVICE;
}
slot->NeedsUpdate = AL_FALSE;
@@ -1336,8 +1330,12 @@ static ALCenum UpdateDeviceParams(ALCdevice *device, const ALCint *attrList)
context = context->next;
}
- RestoreFPUMode(oldMode);
UnlockDevice(device);
+ RestoreFPUMode(oldMode);
+
+ if(ALCdevice_StartPlayback(device) == ALC_FALSE)
+ return ALC_INVALID_DEVICE;
+ device->Flags |= DEVICE_RUNNING;
return ALC_NO_ERROR;
}
diff --git a/Alc/backends/alsa.c b/Alc/backends/alsa.c
index a9f34491..fa5ef1a6 100644
--- a/Alc/backends/alsa.c
+++ b/Alc/backends/alsa.c
@@ -44,6 +44,7 @@ MAKE_FUNC(snd_pcm_bytes_to_frames);
MAKE_FUNC(snd_pcm_hw_params_malloc);
MAKE_FUNC(snd_pcm_hw_params_free);
MAKE_FUNC(snd_pcm_hw_params_any);
+MAKE_FUNC(snd_pcm_hw_params_current);
MAKE_FUNC(snd_pcm_hw_params_set_access);
MAKE_FUNC(snd_pcm_hw_params_set_format);
MAKE_FUNC(snd_pcm_hw_params_set_channels);
@@ -111,6 +112,7 @@ MAKE_FUNC(snd_card_next);
#define snd_pcm_hw_params_malloc psnd_pcm_hw_params_malloc
#define snd_pcm_hw_params_free psnd_pcm_hw_params_free
#define snd_pcm_hw_params_any psnd_pcm_hw_params_any
+#define snd_pcm_hw_params_current psnd_pcm_hw_params_current
#define snd_pcm_hw_params_set_access psnd_pcm_hw_params_set_access
#define snd_pcm_hw_params_set_format psnd_pcm_hw_params_set_format
#define snd_pcm_hw_params_set_channels psnd_pcm_hw_params_set_channels
@@ -196,6 +198,7 @@ static ALCboolean alsa_load(void)
LOAD_FUNC(snd_pcm_hw_params_malloc);
LOAD_FUNC(snd_pcm_hw_params_free);
LOAD_FUNC(snd_pcm_hw_params_any);
+ LOAD_FUNC(snd_pcm_hw_params_current);
LOAD_FUNC(snd_pcm_hw_params_set_access);
LOAD_FUNC(snd_pcm_hw_params_set_format);
LOAD_FUNC(snd_pcm_hw_params_set_channels);
@@ -647,7 +650,6 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
int allowmmap;
int err;
-
format = -1;
switch(device->FmtType)
{
@@ -770,23 +772,52 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
snd_pcm_sw_params_free(sp);
sp = NULL;
+ /* Increase periods by one, since the temp buffer counts as an extra
+ * period */
+ if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
+ device->NumUpdates = periods+1;
+ else
+ device->NumUpdates = periods;
+ device->UpdateSize = periodSizeInFrames;
device->Frequency = rate;
+
SetDefaultChannelOrder(device);
- data->size = snd_pcm_frames_to_bytes(data->pcmHandle, periodSizeInFrames);
+ return ALC_TRUE;
+
+error:
+ ERR("%s failed: %s\n", funcerr, snd_strerror(err));
+ if(hp) snd_pcm_hw_params_free(hp);
+ if(sp) snd_pcm_sw_params_free(sp);
+ return ALC_FALSE;
+}
+
+static ALCboolean alsa_start_playback(ALCdevice *device)
+{
+ alsa_data *data = (alsa_data*)device->ExtraData;
+ snd_pcm_hw_params_t *hp = NULL;
+ snd_pcm_access_t access;
+ const char *funcerr;
+ int err;
+
+ snd_pcm_hw_params_malloc(&hp);
+#define CHECK(x) if((funcerr=#x),(err=(x)) < 0) goto error
+ CHECK(snd_pcm_hw_params_current(data->pcmHandle, hp));
+ /* retrieve configuration info */
+ CHECK(snd_pcm_hw_params_get_access(hp, &access));
+#undef CHECK
+ snd_pcm_hw_params_free(hp);
+ hp = NULL;
+
+ data->size = snd_pcm_frames_to_bytes(data->pcmHandle, device->UpdateSize);
if(access == SND_PCM_ACCESS_RW_INTERLEAVED)
{
- /* Increase periods by one, since the temp buffer counts as an extra
- * period */
- periods++;
data->buffer = malloc(data->size);
if(!data->buffer)
{
ERR("buffer malloc failed\n");
return ALC_FALSE;
}
- device->UpdateSize = periodSizeInFrames;
- device->NumUpdates = periods;
data->thread = StartThread(ALSANoMMapProc, device);
}
else
@@ -797,8 +828,6 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
ERR("snd_pcm_prepare(data->pcmHandle) failed: %s\n", snd_strerror(err));
return ALC_FALSE;
}
- device->UpdateSize = periodSizeInFrames;
- device->NumUpdates = periods;
data->thread = StartThread(ALSAProc, device);
}
if(data->thread == NULL)
@@ -814,7 +843,6 @@ static ALCboolean alsa_reset_playback(ALCdevice *device)
error:
ERR("%s failed: %s\n", funcerr, snd_strerror(err));
if(hp) snd_pcm_hw_params_free(hp);
- if(sp) snd_pcm_sw_params_free(sp);
return ALC_FALSE;
}
@@ -1186,6 +1214,7 @@ static const BackendFuncs alsa_funcs = {
alsa_open_playback,
alsa_close_playback,
alsa_reset_playback,
+ alsa_start_playback,
alsa_stop_playback,
alsa_open_capture,
alsa_close_capture,
diff --git a/Alc/backends/dsound.c b/Alc/backends/dsound.c
index feca3cfa..0eab62a4 100644
--- a/Alc/backends/dsound.c
+++ b/Alc/backends/dsound.c
@@ -392,6 +392,16 @@ static void DSoundClosePlayback(ALCdevice *device)
{
DSoundPlaybackData *pData = device->ExtraData;
+ if(pData->DSnotify)
+ IDirectSoundNotify_Release(pData->DSnotify);
+ pData->DSnotify = NULL;
+ if(pData->DSsbuffer)
+ IDirectSoundBuffer_Release(pData->DSsbuffer);
+ pData->DSsbuffer = NULL;
+ if(pData->DSpbuffer != NULL)
+ IDirectSoundBuffer_Release(pData->DSpbuffer);
+ pData->DSpbuffer = NULL;
+
IDirectSound_Release(pData->lpDS);
CloseHandle(pData->hNotifyEvent);
free(pData);
@@ -408,6 +418,16 @@ static ALCboolean DSoundResetPlayback(ALCdevice *device)
memset(&OutputType, 0, sizeof(OutputType));
+ if(pData->DSnotify)
+ IDirectSoundNotify_Release(pData->DSnotify);
+ pData->DSnotify = NULL;
+ if(pData->DSsbuffer)
+ IDirectSoundBuffer_Release(pData->DSsbuffer);
+ pData->DSsbuffer = NULL;
+ if(pData->DSpbuffer != NULL)
+ IDirectSoundBuffer_Release(pData->DSpbuffer);
+ pData->DSpbuffer = NULL;
+
switch(device->FmtType)
{
case DevFmtByte:
@@ -578,15 +598,6 @@ retry_open:
}
}
- if(SUCCEEDED(hr))
- {
- ResetEvent(pData->hNotifyEvent);
- SetDefaultWFXChannelOrder(device);
- pData->thread = StartThread(DSoundPlaybackProc, device);
- if(pData->thread == NULL)
- hr = E_FAIL;
- }
-
if(FAILED(hr))
{
if(pData->DSnotify != NULL)
@@ -601,6 +612,20 @@ retry_open:
return ALC_FALSE;
}
+ ResetEvent(pData->hNotifyEvent);
+ SetDefaultWFXChannelOrder(device);
+
+ return ALC_TRUE;
+}
+
+static ALCboolean DSoundStartPlayback(ALCdevice *device)
+{
+ DSoundPlaybackData *pData = (DSoundPlaybackData*)device->ExtraData;
+
+ pData->thread = StartThread(DSoundPlaybackProc, device);
+ if(pData->thread == NULL)
+ return ALC_FALSE;
+
return ALC_TRUE;
}
@@ -616,14 +641,7 @@ static void DSoundStopPlayback(ALCdevice *device)
pData->thread = NULL;
pData->killNow = 0;
-
- IDirectSoundNotify_Release(pData->DSnotify);
- pData->DSnotify = NULL;
- IDirectSoundBuffer_Release(pData->DSsbuffer);
- pData->DSsbuffer = NULL;
- if(pData->DSpbuffer != NULL)
- IDirectSoundBuffer_Release(pData->DSpbuffer);
- pData->DSpbuffer = NULL;
+ IDirectSoundBuffer_Stop(pData->DSsbuffer);
}
@@ -918,6 +936,7 @@ static const BackendFuncs DSoundFuncs = {
DSoundOpenPlayback,
DSoundClosePlayback,
DSoundResetPlayback,
+ DSoundStartPlayback,
DSoundStopPlayback,
DSoundOpenCapture,
DSoundCloseCapture,
diff --git a/Alc/backends/loopback.c b/Alc/backends/loopback.c
index 8a576361..3726974c 100644
--- a/Alc/backends/loopback.c
+++ b/Alc/backends/loopback.c
@@ -43,6 +43,12 @@ static ALCboolean loopback_reset_playback(ALCdevice *device)
return ALC_TRUE;
}
+static ALCboolean loopback_start_playback(ALCdevice *device)
+{
+ return ALC_TRUE;
+ (void)device;
+}
+
static void loopback_stop_playback(ALCdevice *device)
{
(void)device;
@@ -52,6 +58,7 @@ static const BackendFuncs loopback_funcs = {
loopback_open_playback,
loopback_close_playback,
loopback_reset_playback,
+ loopback_start_playback,
loopback_stop_playback,
NULL,
NULL,
diff --git a/Alc/backends/mmdevapi.c b/Alc/backends/mmdevapi.c
index 52b54eb4..ccfb1a44 100644
--- a/Alc/backends/mmdevapi.c
+++ b/Alc/backends/mmdevapi.c
@@ -90,9 +90,10 @@ typedef struct {
#define WM_USER_OpenDevice (WM_USER+0)
#define WM_USER_ResetDevice (WM_USER+1)
-#define WM_USER_StopDevice (WM_USER+2)
-#define WM_USER_CloseDevice (WM_USER+3)
-#define WM_USER_Enumerate (WM_USER+4)
+#define WM_USER_StartDevice (WM_USER+2)
+#define WM_USER_StopDevice (WM_USER+3)
+#define WM_USER_CloseDevice (WM_USER+4)
+#define WM_USER_Enumerate (WM_USER+5)
static HRESULT WaitForResponse(ThreadRequest *req)
{
@@ -315,7 +316,6 @@ static HRESULT DoReset(ALCdevice *device)
REFERENCE_TIME min_per, buf_time;
UINT32 buffer_len, min_len;
HRESULT hr;
- void *ptr;
hr = IAudioClient_GetMixFormat(data->client, &wfx);
if(FAILED(hr))
@@ -532,32 +532,6 @@ static HRESULT DoReset(ALCdevice *device)
ERR("Audio client returned buffer_len < period*2; expect break up\n");
}
- ResetEvent(data->hNotifyEvent);
- hr = IAudioClient_SetEventHandle(data->client, data->hNotifyEvent);
- if(SUCCEEDED(hr))
- hr = IAudioClient_Start(data->client);
- if(FAILED(hr))
- {
- ERR("Failed to start audio client: 0x%08lx\n", hr);
- return hr;
- }
-
- hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr);
- if(SUCCEEDED(hr))
- {
- data->render = ptr;
- data->thread = StartThread(MMDevApiProc, device);
- }
- if(!data->thread)
- {
- if(data->render)
- IAudioRenderClient_Release(data->render);
- data->render = NULL;
- IAudioClient_Stop(data->client);
- ERR("Failed to start thread\n");
- return E_FAIL;
- }
-
return hr;
}
@@ -656,6 +630,43 @@ static DWORD CALLBACK MMDevApiMsgProc(void *ptr)
SetEvent(req->FinishedEvt);
continue;
+ case WM_USER_StartDevice:
+ req = (ThreadRequest*)msg.wParam;
+ device = (ALCdevice*)msg.lParam;
+ data = device->ExtraData;
+
+ ResetEvent(data->hNotifyEvent);
+ hr = IAudioClient_SetEventHandle(data->client, data->hNotifyEvent);
+ if(FAILED(hr))
+ ERR("Failed to set event handle: 0x%08lx\n", hr);
+ else
+ {
+ hr = IAudioClient_Start(data->client);
+ if(FAILED(hr))
+ ERR("Failed to start audio client: 0x%08lx\n", hr);
+ }
+
+ if(SUCCEEDED(hr))
+ hr = IAudioClient_GetService(data->client, &IID_IAudioRenderClient, &ptr);
+ if(SUCCEEDED(hr))
+ {
+ data->render = ptr;
+ data->thread = StartThread(MMDevApiProc, device);
+ if(!data->thread)
+ {
+ if(data->render)
+ IAudioRenderClient_Release(data->render);
+ data->render = NULL;
+ IAudioClient_Stop(data->client);
+ ERR("Failed to start thread\n");
+ hr = E_FAIL;
+ }
+ }
+
+ req->result = hr;
+ SetEvent(req->FinishedEvt);
+ continue;
+
case WM_USER_StopDevice:
req = (ThreadRequest*)msg.wParam;
device = (ALCdevice*)msg.lParam;
@@ -885,6 +896,18 @@ static ALCboolean MMDevApiResetPlayback(ALCdevice *device)
return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
}
+static ALCboolean MMDevApiStartPlayback(ALCdevice *device)
+{
+ MMDevApiData *data = device->ExtraData;
+ ThreadRequest req = { data->MsgEvent, 0 };
+ HRESULT hr = E_FAIL;
+
+ if(PostThreadMessage(ThreadID, WM_USER_StartDevice, (WPARAM)&req, (LPARAM)device))
+ hr = WaitForResponse(&req);
+
+ return SUCCEEDED(hr) ? ALC_TRUE : ALC_FALSE;
+}
+
static void MMDevApiStopPlayback(ALCdevice *device)
{
MMDevApiData *data = device->ExtraData;
@@ -899,6 +922,7 @@ static const BackendFuncs MMDevApiFuncs = {
MMDevApiOpenPlayback,
MMDevApiClosePlayback,
MMDevApiResetPlayback,
+ MMDevApiStartPlayback,
MMDevApiStopPlayback,
NULL,
NULL,
diff --git a/Alc/backends/null.c b/Alc/backends/null.c
index 10068630..8fc60b66 100644
--- a/Alc/backends/null.c
+++ b/Alc/backends/null.c
@@ -99,9 +99,13 @@ static void null_close_playback(ALCdevice *device)
static ALCboolean null_reset_playback(ALCdevice *device)
{
- null_data *data = (null_data*)device->ExtraData;
-
SetDefaultWFXChannelOrder(device);
+ return ALC_TRUE;
+}
+
+static ALCboolean null_start_playback(ALCdevice *device)
+{
+ null_data *data = (null_data*)device->ExtraData;
data->thread = StartThread(NullProc, device);
if(data->thread == NULL)
@@ -129,6 +133,7 @@ static const BackendFuncs null_funcs = {
null_open_playback,
null_close_playback,
null_reset_playback,
+ null_start_playback,
null_stop_playback,
NULL,
NULL,
diff --git a/Alc/backends/opensl.c b/Alc/backends/opensl.c
index 58acc828..5ff60276 100644
--- a/Alc/backends/opensl.c
+++ b/Alc/backends/opensl.c
@@ -242,6 +242,10 @@ static void opensl_close_playback(ALCdevice *Device)
{
osl_data *data = Device->ExtraData;
+ if(data->bufferQueueObject != NULL)
+ SLObjectItf_Destroy(data->bufferQueueObject);
+ data->bufferQueueObject = NULL;
+
SLObjectItf_Destroy(data->outputMix);
data->outputMix = NULL;
@@ -257,16 +261,13 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device)
{
osl_data *data = Device->ExtraData;
SLDataLocator_AndroidSimpleBufferQueue loc_bufq;
- SLAndroidSimpleBufferQueueItf bufferQueue;
SLDataLocator_OutputMix loc_outmix;
SLDataFormat_PCM format_pcm;
SLDataSource audioSrc;
SLDataSink audioSnk;
- SLPlayItf player;
SLInterfaceID id;
SLboolean req;
SLresult result;
- ALuint i;
Device->UpdateSize = (ALuint64)Device->UpdateSize * 44100 / Device->Frequency;
@@ -303,6 +304,10 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device)
audioSnk.pFormat = NULL;
+ if(data->bufferQueueObject != NULL)
+ SLObjectItf_Destroy(data->bufferQueueObject);
+ data->bufferQueueObject = NULL;
+
result = SLEngineItf_CreateAudioPlayer(data->engine, &data->bufferQueueObject, &audioSrc, &audioSnk, 1, &id, &req);
PRINTERR(result, "engine->CreateAudioPlayer");
if(SL_RESULT_SUCCESS == result)
@@ -310,11 +315,29 @@ static ALCboolean opensl_reset_playback(ALCdevice *Device)
result = SLObjectItf_Realize(data->bufferQueueObject, SL_BOOLEAN_FALSE);
PRINTERR(result, "bufferQueue->Realize");
}
- if(SL_RESULT_SUCCESS == result)
+
+ if(SL_RESULT_SUCCESS != result)
{
- result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue);
- PRINTERR(result, "bufferQueue->GetInterface");
+ if(data->bufferQueueObject != NULL)
+ SLObjectItf_Destroy(data->bufferQueueObject);
+ data->bufferQueueObject = NULL;
+
+ return ALC_FALSE;
}
+
+ return ALC_TRUE;
+}
+
+static ALCboolean opensl_start_playback(ALCdevice *Device)
+{
+ osl_data *data = Device->ExtraData;
+ SLAndroidSimpleBufferQueueItf bufferQueue;
+ SLPlayItf player;
+ SLresult result;
+ ALuint i;
+
+ result = SLObjectItf_GetInterface(data->bufferQueueObject, SL_IID_BUFFERQUEUE, &bufferQueue);
+ PRINTERR(result, "bufferQueue->GetInterface");
if(SL_RESULT_SUCCESS == result)
{
result = (*bufferQueue)->RegisterCallback(bufferQueue, opensl_callback, Device);
@@ -372,10 +395,6 @@ static void opensl_stop_playback(ALCdevice *Device)
{
osl_data *data = Device->ExtraData;
- if(data->bufferQueueObject != NULL)
- SLObjectItf_Destroy(data->bufferQueueObject);
- data->bufferQueueObject = NULL;
-
free(data->buffer);
data->buffer = NULL;
data->bufferSize = 0;
@@ -386,6 +405,7 @@ static const BackendFuncs opensl_funcs = {
opensl_open_playback,
opensl_close_playback,
opensl_reset_playback,
+ opensl_start_playback,
opensl_stop_playback,
NULL,
NULL,
diff --git a/Alc/backends/oss.c b/Alc/backends/oss.c
index bd489e3e..a577d8be 100644
--- a/Alc/backends/oss.c
+++ b/Alc/backends/oss.c
@@ -268,11 +268,18 @@ static ALCboolean oss_reset_playback(ALCdevice *device)
device->UpdateSize = info.fragsize / frameSize;
device->NumUpdates = info.fragments + 1;
- data->data_size = device->UpdateSize * frameSize;
- data->mix_data = calloc(1, data->data_size);
-
SetDefaultChannelOrder(device);
+ return ALC_TRUE;
+}
+
+static ALCboolean oss_start_playback(ALCdevice *device)
+{
+ oss_data *data = (oss_data*)device->ExtraData;
+
+ data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ data->mix_data = calloc(1, data->data_size);
+
data->thread = StartThread(OSSProc, device);
if(data->thread == NULL)
{
@@ -473,6 +480,7 @@ static const BackendFuncs oss_funcs = {
oss_open_playback,
oss_close_playback,
oss_reset_playback,
+ oss_start_playback,
oss_stop_playback,
oss_open_capture,
oss_close_capture,
diff --git a/Alc/backends/portaudio.c b/Alc/backends/portaudio.c
index 154b6349..03e54d14 100644
--- a/Alc/backends/portaudio.c
+++ b/Alc/backends/portaudio.c
@@ -261,12 +261,19 @@ static ALCboolean pa_reset_playback(ALCdevice *device)
{
pa_data *data = (pa_data*)device->ExtraData;
const PaStreamInfo *streamInfo;
- PaError err;
streamInfo = Pa_GetStreamInfo(data->stream);
device->Frequency = streamInfo->sampleRate;
device->UpdateSize = data->update_size;
+ return ALC_TRUE;
+}
+
+static ALCboolean pa_start_playback(ALCdevice *device)
+{
+ pa_data *data = (pa_data*)device->ExtraData;
+ PaError err;
+
err = Pa_StartStream(data->stream);
if(err != paNoError)
{
@@ -409,6 +416,7 @@ static const BackendFuncs pa_funcs = {
pa_open_playback,
pa_close_playback,
pa_reset_playback,
+ pa_start_playback,
pa_stop_playback,
pa_open_capture,
pa_close_capture,
diff --git a/Alc/backends/pulseaudio.c b/Alc/backends/pulseaudio.c
index 8fe1118b..78854da7 100644
--- a/Alc/backends/pulseaudio.c
+++ b/Alc/backends/pulseaudio.c
@@ -873,6 +873,10 @@ static void pulse_close(ALCdevice *device)
if(data->stream)
{
+#if PA_CHECK_VERSION(0,9,15)
+ if(pa_stream_set_buffer_attr_callback)
+ pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
+#endif
pa_stream_disconnect(data->stream);
pa_stream_unref(data->stream);
}
@@ -968,6 +972,10 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
if(data->stream)
{
+#if PA_CHECK_VERSION(0,9,15)
+ if(pa_stream_set_buffer_attr_callback)
+ pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
+#endif
pa_stream_disconnect(data->stream);
pa_stream_unref(data->stream);
data->stream = NULL;
@@ -1079,28 +1087,25 @@ static ALCboolean pulse_reset_playback(ALCdevice *device)
device->NumUpdates = maxu(device->NumUpdates, 2);
device->UpdateSize = data->attr.minreq / pa_frame_size(&data->spec);
+ pa_threaded_mainloop_unlock(data->loop);
+ return ALC_TRUE;
+}
+
+static ALCboolean pulse_start_playback(ALCdevice *device)
+{
+ pulse_data *data = device->ExtraData;
+
data->thread = StartThread(PulseProc, device);
if(!data->thread)
- {
-#if PA_CHECK_VERSION(0,9,15)
- if(pa_stream_set_buffer_attr_callback)
- pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
-#endif
- pa_stream_disconnect(data->stream);
- pa_stream_unref(data->stream);
- data->stream = NULL;
-
- pa_threaded_mainloop_unlock(data->loop);
return ALC_FALSE;
- }
- pa_threaded_mainloop_unlock(data->loop);
return ALC_TRUE;
}
static void pulse_stop_playback(ALCdevice *device)
{
pulse_data *data = device->ExtraData;
+ pa_operation *o;
if(!data->stream)
return;
@@ -1115,13 +1120,10 @@ static void pulse_stop_playback(ALCdevice *device)
pa_threaded_mainloop_lock(data->loop);
-#if PA_CHECK_VERSION(0,9,15)
- if(pa_stream_set_buffer_attr_callback)
- pa_stream_set_buffer_attr_callback(data->stream, NULL, NULL);
-#endif
- pa_stream_disconnect(data->stream);
- pa_stream_unref(data->stream);
- data->stream = NULL;
+ o = pa_stream_cork(data->stream, 1, stream_success_callback, device);
+ while(pa_operation_get_state(o) == PA_OPERATION_RUNNING)
+ pa_threaded_mainloop_wait(data->loop);
+ pa_operation_unref(o);
pa_threaded_mainloop_unlock(data->loop);
}
@@ -1352,6 +1354,7 @@ static const BackendFuncs pulse_funcs = {
pulse_open_playback,
pulse_close_playback,
pulse_reset_playback,
+ pulse_start_playback,
pulse_stop_playback,
pulse_open_capture,
pulse_close_capture,
diff --git a/Alc/backends/sndio.c b/Alc/backends/sndio.c
index 6be98c2f..fc368951 100644
--- a/Alc/backends/sndio.c
+++ b/Alc/backends/sndio.c
@@ -280,13 +280,20 @@ static ALCboolean sndio_reset_playback(ALCdevice *device)
SetDefaultChannelOrder(device);
+ return ALC_TRUE;
+}
+
+static ALCboolean sndio_start_playback(ALCdevice *device)
+{
+ sndio_data *data = device->ExtraData;
+
if(!sio_start(data->sndHandle))
{
ERR("Error starting playback\n");
return ALC_FALSE;
}
- data->data_size = device->UpdateSize * par.bps * par.pchan;
+ data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
data->mix_data = calloc(1, data->data_size);
data->thread = StartThread(sndio_proc, device);
@@ -325,6 +332,7 @@ static const BackendFuncs sndio_funcs = {
sndio_open_playback,
sndio_close_playback,
sndio_reset_playback,
+ sndio_start_playback,
sndio_stop_playback,
NULL,
NULL,
diff --git a/Alc/backends/solaris.c b/Alc/backends/solaris.c
index bf0f57f5..26d923c7 100644
--- a/Alc/backends/solaris.c
+++ b/Alc/backends/solaris.c
@@ -193,11 +193,18 @@ static ALCboolean solaris_reset_playback(ALCdevice *device)
device->Frequency = info.play.sample_rate;
device->UpdateSize = (info.play.buffer_size/device->NumUpdates) + 1;
- data->data_size = device->UpdateSize * frameSize;
- data->mix_data = calloc(1, data->data_size);
-
SetDefaultChannelOrder(device);
+ return ALC_TRUE;
+}
+
+static ALCboolean solaris_start_playback(ALCdevice *device)
+{
+ solaris_data *data = (solaris_data*)device->ExtraData;
+
+ data->data_size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
+ data->mix_data = calloc(1, data->data_size);
+
data->thread = StartThread(SolarisProc, device);
if(data->thread == NULL)
{
@@ -233,6 +240,7 @@ static const BackendFuncs solaris_funcs = {
solaris_open_playback,
solaris_close_playback,
solaris_reset_playback,
+ solaris_start_playback,
solaris_stop_playback,
NULL,
NULL,
diff --git a/Alc/backends/wave.c b/Alc/backends/wave.c
index ad187896..d9f1fdc7 100644
--- a/Alc/backends/wave.c
+++ b/Alc/backends/wave.c
@@ -258,10 +258,18 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
ERR("Error writing header: %s\n", strerror(errno));
return ALC_FALSE;
}
-
data->DataStart = ftell(data->f);
- data->size = device->UpdateSize * channels * bits / 8;
+ SetDefaultWFXChannelOrder(device);
+
+ return ALC_TRUE;
+}
+
+static ALCboolean wave_start_playback(ALCdevice *device)
+{
+ wave_data *data = (wave_data*)device->ExtraData;
+
+ data->size = device->UpdateSize * FrameSizeFromDevFmt(device->FmtChans, device->FmtType);
data->buffer = malloc(data->size);
if(!data->buffer)
{
@@ -269,8 +277,6 @@ static ALCboolean wave_reset_playback(ALCdevice *device)
return ALC_FALSE;
}
- SetDefaultWFXChannelOrder(device);
-
data->thread = StartThread(WaveProc, device);
if(data->thread == NULL)
{
@@ -316,6 +322,7 @@ static const BackendFuncs wave_funcs = {
wave_open_playback,
wave_close_playback,
wave_reset_playback,
+ wave_start_playback,
wave_stop_playback,
NULL,
NULL,
diff --git a/Alc/backends/winmm.c b/Alc/backends/winmm.c
index 9f2c6316..57d27974 100644
--- a/Alc/backends/winmm.c
+++ b/Alc/backends/winmm.c
@@ -397,6 +397,21 @@ static void WinMMClosePlayback(ALCdevice *device)
static ALCboolean WinMMResetPlayback(ALCdevice *device)
{
WinMMData *pData = (WinMMData*)device->ExtraData;
+
+ device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
+ pData->Frequency / device->Frequency);
+ device->UpdateSize = device->UpdateSize*device->NumUpdates / 4;
+ device->NumUpdates = 4;
+ device->Frequency = pData->Frequency;
+
+ SetDefaultWFXChannelOrder(device);
+
+ return ALC_TRUE;
+}
+
+static ALCboolean WinMMStartPlayback(ALCdevice *device)
+{
+ WinMMData *pData = (WinMMData*)device->ExtraData;
ALbyte *BufferData;
ALint lBufferSize;
ALuint i;
@@ -405,12 +420,6 @@ static ALCboolean WinMMResetPlayback(ALCdevice *device)
if(pData->hWaveThread == NULL)
return ALC_FALSE;
- device->UpdateSize = (ALuint)((ALuint64)device->UpdateSize *
- pData->Frequency / device->Frequency);
- device->Frequency = pData->Frequency;
-
- SetDefaultWFXChannelOrder(device);
-
pData->lWaveBuffersCommitted = 0;
// Create 4 Buffers
@@ -689,6 +698,7 @@ static const BackendFuncs WinMMFuncs = {
WinMMOpenPlayback,
WinMMClosePlayback,
WinMMResetPlayback,
+ WinMMStartPlayback,
WinMMStopPlayback,
WinMMOpenCapture,
WinMMCloseCapture,
diff --git a/OpenAL32/Include/alMain.h b/OpenAL32/Include/alMain.h
index 2fbea8c3..20f6d656 100644
--- a/OpenAL32/Include/alMain.h
+++ b/OpenAL32/Include/alMain.h
@@ -449,6 +449,7 @@ typedef struct {
ALCenum (*OpenPlayback)(ALCdevice*, const ALCchar*);
void (*ClosePlayback)(ALCdevice*);
ALCboolean (*ResetPlayback)(ALCdevice*);
+ ALCboolean (*StartPlayback)(ALCdevice*);
void (*StopPlayback)(ALCdevice*);
ALCenum (*OpenCapture)(ALCdevice*, const ALCchar*);
@@ -630,6 +631,7 @@ struct ALCdevice_struct
#define ALCdevice_OpenPlayback(a,b) ((a)->Funcs->OpenPlayback((a), (b)))
#define ALCdevice_ClosePlayback(a) ((a)->Funcs->ClosePlayback((a)))
#define ALCdevice_ResetPlayback(a) ((a)->Funcs->ResetPlayback((a)))
+#define ALCdevice_StartPlayback(a) ((a)->Funcs->StartPlayback((a)))
#define ALCdevice_StopPlayback(a) ((a)->Funcs->StopPlayback((a)))
#define ALCdevice_OpenCapture(a,b) ((a)->Funcs->OpenCapture((a), (b)))
#define ALCdevice_CloseCapture(a) ((a)->Funcs->CloseCapture((a)))