string xmlString::getSubTag( const tag &in, unsigned int tabNum ) { string ret; string tabs; if( (_format&Tabs) != FALSE ) { for( unsigned int x=0; x<tabNum; x++ ) { tabs += "\t"; } } if( in.type() == tag::None ) { ret += in.contents().toString(); /*if( (_format&NewLines) != FALSE ) { ret += "\n"; }*/ } else { if( in.type() == tag::Open && in.name() != "" ) { ret += tabs + getOpener( in.name(), in.attributes() ); } else if( in.type() == tag::Empty && in.name() != "" ) { ret += tabs + getOpener( in.name(), in.attributes(), TRUE ); } if( (_format&NewLines) != FALSE && ( in.size() > 1 || ( in.size() > 0 && in[0].type() != tag::None ) ) ) { ret += "\n"; } for( unsigned int x=0; x<in.size(); x++ ) { ret += getSubTag( in[x], tabNum + 1 ); } if( in.type() == tag::Open && in.name() != "" ) { if( in.size() > 1 || ( in.size() > 0 && in[0].type() != tag::None ) ) { ret += tabs; } ret += getClose( in.name() ); } if( (_format&NewLines) != FALSE ) { ret += "\n"; } } return ret; }
void *AcquisitionThread ( void *data ) { int doneWaiting = 0; audioinSample *CodecBuffer; #ifdef FILTER_ON long x; long y; #endif #ifdef AUDIOIN_SUPPORT_CALLBACK AUDIOIN_H *phAudioIn = (AUDIOIN_H *)data; #endif pthread_mutex_lock ( &gAudioMutex ); //signal to tell that our thread is now running. if ( pthread_cond_signal ( &gThreadRunning ) != 0 ) { pthread_mutex_unlock ( &gAudioMutex ); PLogError ( "Audio In Error pthread_cond_signal\n" ); exit ( 1 ); } gThreadRunningSignaled = 1; while( 1 ) { while (!doneWaiting) { int rc = pthread_cond_wait(&gOpenExCalled, &gAudioMutex); switch (rc) { case 0: if (!gOpenExCalledSignaled) { // Avoid spurious wakeups continue; } else { gOpenExCalledSignaled = 0; doneWaiting = 1; break; } break; default: PLogError ( "Audio In Error pthread_cond_wait\n" ); pthread_mutex_unlock(&gAudioMutex); return ( (void *)NULL ); } } doneWaiting = 0; pthread_mutex_unlock(&gAudioMutex); if( gTerminateThread == 1 ) break; /* buffer of 16 bits samples */ CodecBuffer = (audioinSample *)malloc ( gCodecFragmentSizeInFrames * sizeof ( audioinSample ) ); if ( CodecBuffer == NULL ) { PLogError ( "Audio In Error pthread_cond_signal\n" ); exit ( 1 ); } while ( !getClose ( ) ) { int iReadFrames = 0; /* number of frames acquired by the codec */ /* NOTE: here a frame is comprised of 1 sample if mono, 2 samples if stereo, etc */ int iReadSamples = 0; /* number of samples acquired by the codec */ if ( ( iReadFrames = snd_pcm_readi ( ghPCM, (void *)CodecBuffer, gCodecFragmentSizeInFrames ) ) < 0 ) { if ( iReadFrames == -EBADFD ) { PLogError ( "Audio In Error PCM Not In The Right State\n" ); } else if ( iReadFrames == -EPIPE ) { snd_pcm_prepare(ghPCM); PLogError ( "Audio In Error Overrun\n" ); } else if ( iReadFrames == -ESTRPIPE ) { PLogError ( "Audio In Error Stream Suspended\n" ); } } iReadSamples = iReadFrames; if ( getRecord ( ) ) /* else continue to read from driver but discard samples */ { if ( iReadSamples < 0 ) { iReadSamples = 0; gAudioInInfo.eStatusInfo = AUDIOIN_HWOVERRUN; } else { #ifdef FILTER_ON /* x: index for start of input samples; y: index for output sample */ for ( x = 0, y = 0; x < iReadSamples; x += pFIR->factor_down ) { FIR_downsample ( pFIR->factor_down, &( CodecBuffer[x] ), &( CodecBuffer[y++] ), pFIR ); } /* update the number samples */ iReadSamples = y; #endif #ifdef SAVE_RAW_AUDIO if ( iReadSamples > 0 ) fwrite ( CodecBuffer, 2, iReadSamples, audio_data ); #endif pthread_mutex_lock ( &gAudioMutex ); if ( gAudioInInfo.u32SamplesAvailable + iReadSamples > SAMPLES_BUFFER_SIZE ) { gAudioInInfo.u32SamplesAvailable = SAMPLES_BUFFER_SIZE; gAudioInInfo.eStatusInfo = AUDIOIN_FIFOOVERRUN; } else { if ( gAudioInInfo.u32SamplesAvailable + iReadSamples > SAMPLES_BUFFER_HIGH_WATERMARK ) { gAudioInInfo.eStatusInfo = AUDIOIN_HIGHWATERMARK; } else if ( gAudioInInfo.eStatusInfo != AUDIOIN_FIFOOVERRUN ) { gAudioInInfo.eStatusInfo = AUDIOIN_NORMAL; } gAudioInInfo.u32SamplesAvailable += iReadSamples; } if ( gWriteIndexPointer + iReadSamples <= SAMPLES_BUFFER_SIZE ) { memcpy ( &( gSamplesBufferCircularFifo[gWriteIndexPointer] ), CodecBuffer, iReadSamples * sizeof ( audioinSample ) ); gWriteIndexPointer += iReadSamples; if ( gWriteIndexPointer >= SAMPLES_BUFFER_SIZE ) gWriteIndexPointer = 0; } else { int NbToCopy; NbToCopy = SAMPLES_BUFFER_SIZE - gWriteIndexPointer; memcpy ( &( gSamplesBufferCircularFifo [gWriteIndexPointer] ), CodecBuffer, NbToCopy * sizeof ( audioinSample ) ); gWriteIndexPointer = 0; memcpy ( gSamplesBufferCircularFifo, &( CodecBuffer [NbToCopy] ), ( iReadSamples-NbToCopy ) * sizeof ( audioinSample ) ); gWriteIndexPointer = iReadSamples - NbToCopy; } #ifdef AUDIOIN_SUPPORT_CALLBACK /* Callback notification. Ideally this audio acquisition thread should be very lean. It should simply read from the low level driver, store the filtered samples in the FIFO, then go back to reading from the driver. The additional data copy for the callback function is ok despite the overhead incurred, but only because there's some buffering done by the low level driver. This design should be revisited to make it more general purpose. */ while ( ( gpCallback != NULL ) && ( gAudioInInfo.u32SamplesAvailable >= gnCallbackSamples ) ) { AUDIOIN_WAVEHDR *pwhdr; pwhdr = malloc ( sizeof ( AUDIOIN_WAVEHDR ) ); if ( pwhdr != NULL ) { pwhdr->nBufferLength = gnCallbackSamples * sizeof ( audioinSample ); pwhdr->nBytesRecorded = pwhdr->nBufferLength; pwhdr->status = gAudioInInfo.eStatusInfo; pwhdr->pData = malloc ( pwhdr->nBufferLength ); if ( pwhdr->pData != NULL ) { if ( gReadIndexPointer + gnCallbackSamples <= SAMPLES_BUFFER_SIZE ) { memcpy ( pwhdr->pData, &( gSamplesBufferCircularFifo [gReadIndexPointer] ), pwhdr->nBufferLength ); gReadIndexPointer += gnCallbackSamples; if ( gReadIndexPointer >= SAMPLES_BUFFER_SIZE ) gReadIndexPointer = 0; } else { size_t nSamplesPart1 = SAMPLES_BUFFER_SIZE - gReadIndexPointer; size_t nSamplesPart2 = gnCallbackSamples - nSamplesPart1; memcpy ( pwhdr->pData, &( gSamplesBufferCircularFifo [gReadIndexPointer] ), nSamplesPart1*sizeof ( audioinSample ) ); gReadIndexPointer = 0; memcpy ( pwhdr->pData + nSamplesPart1 * sizeof (audioinSample ), gSamplesBufferCircularFifo, nSamplesPart2 * sizeof ( audioinSample ) ); gReadIndexPointer = nSamplesPart2; } gAudioInInfo.u32SamplesAvailable -= gnCallbackSamples; /* pass samples to callback function who should deallocate the buffer and structure */ gpCallback ( *phAudioIn, AUDIOIN_MSG_DATA, gpCallbackInstance, pwhdr, NULL ); } else { // error } } else { // error } } #endif /* samples are available to read */ pthread_mutex_unlock ( &gAudioMutex ); timer.tv_sec = 0; timer.tv_usec = 200; select ( 0, NULL, NULL, NULL, &timer ); } } /* if (getRecord()) */ } /* while (!getClose()) */ if ( snd_pcm_close ( ghPCM ) !=0 ) { PLogError ( "Audio In Error Closing Hardware\n" ); } free ( CodecBuffer ); pthread_mutex_lock ( &gAudioMutex ); //signal to tell that our thread is now running. if ( pthread_cond_signal ( &gCloseCalled ) != 0 ) { pthread_mutex_unlock ( &gAudioMutex ); PLogError ( "Audio In Error pthread_cond_signal\n" ); exit ( 1 ); } gCloseCalledSignaled = 1; } pthread_exit ( (void *)NULL ); return ( (void *)NULL ); }