4 slScheduler *slScheduler::current = NULL ;
6 void slScheduler::init ()
12 fprintf ( stderr, "slScheduler: soundcard init failed.\n" ) ;
19 fprintf ( stderr, "slScheduler: Needs a sound card that supports 8 bits per sample.\n" ) ;
26 fprintf ( stderr, "slScheduler: Needs a sound card that supports monophonic replay.\n" ) ;
31 for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
32 samplePlayer [ i ] = NULL ;
36 num_pending_callbacks = 0 ;
41 spare_buffer1 [ 0 ] = NULL ;
42 spare_buffer1 [ 1 ] = NULL ;
43 spare_buffer1 [ 2 ] = NULL ;
44 spare_buffer2 [ 0 ] = NULL ;
45 spare_buffer2 [ 1 ] = NULL ;
46 spare_buffer2 [ 2 ] = NULL ;
51 void slScheduler::initBuffers ()
53 if ( not_working () ) return ;
56 delete spare_buffer1 [ 0 ] ;
57 delete spare_buffer1 [ 1 ] ;
58 delete spare_buffer1 [ 2 ] ;
59 delete spare_buffer2 [ 0 ] ;
60 delete spare_buffer2 [ 1 ] ;
61 delete spare_buffer2 [ 2 ] ;
63 mixer_buffer_size = getDriverBufferSize () ;
65 mixer_buffer = new Uchar [ mixer_buffer_size ] ;
66 memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
68 spare_buffer1 [ 0 ] = new Uchar [ mixer_buffer_size ] ;
69 spare_buffer1 [ 1 ] = new Uchar [ mixer_buffer_size ] ;
70 spare_buffer1 [ 2 ] = new Uchar [ mixer_buffer_size ] ;
72 spare_buffer2 [ 0 ] = new Uchar [ mixer_buffer_size ] ;
73 spare_buffer2 [ 1 ] = new Uchar [ mixer_buffer_size ] ;
74 spare_buffer2 [ 2 ] = new Uchar [ mixer_buffer_size ] ;
77 slScheduler::~slScheduler ()
79 if ( current == this )
84 delete spare_buffer1 [ 0 ] ;
85 delete spare_buffer1 [ 1 ] ;
86 delete spare_buffer1 [ 2 ] ;
87 delete spare_buffer2 [ 0 ] ;
88 delete spare_buffer2 [ 1 ] ;
89 delete spare_buffer2 [ 2 ] ;
92 Uchar *slScheduler::mergeBlock ( Uchar *d )
94 register int l = amount_left ;
96 memset ( d, 0x80, l ) ;
102 Uchar *slScheduler::mergeBlock ( Uchar *d, slSamplePlayer *spa )
104 register int l = spa -> getAmountLeft () ;
106 if ( l > amount_left )
111 memcpy ( d, spa->read(l, spare_buffer1[0], spare_buffer2[0]), l ) ;
117 Uchar *slScheduler::mergeBlock ( Uchar *d, slSamplePlayer *spa, slSamplePlayer *spb )
119 int la = spa -> getAmountLeft () ;
120 int lb = spb -> getAmountLeft () ;
122 register int l = ( la < lb ) ? la : lb ;
124 if ( l > amount_left )
129 register Uchar *a = spa -> read ( l, spare_buffer1[0], spare_buffer2[0] ) ;
130 register Uchar *b = spb -> read ( l, spare_buffer1[1], spare_buffer2[1] ) ;
132 while ( l-- ) *d++ = mix ( *a++, *b++ ) ;
137 Uchar *slScheduler::mergeBlock ( Uchar *d, slSamplePlayer *spa, slSamplePlayer *spb, slSamplePlayer *spc )
139 int la = spa -> getAmountLeft () ;
140 int lb = spb -> getAmountLeft () ;
141 int lc = spc -> getAmountLeft () ;
143 register int l = ( la < lb ) ?
144 (( la < lc ) ? la : lc ) :
145 (( lb < lc ) ? lb : lc ) ;
147 if ( l > amount_left )
152 register Uchar *a = spa -> read ( l, spare_buffer1[0], spare_buffer2[0] ) ;
153 register Uchar *b = spb -> read ( l, spare_buffer1[1], spare_buffer2[1] ) ;
154 register Uchar *c = spc -> read ( l, spare_buffer1[2], spare_buffer2[2] ) ;
156 while ( l-- ) *d++ = mix ( *a++, *b++, *c++ ) ;
162 void slScheduler::mixBuffer ()
164 register Uchar *d = mixer_buffer ;
166 amount_left = mixer_buffer_size ;
168 while ( amount_left > 0 )
169 d = mergeBlock ( d ) ;
173 void slScheduler::mixBuffer ( slSamplePlayer *spa )
175 register Uchar *d = mixer_buffer ;
177 amount_left = mixer_buffer_size ;
179 while ( amount_left > 0 )
181 int la = spa -> getAmountLeft () ;
183 if ( la > 0 ) /* Buffer has data left... */
184 d = mergeBlock ( d, spa ) ;
185 else /* Buffer is empty */
186 d = mergeBlock ( d ) ;
191 void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb )
193 register Uchar *d = mixer_buffer ;
194 amount_left = mixer_buffer_size ;
196 while ( amount_left > 0 )
198 int la = spa -> getAmountLeft () ;
199 int lb = spb -> getAmountLeft () ;
201 if ( la > 0 && lb > 0 ) /* Both buffers have data left... */
202 d = mergeBlock ( d, spa, spb ) ;
204 if ( la > 0 && lb <= 0 ) /* Only the A buffer has data left... */
205 d = mergeBlock ( d, spa ) ;
207 if ( la <= 0 && lb > 0 ) /* Only the B buffer has data left... */
208 d = mergeBlock ( d, spb ) ;
209 else /* Both buffers are empty */
210 d = mergeBlock ( d ) ;
216 void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb,
217 slSamplePlayer *spc )
219 register Uchar *d = mixer_buffer ;
221 amount_left = mixer_buffer_size ;
223 while ( amount_left > 0 )
225 int la = spa -> getAmountLeft () ;
226 int lb = spb -> getAmountLeft () ;
227 int lc = spc -> getAmountLeft () ;
229 if ( lc > 0 ) /* C buffer has data left... */
231 if ( la > 0 && lb > 0 ) /* All three buffers have data left... */
232 d = mergeBlock ( d, spa, spb, spc ) ;
234 if ( la > 0 && lb <= 0 ) /* Only the A&C buffers have data left... */
235 d = mergeBlock ( d, spa, spc ) ;
237 if ( la <= 0 && lb > 0 ) /* Only the B&C buffers have data left... */
238 d = mergeBlock ( d, spb, spc ) ;
239 else /* Only the C buffer has data left */
240 d = mergeBlock ( d, spc ) ;
244 if ( la > 0 && lb > 0 ) /* Only the A&B buffers have data left... */
245 d = mergeBlock ( d, spa, spb ) ;
247 if ( la > 0 && lb <= 0 ) /* Only the A buffer has data left... */
248 d = mergeBlock ( d, spa ) ;
250 if ( la <= 0 && lb > 0 ) /* Only the B buffer has data left... */
251 d = mergeBlock ( d, spb ) ;
252 else /* All three buffers are empty */
253 d = mergeBlock ( d ) ;
259 void slScheduler::realUpdate ( int dump_first )
263 if ( not_working () )
266 while ( secondsUsed() <= safety_margin )
268 slSamplePlayer *psp [ 3 ] ;
271 pri [ 0 ] = pri [ 1 ] = pri [ 2 ] = -1 ;
273 for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
275 if ( samplePlayer [ i ] == NULL )
278 /* Clean up dead sample players */
280 if ( samplePlayer [ i ] -> isDone () )
282 delete samplePlayer [ i ] ;
283 samplePlayer [ i ] = NULL ;
287 if ( samplePlayer [ i ] -> isPaused () )
290 int lowest = ( pri [0] <= pri [2] ) ?
291 (( pri [0] <= pri [1] ) ? 0 : 1 ) :
292 (( pri [1] <= pri [2] ) ? 1 : 2 ) ;
294 if ( samplePlayer[i]->getPriority() > pri[lowest] )
296 psp[lowest] = samplePlayer[i] ;
297 pri[lowest] = samplePlayer[i]->getPriority() ;
301 for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
303 if ( samplePlayer [ i ] == NULL )
306 if ( ! samplePlayer [ i ] -> isPaused () &&
307 samplePlayer [ i ] != psp[0] &&
308 samplePlayer [ i ] != psp[1] &&
309 samplePlayer [ i ] != psp[2] )
311 samplePlayer [ i ] -> preempt ( mixer_buffer_size ) ;
315 if ( pri[0] < 0 ) mixBuffer () ; else
316 if ( pri[1] < 0 ) mixBuffer ( psp[0] ) ; else
317 if ( pri[2] < 0 ) mixBuffer ( psp[0], psp[1] ) ; else
318 mixBuffer ( psp[0], psp[1], psp[2] ) ;
323 dump_first = SL_FALSE ;
326 play ( mixer_buffer, mixer_buffer_size ) ;
328 now += mixer_buffer_size ;
334 void slScheduler::addCallBack ( slCallBack c, slSample *s, slEvent e, int m )
336 if ( num_pending_callbacks >= SL_MAX_CALLBACKS )
338 fprintf ( stderr, "slScheduler: Too many pending callback events!\n" ) ;
342 slPendingCallBack *p = & ( pending_callback [ num_pending_callbacks++ ] ) ;
350 void slScheduler::flushCallBacks ()
353 Execute all the callbacks that we accumulated
356 This is done at the end of 'update' to reduce the risk
357 of nasty side-effects caused by 'unusual' activities
358 in the application's callback function.
361 while ( num_pending_callbacks > 0 )
363 slPendingCallBack *p = & ( pending_callback [ --num_pending_callbacks ] ) ;
366 (*(p->callback))( p->sample, p->event, p->magic ) ;