⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pa_sgi.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 4 页
字号:
        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;
}


/*--------------------------------------------------------------------------------*/
int Pa_CountDevices()       /* Name of this function suggests it only counts and  */
{                           /* is NOT destructive, it however resets whole PA !   */   
    int                        numDevices = 0;        /* Let 's not do that here. */
    internalPortAudioDevice*   currentDevice = sDeviceList;   /* COPY GLOBAL VAR. */
#if 0                       /* Remains from linux_oss v15: Pa_Initialize(), on    */
    if (!currentDevice)     /* its turn, calls PaHost_Init() via file pa_lib.c.   */
        Pa_Initialize();    /* Isn't that a bit too 'rude'?        Don't be too   */
#endif                      /* friendly to clients that forgot to initialize PA.  */
    while (currentDevice)   /* Slower but more elegant than the sNumDevices-way:  */
        {
        numDevices++;
        currentDevice = currentDevice->pad_Next;
        }
    return numDevices;
}

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

/*----------------------------------------------------------------------*/
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(). */
}

/*------------------------------------------------*/
PaDeviceID Pa_GetDefaultInputDeviceID(void)
{
    return 0;   /* 0 is the default device ID. */
}
/*------------------------------------------------*/
PaDeviceID Pa_GetDefaultOutputDeviceID(void)
{
    return 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;
}

/*--------------------------------------------------------------------------------------------*/
#define MIN(a,b)    ((a)<(b)?(a):(b))   /* MIN()-function is used below.                      */
#define kPollSEMA   0                   /* To index the pollfd-array, reads nicer than just   */
#define kPollOUT    1                   /* numbers.                                           */
#define kPollIN     2
void Pa_SgiAudioProcess(void *v)        /* This function is sproc-ed by PaHost_StartEngine()  */
{                                       /* as a separate thread. (Argument must be void*).    */
    short                   evtLoop;    /* Reset by parent indirectly, or at local errors.    */
    PaError                 result;
    struct pollfd           PollFD[3];  /* To catch kPollSEMA-, kPollOUT- and kPollIN-events. */
    internalPortAudioStream *past = (internalPortAudioStream*)v;   /* Copy void-ptr-argument. */
    PaHostSoundControl      *pahsc;
    short                   n, inputEvent, outputEvent, ioEvent, semaEvent = 0;
    short                   *inBuffer, *outBuffer;      /* Only 16 bit for now, may change... */               
    unsigned int            samplesPerInputUserBuffer, samplesPerOutputUserBuffer;

    DBUG(("Entering sproc-thread.\n"));
    if (!past)
        {
        sPaHostError = paInternalError;     /* Or paBadStreamPtr ? */
        ERR_RPT(("argument NULL!\n"));
        goto noPast;
        }
    pahsc = (PaHostSoundControl*)past->past_DeviceData;
    if (!pahsc)
        {
        sPaHostError = paInternalError;     /* The only way is to signal error to shared area?!   */
        ERR_RPT(("past_DeviceData NULL!\n"));
        goto noPahsc;                       /* Sproc-ed threads MAY NOT RETURN paInternalError.   */
        }
    /*----------------------------- open AL-ports here, after sproc(): -----------------------*/
    if (past->past_NumInputChannels > 0)                                  /* Open input port. */
        {       
        pahsc->pahsc_ALportIN = ALopenport("PA sgi in", "r", pahsc->pahsc_ALconfigIN);
        if (!pahsc->pahsc_ALportIN)
            {
            ERR_RPT(("Failed to open AL input port.\n"));
            sPaHostError = paInternalError;
            goto skip;
            }
        DBUG(("Opened %d input channel(s).\n", past->past_NumInputChannels));
        samplesPerInputUserBuffer = pahsc->pahsc_SamplesPerInputHostBuffer /
                                    pahsc->pahsc_UserBuffersPerHostBuffer;
        }
    else
        samplesPerInputUserBuffer = 0; /* Added 2003. */
    if (past->past_NumOutputChannels > 0)                               /* Open output port. */
        {       
        pahsc->pahsc_ALportOUT = ALopenport("PA sgi out", "w", pahsc->pahsc_ALconfigOUT);
        if (!pahsc->pahsc_ALportOUT)
            {
            ERR_RPT(("Failed to open AL output port.\n"));
            sPaHostError = paInternalError;                 /* Assume pahsc_ALconfigs are the */
            goto skip;                                      /* same for IN and OUT in case    */
            }                                               /* both ports are opened (bidir). */
        DBUG(("Opened %d output channel(s).\n", past->past_NumOutputChannels));
        samplesPerOutputUserBuffer = pahsc->pahsc_SamplesPerOutputHostBuffer /
                                     pahsc->pahsc_UserBuffersPerHostBuffer;
        DBUG(("samplesPerOutputUserBuffer = %d\n", samplesPerOutputUserBuffer));
        }
    else
        samplesPerOutputUserBuffer = 0; /* Added 2003. */
    /*-----------------------------------------------------------------------*/
    past->past_IsActive = 1;            /* Wasn't this already done by the calling parent?!   */
    PollFD[kPollIN].fd = ALgetfd(pahsc->pahsc_ALportIN);    /* ALgetfd returns -1 on failures */
    PollFD[kPollIN].events = POLLIN;                        /* such as ALport not there.      */
    PollFD[kPollOUT].fd = ALgetfd(pahsc->pahsc_ALportOUT);
    PollFD[kPollOUT].events = POLLOUT;                      /* .events = POLLOUT is OK.       */
    schedctl(NDPRI, NDPHIMIN);              /* Sets non-degrading priority for this process.  */
    PollFD[kPollSEMA].fd = usopenpollsema(SendSema, 0777);  /* To communicate with parent.    */
    PollFD[kPollSEMA].events = POLLIN;                      /* .events = POLLIN is OK.        */
    uspsema(SendSema);              /* Blocks until ... MUST be here, this uspsema(). */
    evtLoop = ((past->past_StopNow | past->past_StopSoon) == 0);
    while (evtLoop)
        {
        /*----------------------------- SET FILLPOINTS AND WAIT UNTIL SOMETHING HAPPENS: ---------*/
        if (pahsc->pahsc_InputHostBuffer)           /* Then pahsc_ALportIN should also be there.  */
            {
            /* For input port, fill point is number of locations in the sample queue that must be */
            /* filled in order to trigger a return from select(). (or poll())                     */
            /* Notice IRIX docs mention number of samples as argument, not number of sampleframes.*/
            if (ALsetfillpoint(pahsc->pahsc_ALportIN, pahsc->pahsc_SamplesPerInputHostBuffer))
                {                                    /* Multiple amount as transferred per time.  */
                ERR_RPT(("ALsetfillpoint() for ALportIN failed.\n"));
                sPaHostError = paInternalError;         /* (Using exit(-1) would be a bit rude.)  */
                goto skip;
                }
            }
        /* 'else' added march 2003: set only one of both fillpoints: input or output. When    */
        /* setting both fillpoints (as in earlier version) clicks occur at full duplex-mode.  */
        else if (pahsc->pahsc_OutputHostBuffer)     /* Then pahsc_ALportOUT should also be there. */
            {
            /* For output port, fill point is number of locations that must be free in order to   */
            /* wake up from select(). (or poll())                                                 */
            if (ALsetfillpoint(pahsc->pahsc_ALportOUT, pahsc->pahsc_SamplesPerOutputHostBuffer))
                {
                ERR_RPT(("ALsetfillpoint() for ALportOUT failed.\n"));
                sPaHostError = paInternalError;
                goto skip;
                }
            }                       /* poll() with timeout=-1 makes it block until a requested    */
        poll(PollFD, 3, -1);        /* event occurs or until call is interrupted. If fd-value in  */
                                    /* array <0, events is ignored and revents is set to 0.       */
        /*---------------------------- MESSAGE-EVENT FROM PARENT THREAD: -------------------------*/
        semaEvent = PollFD[kPollSEMA].revents & POLLIN;
        if (semaEvent)
            {
            if (past->past_StopSoon)
                evtLoop = 0;
            if (past->past_StopNow)
                goto skip;
            }
        /*------------------------------------- FILLED-EVENT FROM INPUT BUFFER: --------------------------*/
        inputEvent = PollFD[kPollIN].revents & POLLIN;
        if (inputEvent)         /* Don't need to check (pahsc->pahsc_InputHostBuffer):  */
            {                   /* if buffer was not there, ALport not there, no events!  */
            if (ALreadsamps(pahsc->pahsc_ALportIN, (void*)pahsc->pahsc_InputHostBuffer,
                            pahsc->pahsc_SamplesPerInputHostBuffer))
                {                           /* Here again: number of samples instead of number of frames. */
                ERR_RPT(("ALreadsamps() failed.\n"));
                sPaHostError = paInternalError;
                goto skip;
                }
            }
        outputEvent = PollFD[kPollOUT].revents & POLLOUT;
        ioEvent = (inputEvent | outputEvent);   /* Binary or is ok. */
        /*------------------------------------- USER-CALLBACK-ROUTINE: -----------------------------------*/       
        if (ioEvent)                            /* Always true? Or can some other system-event awaken the */
            {                                   /* poll? Sure it wasn't just a "sema"- (i.e. user)-event? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -