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;
}
Exemple #6
0
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;
}
Exemple #11
0
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;
}
Exemple #13
0
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;
}
Exemple #14
0
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;
}
Exemple #16
0
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;
}
Exemple #19
0
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;
}