📄 pa_mac.c
字号:
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 + -