Mercurial > sdl-ios-xcode
annotate src/audio/paudio/SDL_paudio.c @ 4361:991e4bcfc7a8 SDL-1.2
Added an error message for when ALSA audio fails
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 19 Oct 2009 05:15:21 +0000 |
parents | a1b03ba2fcd0 |
children |
rev | line source |
---|---|
0 | 1 /* |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
2 SDL - Simple DirectMedia Layer |
4159 | 3 Copyright (C) 1997-2009 Sam Lantinga |
0 | 4 |
5 This library is free software; you can redistribute it and/or | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
6 modify it under the terms of the GNU Lesser General Public |
0 | 7 License as published by the Free Software Foundation; either |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
8 version 2.1 of the License, or (at your option) any later version. |
0 | 9 |
10 This library is distributed in the hope that it will be useful, | |
11 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
13 Lesser General Public License for more details. |
0 | 14 |
1312
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
15 You should have received a copy of the GNU Lesser General Public |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
16 License along with this library; if not, write to the Free Software |
c9b51268668f
Updated copyright information and removed rcs id lines (problematic in branch merges)
Sam Lantinga <slouken@libsdl.org>
parents:
0
diff
changeset
|
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA |
0 | 18 |
19 Carsten Griwodz | |
20 griff@kom.tu-darmstadt.de | |
21 | |
22 based on linux/SDL_dspaudio.c by Sam Lantinga | |
23 */ | |
1402
d910939febfa
Use consistent identifiers for the various platforms we support.
Sam Lantinga <slouken@libsdl.org>
parents:
1361
diff
changeset
|
24 #include "SDL_config.h" |
0 | 25 |
26 /* Allow access to a raw mixing buffer */ | |
27 | |
28 #include <errno.h> | |
29 #include <unistd.h> | |
30 #include <fcntl.h> | |
31 #include <sys/time.h> | |
32 #include <sys/ioctl.h> | |
33 #include <sys/stat.h> | |
34 | |
1358
c71e05b4dc2e
More header massaging... works great on Windows. ;-)
Sam Lantinga <slouken@libsdl.org>
parents:
1338
diff
changeset
|
35 #include "SDL_timer.h" |
0 | 36 #include "SDL_audio.h" |
1361
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
37 #include "../SDL_audiomem.h" |
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
38 #include "../SDL_audio_c.h" |
19418e4422cb
New configure-based build system. Still work in progress, but much improved
Sam Lantinga <slouken@libsdl.org>
parents:
1358
diff
changeset
|
39 #include "../SDL_audiodev_c.h" |
0 | 40 #include "SDL_paudio.h" |
41 | |
42 #define DEBUG_AUDIO 1 | |
43 | |
44 /* A conflict within AIX 4.3.3 <sys/> headers and probably others as well. | |
45 * I guess nobody ever uses audio... Shame over AIX header files. */ | |
46 #include <sys/machine.h> | |
47 #undef BIG_ENDIAN | |
48 #include <sys/audio.h> | |
49 | |
50 /* The tag name used by paud audio */ | |
51 #define Paud_DRIVER_NAME "paud" | |
52 | |
53 /* Open the audio device for playback, and don't block if busy */ | |
54 /* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */ | |
55 #define OPEN_FLAGS O_WRONLY | |
56 | |
57 /* Audio driver functions */ | |
58 static int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec); | |
59 static void Paud_WaitAudio(_THIS); | |
60 static void Paud_PlayAudio(_THIS); | |
61 static Uint8 *Paud_GetAudioBuf(_THIS); | |
62 static void Paud_CloseAudio(_THIS); | |
63 | |
64 /* Audio driver bootstrap functions */ | |
65 | |
66 static int Audio_Available(void) | |
67 { | |
68 int fd; | |
69 int available; | |
70 | |
71 available = 0; | |
72 fd = SDL_OpenAudioPath(NULL, 0, OPEN_FLAGS, 0); | |
73 if ( fd >= 0 ) { | |
74 available = 1; | |
75 close(fd); | |
76 } | |
77 return(available); | |
78 } | |
79 | |
80 static void Audio_DeleteDevice(SDL_AudioDevice *device) | |
81 { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
82 SDL_free(device->hidden); |
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
83 SDL_free(device); |
0 | 84 } |
85 | |
86 static SDL_AudioDevice *Audio_CreateDevice(int devindex) | |
87 { | |
88 SDL_AudioDevice *this; | |
89 | |
90 /* Initialize all variables that we clean on shutdown */ | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
91 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); |
0 | 92 if ( this ) { |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
93 SDL_memset(this, 0, (sizeof *this)); |
0 | 94 this->hidden = (struct SDL_PrivateAudioData *) |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
95 SDL_malloc((sizeof *this->hidden)); |
0 | 96 } |
97 if ( (this == NULL) || (this->hidden == NULL) ) { | |
98 SDL_OutOfMemory(); | |
99 if ( this ) { | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
100 SDL_free(this); |
0 | 101 } |
102 return(0); | |
103 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
104 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); |
0 | 105 audio_fd = -1; |
106 | |
107 /* Set the function pointers */ | |
108 this->OpenAudio = Paud_OpenAudio; | |
109 this->WaitAudio = Paud_WaitAudio; | |
110 this->PlayAudio = Paud_PlayAudio; | |
111 this->GetAudioBuf = Paud_GetAudioBuf; | |
112 this->CloseAudio = Paud_CloseAudio; | |
113 | |
114 this->free = Audio_DeleteDevice; | |
115 | |
116 return this; | |
117 } | |
118 | |
119 AudioBootStrap Paud_bootstrap = { | |
120 Paud_DRIVER_NAME, "AIX Paudio", | |
121 Audio_Available, Audio_CreateDevice | |
122 }; | |
123 | |
124 /* This function waits until it is possible to write a full sound buffer */ | |
125 static void Paud_WaitAudio(_THIS) | |
126 { | |
127 fd_set fdset; | |
128 | |
129 /* See if we need to use timed audio synchronization */ | |
130 if ( frame_ticks ) { | |
131 /* Use timer for general audio synchronization */ | |
132 Sint32 ticks; | |
133 | |
134 ticks = ((Sint32)(next_frame - SDL_GetTicks()))-FUDGE_TICKS; | |
135 if ( ticks > 0 ) { | |
136 SDL_Delay(ticks); | |
137 } | |
138 } else { | |
139 audio_buffer paud_bufinfo; | |
140 | |
141 /* Use select() for audio synchronization */ | |
142 struct timeval timeout; | |
143 FD_ZERO(&fdset); | |
144 FD_SET(audio_fd, &fdset); | |
145 | |
146 if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { | |
147 #ifdef DEBUG_AUDIO | |
148 fprintf(stderr, "Couldn't get audio buffer information\n"); | |
149 #endif | |
150 timeout.tv_sec = 10; | |
151 timeout.tv_usec = 0; | |
152 } else { | |
153 long ms_in_buf = paud_bufinfo.write_buf_time; | |
154 timeout.tv_sec = ms_in_buf/1000; | |
155 ms_in_buf = ms_in_buf - timeout.tv_sec*1000; | |
156 timeout.tv_usec = ms_in_buf*1000; | |
157 #ifdef DEBUG_AUDIO | |
158 fprintf( stderr, | |
159 "Waiting for write_buf_time=%ld,%ld\n", | |
160 timeout.tv_sec, | |
161 timeout.tv_usec ); | |
162 #endif | |
163 } | |
164 | |
165 #ifdef DEBUG_AUDIO | |
166 fprintf(stderr, "Waiting for audio to get ready\n"); | |
167 #endif | |
168 if ( select(audio_fd+1, NULL, &fdset, NULL, &timeout) <= 0 ) { | |
169 const char *message = "Audio timeout - buggy audio driver? (disabled)"; | |
170 /* | |
171 * In general we should never print to the screen, | |
172 * but in this case we have no other way of letting | |
173 * the user know what happened. | |
174 */ | |
175 fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); | |
176 this->enabled = 0; | |
177 /* Don't try to close - may hang */ | |
178 audio_fd = -1; | |
179 #ifdef DEBUG_AUDIO | |
180 fprintf(stderr, "Done disabling audio\n"); | |
181 #endif | |
182 } | |
183 #ifdef DEBUG_AUDIO | |
184 fprintf(stderr, "Ready!\n"); | |
185 #endif | |
186 } | |
187 } | |
188 | |
189 static void Paud_PlayAudio(_THIS) | |
190 { | |
191 int written; | |
192 | |
193 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | |
194 do { | |
195 written = write(audio_fd, mixbuf, mixlen); | |
196 if ( (written < 0) && ((errno == 0) || (errno == EAGAIN)) ) { | |
197 SDL_Delay(1); /* Let a little CPU time go by */ | |
198 } | |
199 } while ( (written < 0) && | |
200 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR)) ); | |
201 | |
202 /* If timer synchronization is enabled, set the next write frame */ | |
203 if ( frame_ticks ) { | |
204 next_frame += frame_ticks; | |
205 } | |
206 | |
207 /* If we couldn't write, assume fatal error for now */ | |
208 if ( written < 0 ) { | |
209 this->enabled = 0; | |
210 } | |
211 #ifdef DEBUG_AUDIO | |
212 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | |
213 #endif | |
214 } | |
215 | |
216 static Uint8 *Paud_GetAudioBuf(_THIS) | |
217 { | |
218 return mixbuf; | |
219 } | |
220 | |
221 static void Paud_CloseAudio(_THIS) | |
222 { | |
223 if ( mixbuf != NULL ) { | |
224 SDL_FreeAudioMem(mixbuf); | |
225 mixbuf = NULL; | |
226 } | |
227 if ( audio_fd >= 0 ) { | |
228 close(audio_fd); | |
229 audio_fd = -1; | |
230 } | |
231 } | |
232 | |
233 static int Paud_OpenAudio(_THIS, SDL_AudioSpec *spec) | |
234 { | |
235 char audiodev[1024]; | |
236 int format; | |
237 int bytes_per_sample; | |
238 Uint16 test_format; | |
239 audio_init paud_init; | |
240 audio_buffer paud_bufinfo; | |
241 audio_status paud_status; | |
242 audio_control paud_control; | |
243 audio_change paud_change; | |
244 | |
245 /* Reset the timer synchronization flag */ | |
246 frame_ticks = 0.0; | |
247 | |
248 /* Open the audio device */ | |
249 audio_fd = SDL_OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); | |
250 if ( audio_fd < 0 ) { | |
251 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | |
252 return -1; | |
253 } | |
254 | |
255 /* | |
256 * We can't set the buffer size - just ask the device for the maximum | |
257 * that we can have. | |
258 */ | |
259 if ( ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0 ) { | |
260 SDL_SetError("Couldn't get audio buffer information"); | |
261 return -1; | |
262 } | |
263 | |
264 mixbuf = NULL; | |
265 | |
266 if ( spec->channels > 1 ) | |
267 spec->channels = 2; | |
268 else | |
269 spec->channels = 1; | |
270 | |
271 /* | |
272 * Fields in the audio_init structure: | |
273 * | |
274 * Ignored by us: | |
275 * | |
276 * paud.loadpath[LOAD_PATH]; * DSP code to load, MWave chip only? | |
277 * paud.slot_number; * slot number of the adapter | |
278 * paud.device_id; * adapter identification number | |
279 * | |
280 * Input: | |
281 * | |
282 * paud.srate; * the sampling rate in Hz | |
283 * paud.bits_per_sample; * 8, 16, 32, ... | |
284 * paud.bsize; * block size for this rate | |
285 * paud.mode; * ADPCM, PCM, MU_LAW, A_LAW, SOURCE_MIX | |
286 * paud.channels; * 1=mono, 2=stereo | |
287 * paud.flags; * FIXED - fixed length data | |
288 * * LEFT_ALIGNED, RIGHT_ALIGNED (var len only) | |
289 * * TWOS_COMPLEMENT - 2's complement data | |
290 * * SIGNED - signed? comment seems wrong in sys/audio.h | |
291 * * BIG_ENDIAN | |
292 * paud.operation; * PLAY, RECORD | |
293 * | |
294 * Output: | |
295 * | |
296 * paud.flags; * PITCH - pitch is supported | |
297 * * INPUT - input is supported | |
298 * * OUTPUT - output is supported | |
299 * * MONITOR - monitor is supported | |
300 * * VOLUME - volume is supported | |
301 * * VOLUME_DELAY - volume delay is supported | |
302 * * BALANCE - balance is supported | |
303 * * BALANCE_DELAY - balance delay is supported | |
304 * * TREBLE - treble control is supported | |
305 * * BASS - bass control is supported | |
306 * * BESTFIT_PROVIDED - best fit returned | |
307 * * LOAD_CODE - DSP load needed | |
308 * paud.rc; * NO_PLAY - DSP code can't do play requests | |
309 * * NO_RECORD - DSP code can't do record requests | |
310 * * INVALID_REQUEST - request was invalid | |
311 * * CONFLICT - conflict with open's flags | |
312 * * OVERLOADED - out of DSP MIPS or memory | |
313 * paud.position_resolution; * smallest increment for position | |
314 */ | |
315 | |
316 paud_init.srate = spec->freq; | |
317 paud_init.mode = PCM; | |
318 paud_init.operation = PLAY; | |
319 paud_init.channels = spec->channels; | |
320 | |
321 /* Try for a closest match on audio format */ | |
322 format = 0; | |
323 for ( test_format = SDL_FirstAudioFormat(spec->format); | |
324 ! format && test_format; ) { | |
325 #ifdef DEBUG_AUDIO | |
326 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); | |
327 #endif | |
328 switch ( test_format ) { | |
329 case AUDIO_U8: | |
330 bytes_per_sample = 1; | |
331 paud_init.bits_per_sample = 8; | |
332 paud_init.flags = TWOS_COMPLEMENT | FIXED; | |
333 format = 1; | |
334 break; | |
335 case AUDIO_S8: | |
336 bytes_per_sample = 1; | |
337 paud_init.bits_per_sample = 8; | |
338 paud_init.flags = SIGNED | | |
339 TWOS_COMPLEMENT | FIXED; | |
340 format = 1; | |
341 break; | |
342 case AUDIO_S16LSB: | |
343 bytes_per_sample = 2; | |
344 paud_init.bits_per_sample = 16; | |
345 paud_init.flags = SIGNED | | |
346 TWOS_COMPLEMENT | FIXED; | |
347 format = 1; | |
348 break; | |
349 case AUDIO_S16MSB: | |
350 bytes_per_sample = 2; | |
351 paud_init.bits_per_sample = 16; | |
352 paud_init.flags = BIG_ENDIAN | | |
353 SIGNED | | |
354 TWOS_COMPLEMENT | FIXED; | |
355 format = 1; | |
356 break; | |
357 case AUDIO_U16LSB: | |
358 bytes_per_sample = 2; | |
359 paud_init.bits_per_sample = 16; | |
360 paud_init.flags = TWOS_COMPLEMENT | FIXED; | |
361 format = 1; | |
362 break; | |
363 case AUDIO_U16MSB: | |
364 bytes_per_sample = 2; | |
365 paud_init.bits_per_sample = 16; | |
366 paud_init.flags = BIG_ENDIAN | | |
367 TWOS_COMPLEMENT | FIXED; | |
368 format = 1; | |
369 break; | |
370 default: | |
371 break; | |
372 } | |
373 if ( ! format ) { | |
374 test_format = SDL_NextAudioFormat(); | |
375 } | |
376 } | |
377 if ( format == 0 ) { | |
378 #ifdef DEBUG_AUDIO | |
379 fprintf(stderr, "Couldn't find any hardware audio formats\n"); | |
380 #endif | |
381 SDL_SetError("Couldn't find any hardware audio formats"); | |
382 return -1; | |
383 } | |
384 spec->format = test_format; | |
385 | |
386 /* | |
387 * We know the buffer size and the max number of subsequent writes | |
388 * that can be pending. If more than one can pend, allow the application | |
389 * to do something like double buffering between our write buffer and | |
390 * the device's own buffer that we are filling with write() anyway. | |
391 * | |
392 * We calculate spec->samples like this because SDL_CalculateAudioSpec() | |
393 * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2) | |
394 * into spec->size in return. | |
395 */ | |
396 if ( paud_bufinfo.request_buf_cap == 1 ) | |
397 { | |
398 spec->samples = paud_bufinfo.write_buf_cap | |
399 / bytes_per_sample | |
400 / spec->channels; | |
401 } | |
402 else | |
403 { | |
404 spec->samples = paud_bufinfo.write_buf_cap | |
405 / bytes_per_sample | |
406 / spec->channels | |
407 / 2; | |
408 } | |
409 paud_init.bsize = bytes_per_sample * spec->channels; | |
410 | |
411 SDL_CalculateAudioSpec(spec); | |
412 | |
413 /* | |
414 * The AIX paud device init can't modify the values of the audio_init | |
415 * structure that we pass to it. So we don't need any recalculation | |
416 * of this stuff and no reinit call as in linux dsp and dma code. | |
417 * | |
418 * /dev/paud supports all of the encoding formats, so we don't need | |
419 * to do anything like reopening the device, either. | |
420 */ | |
421 if ( ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0 ) { | |
422 switch ( paud_init.rc ) | |
423 { | |
424 case 1 : | |
425 SDL_SetError("Couldn't set audio format: DSP can't do play requests"); | |
426 return -1; | |
427 break; | |
428 case 2 : | |
429 SDL_SetError("Couldn't set audio format: DSP can't do record requests"); | |
430 return -1; | |
431 break; | |
432 case 4 : | |
433 SDL_SetError("Couldn't set audio format: request was invalid"); | |
434 return -1; | |
435 break; | |
436 case 5 : | |
437 SDL_SetError("Couldn't set audio format: conflict with open's flags"); | |
438 return -1; | |
439 break; | |
440 case 6 : | |
441 SDL_SetError("Couldn't set audio format: out of DSP MIPS or memory"); | |
442 return -1; | |
443 break; | |
444 default : | |
445 SDL_SetError("Couldn't set audio format: not documented in sys/audio.h"); | |
446 return -1; | |
447 break; | |
448 } | |
449 } | |
450 | |
451 /* Allocate mixing buffer */ | |
452 mixlen = spec->size; | |
453 mixbuf = (Uint8 *)SDL_AllocAudioMem(mixlen); | |
454 if ( mixbuf == NULL ) { | |
455 return -1; | |
456 } | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
457 SDL_memset(mixbuf, spec->silence, spec->size); |
0 | 458 |
459 /* | |
460 * Set some paramters: full volume, first speaker that we can find. | |
461 * Ignore the other settings for now. | |
462 */ | |
463 paud_change.input = AUDIO_IGNORE; /* the new input source */ | |
464 paud_change.output = OUTPUT_1; /* EXTERNAL_SPEAKER,INTERNAL_SPEAKER,OUTPUT_1 */ | |
465 paud_change.monitor = AUDIO_IGNORE; /* the new monitor state */ | |
466 paud_change.volume = 0x7fffffff; /* volume level [0-0x7fffffff] */ | |
467 paud_change.volume_delay = AUDIO_IGNORE; /* the new volume delay */ | |
468 paud_change.balance = 0x3fffffff; /* the new balance */ | |
469 paud_change.balance_delay = AUDIO_IGNORE; /* the new balance delay */ | |
470 paud_change.treble = AUDIO_IGNORE; /* the new treble state */ | |
471 paud_change.bass = AUDIO_IGNORE; /* the new bass state */ | |
472 paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ | |
473 | |
474 paud_control.ioctl_request = AUDIO_CHANGE; | |
475 paud_control.request_info = (char*)&paud_change; | |
476 if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { | |
477 #ifdef DEBUG_AUDIO | |
478 fprintf(stderr, "Can't change audio display settings\n" ); | |
479 #endif | |
480 } | |
481 | |
482 /* | |
483 * Tell the device to expect data. Actual start will wait for | |
484 * the first write() call. | |
485 */ | |
486 paud_control.ioctl_request = AUDIO_START; | |
487 paud_control.position = 0; | |
488 if ( ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0 ) { | |
489 #ifdef DEBUG_AUDIO | |
490 fprintf(stderr, "Can't start audio play\n" ); | |
491 #endif | |
492 SDL_SetError("Can't start audio play"); | |
493 return -1; | |
494 } | |
495 | |
496 /* Check to see if we need to use select() workaround */ | |
497 { char *workaround; | |
1336
3692456e7b0f
Use SDL_ prefixed versions of C library functions.
Sam Lantinga <slouken@libsdl.org>
parents:
1312
diff
changeset
|
498 workaround = SDL_getenv("SDL_DSP_NOSELECT"); |
0 | 499 if ( workaround ) { |
500 frame_ticks = (float)(spec->samples*1000)/spec->freq; | |
501 next_frame = SDL_GetTicks()+frame_ticks; | |
502 } | |
503 } | |
504 | |
505 /* Get the parent process id (we're the parent of the audio thread) */ | |
506 parent = getpid(); | |
507 | |
508 /* We're ready to rock and roll. :-) */ | |
509 return 0; | |
510 } | |
511 |