void* PaUtil_GroupAllocateMemory( PaUtilAllocationGroup* group, long size ) { struct PaUtilAllocationGroupLink *links, *link; void *result = 0; /* allocate more links if necessary */ if( !group->spareLinks ) { /* double the link count on each block allocation */ links = AllocateLinks( group->linkCount, group->linkBlocks, group->spareLinks ); if( links ) { group->linkCount += group->linkCount; group->linkBlocks = &links[0]; group->spareLinks = &links[1]; } } if( group->spareLinks ) { result = PaUtil_AllocateMemory( size ); if( result ) { link = group->spareLinks; group->spareLinks = link->next; link->buffer = result; link->next = group->allocations; group->allocations = link; } } return result; }
PaUtilAllocationGroup* PaUtil_CreateAllocationGroup( void ) { PaUtilAllocationGroup* result = 0; struct PaUtilAllocationGroupLink *links; links = AllocateLinks( PA_INITIAL_LINK_COUNT_, 0, 0 ); if( links != 0 ) { result = (PaUtilAllocationGroup*)PaUtil_AllocateMemory( sizeof(PaUtilAllocationGroup) ); if( result ) { result->linkCount = PA_INITIAL_LINK_COUNT_; result->linkBlocks = &links[0]; result->spareLinks = &links[1]; result->allocations = 0; } else { PaUtil_FreeMemory( links ); } } return result; }
static PaError InitializeDeviceInfo(PaMacCoreDeviceInfo *macCoreDeviceInfo, AudioDeviceID macCoreDeviceId, PaHostApiIndex hostApiIndex ) { PaDeviceInfo *deviceInfo = &macCoreDeviceInfo->inheritedDeviceInfo; deviceInfo->structVersion = 2; deviceInfo->hostApi = hostApiIndex; PaError err = paNoError; UInt32 propSize; err = conv_err(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, NULL)); // FIXME: this allocation should be part of the allocations group char *name = PaUtil_AllocateMemory(propSize); err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyDeviceName, &propSize, name)); if (!err) { deviceInfo->name = name; } Float64 sampleRate; propSize = sizeof(Float64); err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, 0, kAudioDevicePropertyNominalSampleRate, &propSize, &sampleRate)); if (!err) { deviceInfo->defaultSampleRate = sampleRate; } // Get channel info err = GetChannelInfo(deviceInfo, macCoreDeviceId, 1); err = GetChannelInfo(deviceInfo, macCoreDeviceId, 0); return err; }
/* Allocate a block of links. The first link will have it's buffer member pointing to the block, and it's next member set to <nextBlock>. The remaining links will have NULL buffer members, and each link will point to the next link except the last, which will point to <nextSpare> */ static struct PaUtilAllocationGroupLink *AllocateLinks( long count, struct PaUtilAllocationGroupLink *nextBlock, struct PaUtilAllocationGroupLink *nextSpare ) { struct PaUtilAllocationGroupLink *result; int i; result = (struct PaUtilAllocationGroupLink *)PaUtil_AllocateMemory( sizeof(struct PaUtilAllocationGroupLink) * count ); if( result ) { /* the block link */ result[0].buffer = result; result[0].next = nextBlock; /* the spare links */ for( i=1; i<count; ++i ) { result[i].buffer = 0; result[i].next = &result[i+1]; } result[count-1].next = nextSpare; } return result; }
static PaStreamCallbackTimeInfo *InitializeTimeInfo(const AudioTimeStamp* now, const AudioTimeStamp* inputTime, const AudioTimeStamp* outputTime) { PaStreamCallbackTimeInfo *timeInfo = PaUtil_AllocateMemory(sizeof(PaStreamCallbackTimeInfo)); timeInfo->inputBufferAdcTime = inputTime->mSampleTime; timeInfo->currentTime = now->mSampleTime; timeInfo->outputBufferDacTime = outputTime->mSampleTime; return timeInfo; }
int PaUtil_InitializeHighSpeedLog( LogHandle* phLog, unsigned maxSizeInBytes ) { PaHighPerformanceLog* pLog = (PaHighPerformanceLog*)PaUtil_AllocateMemory(sizeof(PaHighPerformanceLog)); if (pLog == 0) { return paInsufficientMemory; } assert(phLog != 0); *phLog = pLog; pLog->data = (char*)PaUtil_AllocateMemory(maxSizeInBytes); if (pLog->data == 0) { PaUtil_FreeMemory(pLog); return paInsufficientMemory; } pLog->magik = kMagik; pLog->size = maxSizeInBytes; pLog->refTime = PaUtil_GetTime(); return paNoError; }
static OSStatus CheckFormat(AudioDeviceID macCoreDeviceId, const PaStreamParameters *parameters, double sampleRate, int isInput) { UInt32 propSize = sizeof(AudioStreamBasicDescription); AudioStreamBasicDescription *streamDescription = PaUtil_AllocateMemory(propSize); streamDescription->mSampleRate = sampleRate; streamDescription->mFormatID = 0; streamDescription->mFormatFlags = 0; streamDescription->mBytesPerPacket = 0; streamDescription->mFramesPerPacket = 0; streamDescription->mBytesPerFrame = 0; streamDescription->mChannelsPerFrame = 0; streamDescription->mBitsPerChannel = 0; streamDescription->mReserved = 0; OSStatus result = AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamFormatSupported, &propSize, streamDescription); PaUtil_FreeMemory(streamDescription); return result; }
static PaTime GetStreamTime( PaStream *s ) { OSStatus err; PaTime result; PaMacCoreStream *stream = (PaMacCoreStream*)s; AudioTimeStamp *timeStamp = PaUtil_AllocateMemory(sizeof(AudioTimeStamp)); if (stream->inputDevice != kAudioDeviceUnknown) { err = AudioDeviceGetCurrentTime(stream->inputDevice, timeStamp); } else { err = AudioDeviceGetCurrentTime(stream->outputDevice, timeStamp); } result = err ? 0 : timeStamp->mSampleTime; PaUtil_FreeMemory(timeStamp); return result; }
static PaError GetChannelInfo(PaDeviceInfo *deviceInfo, AudioDeviceID macCoreDeviceId, int isInput) { UInt32 propSize; PaError err = paNoError; UInt32 i; int numChannels = 0; AudioBufferList *buflist; err = conv_err(AudioDeviceGetPropertyInfo(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, NULL)); buflist = PaUtil_AllocateMemory(propSize); err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyStreamConfiguration, &propSize, buflist)); if (!err) { for (i = 0; i < buflist->mNumberBuffers; ++i) { numChannels += buflist->mBuffers[i].mNumberChannels; } if (isInput) deviceInfo->maxInputChannels = numChannels; else deviceInfo->maxOutputChannels = numChannels; int frameLatency; propSize = sizeof(UInt32); err = conv_err(AudioDeviceGetProperty(macCoreDeviceId, 0, isInput, kAudioDevicePropertyLatency, &propSize, &frameLatency)); if (!err) { double secondLatency = frameLatency / deviceInfo->defaultSampleRate; if (isInput) { deviceInfo->defaultLowInputLatency = secondLatency; deviceInfo->defaultHighInputLatency = secondLatency; } else { deviceInfo->defaultLowOutputLatency = secondLatency; deviceInfo->defaultHighOutputLatency = secondLatency; } } } PaUtil_FreeMemory(buflist); return err; }
static PaError WdmGetPinPropertyMulti( HANDLE handle, unsigned long pinId, unsigned long property, KSMULTIPLE_ITEM** ksMultipleItem) { unsigned long multipleItemSize = 0; KSP_PIN ksPProp; DWORD bytesReturned; *ksMultipleItem = 0; ksPProp.Property.Set = KSPROPSETID_Pin; ksPProp.Property.Id = property; ksPProp.Property.Flags = KSPROPERTY_TYPE_GET; ksPProp.PinId = pinId; ksPProp.Reserved = 0; if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp.Property, sizeof(KSP_PIN), NULL, 0, &multipleItemSize, NULL ) == 0 && GetLastError() != ERROR_MORE_DATA ) { return paUnanticipatedHostError; } *ksMultipleItem = (KSMULTIPLE_ITEM*)PaUtil_AllocateMemory( multipleItemSize ); if( !*ksMultipleItem ) { return paInsufficientMemory; } if( DeviceIoControl( handle, IOCTL_KS_PROPERTY, &ksPProp, sizeof(KSP_PIN), (void*)*ksMultipleItem, multipleItemSize, &bytesReturned, NULL ) == 0 || bytesReturned != multipleItemSize ) { PaUtil_FreeMemory( ksMultipleItem ); return paUnanticipatedHostError; } return paNoError; }
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, PaStream** s, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData ) { PaError result = paNoError; PaJackHostApiRepresentation *jackHostApi = (PaJackHostApiRepresentation*)hostApi; PaJackStream *stream = 0; char port_string[100]; char regex_pattern[100]; const char **jack_ports; int jack_max_buffer_size = jack_get_buffer_size( jackHostApi->jack_client ); int i; int inputChannelCount, outputChannelCount; PaSampleFormat inputSampleFormat, outputSampleFormat; /* the client has no say over the frames per callback */ if( framesPerBuffer == paFramesPerBufferUnspecified ) framesPerBuffer = jack_max_buffer_size; /* Preliminary checks */ if( inputParameters ) { inputChannelCount = inputParameters->channelCount; inputSampleFormat = inputParameters->sampleFormat; /* 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; /* validate inputStreamInfo */ if( inputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ } else { inputChannelCount = 0; } if( outputParameters ) { outputChannelCount = outputParameters->channelCount; outputSampleFormat = outputParameters->sampleFormat; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( outputParameters->device == paUseHostApiSpecificDeviceSpecification ) return paInvalidDevice; /* check that output device can support inputChannelCount */ if( outputChannelCount > hostApi->deviceInfos[ outputParameters->device ]->maxOutputChannels ) return paInvalidChannelCount; /* validate outputStreamInfo */ if( outputParameters->hostApiSpecificStreamInfo ) return paIncompatibleHostApiSpecificStreamInfo; /* this implementation doesn't use custom stream info */ } else { outputChannelCount = 0; } /* ... check that the sample rate exactly matches the ONE acceptable rate */ #define ABS(x) ( (x) > 0 ? (x) : -(x) ) if( ABS(sampleRate - hostApi->deviceInfos[0]->defaultSampleRate) > 1 ) return paInvalidSampleRate; #undef ABS /* Allocate memory for structuures */ #define MALLOC(size) \ (PaUtil_GroupAllocateMemory( stream->stream_memory, (size) )) #define MEMVERIFY(ptr) \ if( (ptr) == NULL ) \ { \ result = paInsufficientMemory; \ goto error; \ } stream = (PaJackStream*)PaUtil_AllocateMemory( sizeof(PaJackStream) ); MEMVERIFY( stream ); stream->stream_memory = PaUtil_CreateAllocationGroup(); stream->jack_client = jackHostApi->jack_client; PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate ); stream->local_input_ports = (jack_port_t**) MALLOC(sizeof(jack_port_t*) * inputChannelCount ); stream->local_output_ports = (jack_port_t**) MALLOC( sizeof(jack_port_t*) * outputChannelCount ); stream->remote_output_ports = (jack_port_t**) MALLOC( sizeof(jack_port_t*) * inputChannelCount ); stream->remote_input_ports = (jack_port_t**) MALLOC( sizeof(jack_port_t*) * outputChannelCount ); MEMVERIFY( stream->local_input_ports ); MEMVERIFY( stream->local_output_ports ); MEMVERIFY( stream->remote_input_ports ); MEMVERIFY( stream->remote_output_ports ); stream->num_incoming_connections = inputChannelCount; stream->num_outgoing_connections = outputChannelCount; if( streamCallback ) { PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, &jackHostApi->callbackStreamInterface, streamCallback, userData ); } else { /* we do not support blocking I/O */ return paBadIODeviceCombination; } /* create the JACK ports. We cannot connect them until audio * processing begins */ for( i = 0; i < inputChannelCount; i++ ) { sprintf( port_string, "in_%d", i ); stream->local_input_ports[i] = jack_port_register( jackHostApi->jack_client, port_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput, 0 ); } for( i = 0; i < outputChannelCount; i++ ) { sprintf( port_string, "out_%d", i ); stream->local_output_ports[i] = jack_port_register( jackHostApi->jack_client, port_string, JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput, 0 ); } /* look up the jack_port_t's for the remote ports. We could do * this at stream start time, but doing it here ensures the * name lookup only happens once. */ if( inputChannelCount > 0 ) { /* ... remote output ports (that we input from) */ sprintf( regex_pattern, "%s:.*", hostApi->deviceInfos[ inputParameters->device ]->name ); jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern, NULL, JackPortIsOutput); for( i = 0; i < inputChannelCount && jack_ports[i]; i++ ) { stream->remote_output_ports[i] = jack_port_by_name( jackHostApi->jack_client, jack_ports[i] ); } if( i < inputChannelCount ) { /* we found fewer ports than we expected */ return paInternalError; } free( jack_ports ); // XXX: this doesn't happen if we exit prematurely } if( outputChannelCount > 0 ) { /* ... remote input ports (that we output to) */ sprintf( regex_pattern, "%s:.*", hostApi->deviceInfos[ outputParameters->device ]->name ); jack_ports = jack_get_ports( jackHostApi->jack_client, regex_pattern, NULL, JackPortIsInput); for( i = 0; i < outputChannelCount && jack_ports[i]; i++ ) { stream->remote_input_ports[i] = jack_port_by_name( jackHostApi->jack_client, jack_ports[i] ); } if( i < outputChannelCount ) { /* we found fewer ports than we expected */ return paInternalError; } free( jack_ports ); // XXX: this doesn't happen if we exit prematurely } result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor, inputChannelCount, inputSampleFormat, paFloat32, /* hostInputSampleFormat */ outputChannelCount, outputSampleFormat, paFloat32, /* hostOutputSampleFormat */ sampleRate, streamFlags, framesPerBuffer, jack_max_buffer_size, paUtilFixedHostBufferSize, streamCallback, userData ); if( result != paNoError ) goto error; stream->is_running = FALSE; stream->t0 = -1;/* set the first time through the callback*/ stream->total_frames_sent = 0; jack_set_process_callback( jackHostApi->jack_client, JackCallback, stream ); *s = (PaStream*)stream; return result; error: if( stream ) { if( stream->stream_memory ) { PaUtil_FreeAllAllocations( stream->stream_memory ); PaUtil_DestroyAllocationGroup( stream->stream_memory ); } PaUtil_FreeMemory( stream ); } return result; #undef MALLOC #undef MEMVERIFY }
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, PaStream** s, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData ) { PaError err = paNoError; PaMacCoreHostApiRepresentation *macCoreHostApi = (PaMacCoreHostApiRepresentation *)hostApi; PaMacCoreStream *stream = PaUtil_AllocateMemory(sizeof(PaMacCoreStream)); stream->isActive = 0; stream->isStopped = 1; stream->inputDevice = kAudioDeviceUnknown; stream->outputDevice = kAudioDeviceUnknown; PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, ( (streamCallback) ? &macCoreHostApi->callbackStreamInterface : &macCoreHostApi->blockingStreamInterface ), streamCallback, userData ); PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate ); *s = (PaStream*)stream; PaMacClientData *clientData = PaUtil_AllocateMemory(sizeof(PaMacClientData)); clientData->stream = stream; clientData->callback = streamCallback; clientData->userData = userData; clientData->inputBuffer = 0; clientData->outputBuffer = 0; clientData->ditherGenerator = PaUtil_AllocateMemory(sizeof(PaUtilTriangularDitherGenerator)); PaUtil_InitializeTriangularDitherState(clientData->ditherGenerator); if (inputParameters != NULL) { stream->inputDevice = macCoreHostApi->macCoreDeviceIds[inputParameters->device]; clientData->inputConverter = PaUtil_SelectConverter(paFloat32, inputParameters->sampleFormat, streamFlags); clientData->inputBuffer = PaUtil_AllocateMemory(Pa_GetSampleSize(inputParameters->sampleFormat) * framesPerBuffer * inputParameters->channelCount); clientData->inputChannelCount = inputParameters->channelCount; clientData->inputSampleFormat = inputParameters->sampleFormat; err = SetUpUnidirectionalStream(stream->inputDevice, sampleRate, framesPerBuffer, 1); } if (err == paNoError && outputParameters != NULL) { stream->outputDevice = macCoreHostApi->macCoreDeviceIds[outputParameters->device]; clientData->outputConverter = PaUtil_SelectConverter(outputParameters->sampleFormat, paFloat32, streamFlags); clientData->outputBuffer = PaUtil_AllocateMemory(Pa_GetSampleSize(outputParameters->sampleFormat) * framesPerBuffer * outputParameters->channelCount); clientData->outputChannelCount = outputParameters->channelCount; clientData->outputSampleFormat = outputParameters->sampleFormat; err = SetUpUnidirectionalStream(stream->outputDevice, sampleRate, framesPerBuffer, 0); } if (inputParameters == NULL || outputParameters == NULL || stream->inputDevice == stream->outputDevice) { AudioDeviceID device = (inputParameters == NULL) ? stream->outputDevice : stream->inputDevice; AudioDeviceAddIOProc(device, AudioIOProc, clientData); } else { // using different devices for input and output AudioDeviceAddIOProc(stream->inputDevice, AudioInputProc, clientData); AudioDeviceAddIOProc(stream->outputDevice, AudioOutputProc, clientData); } return err; }
PaError PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex) { PaSndioHostApiRepresentation *sndioHostApi; PaDeviceInfo *info; struct sio_hdl *hdl; DPR("PaSndio_Initialize: initializing...\n"); /* unusable APIs should return paNoError and a NULL hostApi */ *hostApi = NULL; sndioHostApi = PaUtil_AllocateMemory(sizeof(PaSndioHostApiRepresentation)); if (sndioHostApi == NULL) return paNoError; info = &sndioHostApi->default_info; info->structVersion = 2; info->name = "default"; info->hostApi = hostApiIndex; info->maxInputChannels = 128; info->maxOutputChannels = 128; info->defaultLowInputLatency = 0.01; info->defaultLowOutputLatency = 0.01; info->defaultHighInputLatency = 0.5; info->defaultHighOutputLatency = 0.5; info->defaultSampleRate = 48000; sndioHostApi->infos[0] = info; *hostApi = &sndioHostApi->base; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paSndio; (*hostApi)->info.name = "sndio"; (*hostApi)->info.deviceCount = 1; (*hostApi)->info.defaultInputDevice = 0; (*hostApi)->info.defaultOutputDevice = 0; (*hostApi)->deviceInfos = sndioHostApi->infos; (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface(&sndioHostApi->blocking, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, BlockingReadStream, BlockingWriteStream, BlockingGetStreamReadAvailable, BlockingGetStreamWriteAvailable); PaUtil_InitializeStreamInterface(&sndioHostApi->callback, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, PaUtil_DummyRead, PaUtil_DummyWrite, PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable); DPR("PaSndio_Initialize: done\n"); return paNoError; }
static PaError OpenStream(struct PaUtilHostApiRepresentation *hostApi, PaStream **stream, const PaStreamParameters *inputPar, const PaStreamParameters *outputPar, double sampleRate, unsigned long framesPerBuffer, PaStreamFlags streamFlags, PaStreamCallback *streamCallback, void *userData) { PaSndioHostApiRepresentation *sndioHostApi = (PaSndioHostApiRepresentation *)hostApi; PaSndioStream *s; PaError err; struct sio_hdl *hdl; struct sio_par par; unsigned mode; int inch, onch; PaSampleFormat ifmt, ofmt, siofmt; DPR("OpenStream:\n"); mode = 0; inch = onch = 0; ifmt = ofmt = 0; sio_initpar(&par); if (outputPar && outputPar->channelCount > 0) { if (outputPar->device != 0) { DPR("OpenStream: %d: bad output device\n", outputPar->device); return paInvalidDevice; } if (outputPar->hostApiSpecificStreamInfo) { DPR("OpenStream: output specific info\n"); return paIncompatibleHostApiSpecificStreamInfo; } if (!sndioSetFmt(&par, outputPar->sampleFormat)) { return paSampleFormatNotSupported; } ofmt = outputPar->sampleFormat; onch = par.pchan = outputPar->channelCount; mode |= SIO_PLAY; } if (inputPar && inputPar->channelCount > 0) { if (inputPar->device != 0) { DPR("OpenStream: %d: bad input device\n", inputPar->device); return paInvalidDevice; } if (inputPar->hostApiSpecificStreamInfo) { DPR("OpenStream: input specific info\n"); return paIncompatibleHostApiSpecificStreamInfo; } if (!sndioSetFmt(&par, inputPar->sampleFormat)) { return paSampleFormatNotSupported; } ifmt = inputPar->sampleFormat; inch = par.rchan = inputPar->channelCount; mode |= SIO_REC; } par.rate = sampleRate; if (framesPerBuffer != paFramesPerBufferUnspecified) par.round = framesPerBuffer; DPR("OpenStream: mode = %x, trying rate = %u\n", mode, par.rate); hdl = sio_open(SIO_DEVANY, mode, 0); if (hdl == NULL) return paUnanticipatedHostError; if (!sio_setpar(hdl, &par)) { sio_close(hdl); return paUnanticipatedHostError; } if (!sio_getpar(hdl, &par)) { sio_close(hdl); return paUnanticipatedHostError; } if (!sndioGetFmt(&par, &siofmt)) { sio_close(hdl); return paSampleFormatNotSupported; } if ((mode & SIO_REC) && par.rchan != inputPar->channelCount) { DPR("OpenStream: rchan(%u) != %d\n", par.rchan, inputPar->channelCount); sio_close(hdl); return paInvalidChannelCount; } if ((mode & SIO_PLAY) && par.pchan != outputPar->channelCount) { DPR("OpenStream: pchan(%u) != %d\n", par.pchan, outputPar->channelCount); sio_close(hdl); return paInvalidChannelCount; } if ((double)par.rate < sampleRate * 0.995 || (double)par.rate > sampleRate * 1.005) { DPR("OpenStream: rate(%u) != %g\n", par.rate, sampleRate); sio_close(hdl); return paInvalidSampleRate; } s = (PaSndioStream *)PaUtil_AllocateMemory(sizeof(PaSndioStream)); if (s == NULL) { sio_close(hdl); return paInsufficientMemory; } PaUtil_InitializeStreamRepresentation(&s->base, streamCallback ? &sndioHostApi->callback : &sndioHostApi->blocking, streamCallback, userData); DPR("inch = %d, onch = %d, ifmt = %x, ofmt = %x\n", inch, onch, ifmt, ofmt); err = PaUtil_InitializeBufferProcessor(&s->bufproc, inch, ifmt, siofmt, onch, ofmt, siofmt, sampleRate, streamFlags, framesPerBuffer, par.round, paUtilFixedHostBufferSize, streamCallback, userData); if (err) { DPR("OpenStream: PaUtil_InitializeBufferProcessor failed\n"); PaUtil_FreeMemory(s); sio_close(hdl); return err; } if (mode & SIO_REC) { s->rbuf = malloc(par.round * par.rchan * par.bps); if (s->rbuf == NULL) { DPR("OpenStream: failed to allocate rbuf\n"); PaUtil_FreeMemory(s); sio_close(hdl); return paInsufficientMemory; } } if (mode & SIO_PLAY) { s->wbuf = malloc(par.round * par.pchan * par.bps); if (s->wbuf == NULL) { DPR("OpenStream: failed to allocate wbuf\n"); free(s->rbuf); PaUtil_FreeMemory(s); sio_close(hdl); return paInsufficientMemory; } } s->base.streamInfo.inputLatency = 0; s->base.streamInfo.outputLatency = (mode & SIO_PLAY) ? (double)(par.bufsz + PaUtil_GetBufferProcessorOutputLatencyFrames(&s->bufproc)) / (double)par.rate : 0; s->base.streamInfo.sampleRate = par.rate; s->active = 0; s->stopped = 1; s->mode = mode; s->hdl = hdl; s->par = par; *stream = s; DPR("OpenStream: done\n"); return paNoError; }
PaError PaSkeleton_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ) { PaError result = paNoError; int i, deviceCount; PaSkeletonHostApiRepresentation *skeletonHostApi; PaDeviceInfo *deviceInfoArray; skeletonHostApi = (PaSkeletonHostApiRepresentation*)PaUtil_AllocateMemory( sizeof(PaSkeletonHostApiRepresentation) ); if( !skeletonHostApi ) { result = paInsufficientMemory; goto error; } skeletonHostApi->allocations = PaUtil_CreateAllocationGroup(); if( !skeletonHostApi->allocations ) { result = paInsufficientMemory; goto error; } *hostApi = &skeletonHostApi->commonHostApiRep; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paInDevelopment; /* IMPLEMENT ME: change to correct type id */ (*hostApi)->info.name = "skeleton implementation"; /* IMPLEMENT ME: change to correct name */ (*hostApi)->deviceCount = 0; (*hostApi)->defaultInputDeviceIndex = paNoDevice; /* IMPLEMENT ME */ (*hostApi)->defaultOutputDeviceIndex = paNoDevice; /* IMPLEMENT ME */ deviceCount = 0; /* IMPLEMENT ME */ if( deviceCount > 0 ) { (*hostApi)->deviceInfos = (PaDeviceInfo**)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, sizeof(PaDeviceInfo*) * deviceCount ); if( !(*hostApi)->deviceInfos ) { result = paInsufficientMemory; goto error; } /* allocate all device info structs in a contiguous block */ deviceInfoArray = (PaDeviceInfo*)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, sizeof(PaDeviceInfo) * deviceCount ); if( !deviceInfoArray ) { result = paInsufficientMemory; goto error; } for( i=0; i < deviceCount; ++i ) { PaDeviceInfo *deviceInfo = &deviceInfoArray[i]; deviceInfo->structVersion = 2; deviceInfo->hostApi = hostApiIndex; deviceInfo->name = 0; /* IMPLEMENT ME: allocate block and copy name eg: deviceName = (char*)PaUtil_GroupAllocateMemory( skeletonHostApi->allocations, strlen(srcName) + 1 ); if( !deviceName ) { result = paInsufficientMemory; goto error; } strcpy( deviceName, srcName ); deviceInfo->name = deviceName; */ /* IMPLEMENT ME: - populate other device info fields */ (*hostApi)->deviceInfos[i] = deviceInfo; ++(*hostApi)->deviceCount; } } (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; PaUtil_InitializeStreamInterface( &skeletonHostApi->callbackStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, GetStreamCpuLoad, PaUtil_DummyReadWrite, PaUtil_DummyReadWrite, PaUtil_DummyGetAvailable, PaUtil_DummyGetAvailable ); PaUtil_InitializeStreamInterface( &skeletonHostApi->blockingStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable ); return result; error: if( skeletonHostApi ) { if( skeletonHostApi->allocations ) { PaUtil_FreeAllAllocations( skeletonHostApi->allocations ); PaUtil_DestroyAllocationGroup( skeletonHostApi->allocations ); } PaUtil_FreeMemory( skeletonHostApi ); } return result; }
PaError PaJack_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ) { PaError result = paNoError; PaJackHostApiRepresentation *jackHostApi; jackHostApi = (PaJackHostApiRepresentation*) PaUtil_AllocateMemory( sizeof(PaJackHostApiRepresentation) ); if( !jackHostApi ) { result = paInsufficientMemory; goto error; } jackHostApi->deviceInfoMemory = NULL; /* Try to become a client of the JACK server. If we cannot do * this, than this API cannot be used. */ jackHostApi->jack_client = jack_client_new( "PortAudio client" ); if( jackHostApi->jack_client == 0 ) { /* the V19 development docs say that if an implementation * detects that it cannot be used, it should return a NULL * interface and paNoError */ result = paNoError; *hostApi = NULL; goto error; } jackHostApi->deviceInfoMemory = PaUtil_CreateAllocationGroup(); if( !jackHostApi->deviceInfoMemory ) { result = paInsufficientMemory; goto error; } jackHostApi->hostApiIndex = hostApiIndex; *hostApi = &jackHostApi->commonHostApiRep; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paInDevelopment; (*hostApi)->info.name = "JACK Audio Connection Kit"; (*hostApi)->info.defaultInputDevice = paNoDevice; /* set in BuildDeviceList() */ (*hostApi)->info.defaultOutputDevice = paNoDevice; /* set in BuildDeviceList() */ (*hostApi)->info.deviceCount = 0; /* set in BuildDeviceList() */ /* Build a device list by querying the JACK server */ result = BuildDeviceList( jackHostApi ); if( result != paNoError ) goto error; /* Register functions */ (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface( &jackHostApi->callbackStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, GetStreamCpuLoad, PaUtil_DummyRead, PaUtil_DummyWrite, PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable ); return result; error: if( jackHostApi ) { if( jackHostApi->deviceInfoMemory ) { PaUtil_FreeAllAllocations( jackHostApi->deviceInfoMemory ); PaUtil_DestroyAllocationGroup( jackHostApi->deviceInfoMemory ); } PaUtil_FreeMemory( jackHostApi ); } return result; }
// HostAPI-specific initialization function PaError PaMacCore_Initialize( PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex ) { PaError result = paNoError; PaMacCoreHostApiRepresentation *macCoreHostApi = (PaMacCoreHostApiRepresentation *)PaUtil_AllocateMemory( sizeof(PaMacCoreHostApiRepresentation) ); if( !macCoreHostApi ) { result = paInsufficientMemory; goto error; } macCoreHostApi->allocations = PaUtil_CreateAllocationGroup(); if( !macCoreHostApi->allocations ) { result = paInsufficientMemory; goto error; } *hostApi = &macCoreHostApi->inheritedHostApiRep; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paCoreAudio; (*hostApi)->info.name = "CoreAudio"; result = InitializeDeviceInfos(macCoreHostApi, hostApiIndex); if (result != paNoError) { goto error; } // Set up the proper callbacks to this HostApi's functions (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface( &macCoreHostApi->callbackStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, GetStreamCpuLoad, PaUtil_DummyRead, PaUtil_DummyWrite, PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable ); PaUtil_InitializeStreamInterface( &macCoreHostApi->blockingStreamInterface, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, ReadStream, WriteStream, GetStreamReadAvailable, GetStreamWriteAvailable ); return result; error: if( macCoreHostApi ) { CleanUp(macCoreHostApi); } return result; }
static PaError OpenStream( struct PaUtilHostApiRepresentation *hostApi, PaStream** s, PaDeviceIndex inputDevice, int numInputChannels, PaSampleFormat inputSampleFormat, unsigned long inputLatency, PaHostApiSpecificStreamInfo *inputStreamInfo, PaDeviceIndex outputDevice, int numOutputChannels, PaSampleFormat outputSampleFormat, unsigned long outputLatency, PaHostApiSpecificStreamInfo *outputStreamInfo, double sampleRate, unsigned long framesPerCallback, PaStreamFlags streamFlags, PortAudioCallback *callback, void *userData ) { PaError result = paNoError; PaSkeletonHostApiRepresentation *skeletonHostApi = (PaSkeletonHostApiRepresentation*)hostApi; PaSkeletonStream *stream = 0; unsigned long framesPerHostBuffer = framesPerCallback; /* these may not be equivalent for all implementations */ PaSampleFormat hostInputSampleFormat, hostOutputSampleFormat; /* unless alternate device specification is supported, reject the use of paUseHostApiSpecificDeviceSpecification */ if( (inputDevice == paUseHostApiSpecificDeviceSpecification) || (outputDevice == paUseHostApiSpecificDeviceSpecification) ) return paInvalidDevice; /* check that input device can support numInputChannels */ if( (inputDevice != paNoDevice) && (numInputChannels > hostApi->deviceInfos[ inputDevice ]->maxInputChannels) ) return paInvalidChannelCount; /* check that output device can support numInputChannels */ if( (outputDevice != paNoDevice) && (numOutputChannels > hostApi->deviceInfos[ outputDevice ]->maxOutputChannels) ) return paInvalidChannelCount; /* IMPLEMENT ME: ( the following two checks are taken care of by PaUtil_InitializeBufferProcessor() FIXME - checks needed? ) - check that input device can support inputSampleFormat, or that we have the capability to convert from outputSampleFormat to a native format - check that output device can support outputSampleFormat, or that we have the capability to convert from outputSampleFormat to a native format - if a full duplex stream is requested, check that the combination of input and output parameters is supported - check that the device supports sampleRate - alter sampleRate to a close allowable rate if possible / necessary - validate inputLatency and outputLatency parameters, use default values where necessary */ /* validate inputStreamInfo */ if( inputStreamInfo ) return paIncompatibleStreamInfo; /* this implementation doesn't use custom stream info */ /* validate outputStreamInfo */ if( outputStreamInfo ) return paIncompatibleStreamInfo; /* this implementation doesn't use custom stream info */ /* validate platform specific flags */ if( (streamFlags & paPlatformSpecificFlags) != 0 ) return paInvalidFlag; /* unexpected platform specific flag */ stream = (PaSkeletonStream*)PaUtil_AllocateMemory( sizeof(PaSkeletonStream) ); if( !stream ) { result = paInsufficientMemory; goto error; } if( callback ) { PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, &skeletonHostApi->callbackStreamInterface, callback, userData ); } else { PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation, &skeletonHostApi->blockingStreamInterface, callback, userData ); } PaUtil_InitializeCpuLoadMeasurer( &stream->cpuLoadMeasurer, sampleRate ); /* IMPLEMENT ME - establish which host formats are available */ hostInputSampleFormat = PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, inputSampleFormat ); /* IMPLEMENT ME - establish which host formats are available */ hostOutputSampleFormat = PaUtil_SelectClosestAvailableFormat( paInt16 /* native formats */, outputSampleFormat ); /* we assume a fixed host buffer size in this example, but the buffer processor can also support bounded and unknown host buffer sized by passing paUtilBoundedHostBufferSize or paUtilUnknownHostBufferSize instead of paUtilFixedHostBufferSize below. */ result = PaUtil_InitializeBufferProcessor( &stream->bufferProcessor, numInputChannels, inputSampleFormat, hostInputSampleFormat, numOutputChannels, outputSampleFormat, hostOutputSampleFormat, sampleRate, streamFlags, framesPerCallback, framesPerHostBuffer, paUtilFixedHostBufferSize, callback, userData ); if( result != paNoError ) goto error; /* IMPLEMENT ME: - additional stream setup + opening */ stream->framesPerHostCallback = framesPerHostBuffer; *s = (PaStream*)stream; return result; error: if( stream ) PaUtil_FreeMemory( stream ); return result; }
PaError PaSndio_Initialize(PaUtilHostApiRepresentation **hostApi, PaHostApiIndex hostApiIndex) { PaSndioHostApiRepresentation *sndioHostApi; PaDeviceInfo *info; struct sio_hdl *hdl; char *audiodevices; char *device; size_t deviceCount; DPR("PaSndio_Initialize: initializing...\n"); /* unusable APIs should return paNoError and a NULL hostApi */ *hostApi = NULL; sndioHostApi = PaUtil_AllocateMemory(sizeof(PaSndioHostApiRepresentation)); if (sndioHostApi == NULL) return paNoError; // Add default device info = &sndioHostApi->device_info[0]; InitDeviceInfo(info, hostApiIndex, SIO_DEVANY); sndioHostApi->infos[0] = info; deviceCount = 1; // Add additional devices as specified in the PA_SNDIO_AUDIODEVICES // environment variable as a colon separated list sndioHostApi->audiodevices = NULL; audiodevices = getenv("PA_SNDIO_AUDIODEVICES"); if (audiodevices != NULL) { sndioHostApi->audiodevices = strdup(audiodevices); if (sndioHostApi->audiodevices == NULL) return paNoError; audiodevices = sndioHostApi->audiodevices; while ((device = strsep(&audiodevices, ":")) != NULL && deviceCount < PA_SNDIO_AUDIODEVICES_MAX) { if (*device == '\0') continue; info = &sndioHostApi->device_info[deviceCount]; InitDeviceInfo(info, hostApiIndex, device); sndioHostApi->infos[deviceCount] = info; deviceCount++; } } *hostApi = &sndioHostApi->base; (*hostApi)->info.structVersion = 1; (*hostApi)->info.type = paSndio; (*hostApi)->info.name = "sndio"; (*hostApi)->info.deviceCount = deviceCount; (*hostApi)->info.defaultInputDevice = 0; (*hostApi)->info.defaultOutputDevice = 0; (*hostApi)->deviceInfos = sndioHostApi->infos; (*hostApi)->Terminate = Terminate; (*hostApi)->OpenStream = OpenStream; (*hostApi)->IsFormatSupported = IsFormatSupported; PaUtil_InitializeStreamInterface(&sndioHostApi->blocking, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, BlockingReadStream, BlockingWriteStream, BlockingGetStreamReadAvailable, BlockingGetStreamWriteAvailable); PaUtil_InitializeStreamInterface(&sndioHostApi->callback, CloseStream, StartStream, StopStream, AbortStream, IsStreamStopped, IsStreamActive, GetStreamTime, PaUtil_DummyGetCpuLoad, PaUtil_DummyRead, PaUtil_DummyWrite, PaUtil_DummyGetReadAvailable, PaUtil_DummyGetWriteAvailable); DPR("PaSndio_Initialize: done\n"); return paNoError; }