Update of /cvsroot/audacity/lib-src/portaudio-v19/src/hostapi/alsa
In directory
23jxhf1.ch3.sourceforge.com:/tmp/cvs-serv29383/lib-src/portaudio-v19/src/hostapi/alsa
Modified Files:
pa_linux_alsa.c
Log Message:
Update portaudio-v19 to current portaudio SVN version, r1414
Index: pa_linux_alsa.c
===================================================================
RCS file:
/cvsroot/audacity/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- pa_linux_alsa.c 31 Dec 2008 15:38:35 -0000 1.10
+++ pa_linux_alsa.c 25 May 2009 21:40:16 -0000 1.11
@@ -5,7 +5,8 @@
* ALSA implementation by Joshua Haberman and Arve Knudsen
*
* Copyright (c) 2002 Joshua Haberman <[email protected]>
- * Copyright (c) 2005-2007 Arve Knudsen <[email protected]>
+ * Copyright (c) 2005-2009 Arve Knudsen <[email protected]>
+ * Copyright (c) 2008 Kevin Kofler <[email protected]>
*
* Based on the Open Source API proposed by Ross Bencina
* Copyright (c) 1999-2002 Ross Bencina, Phil Burk
@@ -99,6 +100,7 @@
static int aErr_; /* Used with ENSURE_ */
static int numPeriods_ = 4;
+static int busyRetries_ = 100;
int PaAlsa_SetNumPeriods( int numPeriods )
{
@@ -118,6 +120,8 @@
unsigned long framesPerBuffer;
int numUserChannels, numHostChannels;
int userInterleaved, hostInterleaved;
+ int canMmap;
+ void *nonMmapBuffer;
PaDeviceIndex device; /* Keep the device index */
snd_pcm_t *pcm;
@@ -321,7 +325,7 @@
* and a suitable result returned. The device is closed before returning.
*/
static PaError GropeDevice( snd_pcm_t* pcm, int isPlug, StreamDirection mode,
int openBlocking,
- PaAlsaDeviceInfo* devInfo, int* canMmap )
+ PaAlsaDeviceInfo* devInfo )
{
PaError result = paNoError;
snd_pcm_hw_params_t *hwParams;
@@ -354,9 +358,6 @@
snd_pcm_hw_params_alloca( &hwParams );
snd_pcm_hw_params_any( pcm, hwParams );
- *canMmap = snd_pcm_hw_params_test_access( pcm, hwParams,
SND_PCM_ACCESS_MMAP_INTERLEAVED ) >= 0 ||
- snd_pcm_hw_params_test_access( pcm, hwParams,
SND_PCM_ACCESS_MMAP_NONINTERLEAVED ) >= 0;
-
if( defaultSr >= 0 )
{
/* Could be that the device opened in one mode supports samplerates
that the other mode wont have,
@@ -539,7 +540,7 @@
**/
static int OpenPcm( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t
stream, int mode, int waitOnBusy )
{
- int tries = 0, maxTries = waitOnBusy ? 100 : 0;
+ int tries = 0, maxTries = waitOnBusy ? busyRetries_ : 0;
int ret = snd_pcm_open( pcmp, name, stream, mode );
for( tries = 0; tries < maxTries && -EBUSY == ret; ++tries )
{
@@ -566,7 +567,6 @@
PaError result = 0;
PaDeviceInfo *baseDeviceInfo = &devInfo->baseDeviceInfo;
snd_pcm_t *pcm;
- int canMmap = -1;
PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;
/* Zero fields */
@@ -580,8 +580,7 @@
OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE,
blocking, 0 )
>= 0 )
{
- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In,
blocking, devInfo,
- &canMmap ) != paNoError )
+ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In,
blocking, devInfo ) != paNoError )
{
/* Error */
PA_DEBUG(("%s: Failed groping %s for capture\n", __FUNCTION__,
deviceName->alsaName));
@@ -594,8 +593,7 @@
OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK,
blocking, 0 )
>= 0 )
{
- if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out,
blocking, devInfo,
- &canMmap ) != paNoError )
+ if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out,
blocking, devInfo ) != paNoError )
{
/* Error */
PA_DEBUG(("%s: Failed groping %s for playback\n", __FUNCTION__,
deviceName->alsaName));
@@ -603,12 +601,6 @@
}
}
- if( 0 == canMmap )
- {
- PA_DEBUG(("%s: Device %s doesn't support mmap\n", __FUNCTION__,
deviceName->alsaName));
- goto end;
- }
-
baseDeviceInfo->structVersion = 2;
baseDeviceInfo->hostApi = alsaApi->hostApiIndex;
baseDeviceInfo->name = deviceName->name;
@@ -1197,6 +1189,8 @@
self->hostInterleaved = self->userInterleaved = !(userSampleFormat &
paNonInterleaved);
self->numUserChannels = params->channelCount;
self->streamDir = streamDir;
+ self->canMmap = 0;
+ self->nonMmapBuffer = NULL;
if( !callbackMode && !self->userInterleaved )
{
@@ -1239,6 +1233,7 @@
PaError result = paNoError;
snd_pcm_access_t accessMode, alternateAccessMode;
+ snd_pcm_access_t rwAccessMode, alternateRwAccessMode;
int dir = 0;
snd_pcm_t *pcm = self->pcm;
double sr = *sampleRate;
@@ -1258,32 +1253,40 @@
if( self->userInterleaved )
{
accessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+ rwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED;
alternateAccessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+ alternateRwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED;
}
else
{
accessMode = SND_PCM_ACCESS_MMAP_NONINTERLEAVED;
+ rwAccessMode = SND_PCM_ACCESS_RW_NONINTERLEAVED;
alternateAccessMode = SND_PCM_ACCESS_MMAP_INTERLEAVED;
+ alternateRwAccessMode = SND_PCM_ACCESS_RW_INTERLEAVED;
}
/* If requested access mode fails, try alternate mode */
+ self->canMmap = 1;
if( snd_pcm_hw_params_set_access( pcm, hwParams, accessMode ) < 0 )
{
- int err = 0;
- if( (err = snd_pcm_hw_params_set_access( pcm, hwParams,
alternateAccessMode )) < 0)
+ if( snd_pcm_hw_params_set_access( pcm, hwParams, rwAccessMode ) >= 0 )
+ self->canMmap = 0;
+ else
{
- result = paUnanticipatedHostError;
- if( -EINVAL == err )
- {
- PaUtil_SetLastHostErrorInfo( paALSA, err, "PA ALSA requires
that a device supports mmap access" );
- }
- else
+ if( snd_pcm_hw_params_set_access( pcm, hwParams,
alternateAccessMode ) < 0 )
{
- PaUtil_SetLastHostErrorInfo( paALSA, err, snd_strerror( err )
);
+ int err = 0;
+ if( (err = snd_pcm_hw_params_set_access( pcm, hwParams,
alternateRwAccessMode )) >= 0)
+ self->canMmap = 0;
+ else
+ {
+ result = paUnanticipatedHostError;
+ PaUtil_SetLastHostErrorInfo( paALSA, err, snd_strerror(
err ) );
+ goto error;
+ }
}
- goto error;
+ /* Flip mode */
+ self->hostInterleaved = !self->userInterleaved;
}
- /* Flip mode */
- self->hostInterleaved = !self->userInterleaved;
}
ENSURE_( snd_pcm_hw_params_set_format( pcm, hwParams, self->nativeFormat
), paUnanticipatedHostError );
@@ -1361,7 +1364,7 @@
ENSURE_( snd_pcm_sw_params_set_avail_min( self->pcm, swParams,
self->framesPerBuffer ), paUnanticipatedHostError );
ENSURE_( snd_pcm_sw_params_set_xfer_align( self->pcm, swParams, 1 ),
paUnanticipatedHostError );
- ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams,
SND_PCM_TSTAMP_MMAP ), paUnanticipatedHostError );
+ ENSURE_( snd_pcm_sw_params_set_tstamp_mode( self->pcm, swParams,
SND_PCM_TSTAMP_ENABLE ), paUnanticipatedHostError );
/* Set the parameters! */
ENSURE_( snd_pcm_sw_params( self->pcm, swParams ),
paUnanticipatedHostError );
@@ -1589,6 +1592,10 @@
}
}
+ /* non-mmap mode needs a reasonably-sized buffer or it'll stutter */
+ if( !self->canMmap && framesPerHostBuffer < 2048 )
+ framesPerHostBuffer = 2048;
+
assert( framesPerHostBuffer > 0 );
{
snd_pcm_uframes_t min = 0, max = 0;
@@ -1831,12 +1838,13 @@
PA_UNLESS( framesPerHostBuffer != 0, paInternalError );
self->maxFramesPerHostBuffer = framesPerHostBuffer;
- if( !accurate )
+ if( !self->playback.canMmap || !accurate )
{
/* Don't know the exact size per host buffer */
*hostBufferSizeMode = paUtilBoundedHostBufferSize;
/* Raise upper bound */
- ++self->maxFramesPerHostBuffer;
+ if( !accurate )
+ ++self->maxFramesPerHostBuffer;
}
error:
@@ -2059,9 +2067,11 @@
{
/* Buffer isn't primed, so prepare and silence */
ENSURE_( snd_pcm_prepare( stream->playback.pcm ),
paUnanticipatedHostError );
- SilenceBuffer( stream );
+ if( stream->playback.canMmap )
+ SilenceBuffer( stream );
}
- ENSURE_( snd_pcm_start( stream->playback.pcm ),
paUnanticipatedHostError );
+ if( stream->playback.canMmap )
+ ENSURE_( snd_pcm_start( stream->playback.pcm ),
paUnanticipatedHostError );
}
else
ENSURE_( snd_pcm_prepare( stream->playback.pcm ),
paUnanticipatedHostError );
@@ -2390,6 +2400,7 @@
snd_pcm_status_t *st;
PaTime now = PaUtil_GetTime();
snd_timestamp_t t;
+ int errplayback = 0, errcapture = 0;
snd_pcm_status_alloca( &st );
@@ -2400,6 +2411,7 @@
{
snd_pcm_status_get_trigger_tstamp( st, &t );
self->underrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime)
t.tv_usec / 1000);
+ errplayback = snd_pcm_recover( self->playback.pcm, -EPIPE, 0 );
}
}
if( self->capture.pcm )
@@ -2409,10 +2421,12 @@
{
snd_pcm_status_get_trigger_tstamp( st, &t );
self->overrun = now * 1000 - ((PaTime) t.tv_sec * 1000 + (PaTime)
t.tv_usec / 1000);
+ errcapture = snd_pcm_recover( self->capture.pcm, -EPIPE, 0 );
}
}
- PA_ENSURE( AlsaRestart( self ) );
+ if( errplayback || errcapture )
+ PA_ENSURE( AlsaRestart( self ) );
end:
return result;
@@ -2563,7 +2577,7 @@
static PaError PaAlsaStreamComponent_EndProcessing( PaAlsaStreamComponent
*self, unsigned long numFrames, int *xrun )
{
PaError result = paNoError;
- int res;
+ int res = 0;
/* @concern FullDuplex It is possible that only one direction is marked
ready after polling, and processed
* afterwards
@@ -2571,7 +2585,34 @@
if( !self->ready )
goto end;
- res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames );
+ if( !self->canMmap && StreamDirection_Out == self->streamDir )
+ {
+ /* Play sound */
+ if( self->hostInterleaved )
+ res = snd_pcm_writei( self->pcm, self->nonMmapBuffer, numFrames );
+ else
+ {
+ void *bufs[self->numHostChannels];
+ int bufsize = snd_pcm_format_size( self->nativeFormat,
self->framesPerBuffer + 1 );
+ unsigned char *buffer = self->nonMmapBuffer;
+ int i;
+ for( i = 0; i < self->numHostChannels; ++i )
+ {
+ bufs[i] = buffer;
+ buffer += bufsize;
+ }
+ res = snd_pcm_writen( self->pcm, bufs, numFrames );
+ }
+ }
+
+ if( self->canMmap )
+ res = snd_pcm_mmap_commit( self->pcm, self->offset, numFrames );
+ else
+ {
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = NULL;
+ }
+
if( res == -EPIPE || res == -ESTRPIPE )
{
*xrun = 1;
@@ -2611,7 +2652,7 @@
if( self->hostInterleaved )
{
int swidth = snd_pcm_format_size( self->nativeFormat, 1 );
- unsigned char *buffer = ExtractAddress( self->channelAreas,
self->offset );
+ unsigned char *buffer = self->canMmap ? ExtractAddress(
self->channelAreas, self->offset ) : self->nonMmapBuffer;
/* Start after the last user channel */
p = buffer + self->numUserChannels * swidth;
@@ -2991,13 +3032,23 @@
goto end;
}
- ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset, numFrames
), paUnanticipatedHostError );
+ if( self->canMmap )
+ {
+ ENSURE_( snd_pcm_mmap_begin( self->pcm, &areas, &self->offset,
numFrames ), paUnanticipatedHostError );
+ /* @concern ChannelAdaption Buffer address is recorded so we can do
some channel adaption later */
+ self->channelAreas = (snd_pcm_channel_area_t *)areas;
+ }
+ else
+ {
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = calloc( self->numHostChannels,
snd_pcm_format_size( self->nativeFormat, self->framesPerBuffer + 1 ) );
+ }
if( self->hostInterleaved )
{
int swidth = snd_pcm_format_size( self->nativeFormat, 1 );
- p = buffer = ExtractAddress( areas, self->offset );
+ p = buffer = self->canMmap ? ExtractAddress( areas, self->offset ) :
self->nonMmapBuffer;
for( i = 0; i < self->numUserChannels; ++i )
{
/* We're setting the channels up to userChannels, but the stride
will be hostChannels samples */
@@ -3007,16 +3058,52 @@
}
else
{
- for( i = 0; i < self->numUserChannels; ++i )
+ if( self->canMmap )
+ for( i = 0; i < self->numUserChannels; ++i )
+ {
+ area = areas + i;
+ buffer = ExtractAddress( area, self->offset );
+ setChannel( bp, i, buffer, 1 );
+ }
+ else
{
- area = areas + i;
- buffer = ExtractAddress( area, self->offset );
- setChannel( bp, i, buffer, 1 );
+ int bufsize = snd_pcm_format_size( self->nativeFormat,
self->framesPerBuffer + 1 );
+ buffer = self->nonMmapBuffer;
+ for( i = 0; i < self->numUserChannels; ++i )
+ {
+ setChannel( bp, i, buffer, 1 );
+ buffer += bufsize;
+ }
}
}
- /* @concern ChannelAdaption Buffer address is recorded so we can do some
channel adaption later */
- self->channelAreas = (snd_pcm_channel_area_t *)areas;
+ if( !self->canMmap && StreamDirection_In == self->streamDir )
+ {
+ /* Read sound */
+ int res;
+ if( self->hostInterleaved )
+ res = snd_pcm_readi( self->pcm, self->nonMmapBuffer, *numFrames );
+ else
+ {
+ void *bufs[self->numHostChannels];
+ int bufsize = snd_pcm_format_size( self->nativeFormat,
self->framesPerBuffer + 1 );
+ unsigned char *buffer = self->nonMmapBuffer;
+ int i;
+ for( i = 0; i < self->numHostChannels; ++i )
+ {
+ bufs[i] = buffer;
+ buffer += bufsize;
+ }
+ res = snd_pcm_readn( self->pcm, bufs, *numFrames );
+ }
+ if( res == -EPIPE || res == -ESTRPIPE )
+ {
+ *xrun = 1;
+ *numFrames = 0;
+ free( self->nonMmapBuffer );
+ self->nonMmapBuffer = NULL;
+ }
+ }
end:
error:
@@ -3584,3 +3671,9 @@
error:
return result;
}
+
+PaError PaAlsa_SetRetriesBusy( int retries )
+{
+ busyRetries_ = retries;
+ return paNoError;
+}
------------------------------------------------------------------------------
Register Now for Creativity and Technology (CaT), June 3rd, NYC. CaT
is a gathering of tech-side developers & brand creativity professionals. Meet
the minds behind Google Creative Lab, Visual Complexity, Processing, &
iPhoneDevCamp asthey present alongside digital heavyweights like Barbarian
Group, R/GA, & Big Spaceship. http://www.creativitycat.com
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs