1
0
Fork 0
flightgear/src/slScheduler.cxx
1998-10-02 21:35:09 +00:00

253 lines
5.1 KiB
C++

#include "sl.h"
char *__slPendingError = NULL ;
slScheduler *slScheduler::current = NULL ;
void slScheduler::init ()
{
current = this ;
if ( not_working () )
{
fprintf ( stderr, "slScheduler: soundcard init failed.\n" ) ;
setError () ;
return ;
}
if ( getBps() != 8 )
{
fprintf ( stderr, "slScheduler: Needs a sound card that supports 8 bits per sample.\n" ) ;
setError () ;
return ;
}
if ( getStereo() )
{
fprintf ( stderr, "slScheduler: Needs a sound card that supports monophonic replay.\n" ) ;
setError () ;
return ;
}
for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
samplePlayer [ i ] = NULL ;
amount_left = 0 ;
now = 0 ;
num_pending_callbacks = 0 ;
safety_margin = 1.0 ;
mixer = NULL ;
mixer_buffer = NULL ;
spare_buffer0 = NULL ;
spare_buffer1 = NULL ;
spare_buffer2 = NULL ;
initBuffers () ;
}
void slScheduler::initBuffers ()
{
if ( not_working () )
return ;
delete mixer_buffer ;
delete spare_buffer0 ;
delete spare_buffer1 ;
delete spare_buffer2 ;
mixer_buffer_size = getDriverBufferSize () ;
mixer_buffer = new Uchar [ mixer_buffer_size ] ;
memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
spare_buffer0 = new Uchar [ mixer_buffer_size ] ;
spare_buffer1 = new Uchar [ mixer_buffer_size ] ;
spare_buffer2 = new Uchar [ mixer_buffer_size ] ;
}
slScheduler::~slScheduler ()
{
if ( current == this )
current = NULL ;
delete mixer_buffer ;
delete spare_buffer0 ;
delete spare_buffer1 ;
delete spare_buffer2 ;
}
void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb )
{
register int l = mixer_buffer_size ;
register Uchar *d = mixer_buffer ;
register Uchar *a = spare_buffer0 ;
register Uchar *b = spare_buffer1 ;
spa -> read ( l, a ) ;
spb -> read ( l, b ) ;
while ( l-- ) *d++ = mix ( *a++, *b++ ) ;
}
void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb,
slSamplePlayer *spc )
{
register int l = mixer_buffer_size ;
register Uchar *d = mixer_buffer ;
register Uchar *a = spare_buffer0 ;
register Uchar *b = spare_buffer1 ;
register Uchar *c = spare_buffer2 ;
spa -> read ( l, a ) ;
spb -> read ( l, b ) ;
spc -> read ( l, c ) ;
while ( l-- ) *d++ = mix ( *a++, *b++, *c++ ) ;
}
void slScheduler::realUpdate ( int dump_first )
{
if ( not_working () )
return ;
if ( __slPendingError != NULL )
{
fprintf ( stderr, "%s", __slPendingError ) ;
exit ( 1 ) ;
}
int i ;
while ( secondsUsed() <= safety_margin )
{
slSamplePlayer *psp [ 3 ] ;
int pri [ 3 ] ;
pri [ 0 ] = pri [ 1 ] = pri [ 2 ] = -1 ;
for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
{
if ( samplePlayer [ i ] == NULL )
continue ;
/* Clean up dead sample players */
if ( samplePlayer [ i ] -> isDone () )
{
delete samplePlayer [ i ] ;
samplePlayer [ i ] = NULL ;
continue ;
}
if ( samplePlayer [ i ] -> isPaused () )
continue ;
int lowest = ( pri [0] <= pri [2] ) ?
(( pri [0] <= pri [1] ) ? 0 : 1 ) :
(( pri [1] <= pri [2] ) ? 1 : 2 ) ;
if ( samplePlayer[i]->getPriority() > pri[lowest] )
{
psp[lowest] = samplePlayer[i] ;
pri[lowest] = samplePlayer[i]->getPriority() ;
}
}
for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
{
if ( samplePlayer [ i ] == NULL )
continue ;
if ( ! samplePlayer [ i ] -> isPaused () &&
samplePlayer [ i ] != psp[0] &&
samplePlayer [ i ] != psp[1] &&
samplePlayer [ i ] != psp[2] )
{
samplePlayer [ i ] -> preempt ( mixer_buffer_size ) ;
}
}
if ( pri[0] < 0 )
{
memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
amount_left = 0 ;
}
else
if ( pri[1] < 0 )
psp[0] -> read ( mixer_buffer_size, mixer_buffer ) ;
else
if ( pri[2] < 0 )
mixBuffer ( psp[0], psp[1] ) ;
else
mixBuffer ( psp[0], psp[1], psp[2] ) ;
if ( dump_first )
{
stop () ;
dump_first = SL_FALSE ;
}
play ( mixer_buffer, mixer_buffer_size ) ;
now += mixer_buffer_size ;
}
flushCallBacks () ;
}
void slScheduler::addCallBack ( slCallBack c, slSample *s, slEvent e, int m )
{
if ( not_working () )
return ;
if ( num_pending_callbacks >= SL_MAX_CALLBACKS )
{
fprintf ( stderr, "slScheduler: Too many pending callback events!\n" ) ;
return ;
}
slPendingCallBack *p = & ( pending_callback [ num_pending_callbacks++ ] ) ;
p -> callback = c ;
p -> sample = s ;
p -> event = e ;
p -> magic = m ;
}
void slScheduler::flushCallBacks ()
{
if ( not_working () )
return ;
/*
Execute all the callbacks that we accumulated
in this iteration.
This is done at the end of 'update' to reduce the risk
of nasty side-effects caused by 'unusual' activities
in the application's callback function.
*/
while ( num_pending_callbacks > 0 )
{
slPendingCallBack *p = & ( pending_callback [ --num_pending_callbacks ] ) ;
if ( p -> callback )
(*(p->callback))( p->sample, p->event, p->magic ) ;
}
}