Update of /cvsroot/audacity/lib-src/portaudio-v19/src/hostapi/alsa
In directory 
sc8-pr-cvs11.sourceforge.net:/tmp/cvs-serv27584/portaudio-v19/src/hostapi/alsa

Modified Files:
        pa_linux_alsa.c 
Log Message:

Update portaudio to 2007-jun-01 snapshot


Index: pa_linux_alsa.c
===================================================================
RCS file: 
/cvsroot/audacity/lib-src/portaudio-v19/src/hostapi/alsa/pa_linux_alsa.c,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- pa_linux_alsa.c     6 Nov 2006 11:28:17 -0000       1.4
+++ pa_linux_alsa.c     3 Jun 2007 08:30:30 -0000       1.5
@@ -70,6 +70,7 @@
 #include "pa_stream.h"
 #include "pa_cpuload.h"
 #include "pa_process.h"
+#include "pa_endianness.h"
 
 #include "pa_linux_alsa.h"
 
@@ -109,6 +110,7 @@
     unsigned long framesPerBuffer;
     int numUserChannels, numHostChannels;
     int userInterleaved, hostInterleaved;
+    PaDeviceIndex device;     /* Keep the device index */
 
     snd_pcm_t *pcm;
     snd_pcm_uframes_t bufferSize;
@@ -135,6 +137,7 @@
     int primeBuffers;
     int callbackMode;              /* bool: are we running in callback mode? */
     int pcmsSynced;                /* Have we successfully synced pcms */
+    int rtSched;
 
     /* the callback thread uses these to poll the sound device(s), waiting
      * for data to be ready/available */
@@ -444,7 +447,43 @@
     int isPlug;
     int hasPlayback;
     int hasCapture;
-} DeviceNames;
+} HwDevInfo;
+
+
+HwDevInfo predefinedNames[] = {
+    { "center_lfe", NULL, 0, 1, 0 },
+/* { "default", NULL, 0, 1, 0 }, */
+/* { "dmix", NULL, 0, 1, 0 }, */
+/* { "dpl", NULL, 0, 1, 0 }, */
+/* { "dsnoop", NULL, 0, 1, 0 }, */
+    { "front", NULL, 0, 1, 0 },
+    { "iec958", NULL, 0, 1, 0 },
+/* { "modem", NULL, 0, 1, 0 }, */
+    { "rear", NULL, 0, 1, 0 },
+    { "side", NULL, 0, 1, 0 },
+/*     { "spdif", NULL, 0, 0, 0 }, */
+    { "surround40", NULL, 0, 1, 0 },
+    { "surround41", NULL, 0, 1, 0 },
+    { "surround50", NULL, 0, 1, 0 },
+    { "surround51", NULL, 0, 1, 0 },
+    { "surround71", NULL, 0, 1, 0 },
+    { NULL, NULL, 0, 1, 0 }
+};
+
+static const HwDevInfo *FindDeviceName( const char *name )
+{
+    int i;
+
+    for( i = 0; predefinedNames[i].alsaName; i++ )
+    {
+       if( strcmp( name, predefinedNames[i].alsaName ) == 0 )
+       {
+           return &predefinedNames[i];
+       }
+    }
+
+    return NULL;
+}
 
 static PaError PaAlsa_StrDup( PaAlsaHostApiRepresentation *alsaApi,
         char **dst,
@@ -468,7 +507,7 @@
 static int IgnorePlugin( const char *pluginId )
 {
     static const char *ignoredPlugins[] = {"hw", "plughw", "plug", "dsnoop", 
"tee",
-        "file", "null", "shm", "cards", NULL};
+        "file", "null", "shm", "cards", "rate_convert", NULL};
     int i = 0;
     while( ignoredPlugins[i] )
     {
@@ -482,16 +521,115 @@
     return 0;
 }
 
-static int snd_pcm_open_with_retry(snd_pcm_t **pcmp, const char *name, 
snd_pcm_stream_t stream, int mode)
+/** Open PCM device.
+ *
+ * Wrapper around snd_pcm_open which may repeatedly retry opening a device if 
it is busy, for
+ * a certain time. This is because dmix may temporarily hold on to a device 
after it (dmix)
+ * has been opened and closed.
+ * @param mode: Open mode (e.g., SND_PCM_BLOCKING).
+ * @param waitOnBusy: Retry opening busy device for up to one second?
+ **/
+static int OpenPcm( snd_pcm_t **pcmp, const char *name, snd_pcm_stream_t 
stream, int mode, int waitOnBusy )
 {
-       int ret = snd_pcm_open(pcmp, name, stream, mode);
-       if (ret==EBUSY) {
-               sleep(1);
-               int ret = snd_pcm_open(pcmp, name, stream, mode);
-       }
-       return ret;
+    int tries = 0, maxTries = waitOnBusy ? 100 : 0;
+    int ret = snd_pcm_open( pcmp, name, stream, mode );
+    for( tries = 0; tries < maxTries && -EBUSY == ret; ++tries )
+    {
+        Pa_Sleep( 10 );
+        ret = snd_pcm_open( pcmp, name, stream, mode );
+        if( -EBUSY != ret )
+        {
+            PA_DEBUG(( "%s: Successfully opened initially busy device after %d 
tries\n",
+                        __FUNCTION__, tries ));
+        }
+    }
+    if( -EBUSY == ret )
+    {
+        PA_DEBUG(( "%s: Failed to open busy device '%s'\n",
+                    __FUNCTION__, name ));
+    }
+
+    return ret;
 }
-                                                                         
+
+static PaError FillInDevInfo( PaAlsaHostApiRepresentation *alsaApi, HwDevInfo* 
deviceName, int blocking,
+        PaAlsaDeviceInfo* devInfo, int* devIdx )
+{
+    PaError result = 0;
+    PaDeviceInfo *baseDeviceInfo = &devInfo->baseDeviceInfo;
+    snd_pcm_t *pcm;
+    int canMmap = -1;
+    PaUtilHostApiRepresentation *baseApi = &alsaApi->baseHostApiRep;
+
+    /* Zero fields */
+    InitializeDeviceInfo( baseDeviceInfo );
+
+    /* to determine device capabilities, we must open the device and query the
+     * hardware parameter configuration space */
+
+    /* Query capture */
+    if( deviceName->hasCapture &&
+            OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_CAPTURE, 
blocking, 0 )
+            >= 0 )
+    {
+        if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_In, 
blocking, devInfo,
+                    &canMmap ) != paNoError )
+        {
+            /* Error */
+            PA_DEBUG(("%s: Failed groping %s for capture\n", __FUNCTION__, 
deviceName->alsaName));
+            goto end;
+        }
+    }
+
+    /* Query playback */
+    if( deviceName->hasPlayback &&
+            OpenPcm( &pcm, deviceName->alsaName, SND_PCM_STREAM_PLAYBACK, 
blocking, 0 )
+            >= 0 )
+    {
+        if( GropeDevice( pcm, deviceName->isPlug, StreamDirection_Out, 
blocking, devInfo,
+                    &canMmap ) != paNoError )
+        {
+            /* Error */
+            PA_DEBUG(("%s: Failed groping %s for playback\n", __FUNCTION__, 
deviceName->alsaName));
+            goto end;
+        }
+    }
+
+    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;
+    devInfo->alsaName = deviceName->alsaName;
+    devInfo->isPlug = deviceName->isPlug;
+
+    /* A: Storing pointer to PaAlsaDeviceInfo object as pointer to 
PaDeviceInfo object.
+     * Should now be safe to add device info, unless the device supports 
neither capture nor playback
+     */
+    if( baseDeviceInfo->maxInputChannels > 0 || 
baseDeviceInfo->maxOutputChannels > 0 )
+    {
+        /* Make device default if there isn't already one or it is the ALSA 
"default" device */
+        if( baseApi->info.defaultInputDevice == paNoDevice && 
baseDeviceInfo->maxInputChannels > 0 )
+            baseApi->info.defaultInputDevice = *devIdx;
+        if( (baseApi->info.defaultOutputDevice == paNoDevice || 
!strcmp(deviceName->alsaName,
+                        "default" )) && baseDeviceInfo->maxOutputChannels > 0 )
+        {
+            baseApi->info.defaultOutputDevice = *devIdx;
+            PA_DEBUG(("Default output device: %s\n", deviceName->name));
+        }
+        PA_DEBUG(("%s: Adding device %s: %d\n", __FUNCTION__, 
deviceName->name, *devIdx));
+        baseApi->deviceInfos[*devIdx] = (PaDeviceInfo *) devInfo;
+        (*devIdx) += 1;
+    }
+
+end:
+    return result;
+}
+
 /* Build PaDeviceInfo list, ignore devices for which we cannot determine 
capabilities (possibly busy, sigh) */
 static PaError BuildDeviceList( PaAlsaHostApiRepresentation *alsaApi )
 {
@@ -501,12 +639,16 @@
     snd_ctl_card_info_t *cardInfo;
     PaError result = paNoError;
     size_t numDeviceNames = 0, maxDeviceNames = 1, i;
-    DeviceNames *deviceNames = NULL;
+    HwDevInfo *hwDevInfos = NULL;
     snd_config_t *topNode = NULL;
     snd_pcm_info_t *pcmInfo;
     int res;
     int blocking = SND_PCM_NONBLOCK;
     char alsaCardName[50];
+#ifdef PA_ENABLE_DEBUG_OUTPUT
+    PaTime startTime = PaUtil_GetTime();
+#endif
+
     if( getenv( "PA_ALSA_INITIALIZE_BLOCK" ) && atoi( getenv( 
"PA_ALSA_INITIALIZE_BLOCK" ) ) )
         blocking = 0;
 
@@ -514,9 +656,9 @@
     baseApi->info.defaultInputDevice = paNoDevice;
     baseApi->info.defaultOutputDevice = paNoDevice;
 
-    /* count the devices by enumerating all the card numbers */
+    /* Gather info about hw devices
 
-    /* snd_card_next() modifies the integer passed to it to be:
+     * snd_card_next() modifies the integer passed to it to be:
      *      the index of the first card if the parameter is -1
      *      the index of the next card if the parameter is the index of a card
      *      -1 if there are no more cards
@@ -550,7 +692,7 @@
             char *alsaDeviceName, *deviceName;
             size_t len;
             int hasPlayback = 0, hasCapture = 0;
-            snprintf( buf, sizeof (buf), "%s:%d,%d", "hw", cardIdx, devIdx );
+            snprintf( buf, sizeof (buf), "hw:%d,%d", cardIdx, devIdx );
 
             /* Obtain info about this particular device */
             snd_pcm_info_set_device( pcmInfo, devIdx );
@@ -569,7 +711,8 @@
 
             if( !hasPlayback && !hasCapture )
             {
-                continue;   /* Error */
+                /* Error */
+                continue;
             }
 
             /* The length of the string written by snprintf plus terminating 0 
*/
@@ -580,25 +723,26 @@
                     snd_pcm_info_get_name( pcmInfo ), buf );
 
             ++numDeviceNames;
-            if( !deviceNames || numDeviceNames > maxDeviceNames )
+            if( !hwDevInfos || numDeviceNames > maxDeviceNames )
             {
                 maxDeviceNames *= 2;
-                PA_UNLESS( deviceNames = (DeviceNames *) realloc( deviceNames, 
maxDeviceNames * sizeof (DeviceNames) ),
+                PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, 
maxDeviceNames * sizeof (HwDevInfo) ),
                         paInsufficientMemory );
             }
 
             PA_ENSURE( PaAlsa_StrDup( alsaApi, &alsaDeviceName, buf ) );
 
-            deviceNames[ numDeviceNames - 1 ].alsaName = alsaDeviceName;
-            deviceNames[ numDeviceNames - 1 ].name = deviceName;
-            deviceNames[ numDeviceNames - 1 ].isPlug = 0;
-            deviceNames[ numDeviceNames - 1 ].hasPlayback = hasPlayback;
-            deviceNames[ numDeviceNames - 1 ].hasCapture = hasCapture;
+            hwDevInfos[ numDeviceNames - 1 ].alsaName = alsaDeviceName;
+            hwDevInfos[ numDeviceNames - 1 ].name = deviceName;
+            hwDevInfos[ numDeviceNames - 1 ].isPlug = 0;
+            hwDevInfos[ numDeviceNames - 1 ].hasPlayback = hasPlayback;
+            hwDevInfos[ numDeviceNames - 1 ].hasCapture = hasCapture;
         }
         snd_ctl_close( ctl );
     }
 
     /* Iterate over plugin devices */
+
     if( NULL == snd_config )
     {
         /* snd_config_update is called implicitly by some functions, if this 
hasn't happened snd_config will be NULL (bleh) */
@@ -616,6 +760,7 @@
             int err = 0;
 
             char *alsaDeviceName, *deviceName;
+           const HwDevInfo *predefined = NULL;
             snd_config_t *n = snd_config_iterator_entry( i ), * tp = NULL;;
 
             if( (err = snd_config_search( n, "type", &tp )) < 0 )
@@ -645,18 +790,31 @@
             strcpy( deviceName, idStr );
 
             ++numDeviceNames;
-            if( !deviceNames || numDeviceNames > maxDeviceNames )
+            if( !hwDevInfos || numDeviceNames > maxDeviceNames )
             {
                 maxDeviceNames *= 2;
-                PA_UNLESS( deviceNames = (DeviceNames *) realloc( deviceNames, 
maxDeviceNames * sizeof (DeviceNames) ),
+                PA_UNLESS( hwDevInfos = (HwDevInfo *) realloc( hwDevInfos, 
maxDeviceNames * sizeof (HwDevInfo) ),
                         paInsufficientMemory );
             }
 
-            deviceNames[numDeviceNames - 1].alsaName = alsaDeviceName;
-            deviceNames[numDeviceNames - 1].name = deviceName;
-            deviceNames[numDeviceNames - 1].isPlug = 1;
-            deviceNames[numDeviceNames - 1].hasPlayback = 1;
-            deviceNames[numDeviceNames - 1].hasCapture = 1;
+           predefined = FindDeviceName( alsaDeviceName );
+
+            hwDevInfos[numDeviceNames - 1].alsaName = alsaDeviceName;
+            hwDevInfos[numDeviceNames - 1].name = deviceName;
+            hwDevInfos[numDeviceNames - 1].isPlug = 1;
+
+           if( predefined )
+           {
+               hwDevInfos[numDeviceNames - 1].hasPlayback =
+                   predefined->hasPlayback;
+               hwDevInfos[numDeviceNames - 1].hasCapture =
+                   predefined->hasCapture;
+           }
+           else
+           {
+               hwDevInfos[numDeviceNames - 1].hasPlayback = 1;
+               hwDevInfos[numDeviceNames - 1].hasCapture = 1;
+           }
         }
     }
     else
@@ -670,80 +828,48 @@
     PA_UNLESS( deviceInfoArray = (PaAlsaDeviceInfo*)PaUtil_GroupAllocateMemory(
             alsaApi->allocations, sizeof(PaAlsaDeviceInfo) * numDeviceNames ), 
paInsufficientMemory );
 
-    /* Loop over list of cards, filling in info, if a device is deemed 
unavailable (can't get name),
+    /* Loop over list of cards, filling in info. If a device is deemed 
unavailable (can't get name),
      * it's ignored.
+     *
+     * Note that we do this in two stages. This is a workaround owing to the 
fact that the 'dmix'
+     * plugin may cause the underlying hardware device to be busy for a short 
while even after it
+     * (dmix) is closed. The 'default' plugin may also point to the dmix 
plugin, so the same goes
+     * for this.
      */
-    /* while( snd_card_next( &cardIdx ) == 0 && cardIdx >= 0 ) */
+
     for( i = 0, devIdx = 0; i < numDeviceNames; ++i )
     {
-        snd_pcm_t *pcm;
-        PaAlsaDeviceInfo *deviceInfo = &deviceInfoArray[devIdx];
-        PaDeviceInfo *baseDeviceInfo = &deviceInfo->baseDeviceInfo;
-        int canMmap = -1;
-
-        /* Zero fields */
-        InitializeDeviceInfo( baseDeviceInfo );
-
-        /* to determine device capabilities, we must open the device and query 
the
-         * hardware parameter configuration space */
-
-        /* Query capture */
-        if( deviceNames[i].hasCapture &&
-                snd_pcm_open_with_retry( &pcm, deviceNames[i].alsaName, 
SND_PCM_STREAM_CAPTURE, blocking ) >= 0 )
-        {
-            if( GropeDevice( pcm, deviceNames[i].isPlug, StreamDirection_In, 
blocking, deviceInfo,
-                        &canMmap ) != paNoError )
-            {
-                /* Error */
-                PA_DEBUG(("%s: Failed groping %s for capture\n", __FUNCTION__, 
deviceNames[i].alsaName));
-                continue;
-            }
-        }
-
-        /* Query playback */
-        if( deviceNames[i].hasPlayback &&
-                snd_pcm_open_with_retry( &pcm, deviceNames[i].alsaName, 
SND_PCM_STREAM_PLAYBACK, blocking ) >= 0 )
+        PaAlsaDeviceInfo* devInfo = &deviceInfoArray[i];
+        HwDevInfo* hwInfo = &hwDevInfos[i];
+        if( !strcmp( hwInfo->name, "dmix" ) || !strcmp( hwInfo->name, 
"default" ) )
         {
-            if( GropeDevice( pcm, deviceNames[i].isPlug, StreamDirection_Out, 
blocking, deviceInfo,
-                        &canMmap ) != paNoError )
-            {
-                /* Error */
-                PA_DEBUG(("%s: Failed groping %s for playback\n", 
__FUNCTION__, deviceNames[i].alsaName));
-                continue;
-            }
+            continue;
         }
 
-        if( 0 == canMmap )
+        PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo, &devIdx 
) );
+    }
+    assert( devIdx < numDeviceNames );
+    /* Now inspect 'dmix' and 'default' plugins */
+    for( i = 0; i < numDeviceNames; ++i )
+    {
+        PaAlsaDeviceInfo* devInfo = &deviceInfoArray[i];
+        HwDevInfo* hwInfo = &hwDevInfos[i];
+        if( strcmp( hwInfo->name, "dmix" ) && strcmp( hwInfo->name, "default" 
) )
         {
-            PA_DEBUG(("%s: Device %s doesn't support mmap\n", __FUNCTION__, 
deviceNames[i].alsaName));
             continue;
         }
 
-        baseDeviceInfo->structVersion = 2;
-        baseDeviceInfo->hostApi = alsaApi->hostApiIndex;
-        baseDeviceInfo->name = deviceNames[i].name;
-        deviceInfo->alsaName = deviceNames[i].alsaName;
-        deviceInfo->isPlug = deviceNames[i].isPlug;
-
-        /* A: Storing pointer to PaAlsaDeviceInfo object as pointer to 
PaDeviceInfo object.
-         * Should now be safe to add device info, unless the device supports 
neither capture nor playback
-         */
-        if( baseDeviceInfo->maxInputChannels > 0 || 
baseDeviceInfo->maxOutputChannels > 0 )
-        {
-            if( baseApi->info.defaultInputDevice == paNoDevice && 
baseDeviceInfo->maxInputChannels > 0 )
-                baseApi->info.defaultInputDevice = devIdx;
-            if(  baseApi->info.defaultOutputDevice == paNoDevice && 
baseDeviceInfo->maxOutputChannels > 0 )
-                baseApi->info.defaultOutputDevice = devIdx;
-           if( strcmp(deviceNames[i].alsaName, "default")==0 )
-                baseApi->info.defaultOutputDevice = devIdx;
-            PA_DEBUG(("%s: Adding device %s\n", __FUNCTION__, 
deviceNames[i].name));
-            baseApi->deviceInfos[devIdx++] = (PaDeviceInfo *) deviceInfo;
-        }
+        PA_ENSURE( FillInDevInfo( alsaApi, hwInfo, blocking, devInfo,
+                    &devIdx ) );
     }
-    free( deviceNames );
+    free( hwDevInfos );
 
     baseApi->info.deviceCount = devIdx;   /* Number of successfully queried 
devices */
 
+#ifdef PA_ENABLE_DEBUG_OUTPUT
+    PA_DEBUG(( "%s: Building device list took %f seconds\n", __FUNCTION__, 
PaUtil_GetTime() - startTime ));
+#endif
+
 end:
     return result;
 
@@ -804,8 +930,13 @@
     if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S32 ) >= 
0)
         available |= paInt32;
 
-    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24 ) >= 
0)
+#ifdef PA_LITTLE_ENDIAN
+    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3LE ) 
>= 0)
         available |= paInt24;
+#elif defined PA_BIG_ENDIAN
+    if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S24_3BE ) 
>= 0)
+        available |= paInt24;
+#endif
 
     if( snd_pcm_hw_params_test_format( pcm, hwParams, SND_PCM_FORMAT_S16 ) >= 
0)
         available |= paInt16;
@@ -830,7 +961,11 @@
             return SND_PCM_FORMAT_S16;
 
         case paInt24:
-            return SND_PCM_FORMAT_S24;
+#ifdef PA_LITTLE_ENDIAN
+            return SND_PCM_FORMAT_S24_3LE;
+#elif defined PA_BIG_ENDIAN
+            return SND_PCM_FORMAT_S24_3BE;
+#endif
 
         case paInt32:
             return SND_PCM_FORMAT_S32;
@@ -879,12 +1014,16 @@
         deviceName = streamInfo->deviceString;
 
     PA_DEBUG(( "%s: Opening device %s\n", __FUNCTION__, deviceName ));
-    if( (ret = snd_pcm_open_with_retry( pcm, deviceName, streamDir == 
StreamDirection_In ? SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
-                    SND_PCM_NONBLOCK )) < 0 )
+    if( (ret = OpenPcm( pcm, deviceName, streamDir == StreamDirection_In ? 
SND_PCM_STREAM_CAPTURE : SND_PCM_STREAM_PLAYBACK,
+                    SND_PCM_NONBLOCK, 1 )) < 0 )
     {
         /* Not to be closed */
         *pcm = NULL;
-        ENSURE_( ret, ret == -EBUSY ? paDeviceUnavailable : 
paBadIODeviceCombination );
+        if( -EBUSY == ret )
+        {
+            PA_DEBUG(( "%s: Device is busy\n", __FUNCTION__ ));
+        }
+        ENSURE_( ret, -EBUSY == ret ? paDeviceUnavailable : 
paBadIODeviceCombination );
     }
     ENSURE_( snd_pcm_nonblock( *pcm, 0 ), paUnanticipatedHostError );
 
@@ -942,7 +1081,23 @@
         int ret = 0;
         if( (ret = snd_pcm_hw_params( pcm, hwParams )) < 0)
         {
-            ENSURE_( ret, ret == -EBUSY ? paDeviceUnavailable : 
paUnanticipatedHostError );
+            if( -EINVAL == ret )
+            {
+                /* Don't know what to return here */
+                result = paBadIODeviceCombination;
+                goto error;
+            }
+            else if( -EBUSY == ret )
+            {
+                result = paDeviceUnavailable;
+                PA_DEBUG(( "%s: Device is busy\n", __FUNCTION__ ));
+            }
+            else
+            {
+                result = paUnanticipatedHostError;
+            }
+
+            ENSURE_( ret, result );
         }
     }
 
@@ -1023,6 +1178,8 @@
         self->numHostChannels = params->channelCount;
     }
 
+    self->device = params->device;
+
     PA_ENSURE( AlsaOpen( &alsaApi->baseHostApiRep, params, streamDir, 
&self->pcm ) );
     self->nfds = snd_pcm_poll_descriptors_count( self->pcm );
     hostSampleFormat = PaUtil_SelectClosestAvailableFormat( 
GetAvailableFormats( self->pcm ), userSampleFormat );
@@ -1051,11 +1208,13 @@
         PaUtil_FreeMemory( self->userBuffers );
 }
 
-int nearbyint_(float value) {
+/*
+static int nearbyint_(float value) {
     if(  value - (int)value > .5 )
         return (int)ceil( value );
     return (int)floor( value );
 }
+*/
 
 /** Initiate configuration, preparing for determining a period size suitable 
for both capture and playback components.
  *
@@ -1161,7 +1320,18 @@
     ENSURE_( snd_pcm_hw_params_set_buffer_size_near( self->pcm, hwParams, 
&bufSz ), paUnanticipatedHostError );
 
     /* Set the parameters! */
-    ENSURE_( snd_pcm_hw_params( self->pcm, hwParams ), 
paUnanticipatedHostError );
+    {
+        int r = snd_pcm_hw_params( self->pcm, hwParams );
+#ifdef PA_ENABLE_DEBUG_OUTPUT
+        if( r < 0 )
+        {
+            snd_output_t *output = NULL;
+            snd_output_stdio_attach( &output, stderr, 0 );
+            snd_pcm_hw_params_dump( hwParams, output );
+        }
+#endif
+        ENSURE_(r, paUnanticipatedHostError );
+    }
     ENSURE_( snd_pcm_hw_params_get_buffer_size( hwParams, &self->bufferSize ), 
paUnanticipatedHostError );
     /* Latency in seconds, one period is not counted as latency */
     *latency = (self->bufferSize - self->framesPerBuffer) / sampleRate;
@@ -1415,15 +1585,15 @@
 
         if( framesPerHostBuffer < min )
         {
-            framesPerHostBuffer = min;
             PA_DEBUG(( "%s: The determined period size (%lu) is less than 
minimum (%lu)\n", __FUNCTION__,
                         framesPerHostBuffer, min ));
+            framesPerHostBuffer = min;
         }
         else if( framesPerHostBuffer > max )
         {
-            framesPerHostBuffer = max;
             PA_DEBUG(( "%s: The determined period size (%lu) is greater than 
maximum (%lu)\n", __FUNCTION__,
                         framesPerHostBuffer, max ));
+            framesPerHostBuffer = max;
         }
 
         assert( framesPerHostBuffer >= min && framesPerHostBuffer <= max );
@@ -1947,7 +2117,7 @@
 
     if( stream->callbackMode )
     {
-        PA_ENSURE( PaUnixThread_New( &stream->thread, &CallbackThreadFunc, 
stream, 1. ) );
+        PA_ENSURE( PaUnixThread_New( &stream->thread, &CallbackThreadFunc, 
stream, 1., stream->rtSched ) );
     }
     else
     {
@@ -1972,6 +2142,17 @@
 static PaError AlsaStop( PaAlsaStream *stream, int abort )
 {
     PaError result = paNoError;
+    /* XXX: Seems that draining the dmix device may trigger a race condition 
in ALSA */
+    if( stream->capture.pcm && !strcmp( Pa_GetDeviceInfo( 
stream->capture.device )->name,
+                "dmix" ) )
+    {
+        abort = 1;
+    }
+    else if( stream->playback.pcm && !strcmp( Pa_GetDeviceInfo( 
stream->playback.device )->name,
+                "dmix" ) )
+    {
+        abort = 1;
+    }
 
     if( abort )
     {
@@ -1991,9 +2172,7 @@
         if( stream->playback.pcm )
         {
             ENSURE_( snd_pcm_nonblock( stream->playback.pcm, 0 ), 
paUnanticipatedHostError );
-           /* draining causes deadlock when we are using dmix */
-            /* if( snd_pcm_drain( stream->playback.pcm ) < 0 ) */
-            if( snd_pcm_drop( stream->playback.pcm ) < 0 )
+            if( snd_pcm_drain( stream->playback.pcm ) < 0 )
             {
                 PA_DEBUG(( "%s: Draining playback handle failed!\n", 
__FUNCTION__ ));
             }
@@ -2001,7 +2180,7 @@
         if( stream->capture.pcm && !stream->pcmsSynced )
         {
             /* We don't need to retrieve any remaining frames */
-            if( snd_pcm_drop( stream->capture.pcm ) < 0 )
+            if( snd_pcm_drain( stream->capture.pcm ) < 0 )
             {
                 PA_DEBUG(( "%s: Draining capture handle failed!\n", 
__FUNCTION__ ));
             }
@@ -3309,7 +3488,7 @@
 
 /* Extensions */
 
-/* Initialize host api specific structure */
+/** Initialize host API specific structure, call this before setting relevant 
attributes. */
 void PaAlsa_InitializeStreamInfo( PaAlsaStreamInfo *info )
 {
     info->size = sizeof (PaAlsaStreamInfo);
@@ -3318,55 +3497,55 @@
     info->deviceString = NULL;
 }
 
+/** Instruct whether to enable real-time priority when starting the audio 
thread.
+ *
+ * If this is turned on by the stream is started, the audio callback thread 
will be created
+ * with the FIFO scheduling policy, which is suitable for realtime operation.
+ **/
 void PaAlsa_EnableRealtimeScheduling( PaStream *s, int enable )
 {
-#if 0
     PaAlsaStream *stream = (PaAlsaStream *) s;
-    stream->threading.rtSched = enable;
-#endif
+    stream->rtSched = enable;
 }
 
+#if 0
 void PaAlsa_EnableWatchdog( PaStream *s, int enable )
 {
-#if 0
     PaAlsaStream *stream = (PaAlsaStream *) s;
-    stream->threading.useWatchdog = enable;
-#endif
+    stream->thread.useWatchdog = enable;
 }
+#endif
 
-int PaAlsa_GetInputCard( PaStream *s )
-{
+/** Get the ALSA-lib card index of this stream's input device. */
+PaError PaAlsa_GetStreamInputCard(PaStream* s, int* card) {
     PaAlsaStream *stream = (PaAlsaStream *) s;
-    snd_pcm_info_t *pcmInfo;
-    int card = -1;
+    snd_pcm_info_t* pcmInfo;
+    PaError result = paNoError;
 
-    if( stream->capture.pcm )
-    {
-        snd_pcm_info_alloca( &pcmInfo );
-        if( snd_pcm_info( stream->capture.pcm, pcmInfo ) >= 0 )
-        {
-            card = snd_pcm_info_get_card( pcmInfo );
-        }
-    }
+    /* XXX: More descriptive error? */
+    PA_UNLESS( stream->capture.pcm, paDeviceUnavailable );
 
-    return card;
+    snd_pcm_info_alloca( &pcmInfo );
+    PA_ENSURE( snd_pcm_info( stream->capture.pcm, pcmInfo ) );
+    *card = snd_pcm_info_get_card( pcmInfo );
+
+error:
+    return result;
 }
 
-int PaAlsa_GetOutputCard( PaStream *s )
-{
+/** Get the ALSA-lib card index of this stream's output device. */
+PaError PaAlsa_GetStreamOutputCard(PaStream* s, int* card) {
     PaAlsaStream *stream = (PaAlsaStream *) s;
-    snd_pcm_info_t *pcmInfo;
-    int card = -1;
+    snd_pcm_info_t* pcmInfo;
+    PaError result = paNoError;
 
-    if( stream->playback.pcm )
-    {
-        snd_pcm_info_alloca( &pcmInfo );
-        if( snd_pcm_info( stream->playback.pcm, pcmInfo ) >= 0 )
-        {
-            card = snd_pcm_info_get_card( pcmInfo );
-        }
-    }
+    /* XXX: More descriptive error? */
+    PA_UNLESS( stream->playback.pcm, paDeviceUnavailable );
 
-    return card;
-}
+    snd_pcm_info_alloca( &pcmInfo );
+    PA_ENSURE( snd_pcm_info( stream->playback.pcm, pcmInfo ) );
+    *card = snd_pcm_info_get_card( pcmInfo );
 
+error:
+    return result;
+}


-------------------------------------------------------------------------
This SF.net email is sponsored by DB2 Express
Download DB2 Express C - the FREE version of DB2 express and take
control of your XML. No limits. Just data. Click to get it now.
http://sourceforge.net/powerbar/db2/
_______________________________________________
Audacity-cvs mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/audacity-cvs

Reply via email to