/**  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 );
};
Example #2
0
/*
=====================
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;
}