/* -*- mode: C; tab-width:8; c-basic-offset:8 -*- * vi:set ts=8: * * al_ext_capture.c * * audio recording extension * */ #include "al_siteconfig.h" #include #include #include #include #include #include "al_ext_needed.h" #include "al_ext_capture.h" #include "al_buffer.h" #include "al_error.h" #include "al_debug.h" #include "al_mixer.h" #include "al_source.h" #include "alc/alc_device.h" #include "alc/alc_context.h" #include "al_types.h" #include "audioconvert/audioconvert.h" #include "backends/alc_backend.h" #include "al_mutexlib.h" #ifdef OPENAL_EXTENSION /* * we are not being build into the library, therefore define the * table that informs openal how to register the extensions upon * dlopen. */ struct { ALubyte *name; void *addr; } alExtension_03222001 [] = { AL_EXT_PAIR(alCaptureInit_EXT), AL_EXT_PAIR(alCaptureStart_EXT), AL_EXT_PAIR(alCaptureStop_EXT), AL_EXT_PAIR(alCaptureGetData_EXT), AL_EXT_PAIR(alCaptureDestroy_EXT), { NULL, NULL } }; /* * We don't need init or fini functions, but we might as well * keep them in place if, in some distant future, they turn out * to be useful. */ void alExtInit_03282000(void) { fprintf(stderr, "alExtInit_03282000 STUB\n"); return; } void alExtFini_03282000(void) { fprintf(stderr, "alExtFini_03282000 STUB\n"); return; } #endif /* OPENAL_EXTENSION */ void alInitCapture(void) { return; } void alFiniCapture(void) { return; } ALboolean alCaptureInit_EXT( UNUSED(ALenum format), UNUSED(ALuint rate), UNUSED(ALsizei bufferSize) ) { ALuint cid; AL_context *cc; AL_device *capture_device; /* get the current context */ capture_device = NULL; cid = _alcCCId; _alcLockContext( cid ); cc = _alcGetContext(cid); if ( cc != NULL ) { capture_device = cc->read_device; if ( capture_device == NULL ) { char spec[1024]; const char *fmt="'( (direction \"read\") (sampling-rate %d))"; snprintf(spec, sizeof(spec), fmt, rate); capture_device = alcOpenDevice((ALchar *)spec); if ( capture_device ) { _alcSetContext(NULL, cid, capture_device); _alcDeviceSet(capture_device); } } } _alcUnlockContext( cid ); return (capture_device != NULL); } ALboolean alCaptureDestroy_EXT( void ) { ALuint cid; AL_context *cc; /* get the current context */ cid = _alcCCId; _alcLockContext( cid ); cc = _alcGetContext(cid); if ( cc == NULL ) { _alcUnlockContext( cid ); return AL_FALSE; } if ( cc->read_device ) { /* Only close it if we opened it originally */ if (cc->write_device && (cc->read_device != cc->write_device)) { alcCloseDevice(cc->read_device); cc->read_device = NULL; } } _alcUnlockContext( cid ); return AL_TRUE; } ALboolean alCaptureStart_EXT( void ) { return AL_FALSE; } ALboolean alCaptureStop_EXT( void ) { return AL_FALSE; } ALsizei alCaptureGetData_EXT( UNUSED(ALvoid* data), ALsizei n, UNUSED(ALenum format), UNUSED(ALuint rate) ) { AL_device *dev; ALuint size; ALuint cid; AL_context *cc; /* get the read device */ cid = _alcCCId; cc = _alcGetContext(cid); if ( cc == NULL ) { return 0; } dev = cc->read_device; if ( (dev->format == format) && (dev->speed == rate) ) { size = _alcDeviceRead(cid, data, (ALuint)n); } else { ALuint samples; void *temp; samples = n / (_alGetBitsFromFormat(format) / 8); /* Set size to the bytes of raw audio data we need */ size = _al_PCMRatioify(rate, dev->speed, format, dev->format, samples); size *= (_alGetBitsFromFormat(dev->format) / 8); if ( n > (ALsizei)size ) temp = malloc( (size_t)n ); else temp = malloc( (size_t)size ); if ( size > 0 ) { size = _alcDeviceRead(cid, temp, size); temp = (void *)_alBufferCanonizeData(dev->format, temp, size, dev->speed, format, rate, &size, AL_TRUE); } else { /* Hmm, zero size in record.. */ memset(temp, 0, (size_t)n); size = n; } if(temp == NULL) { fprintf(stderr, "could not canonize data\n"); return 0; } memcpy(data, temp, size); free( temp ); } return size; }