📄 pa_mac_core.c
字号:
PaError err = paNoError;
UInt32 propSize;
VVDBUG(("InitializeDeviceInfo(): macCoreDeviceId=%ld\n", macCoreDeviceId));
memset(deviceInfo, 0, sizeof(deviceInfo));
deviceInfo->structVersion = 2;
deviceInfo->hostApi = hostApiIndex;
/* Get the device name. Fail if we can't get it. */
err = ERR(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL));
if (err)
return err;
name = PaUtil_GroupAllocateMemory(auhalHostApi->allocations,propSize);
if ( !name )
return paInsufficientMemory;
err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name));
if (err)
return err;
deviceInfo->name = name;
/* Try to get the default sample rate. Don't fail if we can't get this. */
propSize = sizeof(Float64);
err = ERR(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &sampleRate));
if (err)
deviceInfo->defaultSampleRate = 0.0;
else
deviceInfo->defaultSampleRate = sampleRate;
/* Get the maximum number of input and output channels. Fail if we can't get this. */
err = GetChannelInfo(auhalHostApi, deviceInfo, macCoreDeviceId, 1);
if (err)
return err;
err = GetChannelInfo(auhalHostApi, deviceInfo, macCoreDeviceId, 0);
if (err)
return err;
return paNoError;
}
PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex )
{
PaError result = paNoError;
int i;
PaMacAUHAL *auhalHostApi;
PaDeviceInfo *deviceInfoArray;
VVDBUG(("PaMacCore_Initialize(): hostApiIndex=%d\n", hostApiIndex));
auhalHostApi = (PaMacAUHAL*)PaUtil_AllocateMemory( sizeof(PaMacAUHAL) );
if( !auhalHostApi )
{
result = paInsufficientMemory;
goto error;
}
auhalHostApi->allocations = PaUtil_CreateAllocationGroup();
if( !auhalHostApi->allocations )
{
result = paInsufficientMemory;
goto error;
}
auhalHostApi->devIds = NULL;
auhalHostApi->devCount = 0;
/* get the info we need about the devices */
result = gatherDeviceInfo( auhalHostApi );
if( result != paNoError )
goto error;
*hostApi = &auhalHostApi->inheritedHostApiRep;
(*hostApi)->info.structVersion = 1;
(*hostApi)->info.type = paCoreAudio;
(*hostApi)->info.name = "Core Audio";
(*hostApi)->info.defaultInputDevice = paNoDevice;
(*hostApi)->info.defaultOutputDevice = paNoDevice;
(*hostApi)->info.deviceCount = 0;
if( auhalHostApi->devCount > 0 )
{
(*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory(
auhalHostApi->allocations, sizeof(PaDeviceInfo*) * auhalHostApi->devCount);
if( !(*hostApi)->deviceInfos )
{
result = paInsufficientMemory;
goto error;
}
/* allocate all device info structs in a contiguous block */
deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory(
auhalHostApi->allocations, sizeof(PaDeviceInfo) * auhalHostApi->devCount );
if( !deviceInfoArray )
{
result = paInsufficientMemory;
goto error;
}
for( i=0; i < auhalHostApi->devCount; ++i )
{
int err;
err = InitializeDeviceInfo( auhalHostApi, &deviceInfoArray[i],
auhalHostApi->devIds[i],
hostApiIndex );
if (err == paNoError)
{ /* copy some info and set the defaults */
(*hostApi)->deviceInfos[(*hostApi)->info.deviceCount] = &deviceInfoArray[i];
if (auhalHostApi->devIds[i] == auhalHostApi->defaultIn)
(*hostApi)->info.defaultInputDevice = (*hostApi)->info.deviceCount;
if (auhalHostApi->devIds[i] == auhalHostApi->defaultOut)
(*hostApi)->info.defaultOutputDevice = (*hostApi)->info.deviceCount;
(*hostApi)->info.deviceCount++;
}
else
{ /* there was an error. we need to shift the devices down, so we ignore this one */
int j;
auhalHostApi->devCount--;
for( j=i; j<auhalHostApi->devCount; ++j )
auhalHostApi->devIds[j] = auhalHostApi->devIds[j+1];
i--;
}
}
}
(*hostApi)->Terminate = Terminate;
(*hostApi)->OpenStream = OpenStream;
(*hostApi)->IsFormatSupported = IsFormatSupported;
PaUtil_InitializeStreamInterface( &auhalHostApi->callbackStreamInterface,
CloseStream, StartStream,
StopStream, AbortStream, IsStreamStopped,
IsStreamActive,
GetStreamTime, GetStreamCpuLoad,
PaUtil_DummyRead, PaUtil_DummyWrite,
PaUtil_DummyGetReadAvailable,
PaUtil_DummyGetWriteAvailable );
PaUtil_InitializeStreamInterface( &auhalHostApi->blockingStreamInterface,
CloseStream, StartStream,
StopStream, AbortStream, IsStreamStopped,
IsStreamActive,
GetStreamTime, PaUtil_DummyGetCpuLoad,
ReadStream, WriteStream,
GetStreamReadAvailable,
GetStreamWriteAvailable );
return result;
error:
if( auhalHostApi )
{
if( auhalHostApi->allocations )
{
PaUtil_FreeAllAllocations( auhalHostApi->allocations );
PaUtil_DestroyAllocationGroup( auhalHostApi->allocations );
}
PaUtil_FreeMemory( auhalHostApi );
}
return result;
}
static void Terminate( struct PaUtilHostApiRepresentation *hostApi )
{
PaMacAUHAL *auhalHostApi = (PaMacAUHAL*)hostApi;
VVDBUG(("Terminate()\n"));
/*
IMPLEMENT ME:
- clean up any resources not handled by the allocation group
TODO: Double check that everything is handled by alloc group
*/
if( auhalHostApi->allocations )
{
PaUtil_FreeAllAllocations( auhalHostApi->allocations );
PaUtil_DestroyAllocationGroup( auhalHostApi->allocations );
}
PaUtil_FreeMemory( auhalHostApi );
}
static PaError IsFormatSupported( struct PaUtilHostApiRepresentation *hostApi,
const PaStreamParameters *inputParameters,
const PaStreamParameters *outputParameters,
double sampleRate )
{
int inputChannelCount, outputChannelCount;
PaSampleFormat inputSampleFormat, outputSampleFormat;
VVDBUG(("IsFormatSupported(): in chan=%d, in fmt=%ld, out chan=%d, out fmt=%ld sampleRate=%g\n",
inputParameters ? inputParameters->channelCount : -1,
inputParameters ? inputParameters->sampleFormat : -1,
outputParameters ? outputParameters->channelCount : -1,
outputParameters ? outputParameters->sampleFormat : -1,
(float) sampleRate ));
/** These first checks are standard PA checks. We do some fancier checks
later. */
if( inputParameters )
{
inputChannelCount = inputParameters->channelCount;
inputSampleFormat = inputParameters->sampleFormat;
/* all standard sample formats are supported by the buffer adapter,
this implementation doesn't support any custom sample formats */
if( inputSampleFormat & paCustomFormat )
return paSampleFormatNotSupported;
/* unless alternate device specification is supported, reject the use of
paUseHostApiSpecificDeviceSpecification */
if( inputParameters->device == paUseHostApiSpecificDeviceSpecification )
return paInvalidDevice;
/* check that input device can support inputChannelCount */
if( inputChannelCount > hostApi->deviceInfos[ inputParameters->device ]->maxInputChannels )
return paInvalidChannelCount;
}
else
{
inputChannelCount = 0;
}
if( outputParameters )
{
outputChannelCount = outputParameters->channelCount;
outputSampleFormat = outputParameters->sampleFormat;
/* all standard sample formats are supported by the buffer adapter,
this implementation doesn't support any custom sample formats */
if( outputSampleFormat & paCustomFormat )
return paSampleFormatNotSupported;
/* unless alternate device specification is supported, reject the use of
paUseHostApiSpecificDeviceSpecification */
if( outputParameters->device == paUseHostApiSpecificDeviceSpecification )
return paInvalidDevice;
/* check that output device can support outputChannelCount */
if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels )
return paInvalidChannelCount;
}
else
{
outputChannelCount = 0;
}
/* FEEDBACK */
/* I think the only way to check a given format SR combo is */
/* to try opening it. This could be disruptive, is that Okay? */
/* The alternative is to just read off available sample rates, */
/* but this will not work %100 of the time (eg, a device that */
/* supports N output at one rate but only N/2 at a higher rate.)*/
/* The following code opens the device with the requested parameters to
see if it works. */
{
PaError err;
PaStream *s;
err = OpenStream( hostApi, &s, inputParameters, outputParameters,
sampleRate, 1024, 0, (PaStreamCallback *)1, NULL );
if( err != paNoError && err != paInvalidSampleRate )
DBUG( ( "OpenStream @ %g returned: %d: %s\n",
(float) sampleRate, err, Pa_GetErrorText( err ) ) );
if( err )
return err;
err = CloseStream( s );
if( err ) {
/* FEEDBACK: is this more serious? should we assert? */
DBUG( ( "WARNING: could not close Stream. %d: %s\n",
err, Pa_GetErrorText( err ) ) );
}
}
return paFormatIsSupported;
}
static PaError OpenAndSetupOneAudioUnit(
const PaStreamParameters *inStreamParams,
const PaStreamParameters *outStreamParams,
const unsigned long requestedFramesPerBuffer,
unsigned long *actualInputFramesPerBuffer,
unsigned long *actualOutputFramesPerBuffer,
const PaMacAUHAL *auhalHostApi,
AudioUnit *audioUnit,
AudioConverterRef *srConverter,
AudioDeviceID *audioDevice,
const double sampleRate,
void *refCon )
{
ComponentDescription desc;
Component comp;
/*An Apple TN suggests using CAStreamBasicDescription, but that is C++*/
AudioStreamBasicDescription desiredFormat;
OSErr result = noErr;
PaError paResult = paNoError;
int line = 0;
UInt32 callbackKey;
AURenderCallbackStruct rcbs;
unsigned long macInputStreamFlags = paMacCorePlayNice;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -