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 ); } //}}}
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 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); } //}}}