static void stream_read_callback(pa_stream *stream, size_t length, void *pdata) //{{{ { ALCdevice *Device = pdata; pulse_data *data = Device->ExtraData; const void *buf; if(ppa_stream_peek(stream, &buf, &length) < 0) { AL_PRINT("pa_stream_peek() failed: %s\n", ppa_strerror(ppa_context_errno(data->context))); return; } assert(buf); assert(length); length /= data->frame_size; if(data->samples < length) AL_PRINT("stream_read_callback: buffer overflow!\n"); WriteRingBuffer(data->ring, buf, (length<data->samples) ? length : data->samples); ppa_stream_drop(stream); } //}}}
static ALCboolean DSoundOpenPlayback(ALCdevice *device, const ALCchar *deviceName) { DSoundData *pData = NULL; LPGUID guid = NULL; HRESULT hr; if(!DSoundLoad()) return ALC_FALSE; if(!deviceName) deviceName = dsDevice; else if(strcmp(deviceName, dsDevice) != 0) { ALuint i; if(!DeviceList) { hr = pDirectSoundEnumerateA(DSoundEnumDevices, NULL); if(FAILED(hr)) AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); } for(i = 0; i < NumDevices; i++) { if(strcmp(deviceName, DeviceList[i].name) == 0) { if(i > 0) guid = &DeviceList[i].guid; break; } } if(i == NumDevices) return ALC_FALSE; } //Initialise requested device pData = calloc(1, sizeof(DSoundData)); if(!pData) { alcSetError(device, ALC_OUT_OF_MEMORY); return ALC_FALSE; } //DirectSound Init code hr = pDirectSoundCreate(guid, &pData->lpDS, NULL); if(SUCCEEDED(hr)) hr = IDirectSound_SetCooperativeLevel(pData->lpDS, GetForegroundWindow(), DSSCL_PRIORITY); if(FAILED(hr)) { if(pData->lpDS) IDirectSound_Release(pData->lpDS); free(pData); AL_PRINT("Device init failed: 0x%08lx\n", hr); return ALC_FALSE; } device->szDeviceName = strdup(deviceName); device->ExtraData = pData; return ALC_TRUE; }
static pa_stream *connect_playback_stream(ALCdevice *device, pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap) { pulse_data *data = device->ExtraData; pa_stream_state_t state; pa_stream *stream; stream = pa_stream_new(data->context, "Playback Stream", spec, chanmap); if(!stream) { ERR("pa_stream_new() failed: %s\n", pa_strerror(pa_context_errno(data->context))); return NULL; } pa_stream_set_state_callback(stream, stream_state_callback, data->loop); AL_PRINT("Attempting flags 0x%x\n", flags); if (attr) { AL_PRINT("maxlength: %d tlegth: %d prebuf: %d minreq: %d fragsize: %d\n", attr->maxlength, attr->tlength, attr->prebuf, attr->minreq, attr->fragsize); } if(pa_stream_connect_playback(stream, data->device_name, attr, flags, NULL, NULL) < 0) { ERR("Stream did not connect: %s\n", pa_strerror(pa_context_errno(data->context))); pa_stream_unref(stream); return NULL; } while((state=pa_stream_get_state(stream)) != PA_STREAM_READY) { if(!PA_STREAM_IS_GOOD(state)) { ERR("Stream did not get ready: %s\n", pa_strerror(pa_context_errno(data->context))); pa_stream_unref(stream); return NULL; } pa_threaded_mainloop_wait(data->loop); } pa_stream_set_state_callback(stream, NULL, NULL); return stream; }
static pa_context* connect_context( pa_threaded_mainloop* loop ) { const char* name = "OpenAL Soft"; char path_name[PATH_MAX]; pa_context_state_t state; pa_context* context; int err; if ( ppa_get_binary_name( path_name, sizeof( path_name ) ) ) { name = ppa_path_get_filename( path_name ); } context = ppa_context_new( ppa_threaded_mainloop_get_api( loop ), name ); if ( !context ) { AL_PRINT( "pa_context_new() failed\n" ); return NULL; } ppa_context_set_state_callback( context, context_state_callback, loop ); if ( ( err = ppa_context_connect( context, NULL, pulse_ctx_flags, NULL ) ) >= 0 ) { while ( ( state = ppa_context_get_state( context ) ) != PA_CONTEXT_READY ) { if ( !PA_CONTEXT_IS_GOOD( state ) ) { err = ppa_context_errno( context ); break; } ppa_threaded_mainloop_wait( loop ); } } ppa_context_set_state_callback( context, NULL, NULL ); if ( err < 0 ) { AL_PRINT( "Context did not connect: %s\n", ppa_strerror( err ) ); ppa_context_unref( context ); return NULL; } return context; }
ALCvoid ReleaseALC(ALCvoid) { free(alcDeviceList); alcDeviceList = NULL; alcDeviceListSize = 0; free(alcAllDeviceList); alcAllDeviceList = NULL; alcAllDeviceListSize = 0; free(alcCaptureDeviceList); alcCaptureDeviceList = NULL; alcCaptureDeviceListSize = 0; free(alcDefaultDeviceSpecifier); alcDefaultDeviceSpecifier = NULL; free(alcDefaultAllDeviceSpecifier); alcDefaultAllDeviceSpecifier = NULL; free(alcCaptureDefaultDeviceSpecifier); alcCaptureDefaultDeviceSpecifier = NULL; #ifdef _DEBUG if(g_ulDeviceCount > 0) AL_PRINT("exit(): closing %u Device%s\n", g_ulDeviceCount, (g_ulDeviceCount>1)?"s":""); #endif while(g_pDeviceList) { if(g_pDeviceList->IsCaptureDevice) alcCaptureCloseDevice(g_pDeviceList); else alcCloseDevice(g_pDeviceList); } }
static ALenum GetFormatFromString(const char *str) { if(strcasecmp(str, "AL_FORMAT_MONO32") == 0) return AL_FORMAT_MONO_FLOAT32; if(strcasecmp(str, "AL_FORMAT_STEREO32") == 0) return AL_FORMAT_STEREO_FLOAT32; if(strcasecmp(str, "AL_FORMAT_QUAD32") == 0) return AL_FORMAT_QUAD32; if(strcasecmp(str, "AL_FORMAT_51CHN32") == 0) return AL_FORMAT_51CHN32; if(strcasecmp(str, "AL_FORMAT_61CHN32") == 0) return AL_FORMAT_61CHN32; if(strcasecmp(str, "AL_FORMAT_71CHN32") == 0) return AL_FORMAT_71CHN32; if(strcasecmp(str, "AL_FORMAT_MONO16") == 0) return AL_FORMAT_MONO16; if(strcasecmp(str, "AL_FORMAT_STEREO16") == 0) return AL_FORMAT_STEREO16; if(strcasecmp(str, "AL_FORMAT_QUAD16") == 0) return AL_FORMAT_QUAD16; if(strcasecmp(str, "AL_FORMAT_51CHN16") == 0) return AL_FORMAT_51CHN16; if(strcasecmp(str, "AL_FORMAT_61CHN16") == 0) return AL_FORMAT_61CHN16; if(strcasecmp(str, "AL_FORMAT_71CHN16") == 0) return AL_FORMAT_71CHN16; if(strcasecmp(str, "AL_FORMAT_MONO8") == 0) return AL_FORMAT_MONO8; if(strcasecmp(str, "AL_FORMAT_STEREO8") == 0) return AL_FORMAT_STEREO8; if(strcasecmp(str, "AL_FORMAT_QUAD8") == 0) return AL_FORMAT_QUAD8; if(strcasecmp(str, "AL_FORMAT_51CHN8") == 0) return AL_FORMAT_51CHN8; if(strcasecmp(str, "AL_FORMAT_61CHN8") == 0) return AL_FORMAT_61CHN8; if(strcasecmp(str, "AL_FORMAT_71CHN8") == 0) return AL_FORMAT_71CHN8; AL_PRINT("Unknown format: \"%s\"\n", str); return AL_FORMAT_STEREO16; }
static ALuint OSSCaptureProc(ALvoid *ptr) { ALCdevice *pDevice = (ALCdevice*)ptr; oss_data *data = (oss_data*)pDevice->ExtraData; int frameSize; int amt; frameSize = aluBytesFromFormat(pDevice->Format); frameSize *= aluChannelsFromFormat(pDevice->Format); while(!data->killNow) { amt = read(data->fd, data->mix_data, data->data_size); if(amt < 0) { AL_PRINT("read failed: %s\n", strerror(errno)); break; } if(amt == 0) { Sleep(1); continue; } if(data->doCapture) WriteRingBuffer(data->ring, data->mix_data, amt/frameSize); } return 0; }
static ALCuint pulse_available_samples( ALCdevice* device ) //{{{ { pulse_data* data = device->ExtraData; size_t samples; ppa_threaded_mainloop_lock( data->loop ); /* Capture is done in fragment-sized chunks, so we loop until we get all * that's available */ samples = ( device->Connected ? ppa_stream_readable_size( data->stream ) : 0 ); while ( samples > 0 ) { const void* buf; size_t length; if ( ppa_stream_peek( data->stream, &buf, &length ) < 0 ) { AL_PRINT( "pa_stream_peek() failed: %s\n", ppa_strerror( ppa_context_errno( data->context ) ) ); break; } WriteRingBuffer( data->ring, buf, length / data->frame_size ); samples -= length; ppa_stream_drop( data->stream ); } ppa_threaded_mainloop_unlock( data->loop ); return RingBufferSize( data->ring ); } //}}}
/* * ReleaseALBuffers() * * INTERNAL FN : Called by DLLMain on exit to destroy any buffers that still exist */ ALvoid ReleaseALBuffers(ALvoid) { ALbuffer *ALBuffer; ALbuffer *ALBufferTemp; #ifdef _DEBUG if(g_uiBufferCount > 0) AL_PRINT("exit(): deleting %d Buffer(s)\n", g_uiBufferCount); #endif ALBuffer = g_pBuffers; while(ALBuffer) { // Release sample data free(ALBuffer->data); // Release Buffer structure ALBufferTemp = ALBuffer; ALBuffer = ALBuffer->next; memset(ALBufferTemp, 0, sizeof(ALbuffer)); free(ALBufferTemp); } g_pBuffers = NULL; g_uiBufferCount = 0; }
static ALCboolean alsa_open_playback(ALCdevice *device, const ALCchar *deviceName) { alsa_data *data; char driver[64]; int i; if(!alsa_load()) return ALC_FALSE; strncpy(driver, GetConfigValue("alsa", "device", "default"), sizeof(driver)-1); driver[sizeof(driver)-1] = 0; if(!deviceName) deviceName = alsaDevice; else if(strcmp(deviceName, alsaDevice) != 0) { size_t idx; if(!allDevNameMap) allDevNameMap = probe_devices(SND_PCM_STREAM_PLAYBACK, &numDevNames); for(idx = 0;idx < numDevNames;idx++) { if(allDevNameMap[idx].name && strcmp(deviceName, allDevNameMap[idx].name) == 0) { if(idx > 0) sprintf(driver, "hw:%d,%d", allDevNameMap[idx].card, allDevNameMap[idx].dev); break; } } if(idx == numDevNames) return ALC_FALSE; } data = (alsa_data*)calloc(1, sizeof(alsa_data)); i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); if(i < 0) { Sleep(200); i = psnd_pcm_open(&data->pcmHandle, driver, SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); } if(i >= 0) { i = psnd_pcm_nonblock(data->pcmHandle, 0); if(i < 0) psnd_pcm_close(data->pcmHandle); } if(i < 0) { free(data); AL_PRINT("Could not open playback device '%s': %s\n", driver, psnd_strerror(i)); return ALC_FALSE; } device->szDeviceName = strdup(deviceName); device->ExtraData = data; return ALC_TRUE; }
static ALCboolean wave_open_playback(ALCdevice *device, const ALCchar *deviceName) { wave_data *data; const char *fname; fname = GetConfigValue("wave", "file", ""); if(!fname[0]) return ALC_FALSE; if(!deviceName) deviceName = waveDevice; else if(strcmp(deviceName, waveDevice) != 0) return ALC_FALSE; data = (wave_data*)alCalloc(1, sizeof(wave_data)); data->f = fopen(fname, "wb"); if(!data->f) { alFree(data); AL_PRINT("Could not open file '%s': %s\n", fname, strerror(errno)); return ALC_FALSE; } device->szDeviceName = strdup(deviceName); device->ExtraData = data; return ALC_TRUE; }
void alcDSoundProbe(int type) { if(!DSoundLoad()) return; if(type == DEVICE_PROBE) AppendDeviceList(dsDevice); else if(type == ALL_DEVICE_PROBE) { HRESULT hr; ALuint i; for(i = 0;i < NumDevices;++i) free(DeviceList[i].name); free(DeviceList); DeviceList = NULL; NumDevices = 0; hr = pDirectSoundEnumerateA(DSoundEnumDevices, NULL); if(FAILED(hr)) AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); else { for(i = 0;i < NumDevices;i++) AppendAllDeviceList(DeviceList[i].name); } } }
void *DSoundLoad(void) { if(!ds_handle) { #ifdef _WIN32 ds_handle = LoadLibraryA("dsound.dll"); if(ds_handle == NULL) { AL_PRINT("Failed to load dsound.dll\n"); return NULL; } #define LOAD_FUNC(f) do { \ p##f = (void*)GetProcAddress((HMODULE)ds_handle, #f); \ if(p##f == NULL) \ { \ FreeLibrary(ds_handle); \ ds_handle = NULL; \ AL_PRINT("Could not load %s from dsound.dll\n", #f); \ return NULL; \ } \ } while(0) #else ds_handle = (void*)0xDEADBEEF; #define LOAD_FUNC(f) p##f = f #endif LOAD_FUNC(DirectSoundCreate); LOAD_FUNC(DirectSoundEnumerateA); #undef LOAD_FUNC } return ds_handle; }
static ALCboolean oss_open_playback(ALCdevice *device, const ALCchar *deviceName) { char driver[64]; oss_data *data; strncpy(driver, GetConfigValue("oss", "device", "/dev/dsp"), sizeof(driver)-1); driver[sizeof(driver)-1] = 0; if(!deviceName) deviceName = oss_device; else if(strcmp(deviceName, oss_device) != 0) return ALC_FALSE; data = (oss_data*)calloc(1, sizeof(oss_data)); data->killNow = 0; data->fd = open(driver, O_WRONLY); if(data->fd == -1) { free(data); if(errno != ENOENT) AL_PRINT("Could not open %s: %s\n", driver, strerror(errno)); return ALC_FALSE; } device->szDeviceName = strdup(deviceName); device->ExtraData = data; return ALC_TRUE; }
static ALCboolean pulse_open( ALCdevice* device, const ALCchar* device_name ) //{{{ { pulse_data* data = ppa_xmalloc( sizeof( pulse_data ) ); memset( data, 0, sizeof( *data ) ); if ( !( data->loop = ppa_threaded_mainloop_new() ) ) { AL_PRINT( "pa_threaded_mainloop_new() failed!\n" ); goto out; } if ( ppa_threaded_mainloop_start( data->loop ) < 0 ) { AL_PRINT( "pa_threaded_mainloop_start() failed\n" ); goto out; } ppa_threaded_mainloop_lock( data->loop ); device->ExtraData = data; data->context = connect_context( data->loop ); if ( !data->context ) { ppa_threaded_mainloop_unlock( data->loop ); goto out; } ppa_context_set_state_callback( data->context, context_state_callback2, device ); device->szDeviceName = strdup( device_name ); ppa_threaded_mainloop_unlock( data->loop ); return ALC_TRUE; out: if ( data->loop ) { ppa_threaded_mainloop_stop( data->loop ); ppa_threaded_mainloop_free( data->loop ); } device->ExtraData = NULL; ppa_xfree( data ); return ALC_FALSE; } //}}}
void pa_load(void) { const char *str; PaError err; if(load_count == 0) { #ifdef HAVE_DLFCN_H #if defined(__APPLE__) && defined(__MACH__) # define PALIB "libportaudio.2.dylib" #else # define PALIB "libportaudio.so.2" #endif pa_handle = dlopen(PALIB, RTLD_NOW); if(!pa_handle) return; dlerror(); #define LOAD_FUNC(f) do { \ p##f = (typeof(f)*)dlsym(pa_handle, #f); \ if((str=dlerror()) != NULL) \ { \ dlclose(pa_handle); \ pa_handle = NULL; \ AL_PRINT("Could not load %s from "PALIB": %s\n", #f, str); \ return; \ } \ } while(0) #else str = NULL; pa_handle = (void*)0xDEADBEEF; #define LOAD_FUNC(f) p##f = f #endif LOAD_FUNC(Pa_Initialize); LOAD_FUNC(Pa_Terminate); LOAD_FUNC(Pa_GetErrorText); LOAD_FUNC(Pa_StartStream); LOAD_FUNC(Pa_StopStream); LOAD_FUNC(Pa_OpenStream); LOAD_FUNC(Pa_CloseStream); LOAD_FUNC(Pa_GetDefaultOutputDevice); LOAD_FUNC(Pa_GetStreamInfo); #undef LOAD_FUNC if((err=pPa_Initialize()) != paNoError) { AL_PRINT("Pa_Initialize() returned an error: %s\n", pPa_GetErrorText(err)); #ifdef HAVE_DLFCN_H dlclose(pa_handle); #endif pa_handle = NULL; return; } } ++load_count; }
static void pa_stop_capture(ALCdevice *device) { pa_data *data = (pa_data*)device->ExtraData; PaError err; err = pPa_StopStream(data->stream); if(err != paNoError) AL_PRINT("Error stopping stream: %s\n", pPa_GetErrorText(err)); }
static void pulse_capture_samples(ALCdevice *device, ALCvoid *buffer, ALCuint samples) //{{{ { pulse_data *data = device->ExtraData; ALCuint available = RingBufferSize(data->ring); const void *buf; size_t length; available *= data->frame_size; samples *= data->frame_size; ppa_threaded_mainloop_lock(data->loop); if(available+ppa_stream_readable_size(data->stream) < samples) { ppa_threaded_mainloop_unlock(data->loop); alcSetError(device, ALC_INVALID_VALUE); return; } available = min(available, samples); if(available > 0) { ReadRingBuffer(data->ring, buffer, available/data->frame_size); buffer = (ALubyte*)buffer + available; samples -= available; } /* Capture is done in fragment-sized chunks, so we loop until we get all * that's requested */ while(samples > 0) { if(ppa_stream_peek(data->stream, &buf, &length) < 0) { AL_PRINT("pa_stream_peek() failed: %s\n", ppa_strerror(ppa_context_errno(data->context))); break; } available = min(length, samples); memcpy(buffer, buf, available); buffer = (ALubyte*)buffer + available; buf = (const ALubyte*)buf + available; samples -= available; length -= available; /* Any unread data in the fragment will be lost, so save it */ length /= data->frame_size; if(length > 0) { if(length > data->samples) length = data->samples; WriteRingBuffer(data->ring, buf, length); } ppa_stream_drop(data->stream); } ppa_threaded_mainloop_unlock(data->loop); } //}}}
static pa_stream* connect_playback_stream( ALCdevice* device, pa_stream_flags_t flags, pa_buffer_attr* attr, pa_sample_spec* spec, pa_channel_map* chanmap ) { pulse_data* data = device->ExtraData; pa_stream_state_t state; pa_stream* stream; stream = ppa_stream_new( data->context, "Playback Stream", spec, chanmap ); if ( !stream ) { AL_PRINT( "pa_stream_new() failed: %s\n", ppa_strerror( ppa_context_errno( data->context ) ) ); return NULL; } ppa_stream_set_state_callback( stream, stream_state_callback, data->loop ); if ( ppa_stream_connect_playback( stream, data->device_name, attr, flags, NULL, NULL ) < 0 ) { AL_PRINT( "Stream did not connect: %s\n", ppa_strerror( ppa_context_errno( data->context ) ) ); ppa_stream_unref( stream ); return NULL; } while ( ( state = ppa_stream_get_state( stream ) ) != PA_STREAM_READY ) { if ( !PA_STREAM_IS_GOOD( state ) ) { AL_PRINT( "Stream did not get ready: %s\n", ppa_strerror( ppa_context_errno( data->context ) ) ); ppa_stream_unref( stream ); return NULL; } ppa_threaded_mainloop_wait( data->loop ); } ppa_stream_set_state_callback( stream, NULL, NULL ); return stream; }
static ALuint ALSANoMMapProc(ALvoid *ptr) { ALCdevice *pDevice = (ALCdevice*)ptr; alsa_data *data = (alsa_data*)pDevice->ExtraData; snd_pcm_sframes_t avail; char *WritePtr; SetRTPriority(); while(!data->killNow) { int state = verify_state(data->pcmHandle); if(state < 0) { AL_PRINT("Invalid state detected: %s\n", psnd_strerror(state)); aluHandleDisconnect(pDevice); break; } WritePtr = data->buffer; avail = data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1); aluMixData(pDevice, WritePtr, avail); while(avail > 0) { int ret = psnd_pcm_writei(data->pcmHandle, WritePtr, avail); switch (ret) { case -EAGAIN: continue; case -ESTRPIPE: case -EPIPE: case -EINTR: ret = psnd_pcm_recover(data->pcmHandle, ret, 1); if(ret >= 0) psnd_pcm_prepare(data->pcmHandle); break; default: if (ret >= 0) { WritePtr += psnd_pcm_frames_to_bytes(data->pcmHandle, ret); avail -= ret; } break; } if (ret < 0) { ret = psnd_pcm_prepare(data->pcmHandle); if(ret < 0) break; } } } return 0; }
static void context_state_callback2(pa_context *context, void *pdata) //{{{ { ALCdevice *Device = pdata; if(ppa_context_get_state(context) == PA_CONTEXT_FAILED) { AL_PRINT("Received context failure!\n"); aluHandleDisconnect(Device); } }//}}}
static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{ { ALCdevice *Device = pdata; if(ppa_stream_get_state(stream) == PA_STREAM_FAILED) { AL_PRINT("Received stream failure!\n"); aluHandleDisconnect(Device); } }//}}}
void ReadALConfig(void) { FILE *f; cfgBlocks = calloc(1, sizeof(ConfigBlock)); cfgBlocks->name = strdup("general"); cfgCount = 1; #ifdef _WIN32 #else f = fopen("/etc/openal/alsoft.conf", "r"); if(!f) { f = fopen("/etc/openal/config", "r"); if(f) AL_PRINT("Reading /etc/openal/config; this file is deprecated\n" "\tPlease rename it to /etc/openal/alsoft.conf\n"); } if(f) { LoadConfigFromFile(f); fclose(f); } if(getenv("HOME") && *(getenv("HOME"))) { snprintf(buffer, sizeof(buffer), "%s/.alsoftrc", getenv("HOME")); f = fopen(buffer, "r"); if(!f) { snprintf(buffer, sizeof(buffer), "%s/.openalrc", getenv("HOME")); f = fopen(buffer, "r"); if(f) AL_PRINT("Reading ~/.openalrc; this file is deprecated\n" "\tPlease rename it to ~/.alsoftrc\n"); } if(f) { LoadConfigFromFile(f); fclose(f); } } #endif }
static ALuint ALSANoMMapCaptureProc(ALvoid *ptr) { ALCdevice *pDevice = (ALCdevice*)ptr; alsa_data *data = (alsa_data*)pDevice->ExtraData; snd_pcm_sframes_t avail; while(!data->killNow) { int state = verify_state(data->pcmHandle); if(state < 0) { AL_PRINT("Invalid state detected: %s\n", psnd_strerror(state)); aluHandleDisconnect(pDevice); break; } avail = (snd_pcm_uframes_t)data->size / psnd_pcm_frames_to_bytes(data->pcmHandle, 1); avail = psnd_pcm_readi(data->pcmHandle, data->buffer, avail); switch(avail) { case -EAGAIN: continue; case -ESTRPIPE: while((avail=psnd_pcm_resume(data->pcmHandle)) == -EAGAIN) Sleep(1); break; case -EPIPE: break; default: if (avail >= 0 && data->doCapture) WriteRingBuffer(data->ring, data->buffer, avail); break; } if(avail < 0) { avail = psnd_pcm_prepare(data->pcmHandle); if(avail < 0) AL_PRINT("prepare error: %s\n", psnd_strerror(avail)); } } return 0; }
void alcDSoundInit(BackendFuncs *FuncList) { size_t iter = 1; HRESULT hr; *FuncList = DSoundFuncs; hr = DirectSoundEnumerate(DSoundEnumDevices, &iter); if(FAILED(hr)) AL_PRINT("Error enumerating DirectSound devices (%#x)!\n", (unsigned int)hr); }
static int xrun_recovery(snd_pcm_t *handle, int err) { if (err == -EPIPE) { /* under-run */ err = psnd_pcm_prepare(handle); if (err < 0) AL_PRINT("prepare failed: %s\n", psnd_strerror(err)); } else if (err == -ESTRPIPE) { while ((err = psnd_pcm_resume(handle)) == -EAGAIN) Sleep(1); /* wait until the suspend flag is released */ if (err < 0) { err = psnd_pcm_prepare(handle); if (err < 0) AL_PRINT("prepare failed: %s\n", psnd_strerror(err)); } } return err; }
static void stream_state_callback2(pa_stream *stream, void *pdata) //{{{ { ALCdevice *Device = pdata; pulse_data *data = Device->ExtraData; if(ppa_stream_get_state(stream) == PA_STREAM_FAILED) { AL_PRINT("Received stream failure!\n"); aluHandleDisconnect(Device); } ppa_threaded_mainloop_signal(data->loop, 0); }//}}}
static void pa_close_capture(ALCdevice *device) { pa_data *data = (pa_data*)device->ExtraData; PaError err; err = pPa_CloseStream(data->stream); if(err != paNoError) AL_PRINT("Error closing stream: %s\n", pPa_GetErrorText(err)); free(data); device->ExtraData = NULL; }
ALCchar *AppendCaptureDeviceList(char *name) { static size_t pos; ALCchar *ret = alcCaptureDeviceList+pos; if(pos >= sizeof(alcCaptureDeviceList)) { AL_PRINT("Not enough room to add %s!\n", name); return alcCaptureDeviceList + sizeof(alcCaptureDeviceList) - 1; } pos += snprintf(alcCaptureDeviceList+pos, sizeof(alcCaptureDeviceList)-pos-1, "%s", name) + 1; return ret; }
static int xrun_recovery(snd_pcm_t *handle, int err) { if(err == -EINTR || err == -EPIPE || err == -ESTRPIPE) { err = psnd_pcm_recover(handle, err, 1); if(err >= 0) err = psnd_pcm_prepare(handle); if(err < 0) AL_PRINT("recover failed: %s\n", psnd_strerror(err)); } return err; }