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

📄 pa_unix_oss.c

📁 一个开源的sip源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
static void PaOssStreamComponent_Terminate( PaOssStreamComponent *component ){    assert( component );    if( component->fd >= 0 )        close( component->fd );    if( component->buffer )        PaUtil_FreeMemory( component->buffer );    if( component->userBuffers )        PaUtil_FreeMemory( component->userBuffers );    PaUtil_FreeMemory( component );}static PaError ModifyBlocking( int fd, int blocking ){    PaError result = paNoError;    int fflags;    ENSURE_( fflags = fcntl( fd, F_GETFL ), paUnanticipatedHostError );    if( blocking )        fflags &= ~O_NONBLOCK;    else        fflags |= O_NONBLOCK;    ENSURE_( fcntl( fd, F_SETFL, fflags ), paUnanticipatedHostError );error:    return result;}static PaError OpenDevices( const char *idevName, const char *odevName, int *idev, int *odev ){    PaError result = paNoError;    int flags = O_NONBLOCK, duplex = 0;    int enableBits = 0;    *idev = *odev = -1;    if( idevName && odevName )    {        duplex = 1;        flags |= O_RDWR;    }    else if( idevName )        flags |= O_RDONLY;    else        flags |= O_WRONLY;    /* open first in nonblocking mode, in case it's busy...     * A: then unset the non-blocking attribute */    assert( flags & O_NONBLOCK );    if( idevName )    {        ENSURE_( *idev = open( idevName, flags ), paDeviceUnavailable );        PA_ENSURE( ModifyBlocking( *idev, 1 ) ); /* Blocking */        /* Initially disable */        enableBits = ~PCM_ENABLE_INPUT;        ENSURE_( ioctl( *idev, SNDCTL_DSP_SETTRIGGER, &enableBits ), paUnanticipatedHostError );    }    if( odevName )    {        if( !idevName )        {            ENSURE_( *odev = open( odevName, flags ), paDeviceUnavailable );            PA_ENSURE( ModifyBlocking( *odev, 1 ) ); /* Blocking */            /* Initially disable */            enableBits = ~PCM_ENABLE_OUTPUT;            ENSURE_( ioctl( *odev, SNDCTL_DSP_SETTRIGGER, &enableBits ), paUnanticipatedHostError );        }        else        {            ENSURE_( *odev = dup( *idev ), paUnanticipatedHostError );        }    }error:    return result;}static PaError PaOssStream_Initialize( PaOssStream *stream, const PaStreamParameters *inputParameters, const PaStreamParameters *outputParameters,        PaStreamCallback callback, void *userData, PaStreamFlags streamFlags,        PaOSSHostApiRepresentation *ossApi ){    PaError result = paNoError;    int idev, odev;    PaUtilHostApiRepresentation *hostApi = &ossApi->inheritedHostApiRep;    const char *idevName = NULL, *odevName = NULL;    assert( stream );    memset( stream, 0, sizeof (PaOssStream) );    stream->isStopped = 1;    PA_ENSURE( PaUtil_InitializeThreading( &stream->threading ) );    if( inputParameters && outputParameters )    {        if( inputParameters->device == outputParameters->device )            stream->sharedDevice = 1;    }    if( inputParameters )        idevName = hostApi->deviceInfos[inputParameters->device]->name;    if( outputParameters )        odevName = hostApi->deviceInfos[outputParameters->device]->name;    PA_ENSURE( OpenDevices( idevName, odevName, &idev, &odev ) );    if( inputParameters )    {        PA_UNLESS( stream->capture = PaUtil_AllocateMemory( sizeof (PaOssStreamComponent) ), paInsufficientMemory );        PA_ENSURE( PaOssStreamComponent_Initialize( stream->capture, inputParameters, callback != NULL, idev, idevName ) );    }    if( outputParameters )    {        PA_UNLESS( stream->playback = PaUtil_AllocateMemory( sizeof (PaOssStreamComponent) ), paInsufficientMemory );        PA_ENSURE( PaOssStreamComponent_Initialize( stream->playback, outputParameters, callback != NULL, odev, odevName ) );    }    if( callback != NULL )    {        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &ossApi->callbackStreamInterface, callback, userData );        stream->callbackMode = 1;    }    else    {        PaUtil_InitializeStreamRepresentation( &stream->streamRepresentation,                                               &ossApi->blockingStreamInterface, callback, userData );    }        ENSURE_( sem_init( &stream->semaphore, 0, 0 ), paInternalError );error:    return result;}static void PaOssStream_Terminate( PaOssStream *stream ){    assert( stream );    PaUtil_TerminateStreamRepresentation( &stream->streamRepresentation );    PaUtil_TerminateThreading( &stream->threading );    if( stream->capture )        PaOssStreamComponent_Terminate( stream->capture );    if( stream->playback )        PaOssStreamComponent_Terminate( stream->playback );    sem_destroy( &stream->semaphore );    PaUtil_FreeMemory( stream );}/** Translate from PA format to OSS native. * */static PaError Pa2OssFormat( PaSampleFormat paFormat, int *ossFormat ){    switch( paFormat )    {        case paUInt8:            *ossFormat = AFMT_U8;            break;        case paInt8:            *ossFormat = AFMT_S8;            break;        case paInt16:            *ossFormat = AFMT_S16_NE;            break;        default:            return paInternalError;     /* This shouldn't happen */    }    return paNoError;}/** Return the PA-compatible formats that this device can support. * */static PaError GetAvailableFormats( PaOssStreamComponent *component, PaSampleFormat *availableFormats ){    PaError result = paNoError;    int mask = 0;    PaSampleFormat frmts = 0;    ENSURE_( ioctl( component->fd, SNDCTL_DSP_GETFMTS, &mask ), paUnanticipatedHostError );    if( mask & AFMT_U8 )        frmts |= paUInt8;    if( mask & AFMT_S8 )        frmts |= paInt8;    if( mask & AFMT_S16_NE )        frmts |= paInt16;    else        result = paSampleFormatNotSupported;        *availableFormats = frmts;error:    return result;}static unsigned int PaOssStreamComponent_FrameSize( PaOssStreamComponent *component ){    return Pa_GetSampleSize( component->hostFormat ) * component->hostChannelCount;}/** Buffer size in bytes. * */static unsigned long PaOssStreamComponent_BufferSize( PaOssStreamComponent *component ){    return PaOssStreamComponent_FrameSize( component ) * component->hostFrames * component->numBufs;}static int CalcHigherLogTwo( int n ){    int log2 = 0;    while( (1<<log2) < n ) log2++;    return log2;}static PaError PaOssStreamComponent_Configure( PaOssStreamComponent *component, double sampleRate, unsigned long framesPerBuffer,        StreamMode streamMode, PaOssStreamComponent *master ){    PaError result = paNoError;    int temp, nativeFormat;    int sr = (int)sampleRate;    PaSampleFormat availableFormats = 0, hostFormat = 0;    int chans = component->userChannelCount;    int frgmt;    int numBufs;    int bytesPerBuf;    double bufSz;    unsigned long fragSz;    audio_buf_info bufInfo;    /* We may have a situation where only one component (the master) is configured, if both point to the same device.     * In that case, the second component will copy settings from the other */    if( !master )    {        /* Aspect BufferSettings: If framesPerBuffer is unspecified we have to infer a suitable fragment size.         * The hardware need not respect the requested fragment size, so we may have to adapt.         */        if( framesPerBuffer == paFramesPerBufferUnspecified )        {             bufSz = component->latency * sampleRate;            fragSz = bufSz / 4;        }        else        {            fragSz = framesPerBuffer;            bufSz = component->latency * sampleRate + fragSz; /* Latency + 1 buffer */        }        PA_ENSURE( GetAvailableFormats( component, &availableFormats ) );        hostFormat = PaUtil_SelectClosestAvailableFormat( availableFormats, component->userFormat );        /* OSS demands at least 2 buffers, and 16 bytes per buffer */        numBufs = PA_MAX( bufSz / fragSz, 2 );        bytesPerBuf = PA_MAX( fragSz * Pa_GetSampleSize( hostFormat ) * chans, 16 );        /* The fragment parameters are encoded like this:         * Most significant byte: number of fragments         * Least significant byte: exponent of fragment size (i.e., for 256, 8)         */        frgmt = (numBufs << 16) + (CalcHigherLogTwo( bytesPerBuf ) & 0xffff);        ENSURE_( ioctl( component->fd, SNDCTL_DSP_SETFRAGMENT, &frgmt ), paUnanticipatedHostError );        /* A: according to the OSS programmer's guide parameters should be set in this order:         * format, channels, rate */        /* This format should be deemed good before we get this far */        PA_ENSURE( Pa2OssFormat( hostFormat, &temp ) );        nativeFormat = temp;        ENSURE_( ioctl( component->fd, SNDCTL_DSP_SETFMT, &temp ), paUnanticipatedHostError );        PA_UNLESS( temp == nativeFormat, paInternalError );        /* try to set the number of channels */        ENSURE_( ioctl( component->fd, SNDCTL_DSP_CHANNELS, &chans ), paSampleFormatNotSupported );   /* XXX: Should be paInvalidChannelCount? */        /* It's possible that the minimum number of host channels is greater than what the user requested */        PA_UNLESS( chans >= component->userChannelCount, paInvalidChannelCount );        /* try to set the sample rate */        ENSURE_( ioctl( component->fd, SNDCTL_DSP_SPEED, &sr ), paInvalidSampleRate );        /* reject if there's no sample rate within 1% of the one requested */        if( (fabs( sampleRate - sr ) / sampleRate) > 0.01 )        {            PA_DEBUG(("%s: Wanted %f, closest sample rate was %d\n", __FUNCTION__, sampleRate, sr ));                             PA_ENSURE( paInvalidSampleRate );        }        ENSURE_( ioctl( component->fd, streamMode == StreamMode_In ? SNDCTL_DSP_GETISPACE : SNDCTL_DSP_GETOSPACE, &bufInfo ),                paUnanticipatedHostError );        component->numBufs = bufInfo.fragstotal;        /* This needs to be the last ioctl call before the first read/write, according to the OSS programmer's guide */        ENSURE_( ioctl( component->fd, SNDCTL_DSP_GETBLKSIZE, &bytesPerBuf ), paUnanticipatedHostError );        component->hostFrames = bytesPerBuf / Pa_GetSampleSize( hostFormat ) / chans;        component->hostChannelCount = chans;        component->hostFormat = hostFormat;    }    else    {        component->hostFormat = master->hostFormat;        component->hostFrames = master->hostFrames;        component->hostChannelCount = master->hostChannelCount;        component->numBufs = master->numBufs;    }    PA_UNLESS( component->buffer = PaUtil_AllocateMemory( PaOssStreamComponent_BufferSize( component ) ),            paInsufficientMemory );error:    return result;}static PaError PaOssStreamComponent_Read( PaOssStreamComponent *component, unsigned long *frames ){    PaError result = paNoError;    size_t len = *frames * PaOssStreamComponent_FrameSize( component );    ssize_t bytesRead;    ENSURE_( bytesRead = read( component->fd, component->buffer, len ), paUnanticipatedHostError );    *frames = bytesRead / PaOssStreamComponent_FrameSize( component );    /* TODO: Handle condition where number of frames read doesn't equal number of frames requested */error:    return result;}static PaError PaOssStreamComponent_Write( PaOssStreamComponent *component, unsigned long *frames ){    PaError result = paNoError;    size_t len = *frames * PaOssStreamComponent_FrameSize( component );    ssize_t bytesWritten;    ENSURE_( bytesWritten = write( component->fd, component->buffer, len ), paUnanticipatedHostError );    *frames = bytesWritten / PaOssStreamComponent_FrameSize( component );    /* TODO: Handle condition where number of frames written doesn't equal number of frames requested */error:    return result;}/** Configure the stream according to input/output parameters. * * Aspect StreamChannels: The minimum number of channels supported by the device may exceed that requested by * the user, if so we'll record the actual number of host channels and adapt later. */static PaError PaOssStream_Configure( PaOssStream *stream, double sampleRate, unsigned long framesPerBuffer,        double *inputLatency, double *outputLatency ){    PaError result = paNoError;    int duplex = stream->capture && stream->playback;    unsigned long framesPerHostBuffer = 0;    /* We should request full duplex first thing after opening the device */    if( duplex && stream->sharedDevice )        ENSURE_( ioctl( stream->capture->fd, SNDCTL_DSP_SETDUPLEX, 0 ), paUnanticipatedHostError );    if( stream->capture )    {        PaOssStreamComponent *component = stream->capture;        PaOssStreamComponent_Configure( component, sampleRate, framesPerBuffer, StreamMode_In, NULL );        assert( component->hostChannelCount > 0 );        assert( component->hostFrames > 0 );        *inputLatency = component->hostFrames * (component->numBufs - 1) / sampleRate;    }

⌨️ 快捷键说明

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