static PaError Pa_PauseAndFlush(int devHandle)
{
  audio_info_t solaris_info;
  AUDIO_INITINFO(&solaris_info);

  solaris_info.play.pause = solaris_info.record.pause = 1;

  if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)
    {
      ERR_RPT(("Pa_FlushStream failed.\n"));
      return paHostError;
    }

  if (ioctl(devHandle, I_FLUSH, FLUSHRW) == -1)
    {
      ERR_RPT(("Pa_FlushStream failed.\n"));

      /* Unpause! */
      AUDIO_INITINFO(&solaris_info);
      solaris_info.play.pause = solaris_info.record.pause = 0;
      ioctl(devHandle, AUDIO_SETINFO, &solaris_info);

      return paHostError;
    }
  return paNoError;
}
Exemple #2
0
PaError PaHost_CloseStream( internalPortAudioStream   *past )
{
    PaHostSoundControl *pahsc;

    if( past == NULL ) return paBadStreamPtr;
    pahsc = (PaHostSoundControl *) past->past_DeviceData;
    if( pahsc == NULL ) return paNoError;

    if( pahsc->pahsc_OutputHandle != BAD_DEVICE_ID )
    {
        int err = 0;
        DBUG(("PaHost_CloseStream: attempt to close output device handle = %d\n",
              pahsc->pahsc_OutputHandle ));

        Pa_FlushStream(pahsc->pahsc_OutputHandle);

        err = close(pahsc->pahsc_OutputHandle);
        if( err < 0 )
        {
            ERR_RPT(("PaHost_CloseStream: warning, closing output device failed.\n"));
        }
    }

    if( (pahsc->pahsc_InputHandle != BAD_DEVICE_ID) &&
            (pahsc->pahsc_InputHandle != pahsc->pahsc_OutputHandle) )
    {
        int err = 0;
        DBUG(("PaHost_CloseStream: attempt to close input device handle = %d\n",
              pahsc->pahsc_InputHandle ));

        Pa_FlushStream(pahsc->pahsc_InputHandle);

        err = close(pahsc->pahsc_InputHandle);
        if( err < 0 )
        {
            ERR_RPT(("PaHost_CloseStream: warning, closing input device failed.\n"));
        }
    }
    pahsc->pahsc_OutputHandle = BAD_DEVICE_ID;
    pahsc->pahsc_InputHandle = BAD_DEVICE_ID;

    if( pahsc->pahsc_NativeInputBuffer )
    {
        free( pahsc->pahsc_NativeInputBuffer );
        pahsc->pahsc_NativeInputBuffer = NULL;
    }
    if( pahsc->pahsc_NativeOutputBuffer )
    {
        free( pahsc->pahsc_NativeOutputBuffer );
        pahsc->pahsc_NativeOutputBuffer = NULL;
    }

    free( pahsc );
    past->past_DeviceData = NULL;
    return paNoError;
}
Exemple #3
0
/* Tries to set various rates and formats and fill in the device info structure.            */
static PaError Pa_sgiQueryDevice(long                     ALdev,  /* (AL_DEFAULT_DEVICE)    */
                                 PaDeviceID               id,     /* (DefaultI|ODeviceID()) */
                                 char*                    name,   /* (for example "SGI AL") */
                                 internalPortAudioDevice* pad)    /* Result written to pad. */
{
	int     format;
    long    min, max;                           /* To catch hardware characteristics.       */
    ALseterrorhandler(0);                       /* 0 = turn off the default error handler.  */
    /*--------------------------------------------------------------------------------------*/
    pad->pad_ALdevice = ALdev;                              /* Set the AL device number.    */
    pad->pad_DeviceID = id;                                 /* Set the PA device number.    */
    if (strlen(name) > MAX_CHARS_DEVNAME)                   /* MAX_CHARS defined above.     */
        {
        ERR_RPT(("Pa_QueryDevice(): name too long (%s).\n", name));
        return paHostError;
        }
    strcpy(pad->pad_DeviceName, name);                      /* Write name-string.           */
	pad->pad_Info.name = pad->pad_DeviceName;               /* Set pointer,..hmmm.          */
    /*--------------------------------- natively supported sample formats: -----------------*/
    pad->pad_Info.nativeSampleFormats = paInt16; /* Later also include paFloat32 | ..| etc. */
                                                 /* Then also choose other CallConvertXX()! */
    /*--------------------------------- number of available i/o channels: ------------------*/
    if (ALgetminmax(ALdev, AL_INPUT_COUNT, &min, &max))
        return translateSGIerror();
	pad->pad_Info.maxInputChannels = max;
	DBUG(("Pa_QueryDevice: maxInputChannels = %d\n", pad->pad_Info.maxInputChannels))
    if (ALgetminmax(ALdev, AL_OUTPUT_COUNT, &min, &max))
        return translateSGIerror();
	pad->pad_Info.maxOutputChannels = max;
	DBUG(("Pa_QueryDevice: maxOutputChannels = %d\n", pad->pad_Info.maxOutputChannels))
    /*--------------------------------- supported samplerates: ----------------------*/ 
	pad->pad_Info.numSampleRates = 7;   
	pad->pad_Info.sampleRates = pad->pad_SampleRates;
    pad->pad_SampleRates[0] = (double)AL_RATE_8000;     /* long -> double. */
    pad->pad_SampleRates[1] = (double)AL_RATE_11025;
    pad->pad_SampleRates[2] = (double)AL_RATE_16000;
    pad->pad_SampleRates[3] = (double)AL_RATE_22050;
    pad->pad_SampleRates[4] = (double)AL_RATE_32000;
    pad->pad_SampleRates[5] = (double)AL_RATE_44100;
    pad->pad_SampleRates[6] = (double)AL_RATE_48000;
    if (ALgetminmax(ALdev, AL_INPUT_RATE, &min, &max))  /* Ask INPUT rate-max.       */
        return translateSGIerror();                     /* double -> long.           */
    if (max != (long)(0.5 + pad->pad_SampleRates[6]))   /* FP-compare not recommndd. */
        goto weird;
    if (ALgetminmax(ALdev, AL_OUTPUT_RATE, &min, &max)) /* Ask OUTPUT rate-max.      */
        return translateSGIerror();
    if (max != (long)(0.5 + pad->pad_SampleRates[6]))
        {
weird:  ERR_RPT(("Pa_sgiQueryDevice() did not confirm max samplerate (%ld)\n",max));
        return paHostError;             /* Or make it a warning and just carry on... */
        }
    /*-------------------------------------------------------------------------------*/ 
	return paNoError;
}
PaError Pa_SetupOutputDeviceFormat( int devHandle, int numChannels, int sampleRate )
{
    audio_info_t solaris_info;
    AUDIO_INITINFO(&solaris_info);

    /* Sam Bayer/Bryan George 1/10/02: Various folks have
       reported that on Solaris Ultra II, the not-right thing
       happens on read unless you make sure the audio device is
       flushed. The folks who wrote the Robust Audio Tool say:
       + XXX driver issue - on Ultra II's if you don't drain
       * the device before reading commences then the device
       * reads in blocks of 500ms irrespective of the
       * blocksize set. After a minute or so it flips into the
       * correct mode, but obviously this is too late to be + * useful for most apps. grrr.
       */
    /* AS: And the Solaris man audio pages say you should flush before changing formats
       anyway.  So there you go. */
    if (Pa_FlushStream(devHandle) != paNoError)
      return paHostError;

    solaris_info.play.encoding = AUDIO_ENCODING_LINEAR;
    solaris_info.play.sample_rate = sampleRate;
    solaris_info.play.precision = 16;
    solaris_info.play.channels = numChannels;

    if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)
      {
        ERR_RPT(("Pa_SetupDeviceFormat: could not set audio info\n" ));
        return paHostError;
      }

    return paNoError;
}
static PaError Pa_PauseAndFlush(int devHandle)
{
  audio_info_t solaris_info;
  AUDIO_INITINFO(&solaris_info);

  solaris_info.play.pause = solaris_info.record.pause = 1;

  if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)
    {
      ERR_RPT(("Pa_FlushStream failed.\n"));
      return paHostError;
    }

#if defined I_FLUSH && defined FLUSHRW
  /* Flush the audiobuffer */
  if (ioctl(devHandle, I_FLUSH, FLUSHRW) == -1)
    {
      ERR_RPT(("Pa_FlushStream failed.\n"));

      /* Unpause! */
      AUDIO_INITINFO(&solaris_info);
      solaris_info.play.pause = solaris_info.record.pause = 0;
      ioctl(devHandle, AUDIO_SETINFO, &solaris_info);

      return paHostError;
    }
#endif

#if defined AUDIO_FLUSH
    if (ioctl(devHandle, AUDIO_FLUSH, NULL) == -1)
    {
      ERR_RPT(("Pa_FlushStream failed.\n"));

      /* Unpause! */
      AUDIO_INITINFO(&solaris_info);
      solaris_info.play.pause = solaris_info.record.pause = 0;
      ioctl(devHandle, AUDIO_SETINFO, &solaris_info);

      return paHostError;
    }
#endif

  return paNoError;
}
Exemple #6
0
/*----------------------------------------------------------------------*/
const PaDeviceInfo* Pa_GetDeviceInfo(PaDeviceID id)
{
    PaDeviceInfo*             res = (PaDeviceInfo*)NULL;
	internalPortAudioDevice*  pad = Pa_GetInternalDevice(id);  /* Call. */
    if (pad)
	    res = &pad->pad_Info;   /* Not finding the specified ID is not  */
    if (!res)                   /* the same as &pad->pad_Info == NULL.  */
        ERR_RPT(("Pa_GetDeviceInfo() could not find it (ID=%d).\n", id));
    return res;                 /* So (maybe) a second/third ERR_RPT(). */
}
void Pa_SetLatency( int devHandle, int numBuffers, int framesPerBuffer, int channelsPerFrame  )
{
  int     bufferSize;
  audio_info_t solaris_info;

  /* Increase size of buffers and reduce number of buffers to reduce latency inside driver. */
  while( numBuffers > 8 )
    {
      numBuffers = (numBuffers + 1) >> 1;
      framesPerBuffer = framesPerBuffer << 1;
    }

  /* calculate size of buffers in bytes */
  bufferSize = framesPerBuffer * channelsPerFrame * sizeof(short); /* FIXME - other sizes? */

  DBUG(("Pa_SetLatency: numBuffers = %d, framesPerBuffer = %d\n",
	numBuffers, framesPerBuffer));

  /* SAM 6/6/02: Documentation says to pause and flush before
     changing buffer size. */

  if (Pa_PauseAndFlush(devHandle) != paNoError) {
    ERR_RPT(("Pa_SetLatency: could not pause audio\n" ));
    return;
  }

  AUDIO_INITINFO(&solaris_info);

  /* AS: Doesn't look like solaris has multiple buffers,
     so I'm being conservative and
     making one buffer.  Might not be what we want... */

  solaris_info.play.buffer_size = solaris_info.record.buffer_size = bufferSize;

  if (ioctl(devHandle, AUDIO_SETINFO, &solaris_info) == -1)
    {
      ERR_RPT(("Pa_SetLatency: could not set audio info\n" ));
    }
  Pa_Unpause(devHandle);
}
Exemple #8
0
/* Build linked a list with all the available audio devices on this SGI machine (only 1 for now).  */
PaError PaHost_Init(void)                              /* Called by Pa_Initialize() from pa_lib.c. */
{
    internalPortAudioDevice*    pad;
	PaError                     r = paNoError;
    int                         audioLibFileID;             /* To test for the presence of audio.  */

    if (sDeviceList)                                        /* Allow re-init, only warn, no error. */
        {
        ERR_RPT(("Warning: PaHost_Init() did not really re-init PA.\n"));
        return r;
        }
    /*------------- ADD THE SGI DEFAULT DEVICE TO THE LIST: ---------------------------------------*/
    audioLibFileID = open("/dev/hdsp/hdsp0master", O_RDONLY);   /* Try to open Indigo style audio  */
    if (audioLibFileID < 0)                                     /* IO port. On failure, machine    */
        {                                                       /* has no audio ability.           */
        ERR_RPT(("PaHost_Init(): This machine has no (Indigo-style) audio abilities.\n"));
        return paHostError;
        }
    close(audioLibFileID);                              /* Allocate fast mem to hold device info.  */
	pad = PaHost_AllocateFastMemory(sizeof(internalPortAudioDevice));
	if (pad == NULL)
        return paInsufficientMemory;
    memset(pad, 0, sizeof(internalPortAudioDevice));    /* "pad->pad_Next = NULL" is more elegant. */
	r = Pa_sgiQueryDevice(AL_DEFAULT_DEVICE,            /* Set AL device num (AL_DEFAULT_DEVICE).  */
                          Pa_GetDefaultOutputDeviceID(),/* Set PA device num (or InputDeviceID()). */
                          "AL default",                 /* A suitable name.                        */
                          pad);                         /* Write args and queried info into pad.   */
	if (r != paNoError)
		{
        ERR_RPT(("Pa_QueryDevice for '%s' returned: %d\n", pad->pad_DeviceName, r));
		PaHost_FreeFastMemory(pad, sizeof(internalPortAudioDevice));   /* sDeviceList still NULL ! */
		}
    else
        sDeviceList = pad;            /* First element in linked list. pad->pad_Next already NULL. */
    /*------------- QUERY AND ADD MORE POSSIBLE SGI DEVICES TO THE LINKED LIST: -------------------*/
    /*---------------------------------------------------------------------------------------------*/
	return r;
}
Exemple #9
0
/*-------------------------------------------------------------------------------*/
static internalPortAudioDevice *Pa_GetInternalDevice(PaDeviceID id)
{
    int                         numDevices = 0;
    internalPortAudioDevice     *res = (internalPortAudioDevice*)NULL;
	internalPortAudioDevice     *pad = sDeviceList;         /* COPY GLOBAL VAR.  */
    while (pad)                         /* pad may be NULL, that's ok, return 0. */
        {  /* (Added ->pad_DeviceID field to the pad-struct, Pieter, 2001.)      */
        if (pad->pad_DeviceID == id)    /* This the device we were looking for?  */
            res = pad;                  /* But keep on(!) counting so we don't   */
        numDevices++;                   /* have to call Pa_CountDevices() later. */
        pad = pad->pad_Next;            /* Advance to the next device or NULL.   */
        }                               /* No assumptions about order of ID's in */
    if (!res)                           /* the list.                             */
        ERR_RPT(("Pa_GetInternalDevice() could not find specified ID (%d).\n",id));
    if ((id < 0) || (id >= numDevices))
        {
        ERR_RPT(("Pa_GetInternalDevice() supplied with an illegal ID (%d).\n",id));
#if 1                                             /* Be strict, even when found, */
        res = (internalPortAudioDevice*)NULL;     /* do not accept illegal ID's. */
#endif
        }
	return res;
}
Exemple #10
0
/*********************************************************************
 * Try to open the named device.
 * If it opens, try to set various rates and formats and fill in 
 * the device info structure.
 */
PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad )
{
    int result = paHostError;
    int tempDevHandle;
    int numChannels, maxNumChannels;
    int format;
    int numSampleRates;
    int sampleRate;
    int numRatesToTry;
    int lastRate;
    int ratesToTry[9] = {96000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};
    int i;

    /* douglas:
     we have to do this querying in a slightly different order. apparently
     some sound cards will give you different info based on their settings. 
     e.g. a card might give you stereo at 22kHz but only mono at 44kHz.
     the correct order for OSS is: format, channels, sample rate
     
    */
    if ( (tempDevHandle = open(deviceName,O_WRONLY|O_NONBLOCK))  == -1 )
    {
        DBUG(("Pa_QueryDevice: could not open %s\n", deviceName ));
        return paHostError;
    }

    /*  Ask OSS what formats are supported by the hardware. */
    pad->pad_Info.nativeSampleFormats = 0;

    if (ioctl(tempDevHandle, SNDCTL_DSP_GETFMTS, &format) == -1)
    {
        ERR_RPT(("Pa_QueryDevice: could not get format info\n" ));
        goto error;
    }
    if( format & AFMT_U8 )     pad->pad_Info.nativeSampleFormats |= paUInt8;
    if( format & AFMT_S16_NE ) pad->pad_Info.nativeSampleFormats |= paInt16;

    /* Negotiate for the maximum number of channels for this device. PLB20010927
     * Consider up to 16 as the upper number of channels.
     * Variable numChannels should contain the actual upper limit after the call.
     * Thanks to John Lazzaro and Heiko Purnhagen for suggestions.
     */
    maxNumChannels = 0;
    for( numChannels = 1; numChannels <= 16; numChannels++ )
    {
        int temp = numChannels;
        DBUG(("Pa_QueryDevice: use SNDCTL_DSP_CHANNELS, numChannels = %d\n", numChannels ))
        if(ioctl(tempDevHandle, SNDCTL_DSP_CHANNELS, &temp) < 0 )
        {
            /* ioctl() failed so bail out if we already have stereo */
            if( numChannels > 2 ) break;
        }
        else
        {
            /* ioctl() worked but bail out if it does not support numChannels.
             * We don't want to leave gaps in the numChannels supported.
             */
            if( (numChannels > 2) && (temp != numChannels) ) break;
            DBUG(("Pa_QueryDevice: temp = %d\n", temp ))
            if( temp > maxNumChannels ) maxNumChannels = temp; /* Save maximum. */
        }
    }

    /* The above negotiation may fail for an old driver so try this older technique. */
    if( maxNumChannels < 1 )
    {
        int stereo = 1;
        if(ioctl(tempDevHandle, SNDCTL_DSP_STEREO, &stereo) < 0)
        {
            maxNumChannels = 1;
        }
        else
        {
            maxNumChannels = (stereo) ? 2 : 1;
        }
        DBUG(("Pa_QueryDevice: use SNDCTL_DSP_STEREO, maxNumChannels = %d\n", maxNumChannels ))
    }
Exemple #11
0
PaError PaHost_OpenStream( internalPortAudioStream   *past )
{
    PaError          result = paNoError;
    PaHostSoundControl *pahsc;
    unsigned int     minNumBuffers;
    internalPortAudioDevice *pad;
    DBUG(("PaHost_OpenStream() called.\n" ));

    /* Allocate and initialize host data. */
    pahsc = (PaHostSoundControl *) malloc(sizeof(PaHostSoundControl));
    if( pahsc == NULL )
    {
        result = paInsufficientMemory;
        goto error;
    }
    memset( pahsc, 0, sizeof(PaHostSoundControl) );
    past->past_DeviceData = (void *) pahsc;

    pahsc->pahsc_OutputHandle = BAD_DEVICE_ID; /* No device currently opened. */
    pahsc->pahsc_InputHandle = BAD_DEVICE_ID;
    pahsc->pahsc_IsAudioThreadValid = 0;
    pahsc->pahsc_IsWatchDogThreadValid = 0;

    /* Allocate native buffers. */
    pahsc->pahsc_BytesPerInputBuffer = past->past_FramesPerUserBuffer *
                                       past->past_NumInputChannels * sizeof(short);
    if( past->past_NumInputChannels > 0)
    {
        pahsc->pahsc_NativeInputBuffer = (short *) malloc(pahsc->pahsc_BytesPerInputBuffer);
        if( pahsc->pahsc_NativeInputBuffer == NULL )
        {
            result = paInsufficientMemory;
            goto error;
        }
    }
    pahsc->pahsc_BytesPerOutputBuffer = past->past_FramesPerUserBuffer *
                                        past->past_NumOutputChannels * sizeof(short);
    if( past->past_NumOutputChannels > 0)
    {
        pahsc->pahsc_NativeOutputBuffer = (short *) malloc(pahsc->pahsc_BytesPerOutputBuffer);
        if( pahsc->pahsc_NativeOutputBuffer == NULL )
        {
            result = paInsufficientMemory;
            goto error;
        }
    }

    /* DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer )); */
    minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate );
    past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers;

    pahsc->pahsc_InverseMicrosPerBuffer = past->past_SampleRate / (1000000.0 * past->past_FramesPerUserBuffer);
    DBUG(("past_SampleRate = %g\n", past->past_SampleRate ));
    DBUG(("past_FramesPerUserBuffer = %d\n", past->past_FramesPerUserBuffer ));
    DBUG(("pahsc_InverseMicrosPerBuffer = %g\n", pahsc->pahsc_InverseMicrosPerBuffer ));

    /* ------------------------- OPEN DEVICE -----------------------*/

    /* just output */
    if (past->past_OutputDeviceID == past->past_InputDeviceID)
    {

        if ((past->past_NumOutputChannels > 0) && (past->past_NumInputChannels > 0) )
        {
            pad = Pa_GetInternalDevice( past->past_OutputDeviceID );
            DBUG(("PaHost_OpenStream: attempt to open %s for O_RDWR\n", pad->pad_DeviceName ));

            /* dmazzoni: test it first in nonblocking mode to
               make sure the device is not busy */
            pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDWR|O_NONBLOCK);
            if(pahsc->pahsc_InputHandle==-1)
            {
                ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDWR\n", pad->pad_DeviceName ));
                result = paHostError;
                goto error;
            }
            close(pahsc->pahsc_InputHandle);

            pahsc->pahsc_OutputHandle = pahsc->pahsc_InputHandle =
                                            open(pad->pad_DeviceName,O_RDWR);
            if(pahsc->pahsc_InputHandle==-1)
            {
                ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDWR\n", pad->pad_DeviceName ));
                result = paHostError;
                goto error;
            }
            Pa_SetLatency( pahsc->pahsc_OutputHandle,
                           past->past_NumUserBuffers, past->past_FramesPerUserBuffer,
                           past->past_NumOutputChannels );
            result = Pa_SetupDeviceFormat( pahsc->pahsc_OutputHandle,
                                           past->past_NumOutputChannels, (int)past->past_SampleRate );
        }
    }
    else
    {
        if (past->past_NumOutputChannels > 0)
        {
            pad = Pa_GetInternalDevice( past->past_OutputDeviceID );
            DBUG(("PaHost_OpenStream: attempt to open %s for O_WRONLY\n", pad->pad_DeviceName ));
            /* dmazzoni: test it first in nonblocking mode to
               make sure the device is not busy */
            pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY|O_NONBLOCK);
            if(pahsc->pahsc_OutputHandle==-1)
            {
                ERR_RPT(("PaHost_OpenStream: could not open %s for O_WRONLY\n", pad->pad_DeviceName ));
                result = paHostError;
                goto error;
            }
            close(pahsc->pahsc_OutputHandle);

            pahsc->pahsc_OutputHandle = open(pad->pad_DeviceName,O_WRONLY);
            if(pahsc->pahsc_OutputHandle==-1)
            {
                ERR_RPT(("PaHost_OpenStream: could not open %s for O_WRONLY\n", pad->pad_DeviceName ));
                result = paHostError;
                goto error;
            }
            Pa_SetLatency( pahsc->pahsc_OutputHandle,
                           past->past_NumUserBuffers, past->past_FramesPerUserBuffer,
                           past->past_NumOutputChannels );
            result = Pa_SetupOutputDeviceFormat( pahsc->pahsc_OutputHandle,
                                           past->past_NumOutputChannels, (int)past->past_SampleRate );
        }

        if (past->past_NumInputChannels > 0)
        {
            pad = Pa_GetInternalDevice( past->past_InputDeviceID );
            DBUG(("PaHost_OpenStream: attempt to open %s for O_RDONLY\n", pad->pad_DeviceName ));
            /* dmazzoni: test it first in nonblocking mode to
               make sure the device is not busy */
            pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY|O_NONBLOCK);
            if(pahsc->pahsc_InputHandle==-1)
            {
                ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDONLY\n", pad->pad_DeviceName ));
                result = paHostError;
                goto error;
            }
            close(pahsc->pahsc_InputHandle);

            pahsc->pahsc_InputHandle = open(pad->pad_DeviceName,O_RDONLY);
            if(pahsc->pahsc_InputHandle==-1)
            {
                ERR_RPT(("PaHost_OpenStream: could not open %s for O_RDONLY\n", pad->pad_DeviceName ));
                result = paHostError;
                goto error;
            }
            Pa_SetLatency( pahsc->pahsc_InputHandle, /* DH20010115 - was OutputHandle! */
                           past->past_NumUserBuffers, past->past_FramesPerUserBuffer,
                           past->past_NumInputChannels );
            result = Pa_SetupInputDeviceFormat( pahsc->pahsc_InputHandle,
                                           past->past_NumInputChannels, (int)past->past_SampleRate );
        }
    }


    DBUG(("PaHost_OpenStream: SUCCESS - result = %d\n", result ));
    return result;

error:
    ERR_RPT(("PaHost_OpenStream: ERROR - result = %d\n", result ));
    PaHost_CloseStream( past );
    return result;
}
Exemple #12
0
static PaError Pa_AudioThreadProc( internalPortAudioStream   *past )
{
    PaError      result;
    PaHostSoundControl             *pahsc;
    ssize_t      bytes_read, bytes_written;

    pahsc = (PaHostSoundControl *) past->past_DeviceData;
    if( pahsc == NULL ) return paInternalError;

#ifdef GNUSTEP
    GSRegisterCurrentThread(); /* SB20010904 */
#endif

    result = PaHost_BoostPriority( past );
    if( result < 0 ) goto error;

    past->past_IsActive = 1;
    DBUG(("entering thread.\n"));

    while( (past->past_StopNow == 0) && (past->past_StopSoon == 0) )
    {
        /* Read data from device */
        if(pahsc->pahsc_NativeInputBuffer)
        {
            unsigned int totalread = 0;
            DBUG(("Pa_AudioThreadProc: attempt to read %d bytes\n", pahsc->pahsc_BytesPerInputBuffer));
            do
            {
                bytes_read = read(pahsc->pahsc_InputHandle,
                    (char *)pahsc->pahsc_NativeInputBuffer + totalread,
                    pahsc->pahsc_BytesPerInputBuffer - totalread);

                if (bytes_read < 0)
                {
                    ERR_RPT(("PortAudio: read interrupted!\n"));
                    break;
                }

                totalread += bytes_read;
            } while( totalread < pahsc->pahsc_BytesPerInputBuffer);
        }

        /* Convert 16 bit native data to user data and call user routine. */
        DBUG(("converting...\n"));
        Pa_StartUsageCalculation( past );
        result = Pa_CallConvertInt16( past,
                                      pahsc->pahsc_NativeInputBuffer,
                                      pahsc->pahsc_NativeOutputBuffer );
        Pa_EndUsageCalculation( past );
        if( result != 0)
        {
            DBUG(("hmm, Pa_CallConvertInt16() says: %d. i'm bailing.\n",
                  result));
            break;
        }

        /* Write data to device. */
        if( pahsc->pahsc_NativeOutputBuffer )
        {
            unsigned int totalwritten = 0;
            do
            {
                bytes_written = write(pahsc->pahsc_OutputHandle,
                    (void *)pahsc->pahsc_NativeOutputBuffer,
                    pahsc->pahsc_BytesPerOutputBuffer);
                if( bytes_written < 0 )
                {
                    ERR_RPT(("PortAudio: write interrupted!"));
                    break;
                }

                totalwritten += bytes_written;
            } while( totalwritten < pahsc->pahsc_BytesPerOutputBuffer);
        }

        Pa_UpdateStreamTime(pahsc);
    }
    DBUG(("Pa_AudioThreadProc: left audio loop.\n"));

    past->past_IsActive = 0;
    PaHost_StopWatchDog( pahsc );

error:
    DBUG(("leaving audio thread.\n"));
#ifdef GNUSTEP
    GSUnregisterCurrentThread();  /* SB20010904 */
#endif
    return result;
}
Exemple #13
0
static PaError PaHost_WatchDogProc( PaHostSoundControl   *pahsc )
{
    struct sched_param    schp = { 0 };
    int                   maxPri;

#ifdef GNUSTEP
    GSRegisterCurrentThread(); /* SB20010904 */
#endif

/* Run at a priority level above audio thread so we can still run if it hangs. */
/* Rise more than 1 because of rumored off-by-one scheduler bugs. */
    schp.sched_priority = pahsc->pahsc_AudioPriority + 4;
    maxPri = sched_get_priority_max(SCHEDULER_POLICY);
    if( schp.sched_priority > maxPri ) schp.sched_priority = maxPri;

    if (sched_setscheduler(0, SCHEDULER_POLICY, &schp) != 0)
    {
        ERR_RPT(("PaHost_WatchDogProc: cannot set watch dog priority!\n"));
        goto killAudio;
    }

    /* Compare watchdog time with audio and canary thread times. */
    /* Sleep for a while or until thread cancelled. */
    while( pahsc->pahsc_WatchDogRun )
    {

        int              delta;
        struct timeval   currentTime;

        usleep( WATCHDOG_INTERVAL_USEC );
        gettimeofday( &currentTime, NULL );

        /* If audio thread is not advancing, then it must be hung so kill it. */
        delta = currentTime.tv_sec - pahsc->pahsc_EntryTime.tv_sec;
        DBUG(("PaHost_WatchDogProc: audio delta = %d\n", delta ));
        if( delta > WATCHDOG_MAX_SECONDS )
        {
            goto killAudio;
        }

        /* If canary died, then lower audio priority and halt canary. */
        delta = currentTime.tv_sec - pahsc->pahsc_CanaryTime.tv_sec;
        if( delta > WATCHDOG_MAX_SECONDS )
        {
            ERR_RPT(("PaHost_WatchDogProc: canary died!\n"));
            goto lowerAudio;
        }
    }

    DBUG(("PaHost_WatchDogProc: exiting.\n"));
#ifdef GNUSTEP
    GSUnregisterCurrentThread();  /* SB20010904 */
#endif
    return 0;

lowerAudio:
    {
        struct sched_param    schat = { 0 };
        if( sched_setscheduler(pahsc->pahsc_AudioThreadPID, SCHED_OTHER, &schat) != 0)
        {
            ERR_RPT(("PaHost_WatchDogProc: failed to lower audio priority. errno = %d\n", errno ));
            /* Fall through into killing audio thread. */
        }
        else
        {
            ERR_RPT(("PaHost_WatchDogProc: lowered audio priority to prevent hogging of CPU.\n"));
            goto cleanup;
        }
    }

killAudio:
    ERR_RPT(("PaHost_WatchDogProc: killing hung audio thread!\n"));
    pthread_kill( pahsc->pahsc_AudioThread, SIGKILL );

cleanup:
    pahsc->pahsc_CanaryRun = 0;
    DBUG(("PaHost_WatchDogProc: cancel Canary\n"));
    pthread_cancel( pahsc->pahsc_CanaryThread );
    DBUG(("PaHost_WatchDogProc: join Canary\n"));
    pthread_join( pahsc->pahsc_CanaryThread, NULL );
    DBUG(("PaHost_WatchDogProc: forget Canary\n"));
    pahsc->pahsc_IsCanaryThreadValid = 0;

#ifdef GNUSTEP
    GSUnregisterCurrentThread();  /* SB20010904 */
#endif
    return 0;
}
Exemple #14
0
static int WatchDogProc( prioboost *b )
{
	struct sched_param    schp = { 0 };
	int                   maxPri;

	/* Run at a priority level above main thread so we can still run if it hangs. */
	/* Rise more than 1 because of rumored off-by-one scheduler bugs. */
	schp.sched_priority = b->priority + 4;
	maxPri = sched_get_priority_max(SCHEDULER_POLICY);
	if( schp.sched_priority > maxPri ) schp.sched_priority = maxPri;

	if (pthread_setschedparam(pthread_self(), SCHEDULER_POLICY, &schp) != 0)
	{
		ERR_RPT("WatchDogProc: cannot set watch dog priority!\n");
		goto killAudio;
	}

	DBUG("prioboost: WatchDog priority set to level %d!\n", schp.sched_priority);

	/* Compare watchdog time with audio and canary thread times. */
	/* Sleep for a while or until thread cancelled. */
	while( b->WatchDogRun )
	{

		int              delta;
		struct timeval   currentTime;

		usleep( WATCHDOG_INTERVAL_USEC );
		gettimeofday( &currentTime, NULL );

#if 0
		/* If audio thread is not advancing, then it must be hung so kill it. */
		delta = currentTime.tv_sec - b->EntryTime.tv_sec;
		DBUG(("WatchDogProc: audio delta = %d\n", delta ));
		if( delta > WATCHDOG_MAX_SECONDS )
		{
			goto killAudio;
		}
#endif

		/* If canary died, then lower audio priority and halt canary. */
		delta = currentTime.tv_sec - b->CanaryTime.tv_sec;
		DBUG("WatchDogProc: dogging, delta = %ld, mysec=%d\n", delta, currentTime.tv_sec);
		if( delta > WATCHDOG_MAX_SECONDS )
		{
			ERR_RPT("WatchDogProc: canary died!\n");
			goto lowerAudio;
		}
	}

	DBUG("WatchDogProc: exiting.\n");
	return 0;

lowerAudio:
	{
		struct sched_param    schat = { 0 };
		if( pthread_setschedparam(b->ThreadID, SCHED_OTHER, &schat) != 0)
		{
			ERR_RPT("WatchDogProc: failed to lower audio priority. errno = %d\n", errno );
			/* Fall through into killing audio thread. */
		}
		else
		{
			ERR_RPT("WatchDogProc: lowered audio priority to prevent hogging of CPU.\n");
			goto cleanup;
		}
	}

killAudio:
	ERR_RPT("WatchDogProc: killing hung audio thread!\n");
	//pthread_cancel( b->ThreadID);
	//pthread_join( b->ThreadID);
	exit(1);

cleanup:
	b->CanaryRun = 0;
	DBUG("WatchDogProc: cancel Canary\n");
	pthread_cancel( b->CanaryThread );
	DBUG("WatchDogProc: join Canary\n");
	pthread_join( b->CanaryThread, NULL );
	DBUG("WatchDogProc: forget Canary\n");
	b->IsCanaryThreadValid = 0;

#ifdef GNUSTEP
	GSUnregisterCurrentThread();  /* SB20010904 */
#endif
	return 0;
}
Exemple #15
0
PaError PaHost_OpenStream( internalPortAudioStream   *past )
{
	HRESULT          hr;
	PaError          result = paNoError;
	PaHostSoundControl *pahsc;
	int              numBytes, maxChannels;
	unsigned int     minNumBuffers;
	internalPortAudioDevice *pad;
	DSoundWrapper   *dsw;
/* Allocate and initialize host data. */
	pahsc = (PaHostSoundControl *) PaHost_AllocateFastMemory(sizeof(PaHostSoundControl)); /* MEM */
	if( pahsc == NULL )
	{
		result = paInsufficientMemory;
		goto error;
	}
	memset( pahsc, 0, sizeof(PaHostSoundControl) );
	past->past_DeviceData = (void *) pahsc;
	pahsc->pahsc_TimerID = 0;
	dsw = &pahsc->pahsc_DSoundWrapper;
	DSW_Init( dsw );
/* Allocate native buffer. */
	maxChannels = ( past->past_NumOutputChannels > past->past_NumInputChannels ) ?
		past->past_NumOutputChannels : past->past_NumInputChannels;
	pahsc->pahsc_BytesPerBuffer = past->past_FramesPerUserBuffer * maxChannels * sizeof(short);
	if( maxChannels > 0 )
	{
		pahsc->pahsc_NativeBuffer = (short *) PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerBuffer); /* MEM */
		if( pahsc->pahsc_NativeBuffer == NULL )
		{
			result = paInsufficientMemory;
			goto error;
		}
	}
	else
	{
		result = paInvalidChannelCount;
		goto error;
	}
	
	DBUG(("PaHost_OpenStream: pahsc_MinFramesPerHostBuffer = %d\n", pahsc->pahsc_MinFramesPerHostBuffer ));
	minNumBuffers = Pa_GetMinNumBuffers( past->past_FramesPerUserBuffer, past->past_SampleRate );
	past->past_NumUserBuffers = ( minNumBuffers > past->past_NumUserBuffers ) ? minNumBuffers : past->past_NumUserBuffers;
	numBytes = pahsc->pahsc_BytesPerBuffer * past->past_NumUserBuffers;
	if( numBytes < DSBSIZE_MIN )
	{
		result = paBufferTooSmall;
		goto error;
	}
	if( numBytes > DSBSIZE_MAX )
	{
		result = paBufferTooBig;
		goto error;
	}
	pahsc->pahsc_FramesPerDSBuffer = past->past_FramesPerUserBuffer * past->past_NumUserBuffers;
	{
		int msecLatency = (int) ((pahsc->pahsc_FramesPerDSBuffer * 1000) / past->past_SampleRate);
		PRINT(("PortAudio on DirectSound - Latency = %d frames, %d msec\n", pahsc->pahsc_FramesPerDSBuffer, msecLatency ));
	}
/* ------------------ OUTPUT */
	if( (past->past_OutputDeviceID >= 0) && (past->past_NumOutputChannels > 0) )
	{
		DBUG(("PaHost_OpenStream: deviceID = 0x%x\n", past->past_OutputDeviceID));
		pad = Pa_GetInternalDevice( past->past_OutputDeviceID );
		hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound,   NULL );
/* If this fails, then try each output device until we find one that works. */
		if( hr != DS_OK )
		{
			int i;
			ERR_RPT(("Creation of requested Audio Output device '%s' failed.\n",
				((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) ));
			for( i=0; i<Pa_CountDevices(); i++ )
			{
				pad = Pa_GetInternalDevice( i );
				if( pad->pad_Info.maxOutputChannels >= past->past_NumOutputChannels )
				{
					DBUG(("Try device '%s' instead.\n", pad->pad_Info.name ));
					hr = DirectSoundCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSound,   NULL );
					if( hr == DS_OK )
					{
						ERR_RPT(("Using device '%s' instead.\n", pad->pad_Info.name ));
						break;
					}
				}
			}
		}
		if( hr != DS_OK )
		{
			ERR_RPT(("PortAudio: DirectSoundCreate() failed!\n"));
			result = paHostError;
			sPaHostError = hr;
			goto error;
		}
		hr = DSW_InitOutputBuffer( dsw,
			(unsigned long) (past->past_SampleRate + 0.5),
			past->past_NumOutputChannels, numBytes );
		DBUG(("DSW_InitOutputBuffer() returns %x\n", hr));
		if( hr != DS_OK )
		{
			result = paHostError;
			sPaHostError = hr;
			goto error;
		}
		past->past_FrameCount = pahsc->pahsc_DSoundWrapper.dsw_FramesWritten;
	}
#if SUPPORT_AUDIO_CAPTURE
/* ------------------ INPUT */
	if( (past->past_InputDeviceID >= 0) && (past->past_NumInputChannels > 0) )
	{
		pad = Pa_GetInternalDevice( past->past_InputDeviceID );
		hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture,   NULL );
/* If this fails, then try each input device until we find one that works. */
		if( hr != DS_OK )
		{
			int i;
			ERR_RPT(("Creation of requested Audio Capture device '%s' failed.\n",
				((pad->pad_lpGUID == NULL) ? "Default" : pad->pad_Info.name) ));
			for( i=0; i<Pa_CountDevices(); i++ )
			{
				pad = Pa_GetInternalDevice( i );
				if( pad->pad_Info.maxInputChannels >= past->past_NumInputChannels )
				{
					PRINT(("Try device '%s' instead.\n", pad->pad_Info.name ));
					hr = DirectSoundCaptureCreate( pad->pad_lpGUID, &dsw->dsw_pDirectSoundCapture,   NULL );
					if( hr == DS_OK ) break;
				}
			}
		}
		if( hr != DS_OK )
		{
			ERR_RPT(("PortAudio: DirectSoundCaptureCreate() failed!\n"));
			result = paHostError;
			sPaHostError = hr;
			goto error;
		}
		hr = DSW_InitInputBuffer( dsw,
			(unsigned long) (past->past_SampleRate + 0.5),
			past->past_NumInputChannels, numBytes );
		DBUG(("DSW_InitInputBuffer() returns %x\n", hr));
		if( hr != DS_OK )
		{
			ERR_RPT(("PortAudio: DSW_InitInputBuffer() returns %x\n", hr));
			result = paHostError;
			sPaHostError = hr;
			goto error;
		}
	}
#endif /* SUPPORT_AUDIO_CAPTURE */
	/* Calculate scalar used in CPULoad calculation. */ 
	{
		LARGE_INTEGER frequency;
		if( QueryPerformanceFrequency( &frequency ) == 0 )
		{
			pahsc->pahsc_InverseTicksPerUserBuffer = 0.0;
		}
		else
		{
			pahsc->pahsc_InverseTicksPerUserBuffer = past->past_SampleRate /
				( (double)frequency.QuadPart * past->past_FramesPerUserBuffer );
			DBUG(("pahsc_InverseTicksPerUserBuffer = %g\n", pahsc->pahsc_InverseTicksPerUserBuffer ));
		}
	}
	return result;
error:
	PaHost_CloseStream( past );
	return result;
}
Exemple #16
0
static PaError Pa_TimeSlice( internalPortAudioStream   *past )
{
	PaError           result = 0;
	long              bytesEmpty = 0;
	long              bytesFilled = 0;
	long              bytesToXfer = 0;
	long              numChunks;
	HRESULT           hresult;
	PaHostSoundControl  *pahsc;
	short            *nativeBufPtr;
	past->past_NumCallbacks += 1;
	pahsc = (PaHostSoundControl *) past->past_DeviceData;
	if( pahsc == NULL ) return paInternalError;
/* How much input data is available? */
#if SUPPORT_AUDIO_CAPTURE
	if( past->past_NumInputChannels > 0 )
	{
		DSW_QueryInputFilled( &pahsc->pahsc_DSoundWrapper, &bytesFilled );
		bytesToXfer = bytesFilled;
	}
#endif /* SUPPORT_AUDIO_CAPTURE */
/* How much output room is available? */
	if( past->past_NumOutputChannels > 0 )
	{
		DSW_QueryOutputSpace( &pahsc->pahsc_DSoundWrapper, &bytesEmpty );
		bytesToXfer = bytesEmpty;
	}
	AddTraceMessage( "bytesEmpty ", bytesEmpty );
/* Choose smallest value if both are active. */
	if( (past->past_NumInputChannels > 0) && (past->past_NumOutputChannels > 0) )
	{
		bytesToXfer = ( bytesFilled < bytesEmpty ) ? bytesFilled : bytesEmpty;
	}
/*	printf("bytesFilled = %d, bytesEmpty = %d, bytesToXfer = %d\n",
		bytesFilled, bytesEmpty, bytesToXfer);
*/
/* Quantize to multiples of a buffer. */
	numChunks = bytesToXfer / pahsc->pahsc_BytesPerBuffer;
	if( numChunks > (long)(past->past_NumUserBuffers/2) )
	{
		numChunks = (long)past->past_NumUserBuffers/2;
	}
	else if( numChunks < 0 )
	{
		numChunks = 0;
	}
	AddTraceMessage( "numChunks ", numChunks );
	nativeBufPtr = pahsc->pahsc_NativeBuffer;
	if( numChunks > 0 )
	{
		while( numChunks-- > 0 )
		{
		/* Measure usage based on time to process one user buffer. */
			Pa_StartUsageCalculation( past );
	#if SUPPORT_AUDIO_CAPTURE
	/* Get native data from DirectSound. */
			if( past->past_NumInputChannels > 0 )
			{
				hresult = DSW_ReadBlock( &pahsc->pahsc_DSoundWrapper, (char *) nativeBufPtr, pahsc->pahsc_BytesPerBuffer );
				if( hresult < 0 )
				{
					ERR_RPT(("DirectSound ReadBlock failed, hresult = 0x%x\n",hresult));
					sPaHostError = hresult;
					break;
				}
			}
	#endif /* SUPPORT_AUDIO_CAPTURE */
	/* Convert 16 bit native data to user data and call user routine. */
			result = Pa_CallConvertInt16( past, nativeBufPtr, nativeBufPtr );
			if( result != 0) break;
	/* Pass native data to DirectSound. */
			if( past->past_NumOutputChannels > 0 )
			{
			/*	static short DEBUGHACK = 0;
				DEBUGHACK += 0x0049;
				nativeBufPtr[0] = DEBUGHACK; /* Make buzz to see if DirectSound still running. */
				hresult = DSW_WriteBlock( &pahsc->pahsc_DSoundWrapper, (char *) nativeBufPtr, pahsc->pahsc_BytesPerBuffer );
				if( hresult < 0 )
				{
					ERR_RPT(("DirectSound WriteBlock failed, result = 0x%x\n",hresult));
					sPaHostError = hresult;
					break;
				}
			}
			Pa_EndUsageCalculation( past );
		}
	}
	return result;
}
/*********************************************************************
 * Try to open the named device.
 * If it opens, try to set various rates and formats and fill in
 * the device info structure.
 */
PaError Pa_QueryDevice( const char *deviceName, internalPortAudioDevice *pad )
{
    int result = paHostError;
    int tempDevHandle;
    int numChannels, maxNumChannels;
    int numSampleRates;
    int sampleRate;
    int numRatesToTry;
    int ratesToTry[9] = {96000, 48000, 44100, 32000, 24000, 22050, 16000, 11025, 8000};
    int i;
    audio_info_t solaris_info;
    audio_device_t device_info;

    /* douglas:
     we have to do this querying in a slightly different order. apparently
     some sound cards will give you different info based on their settins.
     e.g. a card might give you stereo at 22kHz but only mono at 44kHz.
     the correct order for OSS is: format, channels, sample rate

    */
	/*
	 to check a device for it's capabilities, it's probably better to use the
	 equivalent "-ctl"-descriptor - MR
	*/
    char devname[strlen(deviceName) + 4];
    snprintf(devname,(strlen(deviceName) + 4),"%sctl",deviceName);

    if ((tempDevHandle = open(devname, O_WRONLY|O_NONBLOCK))  == -1 )
    {
        DBUG(("Pa_QueryDevice: could not open %s\n", deviceName ));
        return paHostError;
    }

    /*  Ask OSS what formats are supported by the hardware. */
    pad->pad_Info.nativeSampleFormats = 0;
    AUDIO_INITINFO(&solaris_info);

    /* SAM 12/31/01: Sparc native does mulaw, alaw and PCM.
       I think PCM is signed. */

    for (i = 8; i <= 32; i += 8) {
      solaris_info.play.precision = i;
      solaris_info.play.encoding = AUDIO_ENCODING_LINEAR;
      /* If there are no errors, add the format. */
      if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) > -1) {
	switch (i) {
	case 8:
	  pad->pad_Info.nativeSampleFormats |= paInt8;
	  break;
	case 16:
	  pad->pad_Info.nativeSampleFormats |= paInt16;
	  break;
	case 24:
	  pad->pad_Info.nativeSampleFormats |= paInt24;
	  break;
	case 32:
	  pad->pad_Info.nativeSampleFormats |= paInt32;
	  break;
	}
      }
    }

    maxNumChannels = 0;
    for( numChannels = 1; numChannels <= 16; numChannels++ )
      {
	int temp = numChannels;
	DBUG(("Pa_QueryDevice: use SNDCTL_DSP_CHANNELS, numChannels = %d\n", numChannels ))
	  AUDIO_INITINFO(&solaris_info);
	solaris_info.play.channels = temp;
	if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) < 0)
	  {
	    /* ioctl() failed so bail out if we already have stereo */
	    if( numChannels > 2 ) break;
	  }
	else
	  {
	    /* ioctl() worked but bail out if it does not support numChannels.
	     * We don't want to leave gaps in the numChannels supported.
	     */
	    if( (numChannels > 2) && (temp != numChannels) ) break;
	    DBUG(("Pa_QueryDevice: temp = %d\n", temp ))
	      if( temp > maxNumChannels ) maxNumChannels = temp; /* Save maximum. */
	  }
      }

    pad->pad_Info.maxOutputChannels = maxNumChannels;
    DBUG(("Pa_QueryDevice: maxNumChannels = %d\n", maxNumChannels))

    /* FIXME - for now, assume maxInputChannels = maxOutputChannels.
     *    Eventually do separate queries for O_WRONLY and O_RDONLY
    */
    pad->pad_Info.maxInputChannels = pad->pad_Info.maxOutputChannels;

    DBUG(("Pa_QueryDevice: maxInputChannels = %d\n",
          pad->pad_Info.maxInputChannels))


    /* Determine available sample rates by trying each one and seeing result.
     */
    numSampleRates = 0;

    AUDIO_INITINFO(&solaris_info);

    numRatesToTry = sizeof(ratesToTry)/sizeof(int);
    for (i = 0; i < numRatesToTry; i++)
    {
        sampleRate = ratesToTry[i];

	solaris_info.play.sample_rate = sampleRate; /* AS: We opened for Write, so set play */
        if (ioctl(tempDevHandle, AUDIO_SETINFO, &solaris_info) >= 0 ) /* PLB20010817 */
        {
            if (sampleRate == ratesToTry[i])
            {
                DBUG(("Pa_QueryDevice: got sample rate: %d\n", sampleRate))
                pad->pad_SampleRates[numSampleRates] = (float)ratesToTry[i];
                numSampleRates++;
            }
        }
    }

    DBUG(("Pa_QueryDevice: final numSampleRates = %d\n", numSampleRates))
    if (numSampleRates==0)   /* HP20010922 */
    {
        ERR_RPT(("Pa_QueryDevice: no supported sample rate (or SNDCTL_DSP_SPEED ioctl call failed).\n" ));
        goto error;
    }

    pad->pad_Info.numSampleRates = numSampleRates;
    pad->pad_Info.sampleRates = pad->pad_SampleRates;

    /* query for the device name instead of using the filesystem-device - MR */
	if (ioctl(tempDevHandle, AUDIO_GETDEV, &device_info) == -1) {
      pad->pad_Info.name = deviceName;
    } else {
      char *pt = (char *)PaHost_AllocateFastMemory(strlen(device_info.name));
      strcpy(pt, device_info.name);
      pad->pad_Info.name = pt;
    }

    result = paNoError;

error:
    /* We MUST close the handle here or we won't be able to reopen it later!!!  */
    close(tempDevHandle);

    return result;
}
Exemple #18
0
/*--------------------------------------------------------------------------------------*/
PaError translateSGIerror(void) /* Calls oserror(), may be used after an SGI AL-library */
{                               /* call to report via ERR_RPT(), yields a PaError-num.  */
    const char* a = "SGI AL ";  /* (Not absolutely sure errno came from THIS thread!    */
    switch(oserror())           /* Read IRIX man-pages about the _SGI_MP_SOURCE macro.) */
        {
        case AL_BAD_OUT_OF_MEM:
             ERR_RPT(("%sout of memory.\n", a)); 
             return paInsufficientMemory;                   /* Known PaError.   */
        case AL_BAD_CONFIG:
             ERR_RPT(("%sconfiguration invalid or NULL.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_CHANNELS:
             ERR_RPT(("%schannels not 1,2 or 4.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_NO_PORTS:
             ERR_RPT(("%sout of audio ports.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_DEVICE:
             ERR_RPT(("%swrong device number.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_DEVICE_ACCESS:
             ERR_RPT(("%swrong device access.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_DIRECTION:
             ERR_RPT(("%sinvalid direction.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_SAMPFMT:
             ERR_RPT(("%sdoesn't accept sampleformat.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_FLOATMAX:
             ERR_RPT(("%smax float value is zero.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_WIDTH:
             ERR_RPT(("%sunsupported samplewidth.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_QSIZE:
             ERR_RPT(("%sinvalid queue size.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_PVBUFFER:
             ERR_RPT(("%sPVbuffer null.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_BUFFERLENGTH_NEG:
             ERR_RPT(("%snegative bufferlength.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_BUFFERLENGTH_ODD:
             ERR_RPT(("%sodd bufferlength.\n", a));
             return paHostError;                            /* Generic PaError. */
        case AL_BAD_PARAM:
             ERR_RPT(("%sparameter not valid for device.\n", a));
             return paHostError;                            /* Generic PaError. */
        default:
             ERR_RPT(("%sunknown error.\n", a));
             return paHostError;                            /* Generic PaError. */
        }
}
Exemple #19
0
/*--------------------------------------------------------------------------------------*/
PaError PaHost_OpenStream(internalPortAudioStream *past)
{
	PaError                 result = paNoError;
	PaHostSoundControl      *pahsc;
	unsigned int            minNumBuffers;
	internalPortAudioDevice *padIN, *padOUT;        /* For looking up native AL-numbers. */
    ALconfig                sgiALconfig = NULL;     /* IRIX-datatype.   */
    long                    pvbuf[8];               /* To get/set hardware configs.      */
    long                    sr, ALqsize;
    DBUG(("PaHost_OpenStream() called.\n"));        /* Alloc FASTMEM and init host data. */
    if (!past)
        {
        ERR_RPT(("Streampointer NULL!\n"));
        result = paBadStreamPtr;        goto done;
        }
	pahsc = (PaHostSoundControl*)PaHost_AllocateFastMemory(sizeof(PaHostSoundControl));
	if (pahsc == NULL)
	    {
        ERR_RPT(("FAST Memory allocation failed.\n"));  /* Pass trough some ERR_RPT-exit-  */
        result = paInsufficientMemory;  goto done;      /* code (nothing will be freed).   */
	    }
	memset(pahsc, 0, sizeof(PaHostSoundControl));
/*  pahsc->pahsc_threadPID = -1;                       Should pahsc_threadPID be inited to */
	past->past_DeviceData = (void*)pahsc;           /* -1 instead of 0 ??                  */
    /*--------------------------------------------------- Allocate native buffers: --------*/
    pahsc->pahsc_SamplesPerInputBuffer = past->past_FramesPerUserBuffer * /* Needed by the */
                                         past->past_NumInputChannels;     /* audio-thread. */
	pahsc->pahsc_BytesPerInputBuffer   = pahsc->pahsc_SamplesPerInputBuffer * sizeof(short);
	if (past->past_NumInputChannels > 0)                       /* Assumes short = 16 bits! */
	    {
		pahsc->pahsc_NativeInputBuffer = (short*)PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerInputBuffer);        
		if( pahsc->pahsc_NativeInputBuffer == NULL )
		    {
            ERR_RPT(("Fast memory allocation for input-buffer failed.\n"));
			result = paInsufficientMemory;  goto done;
		    }
	    }
    pahsc->pahsc_SamplesPerOutputBuffer = past->past_FramesPerUserBuffer * /* Needed by the */
                                          past->past_NumOutputChannels;    /* audio-thread. */
	pahsc->pahsc_BytesPerOutputBuffer   = pahsc->pahsc_SamplesPerOutputBuffer * sizeof(short);
	if (past->past_NumOutputChannels > 0)                       /* Assumes short = 16 bits! */
	    {
		pahsc->pahsc_NativeOutputBuffer = (short*)PaHost_AllocateFastMemory(pahsc->pahsc_BytesPerOutputBuffer);
		if (pahsc->pahsc_NativeOutputBuffer == NULL)
		    {
            ERR_RPT(("Fast memory allocation for output-buffer failed.\n"));
			result = paInsufficientMemory;  goto done;
		    }
	    }
    /*------------------------------------------ Manipulate hardware if necessary and allowed: --*/
    ALseterrorhandler(0);                           /* 0 = turn off the default error handler.   */
    pvbuf[0] = AL_INPUT_RATE;
    pvbuf[2] = AL_INPUT_COUNT;
    pvbuf[4] = AL_OUTPUT_RATE;              /* TO FIX: rates may be logically, not always in Hz! */
    pvbuf[6] = AL_OUTPUT_COUNT;
    sr = (long)(past->past_SampleRate + 0.5);   /* Common for input and output :-)               */
    if (past->past_NumInputChannels > 0)                        /* We need to lookup the corre-  */
        {                                                       /* sponding native AL-number(s). */
        padIN = Pa_GetInternalDevice(past->past_InputDeviceID);
        if (!padIN)
            {
            ERR_RPT(("Pa_GetInternalDevice() for input failed.\n"));
	        result = paHostError;  goto done;
            }
        if (ALgetparams(padIN->pad_ALdevice, &pvbuf[0], 4)) /* Although input and output will both be on */
            goto sgiError;                                  /* the same AL-device, the AL-library might  */
        if (pvbuf[1] != sr)                                 /* contain more than AL_DEFAULT_DEVICE in    */
            {  /* Rate different from current harware-rate?    the future. Therefore 2 seperate queries. */
            if (pvbuf[3] > 0)     /* Means, there's other clients using AL-input-ports */
                {
                ERR_RPT(("Sorry, not allowed to switch input-hardware to %ld Hz because \
another process is currently using input at %ld kHz.\n", sr, pvbuf[1]));
                result = paHostError;   goto done;
                }
            pvbuf[1] = sr;                  /* Then set input-rate. */
            if (ALsetparams(padIN->pad_ALdevice, &pvbuf[0], 2))
                goto sgiError;      /* WHETHER THIS SAMPLERATE WAS REALLY PRESENT IN OUR ARRAY OF RATES, */
            }                       /* IS NOT CHECKED, AT LEAST NOT BY ME, WITHIN THIS FILE! Does PA do? */
Exemple #20
0
/*---------------------------------------------------------------------------------------------------*/
static PaError Pa_SgiAudioProcess(internalPortAudioStream *past) /* Spawned by PaHost_StartEngine(). */
{
    PaError                 result = paNoError;
    PaHostSoundControl      *pahsc;
    
    if (!past)
        return paBadStreamPtr;
    pahsc = (PaHostSoundControl*)past->past_DeviceData;
	if (!pahsc)
        return paInternalError;
	past->past_IsActive = 1;            /* Wasn't this already done by the calling parent?!   */
    DBUG(("entering thread.\n"));

    while (!past->past_StopSoon)        /* OR-ing StopSoon and StopNow here gives problems! */
        {
        /*---------------------------------------- INPUT: ------------------------------------*/
        if (pahsc->pahsc_NativeInputBuffer)     /* Then pahsc_ALportIN should also be there!  */
            {
            while (ALgetfilled(pahsc->pahsc_ALportIN) < pahsc->pahsc_SamplesPerInputBuffer)
                {
                /* Trying sginap(1); and usleep(); here... things get blocked under IRIX6.2. */
                if (past->past_StopNow)    /* Don't let ALreadsamps() block */
                    goto done;
                }
            if (ALreadsamps(pahsc->pahsc_ALportIN, (void*)pahsc->pahsc_NativeInputBuffer,
                            pahsc->pahsc_SamplesPerInputBuffer))    /* Number of samples instead  */
                {                                                   /* of number of frames.       */
                ERR_RPT(("ALreadsamps() failed.\n"));
                result =  paInternalError;
                goto done;
                }
            }
        /*---------------------------------------------------- USER CALLBACK ROUTINE: ----------*/
        /* DBUG(("Calling Pa_CallConvertInt16()...\n")); */
        Pa_StartUsageCalculation(past);                     /* Convert 16 bit native data to    */
	    result = Pa_CallConvertInt16(past,                  /* user data and call user routine. */
				                 pahsc->pahsc_NativeInputBuffer, pahsc->pahsc_NativeOutputBuffer);
	    Pa_EndUsageCalculation(past);
	    if (result) 
		    {
			DBUG(("Pa_CallConvertInt16() returned %d, stopping...\n", result));
            goto done;                      /* This is apparently NOT an error!       */
		    }                               /* Just letting the userCallBack stop us. */
        /*---------------------------------------- OUTPUT: ------------------------------------*/
        if (pahsc->pahsc_NativeOutputBuffer)    /* Then pahsc_ALportOUT should also be there!  */
            {
            while (ALgetfillable(pahsc->pahsc_ALportOUT) < pahsc->pahsc_SamplesPerOutputBuffer)
                {
                /* Trying sginap(1); and usleep(); here... things get blocked under IRIX6.2. */
                if (past->past_StopNow)    /* Don't let ALwritesamps() block */
                    goto done;
                }
            if (ALwritesamps(pahsc->pahsc_ALportOUT, (void*)pahsc->pahsc_NativeOutputBuffer,
                             pahsc->pahsc_SamplesPerOutputBuffer))
                {
                ERR_RPT(("ALwritesamps() failed.\n"));
                result = paInternalError;
                goto done;
                }
            }
        /*-------------------------------------------------------------------------------------*/
        }
done:
    /* pahsc->pahsc_ThreadPID = -1;   Hu? doesn't help!! (added by Pieter) */
    past->past_IsActive = 0;
    DBUG(("leaving thread.\n"));
    return result;
}