Index: src/al_ext.c
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/al_ext.c,v
retrieving revision 1.6
diff -u -r1.6 al_ext.c
--- src/al_ext.c	20 Jun 2003 19:23:05 -0000	1.6
+++ src/al_ext.c	14 Mar 2004 07:33:46 -0000
@@ -993,5 +993,9 @@
 		return ALC_TRUE;
 	}
 
+	if(ustrcmp("ALC_CAPTURE_SAMPLES", ename) == 0) {
+		return 0x312;
+	}
+
 	return 0;
 }
Index: src/al_main.c
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/al_main.c,v
retrieving revision 1.9
diff -u -r1.9 al_main.c
--- src/al_main.c	10 Aug 2003 07:58:31 -0000	1.9
+++ src/al_main.c	14 Mar 2004 07:33:47 -0000
@@ -133,6 +133,7 @@
 
 #ifdef CAPTURE_SUPPORT
 	_alRegisterExtensionGroup( (const ALubyte*) "AL_EXT_capture" );
+	_alRegisterExtensionGroup( (const ALubyte*) "ALC_EXT_capture" );
 #endif /* CAPTURE_SUPPORT */
 
 #endif /* BUILTIN_EXT_LOKI */
Index: src/alc/alc_context.c
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/alc/alc_context.c,v
retrieving revision 1.11
diff -u -r1.11 alc_context.c
--- src/alc/alc_context.c	12 Mar 2004 03:48:06 -0000	1.11
+++ src/alc/alc_context.c	14 Mar 2004 07:33:47 -0000
@@ -1525,6 +1525,9 @@
 	return deviceHandle->cc;
 }
 
+
+ALint __alcGetAvailableSamples(ALvoid);
+
 void alcGetIntegerv( ALCdevice *deviceHandle, ALCenum  token,
 		     ALCsizei  size , ALCint *dest )
 {
@@ -1546,6 +1549,9 @@
 		     time.
 		     Check size
 		   */
+		case 0x312:  /*ALC_CAPTURE_SAMPLES:*/
+          *dest = __alcGetAvailableSamples();
+          break;
 		case ALC_MAJOR_VERSION:
 		  *dest = 1;
 		  break;
Index: src/extensions/al_ext_capture.c
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/extensions/al_ext_capture.c,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 al_ext_capture.c
--- src/extensions/al_ext_capture.c	18 Mar 2002 14:41:44 -0000	1.1.1.1
+++ src/extensions/al_ext_capture.c	14 Mar 2004 07:33:47 -0000
@@ -45,6 +45,11 @@
 	AL_EXT_PAIR(alCaptureStop_EXT),
 	AL_EXT_PAIR(alCaptureGetData_EXT),
 	AL_EXT_PAIR(alCaptureDestroy_EXT),
+	AL_EXT_PAIR(alcCaptureOpenDevice),
+	AL_EXT_PAIR(alcCaptureCloseDevice),
+	AL_EXT_PAIR(alcCaptureStart),
+	AL_EXT_PAIR(alcCaptureStop),
+	AL_EXT_PAIR(alcCaptureSamples),
 	{ NULL, NULL }
 };
 
@@ -72,8 +77,8 @@
 	return;
 }
 
-ALboolean alCaptureInit_EXT( UNUSED(ALenum format),
-                             UNUSED(ALuint rate),
+ALboolean alCaptureInit_EXT( ALenum format,
+                             ALuint rate,
                              UNUSED(ALsizei bufferSize) )
 {
 	ALuint cid;
@@ -89,9 +94,26 @@
 		capture_device = cc->read_device;
 		if ( capture_device == NULL ) {
 			char spec[1024];
-			char *fmt="'( (direction \"read\") (sampling-rate %d))";
+			int speakers;
+			char *fmt="'( (direction \"read\") (sampling-rate %d) (speaker-num %d) )";
 
-			sprintf(spec, fmt, rate);
+			switch (format) {
+				case AL_FORMAT_MONO8:
+				case AL_FORMAT_MONO16:
+				default:
+					speakers = 1;
+					break;
+				case AL_FORMAT_STEREO8:
+				case AL_FORMAT_STEREO16:
+					speakers = 2;
+					break;
+				case AL_FORMAT_QUAD8_LOKI:
+				case AL_FORMAT_QUAD16_LOKI:
+					speakers = 4;
+					break;
+			}
+
+			sprintf(spec, fmt, rate, speakers);
 			capture_device = alcOpenDevice((ALubyte *)spec);
 			if ( capture_device ) {
 				_alcSetContext(NULL, cid, capture_device);
@@ -171,14 +193,16 @@
 		                       format, dev->format, samples);
 		size *= (_al_formatbits(dev->format) / 8);
 
-        	if ( n > (ALsizei)size )
+       	if ( n > (ALsizei)size )
 			temp = malloc( n );
 		else
 			temp = malloc( size );
 
 		if ( size > 0 ) {
 			size = _alcDeviceRead(cid, temp, size);
+		}
 
+		if ( size > 0 ) {
 			temp = _alBufferCanonizeData(dev->format,
 						     temp,
 						     size,
@@ -189,8 +213,8 @@
 						     AL_TRUE);
 		} else {
 			/* Hmm, zero size in record.. */
-			memset(temp, 0, n);
-			size = n;
+			/*memset(temp, 0, n);*/
+			size = 0;
 		}
 		if(temp == NULL) {
 			fprintf(stderr, "could not canonize data\n");
@@ -203,3 +227,228 @@
 	}
 	return size;
 }
+
+
+/* Hacked in ALC_EXT_capture support.  --ryan. */
+/* This doesn't support multiple devices, device enumeration, or capture */
+/*  devices seperate from an existing context. How painful. */
+
+/* ring buffer functionality... */
+
+typedef struct
+{
+    ALubyte *buffer;
+    ALsizei size;
+    ALsizei write;
+    ALsizei read;
+    ALsizei used;
+} __ALRingBuffer;
+
+static ALboolean __alRingBufferInit(__ALRingBuffer *ring, ALsizei size);
+static ALvoid __alRingBufferShutdown(__ALRingBuffer *ring);
+static ALsizei __alRingBufferSize(__ALRingBuffer *ring);
+static ALvoid __alRingBufferPut(__ALRingBuffer *ring, ALubyte *data, ALsizei size);
+static ALsizei __alRingBufferGet(__ALRingBuffer *ring, ALubyte *data, ALsizei size);
+
+static __ALRingBuffer captureRing;
+
+static ALboolean __alRingBufferInit(__ALRingBuffer *ring, ALsizei size)
+{
+    ALubyte *ptr = (ALubyte *) realloc(ring->buffer, size);
+    if (ptr == NULL)
+        return(AL_FALSE);
+
+    ring->buffer = ptr;
+    ring->size = size;
+    ring->write = 0;
+    ring->read = 0;
+    ring->used = 0;
+    return(AL_TRUE);
+} /* __alRingBufferInit */
+
+static ALvoid __alRingBufferShutdown(__ALRingBuffer *ring)
+{
+    free(ring->buffer);
+    ring->buffer = NULL;
+} /* __alRingBufferShutdown */
+
+static ALsizei __alRingBufferSize(__ALRingBuffer *ring)
+{
+    return(ring->used);
+} /* __alRingBufferSize */
+
+static ALvoid __alRingBufferPut(__ALRingBuffer *ring, ALubyte *data, ALsizei _size)
+{
+    register ALsizei size = _size;
+    register ALsizei cpy;
+    register ALsizei avail;
+
+    if (!size)   /* just in case... */
+        return;
+
+    /* Putting more data than ring buffer holds in total? Replace it all. */
+    if (size > ring->size)
+    {
+        ring->write = 0;
+        ring->read = 0;
+        ring->used = ring->size;
+        memcpy(ring->buffer, data + (size - ring->size), ring->size);
+        return;
+    } /* if */
+
+    /* Buffer overflow? Push read pointer to oldest sample not overwritten. */
+    avail = ring->size - ring->used;
+    if (size > avail)
+    {
+        ring->read += size - avail;
+        if (ring->read > ring->size)
+            ring->read -= ring->size;
+    } /* if */
+
+    /* Clip to end of buffer and copy first block... */
+    cpy = ring->size - ring->write;
+    if (size < cpy)
+        cpy = size;
+    if (cpy) memcpy(ring->buffer + ring->write, data, cpy);
+
+    /* Wrap around to front of ring buffer and copy remaining data... */
+    avail = size - cpy;
+    if (avail) memcpy(ring->buffer, data + cpy, avail);
+
+    /* Update write pointer... */
+    ring->write += size;
+    if (ring->write > ring->size)
+        ring->write -= ring->size;
+
+    ring->used += size;
+    if (ring->used > ring->size)
+        ring->used = ring->size;
+} /* __alRingBufferPut */
+
+static ALsizei __alRingBufferGet(__ALRingBuffer *ring, ALubyte *data, ALsizei _size)
+{
+    register ALsizei cpy;
+    register ALsizei size = _size;
+    register ALsizei avail = ring->used;
+
+    /* Clamp amount to read to available data... */
+    if (size > avail)
+        size = avail;
+    
+    /* Clip to end of buffer and copy first block... */
+    cpy = ring->size - ring->read;
+    if (cpy > size) cpy = size;
+    if (cpy) memcpy(data, ring->buffer + ring->read, cpy);
+    
+    /* Wrap around to front of ring buffer and copy remaining data... */
+    avail = size - cpy;
+    if (avail) memcpy(data + cpy, ring->buffer, avail);
+
+    /* Update read pointer... */
+    ring->read += size;
+    if (ring->read > ring->size)
+        ring->read -= ring->size;
+
+    ring->used -= size;
+
+    return(size);  /* may have been clamped if there wasn't enough data... */
+} /* __alRingBufferGet */
+
+
+static ALenum captureFmt = AL_NONE;
+static ALuint captureFreq = 0;
+static ALint captureFmtSize = 0;
+
+ALCdevice *alcCaptureOpenDevice(const ALubyte *deviceName,
+                                ALuint freq, ALenum fmt,
+                                ALsizei bufsize)
+{
+    ALCdevice *retval;
+	AL_context *cc;
+	ALuint cid;
+
+    if (deviceName != NULL)  /* !!! FIXME */
+        return NULL;
+
+    switch (fmt)  /* try to keep this sane for now... */
+    {
+        case AL_FORMAT_MONO8:
+        case AL_FORMAT_MONO16:
+        case AL_FORMAT_STEREO8:
+        case AL_FORMAT_STEREO16:
+            break;  /* okay format. */
+
+        default:
+            return(NULL);
+    }
+
+    captureFmt = fmt;
+    captureFreq = freq;
+    captureFmtSize = (_al_formatbits(fmt) / 8);
+    if ((fmt == AL_FORMAT_STEREO8) || (fmt == AL_FORMAT_STEREO16))
+        captureFmtSize *= 2;
+
+    bufsize *= captureFmtSize;
+
+    if (!__alRingBufferInit(&captureRing, bufsize))
+        return NULL;
+
+    if (!alCaptureInit_EXT(fmt, freq, bufsize))
+        return NULL;
+
+	cid = _alcCCId;
+	_alcLockContext( cid );
+	cc = _alcGetContext(cid);
+    retval = cc->read_device;
+	retval->cc = cc;
+    _alcUnlockContext( cid );
+
+    fprintf(stderr, "WARNING: ALC_EXT_capture is subject to change!\n");
+
+    return(retval);
+}
+
+ALvoid alcCaptureCloseDevice(ALCdevice *dev)
+{
+    if (dev == NULL)
+        return;
+
+    alCaptureDestroy_EXT();
+    __alRingBufferShutdown(&captureRing);
+}
+
+ALvoid alcCaptureStart(void)
+{
+    alCaptureStart_EXT();
+}
+
+ALvoid alcCaptureStop(void)
+{
+    alCaptureStop_EXT();
+}
+
+/* !!! FIXME: Not ideal; reads samples in ALC_CAPTURE_SAMPLES query */
+/* !!! FIXME: should query hardware here and do read in alcCaptureSamples() */
+ALint __alcGetAvailableSamples(ALvoid)
+{
+    static ALubyte buf[2048];
+    ALsizei got;
+    
+    while ((got = alCaptureGetData_EXT(buf, sizeof (buf),
+                                       captureFmt, captureFreq)) > 0)
+        __alRingBufferPut(&captureRing, buf, got);
+
+    /*printf("got %d have %d\n", (int) got, (int) (__alRingBufferSize(&captureRing) / captureFmtSize));*/
+
+    return(__alRingBufferSize(&captureRing) / captureFmtSize);
+}
+
+
+ALvoid alcCaptureSamples(UNUSED(ALCdevice *device), ALvoid *buf, ALsizei samps)
+{
+    if ((__alRingBufferSize(&captureRing) / captureFmtSize) < samps)
+        return;  /* !!! FIXME: This is an error condition! */
+
+    __alRingBufferGet(&captureRing, buf, samps * captureFmtSize);
+}
+
Index: src/extensions/al_ext_capture.h
===================================================================
RCS file: /usr/local/cvs-repository/openal/linux/src/extensions/al_ext_capture.h,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 al_ext_capture.h
--- src/extensions/al_ext_capture.h	18 Mar 2002 14:41:44 -0000	1.1.1.1
+++ src/extensions/al_ext_capture.h	14 Mar 2004 07:33:47 -0000
@@ -13,6 +13,16 @@
 
 #include <AL/alext.h>
 
+ALCdevice *alcCaptureOpenDevice(const ALubyte *deviceName,
+                                ALuint freq, ALenum fmt,
+                                ALsizei bufsize);
+ALvoid alcCaptureCloseDevice(ALCdevice *dev);
+ALvoid alcCaptureStart(void);
+ALvoid alcCaptureStop(void);
+ALint __alcGetAvailableSamples(ALvoid);
+ALvoid alcCaptureSamples(ALCdevice *device, ALvoid *buf, ALsizei samps);
+
+
 /*
  * alInitCapture( void )
  *
@@ -38,7 +48,12 @@
 	AL_EXT_PAIR(alCaptureStart_EXT),                           \
 	AL_EXT_PAIR(alCaptureStop_EXT),                            \
 	AL_EXT_PAIR(alCaptureGetData_EXT),                         \
-	AL_EXT_PAIR(alCaptureDestroy_EXT)                         \
+	AL_EXT_PAIR(alCaptureDestroy_EXT),                         \
+	AL_EXT_PAIR(alcCaptureOpenDevice),                         \
+	AL_EXT_PAIR(alcCaptureCloseDevice),                         \
+	AL_EXT_PAIR(alcCaptureStart),                         \
+	AL_EXT_PAIR(alcCaptureStop),                         \
+	AL_EXT_PAIR(alcCaptureSamples)                         \
 
 /* initialization and destruction functions */
 
