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

📄 pa_mac.c

📁 ppciaxclient softphone
💻 C
📖 第 1 页 / 共 5 页
字号:
    if( err < 0 ) return err;
    else return paNoError;
}

/*************************************************************************
 PaMac_ScanOutputDevices() queries the properties of all output devices.
*/
static PaError PaMac_ScanOutputDevices( void )
{
    PaError       err;
    Component     identifier=0;
    ComponentDescription criteria = { kSoundOutputDeviceType, 0, 0, 0, 0 };
    long       numComponents, i;

    /* Search the system linked list for output components  */
    numComponents = CountComponents (&criteria);
    identifier = 0;
    sDefaultOutputDeviceID = sNumDevices; /* FIXME - query somehow */
    for (i = 0; i < numComponents; i++)
    {
        /* passing nil returns first matching component. */
        identifier = FindNextComponent( identifier, &criteria);
        sDevices[sNumDevices].pad_Identifier = identifier;

        /* Set up for default OUTPUT devices. */
        err = PaMac_QueryOutputDeviceInfo( identifier, &sDevices[sNumDevices] );
        if( err < 0 ) return err;
        else  sNumDevices++;

    }

    return paNoError;
}

/*************************************************************************
 PaMac_ScanInputDevices() queries the properties of all input devices.
*/
static PaError PaMac_ScanInputDevices( void )
{
    Str255     deviceName;
    int        count;
    Handle     iconHandle;
    PaError    err;
    OSErr      oserr;
    count = 1;
    sDefaultInputDeviceID = sNumDevices; /* FIXME - query somehow */ /* PLB20010415 - was setting sDefaultOutputDeviceID */
    while(true)
    {
        /* Thanks Chris Rolfe and Alberto Ricci for this trick. */
        oserr = SPBGetIndexedDevice(count++, deviceName, &iconHandle);
        DBUG(("PaMac_ScanInputDevices: SPBGetIndexedDevice returned %d\n", oserr ));
#if 1
        /* PLB20010415 - was giving error for anything other than siBadSoundInDevice, but some Macs may return other errors! */
        if(oserr != noErr) break; /* Some type of error is expected when count > devices */
#else
        if(oserr == siBadSoundInDevice)
        {  /* it's expected when count > devices */
            oserr = noErr;
            break;
        }
        if(oserr != noErr)
        {
            ERR_RPT(("ERROR: SPBGetIndexedDevice(%d,,) returned %d\n", count-1, oserr ));
            sPaHostError = oserr;
            return paHostError;
        }
#endif
        DisposeHandle(iconHandle);   /* Don't need the icon */

        err = PaMac_QueryInputDeviceInfo( deviceName, &sDevices[sNumDevices] );
        DBUG(("PaMac_ScanInputDevices: PaMac_QueryInputDeviceInfo returned %d\n", err ));
        if( err < 0 ) return err;
        else if( err == 1 ) sNumDevices++;
    }

    return paNoError;
}

/* Sample rate info returned by using siSampleRateAvailable selector in SPBGetDeviceInfo() */
/* Thanks to Chris Rolfe for help with this query. */
#pragma options align=mac68k
typedef  struct
{
    int16                   numRates;
    UnsignedFixed           (**rates)[]; /* Handle created by SPBGetDeviceInfo */
}
SRateInfo;
#pragma options align=reset

/*************************************************************************
** PaMac_QueryOutputDeviceInfo()
** Query information about a named output device.
** Clears contents of ipad and writes info based on queries.
** Return one if OK,
**        zero if device cannot be used,
**        or negative error.
*/
static PaError PaMac_QueryOutputDeviceInfo( Component identifier, internalPortAudioDevice *ipad )
{
    int     len;
    OSErr   err;
    PaDeviceInfo *dev =  &ipad->pad_Info;
    SRateInfo srinfo = {0};
    int     numRates;
    ComponentDescription tempD;
    Handle nameH=nil, infoH=nil, iconH=nil;

    memset( ipad, 0, sizeof(internalPortAudioDevice) );

    dev->structVersion = 1;
    dev->maxInputChannels = 0;
    dev->maxOutputChannels = 2;
    dev->nativeSampleFormats = paInt16; /* FIXME - query to see if 24 or 32 bit data can be handled. */

    /* Get sample rates supported. */
    err = GetSoundOutputInfo(identifier, siSampleRateAvailable, (Ptr) &srinfo);
    if(err != noErr)
    {
        ERR_RPT(("Error in PaMac_QueryOutputDeviceInfo: GetSoundOutputInfo siSampleRateAvailable returned %d\n", err ));
        goto error;
    }
    numRates = srinfo.numRates;
    DBUG(("PaMac_QueryOutputDeviceInfo: srinfo.numRates = %d\n", srinfo.numRates ));
    if( numRates == 0 )
    {
        dev->numSampleRates = -1;
        numRates = 2;
    }
    else
    {
        dev->numSampleRates = numRates;
    }
    dev->sampleRates = PaMac_GetSampleRatesFromHandle( numRates, (Handle) srinfo.rates );
    if(dev->sampleRates == NULL)
    {
    	DBUG(("PaMac_QueryOutputDeviceInfo: PaMac_GetSampleRatesFromHandle alloc failed.\n"));
    	return paInsufficientMemory;
    }
    
    /* SPBGetDeviceInfo created the handle, but it's OUR job to release it. */
    DisposeHandle((Handle) srinfo.rates);

    /* Device name */
    /*  we pass an existing handle for the component name;
     we don't care about the info (type, subtype, etc.) or icon, so set them to nil */
	DBUG(("PaMac_QueryOutputDeviceInfo: get component name.\n"));
    infoH = nil;
    iconH = nil;
    nameH = NewHandle(0);
    if(nameH == nil) return paInsufficientMemory;
    err = GetComponentInfo(identifier, &tempD, nameH, infoH, iconH);
    if (err)
    {
        ERR_RPT(("Error in PaMac_QueryOutputDeviceInfo: GetComponentInfo returned %d\n", err ));
        goto error;
    }
    /* Cast as uchar* so that we get a proper pascal string length. */
	len = ((unsigned char *)(*nameH))[0] + 1;  /* PLB20020612 - fix allocation error on Mac 8600 */
	DBUG(("PaMac_QueryOutputDeviceInfo: new len = %d\n", len ));

    dev->name = (char *) malloc(len);  /* MEM_010 */
    if( dev->name == NULL )
    {
        DisposeHandle(nameH);
        return paInsufficientMemory;
    }
    else
    {
        PToCString((unsigned char *)(*nameH), (char *) dev->name);
        DisposeHandle(nameH);
    }

    DBUG(("PaMac_QueryOutputDeviceInfo: dev->name = %s\n", dev->name ));
    return paNoError;

error:
    sPaHostError = err;
    return paHostError;

}

/*************************************************************************
** PaMac_QueryInputDeviceInfo()
** Query information about a named input device.
** Clears contents of ipad and writes info based on queries.
** Return one if OK,
**        zero if device cannot be used,
**        or negative error.
*/
static PaError PaMac_QueryInputDeviceInfo( Str255 deviceName, internalPortAudioDevice *ipad )
{
    PaError result = paNoError;
    int     len;
    OSErr   err;
    long    mRefNum = 0;
    long    tempL;
    int16   tempS;
    Fixed   tempF;
    PaDeviceInfo *dev =  &ipad->pad_Info;
    SRateInfo srinfo = {0};
    int     numRates;

    memset( ipad, 0, sizeof(internalPortAudioDevice) );
    dev->maxOutputChannels = 0;

    /* Open device based on name. If device is in use, it may not be able to open in write mode. */
    err = SPBOpenDevice( deviceName, siWritePermission, &mRefNum);
    if (err)
    {
        /* If device is in use, it may not be able to open in write mode so try read mode. */
        err = SPBOpenDevice( deviceName, siReadPermission, &mRefNum);
        if (err)
        {
            ERR_RPT(("Error in PaMac_QueryInputDeviceInfo: SPBOpenDevice returned %d\n", err ));
            sPaHostError = err;
            return paHostError;
        }
    }

    /* Define macros for printing out device info. */
#define PrintDeviceInfo(selector,var) \
    err = SPBGetDeviceInfo(mRefNum, selector, (Ptr) &var); \
    if (err) { \
        DBUG(("query %s failed\n", #selector )); \
    }\
    else { \
        DBUG(("query %s = 0x%x\n", #selector, var )); \
    }

    PrintDeviceInfo( siContinuous, tempS );
    PrintDeviceInfo( siAsync, tempS );
    PrintDeviceInfo( siNumberChannels, tempS );
    PrintDeviceInfo( siSampleSize, tempS );
    PrintDeviceInfo( siSampleRate, tempF );
    PrintDeviceInfo( siChannelAvailable, tempS );
    PrintDeviceInfo( siActiveChannels, tempL );
    PrintDeviceInfo( siDeviceBufferInfo, tempL );

    err = SPBGetDeviceInfo(mRefNum, siActiveChannels, (Ptr) &tempL);
    if (err == 0) DBUG(("%s = 0x%x\n", "siActiveChannels", tempL ));
    /* Can we use this device? */
    err = SPBGetDeviceInfo(mRefNum, siAsync, (Ptr) &tempS);
    if (err)
    {
        ERR_RPT(("Error in PaMac_QueryInputDeviceInfo: SPBGetDeviceInfo siAsync returned %d\n", err ));
        goto error;
    }
    if( tempS == 0 ) goto useless; /* Does not support async recording so forget about it. */

    err = SPBGetDeviceInfo(mRefNum, siChannelAvailable, (Ptr) &tempS);
    if (err)
    {
        ERR_RPT(("Error in PaMac_QueryInputDeviceInfo: SPBGetDeviceInfo siChannelAvailable returned %d\n", err ));
        goto error;
    }
    dev->maxInputChannels = tempS;

    /* Get sample rates supported. */
    err = SPBGetDeviceInfo(mRefNum, siSampleRateAvailable, (Ptr) &srinfo);
    if (err)
    {
        ERR_RPT(("Error in PaMac_QueryInputDeviceInfo: SPBGetDeviceInfo siSampleRateAvailable returned %d\n", err ));
        goto error;
    }

    numRates = srinfo.numRates;
    DBUG(("numRates = 0x%x\n", numRates ));
    if( numRates == 0 )
    {
        dev->numSampleRates = -1;
        numRates = 2;
    }
    else
    {
        dev->numSampleRates = numRates;
    }
    dev->sampleRates = PaMac_GetSampleRatesFromHandle( numRates, (Handle) srinfo.rates );
    /* SPBGetDeviceInfo created the handle, but it's OUR job to release it. */
    DisposeHandle((Handle) srinfo.rates);

    /* Get size of device buffer. */
    err = SPBGetDeviceInfo(mRefNum, siDeviceBufferInfo, (Ptr) &tempL);
    if (err)
    {
        ERR_RPT(("Error in PaMac_QueryInputDeviceInfo: SPBGetDeviceInfo siDeviceBufferInfo returned %d\n", err ));
        goto error;
    }
    ipad->pad_DeviceBufferSize = tempL;
    DBUG(("siDeviceBufferInfo = %d\n", tempL ));

    /* Set format based on sample size. */
    err = SPBGetDeviceInfo(mRefNum, siSampleSize, (Ptr) &tempS);
    if (err)
    {
        ERR_RPT(("Error in PaMac_QueryInputDeviceInfo: SPBGetDeviceInfo siSampleSize returned %d\n", err ));
        goto error;
    }
    switch( tempS )
    {
    case 0x0020:
        dev->nativeSampleFormats = paInt32;  /* FIXME - warning, code probably won't support this! */
        break;
    case 0x0010:
    default: /* FIXME - What about other formats? */
        dev->nativeSampleFormats = paInt16;
        break;
    }
    DBUG(("nativeSampleFormats = %d\n", dev->nativeSampleFormats ));

    /* Device name */
    len = deviceName[0] + 1;  /* Get length of Pascal string */
    dev->name = (char *) malloc(len);  /* MEM_010 */
    if( dev->name == NULL )
    {
        result = paInsufficientMemory;
        goto cleanup;
    }
    PToCString(deviceName, (char *) dev->name);
    DBUG(("deviceName = %s\n", dev->name ));
    result = (PaError) 1;
    /* All done so close up device. */
cleanup:
    if( mRefNum )  SPBCloseDevice(mRefNum);
    return result;

error:
    if( mRefNum )  SPBCloseDevice(mRefNum);
    sPaHostError = err;
    return paHostError;

useless:
    if( mRefNum )  SPBCloseDevice(mRefNum);
    return (PaError) 0;
}

/*************************************************************************
** Allocate a double array and fill it with listed sample rates.
*/

⌨️ 快捷键说明

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