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