/** This returns a list of descriptors of calls to external DSO functions that * implement a named shadeop, entries are returned for each polymorphic function */ std::list<SqDSOExternalCall*>* CqDSORepository::getShadeOpMethods(CqString* pShadeOpName) { CqString strTableSymbol = *pShadeOpName + "_shadeops" ; std::list<SqDSOExternalCall*>* oplist = new (std::list<SqDSOExternalCall*>); std::list<CqString>::iterator itPathEntry; SqShadeOp *pTableSymbol = NULL; Aqsis::log() << debug << "Looking for DSO candidates for shadeop \"" << pShadeOpName->c_str() << "\"" << std::endl; for ( itPathEntry = m_DSOPathList.begin() ; itPathEntry != m_DSOPathList.end() ; itPathEntry++ ) { Aqsis::log() << debug << "Looking in shared library : " << itPathEntry->c_str() << std::endl; void *handle = DLOpen( &(*itPathEntry) ); if( handle != NULL ) { pTableSymbol = (SqShadeOp*) DLSym( handle, &strTableSymbol ); if ( pTableSymbol != NULL ) { //We have an appropriate named shadeop table SqShadeOp *pShadeOp = (SqShadeOp*) pTableSymbol; while( ( pShadeOp->m_opspec )[0] != (char) NULL ) { SqDSOExternalCall *pDSOCall = NULL; pDSOCall = parseShadeOpTableEntry( handle, pShadeOp ); if ( pDSOCall != NULL ) oplist->push_back( pDSOCall ); pShadeOp++; }; }; // Failure here does not neccesarily mean anything since } else { CqString strError = DLError(); Aqsis::log() << error << "DLOpen: " << strError.c_str() << std::endl; }; }; std::stringstream resultStr; if(oplist->empty()) resultStr << "(none found)"; else resultStr << "(found " << oplist->size() << " possibilities)"; Aqsis::log() << debug << "Finished looking for DSO candidates "<< resultStr.str().c_str() << std::endl; return ( oplist->empty() ? NULL : oplist ); };
/* ===================== idAudioHardwareALSA::Initialize ===================== */ bool idAudioHardwareALSA::Initialize( void ) { int err; common->Printf( "------ Alsa Sound Initialization -----\n" ); if ( !DLOpen() ) { InitFailed(); return false; } if ( ( err = id_snd_pcm_open( &m_pcm_handle, s_alsa_pcm.GetString(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK ) ) < 0 ) { common->Printf( "snd_pcm_open SND_PCM_STREAM_PLAYBACK '%s' failed: %s\n", s_alsa_pcm.GetString(), id_snd_strerror( err ) ); InitFailed(); return false; } common->Printf( "opened Alsa PCM device %s for playback\n", s_alsa_pcm.GetString() ); // set hardware parameters ---------------------------------------------------------------------- // init hwparams with the full configuration space snd_pcm_hw_params_t *hwparams; // this one is a define id_snd_pcm_hw_params_alloca( &hwparams ); if ( ( err = id_snd_pcm_hw_params_any( m_pcm_handle, hwparams ) ) < 0 ) { common->Printf( "cannot configure the PCM device: %s\n", id_snd_strerror( err ) ); InitFailed(); return false; } if ( ( err = id_snd_pcm_hw_params_set_access( m_pcm_handle, hwparams, SND_PCM_ACCESS_RW_INTERLEAVED ) ) < 0 ) { common->Printf( "SND_PCM_ACCESS_RW_INTERLEAVED failed: %s\n", id_snd_strerror( err ) ); InitFailed(); return false; } if ( ( err = id_snd_pcm_hw_params_set_format( m_pcm_handle, hwparams, SND_PCM_FORMAT_S16_LE ) ) < 0 ) { common->Printf( "SND_PCM_FORMAT_S16_LE failed: %s\n", id_snd_strerror( err ) ); InitFailed(); return false; } // channels // sanity over number of speakers if ( idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 6 && idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 ) { common->Warning( "invalid value for s_numberOfSpeakers. Use either 2 or 6" ); idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 ); } m_channels = idSoundSystemLocal::s_numberOfSpeakers.GetInteger(); if ( ( err = id_snd_pcm_hw_params_set_channels( m_pcm_handle, hwparams, m_channels ) ) < 0 ) { common->Printf( "error setting %d channels: %s\n", m_channels, id_snd_strerror( err ) ); if ( idSoundSystemLocal::s_numberOfSpeakers.GetInteger() != 2 ) { // fallback to stereo if that works m_channels = 2; if ( ( err = id_snd_pcm_hw_params_set_channels( m_pcm_handle, hwparams, m_channels ) ) < 0 ) { common->Printf( "fallback to stereo failed: %s\n", id_snd_strerror( err ) ); InitFailed(); return false; } else { common->Printf( "fallback to stereo\n" ); idSoundSystemLocal::s_numberOfSpeakers.SetInteger( 2 ); } } else { InitFailed(); return false; } } // set sample rate (frequency) if ( ( err = id_snd_pcm_hw_params_set_rate( m_pcm_handle, hwparams, PRIMARYFREQ, 0 ) ) < 0 ) { common->Printf( "failed to set 44.1KHz rate: %s - try ( +set s_alsa_pcm plughw:0 ? )\n", id_snd_strerror( err ) ); InitFailed(); return false; } // have enough space in the input buffer for our MIXBUFFER_SAMPLE feedings and async ticks snd_pcm_uframes_t frames; frames = MIXBUFFER_SAMPLES + MIXBUFFER_SAMPLES / 3; if ( ( err = id_snd_pcm_hw_params_set_buffer_size_min( m_pcm_handle, hwparams, &frames ) ) < 0 ) { common->Printf( "buffer size select failed: %s\n", id_snd_strerror( err ) ); InitFailed(); return false; } // apply parameters if ( ( err = id_snd_pcm_hw_params( m_pcm_handle, hwparams ) ) < 0 ) { common->Printf( "snd_pcm_hw_params failed: %s\n", id_snd_strerror( err ) ); InitFailed(); return false; } // check the buffer size if ( ( err = id_snd_pcm_hw_params_get_buffer_size( hwparams, &frames ) ) < 0 ) { common->Printf( "snd_pcm_hw_params_get_buffer_size failed: %s\n", id_snd_strerror( err ) ); } else { common->Printf( "device buffer size: %lu frames ( %lu bytes )\n", ( long unsigned int )frames, frames * m_channels * 2 ); } // TODO: can use swparams to setup the device so it doesn't underrun but rather loops over // snd_pcm_sw_params_set_stop_threshold // To get alsa to just loop on underruns. set the swparam stop_threshold to equal buffer size. The sound buffer will just loop and never throw an xrun. // allocate the final mix buffer m_buffer_size = MIXBUFFER_SAMPLES * m_channels * 2; m_buffer = malloc( m_buffer_size ); common->Printf( "allocated a mix buffer of %d bytes\n", m_buffer_size ); #ifdef _DEBUG // verbose the state snd_pcm_state_t curstate = id_snd_pcm_state( m_pcm_handle ); assert( curstate == SND_PCM_STATE_PREPARED ); #endif common->Printf( "--------------------------------------\n" ); return true; }