On Thu, Feb 04, 2010 at 08:08:32PM +0100, Alexandre Ratchov wrote:
> On Thu, Feb 04, 2010 at 02:42:33PM +0000, Jacob Meuser wrote:
> > On Thu, Feb 04, 2010 at 10:20:40AM +0100, Alexandre Ratchov wrote:
> > > On Wed, Feb 03, 2010 at 04:10:48PM +0000, Jacob Meuser wrote:
> > > > I wonder if these problems would go away if jack support were dropped
> > > > from portaudio.  only working with 32-bit sounds suspicious.
> > > > 
> > > 
> > > that's easy to check by disabling it, I'll try it..
> > > 
> > > AFAIU, ALSA supports any format and seldom triggers
> > > conversion code of audacity and/or portaudio.
> > > 
> > > sndio backend uses sio_getacap() to return native parameters
> > > and lets portaudio/audacity do the necessary conversions,
> > > since it claims it can. As far as I understand portaudio
> > > internals, this is the ``right thing''. So I bet we trigger
> > > various bugs.
> > > 
> > > I don't exclude there's a bug in sndio backend though.  But,
> > > I wonder whether we shouldn't just claim that any format is
> > > supported and stop using sio_getcap() here.
> > 
> > that might cause other problems if aucat isn't used?
> 
> that shouldn't be a problem. Portaudio exposes the result of
> sio_getpar() to allow the app to display a nice drop-down
> list with the supported parameters.
> 
> But if sio_setpar() fails, it will setup the appropriate
> conversion layer.
> 
> AFAIU, audacity is misusing this mechanism. Not sure yet.
> I'm trying this right now...
> 

Indeed removing sio_getcap() fixes all these problems.  If I
try to record mono on a stereo only device, it just displays
a pop-up with ``format not supported''.

With this diff, I don't observe hangs caused by sample rate
mismatch anymore.

-- Alexandre

Index: Makefile
===================================================================
RCS file: /cvs/ports/audio/portaudio-svn/Makefile,v
retrieving revision 1.6
diff -u -p -r1.6 Makefile
--- Makefile    14 Mar 2009 02:31:40 -0000      1.6
+++ Makefile    4 Feb 2010 20:05:35 -0000
@@ -2,6 +2,7 @@
 
 COMMENT=               portable cross-platform audio API
 DISTNAME=              portaudio-svn-1406
+PKGNAME=               ${DISTNAME}p3
 
 SHARED_LIBS=           portaudio       0.0
 
Index: files/pa_sndio.c
===================================================================
RCS file: /cvs/ports/audio/portaudio-svn/files/pa_sndio.c,v
retrieving revision 1.1
diff -u -p -r1.1 pa_sndio.c
--- files/pa_sndio.c    14 Mar 2009 02:31:40 -0000      1.1
+++ files/pa_sndio.c    4 Feb 2010 20:05:35 -0000
@@ -61,12 +61,11 @@ typedef struct PaSndioHostApiRepresentat
        PaUtilStreamInterface callback;
        PaUtilStreamInterface blocking;
        /*
-        * libsndio has no device discovery mechanism, so expose only
+        * sndio has no device discovery mechanism, so expose only
         * the default device, the user will have a chance to change it
         * using the environment variable
         */
        PaDeviceInfo *infos[1], default_info;
-       struct sio_cap *caps[1], default_cap;
 } PaSndioHostApiRepresentation;
 
 /*
@@ -81,7 +80,7 @@ sndioOnMove(void *addr, int delta)
 }
 
 /*
- * convert PA encoding to libsndio encoding, retrun true on success
+ * convert PA encoding to sndio encoding, retrun true on success
  */
 static int
 sndioSetFmt(struct sio_par *sio, PaSampleFormat fmt)
@@ -118,7 +117,7 @@ sndioSetFmt(struct sio_par *sio, PaSampl
 }
 
 /*
- * convert libsndio encoding to PA encoding, retrun true on success
+ * convert sndio encoding to PA encoding, retrun true on success
  */
 static int
 sndioGetFmt(struct sio_par *sio, PaSampleFormat *fmt)
@@ -139,7 +138,7 @@ sndioGetFmt(struct sio_par *sio, PaSampl
        case 24:
                if (!sio->sig)
                        return 0;
-               *fmt = paInt24;
+               *fmt = (sio->bps == 3) ? paInt24 : paInt32;
                break;
        case 16:
                if (!sio->sig)
@@ -371,8 +370,7 @@ OpenStream(struct PaUtilHostApiRepresent
                        return paInsufficientMemory;
                }
        }       
-       s->base.streamInfo.inputLatency = (mode & SIO_REC) ?
-           (double)(par.bufsz + 
PaUtil_GetBufferProcessorInputLatency(&s->bufproc)) / (double)par.rate : 0;
+       s->base.streamInfo.inputLatency = 0;
        s->base.streamInfo.outputLatency = (mode & SIO_PLAY) ?
            (double)(par.bufsz + 
PaUtil_GetBufferProcessorOutputLatency(&s->bufproc)) / (double)par.rate : 0;
        s->base.streamInfo.sampleRate = par.rate;
@@ -490,8 +488,10 @@ BlockingGetStreamWriteAvailable(PaStream
 static PaError
 BlockingWaitEmpty( PaStream *stream )
 {
+       PaSndioStream *s = (PaSndioStream *)stream;
+
        /*
-        * drain playback buffers; libsndio always does it in background
+        * drain playback buffers; sndio always does it in background
         * and there is no way to wait for completion
         */
        DPR("BlockingWaitEmpty: s=%d, a=%d\n", s->stopped, s->active);
@@ -630,61 +630,6 @@ IsFormatSupported(struct PaUtilHostApiRe
     const PaStreamParameters *outputPar,
     double sampleRate)
 {
-       PaSndioHostApiRepresentation *sndioHostApi = 
(PaSndioHostApiRepresentation *)hostApi;
-       struct sio_cap *cap = sndioHostApi->caps[0];
-       struct sio_conf *cf = &cap->confs[0];
-       unsigned i;
-       
-
-       if (inputPar && inputPar->channelCount > 0) {
-               if (inputPar->device != 0) {
-                       DPR("IsFormatSupported: %d: bad input device\n", 
inputPar->device);
-                       return paInvalidDevice;
-               }
-               if (inputPar->hostApiSpecificStreamInfo) {
-                       DPR("IsFormatSupported: input specific info\n");
-                       return paIncompatibleHostApiSpecificStreamInfo;
-               }
-               for (i = 0; ; i++) {
-                       if (i == 8 * sizeof(unsigned)) {
-                               DPR("IsFormatSupported: input channel not 
found\n");
-                               return paInvalidChannelCount;
-                       }
-                       if ((cf->rchan & (1 << i)) &&
-                           (cap->rchan[i] == inputPar->channelCount))
-                               break;
-               }
-       }
-       if (outputPar && outputPar->channelCount > 0) {
-               if (outputPar->device != 0) {
-                       DPR("IsFormatSupported: %d: bad output device\n", 
outputPar->device);
-                       return paInvalidDevice;
-               }
-               if (outputPar->hostApiSpecificStreamInfo) {
-                       DPR("IsFormatSupported: output specific info\n");
-                       return paIncompatibleHostApiSpecificStreamInfo;
-               }
-               for (i = 0; ; i++) {
-                       if (i == 8 * sizeof(unsigned)) {
-                               DPR("IsFormatSupported: output channel not 
found\n");
-                               return paInvalidChannelCount;
-                       }
-                       if ((cf->pchan & (1 << i)) &&
-                           (cap->pchan[i] == outputPar->channelCount))
-                               break;
-               }
-       }
-
-       for (i = 0; ; i++) {
-               if (i == 8 * sizeof(unsigned)) {
-                       DPR("IsFormatSupported: rate not found\n");
-                       return paInvalidSampleRate;
-               }
-               if ((cf->rate & (1 << i)) &&
-                   (double)cap->rate[i] > sampleRate * 0.995 &&
-                   (double)cap->rate[i] < sampleRate * 1.005)
-                       break;
-       }
        return paFormatIsSupported;
 }
 
@@ -700,9 +645,6 @@ PaSndio_Initialize(PaUtilHostApiRepresen
        PaSndioHostApiRepresentation *sndioHostApi;
        PaDeviceInfo *info;
        struct sio_hdl *hdl;
-       struct sio_cap *cap;
-       struct sio_conf *cf;
-       unsigned i, maxpchan, maxrchan, maxrate;
        
        DPR("PaSndio_Initialize: initializing...\n");
 
@@ -713,47 +655,23 @@ PaSndio_Initialize(PaUtilHostApiRepresen
        if (sndioHostApi == NULL)
                return paNoError;
 
-       if (!(hdl = sio_open(NULL, SIO_PLAY | SIO_REC, 0)) &&
-           !(hdl = sio_open(NULL, SIO_REC, 0)) &&
-           !(hdl = sio_open(NULL, SIO_PLAY, 0))) {
-               PaUtil_FreeMemory(sndioHostApi);
-               return paNoError;
-       }
-       cap = &sndioHostApi->default_cap;
-       if (!sio_getcap(hdl, cap)) {
-               PaUtil_FreeMemory(sndioHostApi);
-               return paNoError;
-       }
-       cf = &cap->confs[0];
-       maxpchan = maxrchan = maxrate = 0;
-       for (i = 0; i < 8 * sizeof(unsigned); i++) {
-               if ((cf->rchan & (1 << i)) && (maxrchan < cap->rchan[i]))
-                       maxrchan = cap->rchan[i];
-               if ((cf->pchan & (1 << i)) && (maxpchan < cap->pchan[i]))
-                       maxpchan = cap->pchan[i];
-               if ((cf->rate & (1 << i)) && (maxrate < cap->rate[i]))
-                       maxrate  = cap->rate[i];
-       }
-       sio_close(hdl);
-       sndioHostApi->caps[0] = cap;
-       
        info = &sndioHostApi->default_info;
        info->structVersion = 2;
        info->name = "default";
        info->hostApi = hostApiIndex;
-       info->maxInputChannels = maxrchan;
-       info->maxOutputChannels = maxpchan;
+       info->maxInputChannels = 65536;
+       info->maxOutputChannels = 65536;
        info->defaultLowInputLatency = 0.01;
        info->defaultLowOutputLatency = 0.01;
        info->defaultHighInputLatency = 0.5;
        info->defaultHighOutputLatency = 0.5;
-       info->defaultSampleRate = maxrate;
+       info->defaultSampleRate = 192000;
        sndioHostApi->infos[0] = info;
        
        *hostApi = &sndioHostApi->base;
        (*hostApi)->info.structVersion = 1;
        (*hostApi)->info.type = paSndio;
-       (*hostApi)->info.name = "libsndio";
+       (*hostApi)->info.name = "sndio";
        (*hostApi)->info.deviceCount = 1;
        (*hostApi)->info.defaultInputDevice = 0;
        (*hostApi)->info.defaultOutputDevice = 0;

Reply via email to