]> git.mxchange.org Git - flightgear.git/blob - src/slScheduler.cxx
FreeBSD support.
[flightgear.git] / src / slScheduler.cxx
1
2 #include "sl.h"
3
4 char *__slPendingError = NULL ;
5
6 slScheduler *slScheduler::current = NULL ;
7
8 void slScheduler::init ()
9 {
10   current = this ;
11
12   if ( not_working () )
13   {
14     fprintf ( stderr, "slScheduler: soundcard init failed.\n" ) ;
15     setError () ;
16     return ;
17   }
18
19   if ( getBps() != 8 )
20   {
21     fprintf ( stderr, "slScheduler: Needs a sound card that supports 8 bits per sample.\n" ) ;
22     setError () ;
23     return ;
24   }
25
26   if ( getStereo() )
27   {
28     fprintf ( stderr, "slScheduler: Needs a sound card that supports monophonic replay.\n" ) ;
29     setError () ;
30     return ;
31   }
32
33   for ( int i = 0 ; i < SL_MAX_SAMPLES ; i++ )
34     samplePlayer [ i ] = NULL ;
35
36   amount_left = 0 ;
37   now = 0 ;
38   num_pending_callbacks = 0 ;
39   safety_margin = 1.0 ;
40
41   mixer = NULL ;
42
43   mixer_buffer  = NULL ;
44   spare_buffer0 = NULL ;
45   spare_buffer1 = NULL ;
46   spare_buffer2 = NULL ;
47
48   initBuffers () ;
49 }
50
51 void slScheduler::initBuffers ()
52 {
53   if ( not_working () )
54     return ;
55
56   delete mixer_buffer ;
57   delete spare_buffer0 ;
58   delete spare_buffer1 ;
59   delete spare_buffer2 ;
60
61   mixer_buffer_size = getDriverBufferSize () ;
62
63   mixer_buffer = new Uchar [ mixer_buffer_size ] ;
64   memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
65
66   spare_buffer0 = new Uchar [ mixer_buffer_size ] ;
67   spare_buffer1 = new Uchar [ mixer_buffer_size ] ;
68   spare_buffer2 = new Uchar [ mixer_buffer_size ] ;
69 }
70
71 slScheduler::~slScheduler ()
72 {
73   if ( current == this )
74     current = NULL ;
75
76   delete mixer_buffer ;
77
78   delete spare_buffer0 ;
79   delete spare_buffer1 ;
80   delete spare_buffer2 ;
81 }
82
83
84
85
86
87 void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb )
88 {
89   register int    l = mixer_buffer_size ;
90   register Uchar *d = mixer_buffer ;
91
92   register Uchar *a = spare_buffer0 ;
93   register Uchar *b = spare_buffer1 ;
94
95   spa -> read ( l, a ) ;
96   spb -> read ( l, b ) ;
97
98   while ( l-- ) *d++ = mix ( *a++, *b++ ) ;
99 }
100
101
102
103 void slScheduler::mixBuffer ( slSamplePlayer *spa, slSamplePlayer *spb,
104                               slSamplePlayer *spc )
105 {
106   register int    l = mixer_buffer_size ;
107   register Uchar *d = mixer_buffer ;
108
109   register Uchar *a = spare_buffer0 ;
110   register Uchar *b = spare_buffer1 ;
111   register Uchar *c = spare_buffer2 ;
112
113   spa -> read ( l, a ) ;
114   spb -> read ( l, b ) ;
115   spc -> read ( l, c ) ;
116
117   while ( l-- ) *d++ = mix ( *a++, *b++, *c++ ) ;
118 }
119
120
121 void slScheduler::realUpdate ( int dump_first )
122 {
123   if ( not_working () )
124     return ;
125
126   if ( __slPendingError != NULL )
127   {
128     fprintf ( stderr, "%s", __slPendingError ) ;
129     exit ( 1 ) ;
130   }
131
132   int i ;
133
134   while ( secondsUsed() <= safety_margin )
135   {
136     slSamplePlayer *psp [ 3 ] ;
137     int             pri [ 3 ] ;
138
139     pri [ 0 ] = pri [ 1 ] = pri [ 2 ] =  -1  ;
140
141     for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
142     {
143       if ( samplePlayer [ i ] == NULL )
144         continue ;
145
146       /* Clean up dead sample players */
147
148       if ( samplePlayer [ i ] -> isDone () )
149       {
150         delete samplePlayer [ i ] ;
151         samplePlayer [ i ] = NULL ;
152         continue ;
153       }
154
155       if ( samplePlayer [ i ] -> isPaused () )
156         continue ;
157
158       int lowest = ( pri [0] <= pri [2] ) ?
159                      (( pri [0] <= pri [1] ) ? 0 : 1 ) :
160                      (( pri [1] <= pri [2] ) ? 1 : 2 ) ;
161
162       if ( samplePlayer[i]->getPriority() > pri[lowest] )
163       {
164         psp[lowest] = samplePlayer[i] ;
165         pri[lowest] = samplePlayer[i]->getPriority() ;
166       }
167     }
168
169     for ( i = 0 ; i < SL_MAX_SAMPLES ; i++ )
170     {
171       if ( samplePlayer [ i ] == NULL )
172         continue ;
173
174       if ( ! samplePlayer [ i ] -> isPaused () &&
175            samplePlayer [ i ] != psp[0] &&
176            samplePlayer [ i ] != psp[1] &&
177            samplePlayer [ i ] != psp[2] )
178       {
179         samplePlayer [ i ] -> preempt ( mixer_buffer_size ) ;
180       }
181     }
182
183     if ( pri[0] < 0 )
184     {
185       memset ( mixer_buffer, 0x80, mixer_buffer_size ) ;
186       amount_left = 0 ;
187     }
188     else
189     if ( pri[1] < 0 )
190       psp[0] -> read ( mixer_buffer_size, mixer_buffer ) ;
191     else
192     if ( pri[2] < 0 )
193       mixBuffer ( psp[0], psp[1] ) ;
194     else
195       mixBuffer ( psp[0], psp[1], psp[2] ) ;
196
197     if ( dump_first )
198     {
199       stop () ;
200       dump_first = SL_FALSE ;
201     }
202
203     play ( mixer_buffer, mixer_buffer_size ) ;
204
205     now += mixer_buffer_size ;
206   }
207
208   flushCallBacks () ;
209 }
210
211 void slScheduler::addCallBack ( slCallBack c, slSample *s, slEvent e, int m )
212 {
213   if ( not_working () )
214     return ;
215
216   if ( num_pending_callbacks >= SL_MAX_CALLBACKS )
217   {
218     fprintf ( stderr, "slScheduler: Too many pending callback events!\n" ) ;
219     return ;
220   }
221
222   slPendingCallBack *p = & ( pending_callback [ num_pending_callbacks++ ] ) ;
223
224   p -> callback = c ;
225   p -> sample   = s ;
226   p -> event    = e ;
227   p -> magic    = m ;
228 }
229
230 void slScheduler::flushCallBacks ()
231 {
232   if ( not_working () )
233     return ;
234
235   /*
236     Execute all the callbacks that we accumulated
237     in this iteration.
238
239     This is done at the end of 'update' to reduce the risk
240     of nasty side-effects caused by 'unusual' activities
241     in the application's callback function.
242   */
243
244   while ( num_pending_callbacks > 0 )
245   {
246     slPendingCallBack *p = & ( pending_callback [ --num_pending_callbacks ] ) ;
247
248     if ( p -> callback )
249       (*(p->callback))( p->sample, p->event, p->magic ) ;
250   }
251 }
252
253