Mercurial > sdl-ios-xcode
comparison src/audio/paudio/SDL_paudio.c @ 3832:ca74a71063ac SDL-ryan-multiple-audio-device
Paudio driver moved to 1.3 API.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 07 Oct 2006 20:20:59 +0000 |
parents | 7852b5b78af5 |
children | 66fb40445587 |
comparison
equal
deleted
inserted
replaced
3831:7df0d3efe682 | 3832:ca74a71063ac |
---|---|
38 #include "SDL_stdinc.h" | 38 #include "SDL_stdinc.h" |
39 #include "../SDL_audiomem.h" | 39 #include "../SDL_audiomem.h" |
40 #include "../SDL_audio_c.h" | 40 #include "../SDL_audio_c.h" |
41 #include "SDL_paudio.h" | 41 #include "SDL_paudio.h" |
42 | 42 |
43 #define DEBUG_AUDIO 1 | 43 #define DEBUG_AUDIO 0 |
44 | 44 |
45 /* A conflict within AIX 4.3.3 <sys/> headers and probably others as well. | 45 /* A conflict within AIX 4.3.3 <sys/> headers and probably others as well. |
46 * I guess nobody ever uses audio... Shame over AIX header files. */ | 46 * I guess nobody ever uses audio... Shame over AIX header files. */ |
47 #include <sys/machine.h> | 47 #include <sys/machine.h> |
48 #undef BIG_ENDIAN | 48 #undef BIG_ENDIAN |
49 #include <sys/audio.h> | 49 #include <sys/audio.h> |
50 | 50 |
51 /* The tag name used by paud audio */ | 51 /* The tag name used by paud audio */ |
52 #define Paud_DRIVER_NAME "paud" | 52 #define PAUDIO_DRIVER_NAME "paud" |
53 | 53 |
54 /* Open the audio device for playback, and don't block if busy */ | 54 /* Open the audio device for playback, and don't block if busy */ |
55 /* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */ | 55 /* #define OPEN_FLAGS (O_WRONLY|O_NONBLOCK) */ |
56 #define OPEN_FLAGS O_WRONLY | 56 #define OPEN_FLAGS O_WRONLY |
57 | |
58 /* Audio driver functions */ | |
59 static int Paud_OpenAudio(_THIS, SDL_AudioSpec * spec); | |
60 static void Paud_WaitAudio(_THIS); | |
61 static void Paud_PlayAudio(_THIS); | |
62 static Uint8 *Paud_GetAudioBuf(_THIS); | |
63 static void Paud_CloseAudio(_THIS); | |
64 | |
65 | 57 |
66 /* Get the name of the audio device we use for output */ | 58 /* Get the name of the audio device we use for output */ |
67 | 59 |
68 #ifndef _PATH_DEV_DSP | 60 #ifndef _PATH_DEV_DSP |
69 #define _PATH_DEV_DSP "/dev/%caud%c/%c" | 61 #define _PATH_DEV_DSP "/dev/%caud%c/%c" |
83 | 75 |
84 static int | 76 static int |
85 OpenUserDefinedDevice(char *path, int maxlen, int flags) | 77 OpenUserDefinedDevice(char *path, int maxlen, int flags) |
86 { | 78 { |
87 const char *audiodev; | 79 const char *audiodev; |
88 int audio_fd; | 80 int fd; |
89 | 81 |
90 /* Figure out what our audio device is */ | 82 /* Figure out what our audio device is */ |
91 if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) { | 83 if ((audiodev = SDL_getenv("SDL_PATH_DSP")) == NULL) { |
92 audiodev = SDL_getenv("AUDIODEV"); | 84 audiodev = SDL_getenv("AUDIODEV"); |
93 } | 85 } |
94 if (audiodev == NULL) { | 86 if (audiodev == NULL) { |
95 return -1; | 87 return -1; |
96 } | 88 } |
97 audio_fd = open(audiodev, flags, 0); | 89 fd = open(audiodev, flags, 0); |
98 if (path != NULL) { | 90 if (path != NULL) { |
99 SDL_strlcpy(path, audiodev, maxlen); | 91 SDL_strlcpy(path, audiodev, maxlen); |
100 path[maxlen - 1] = '\0'; | 92 path[maxlen - 1] = '\0'; |
101 } | 93 } |
102 return audio_fd; | 94 return fd; |
103 } | 95 } |
104 | 96 |
105 int | 97 static int |
106 OpenAudioPath(char *path, int maxlen, int flags, int classic) | 98 OpenAudioPath(char *path, int maxlen, int flags, int classic) |
107 { | 99 { |
108 struct stat sb; | 100 struct stat sb; |
109 int audio_fd; | 101 int cycle = 0; |
110 char audiopath[1024]; | 102 int fd = OpenUserDefinedDevice(path, maxlen, flags); |
111 int cycle; | 103 |
112 | 104 if (fd != -1) { |
113 audio_fd = OpenUserDefinedDevice(path, maxlen, flags); | 105 return fd; |
114 if (audio_fd != -1) { | 106 } |
115 return audio_fd; | 107 |
116 } | |
117 | |
118 cycle = 0; | |
119 /* !!! FIXME: do we really need a table here? */ | 108 /* !!! FIXME: do we really need a table here? */ |
120 while (devsettings[cycle][0] != '\0') { | 109 while (devsettings[cycle][0] != '\0') { |
110 char audiopath[1024]; | |
121 SDL_snprintf(audiopath, SDL_arraysize(audiopath), | 111 SDL_snprintf(audiopath, SDL_arraysize(audiopath), |
122 _PATH_DEV_DSP, | 112 _PATH_DEV_DSP, |
123 devsettings[cycle][0], | 113 devsettings[cycle][0], |
124 devsettings[cycle][1], devsettings[cycle][2]); | 114 devsettings[cycle][1], devsettings[cycle][2]); |
125 | 115 |
126 if (stat(audiopath, &sb) == 0) { | 116 if (stat(audiopath, &sb) == 0) { |
127 audio_fd = open(audiopath, flags, 0); | 117 fd = open(audiopath, flags, 0); |
128 if (audio_fd > 0) { | 118 if (fd > 0) { |
129 if (path != NULL) { | 119 if (path != NULL) { |
130 SDL_strlcpy(path, audiopath, maxlen); | 120 SDL_strlcpy(path, audiopath, maxlen); |
131 } | 121 } |
132 return audio_fd; | 122 return fd; |
133 } | 123 } |
134 } | 124 } |
135 } | 125 } |
136 return -1; | 126 return -1; |
137 } | 127 } |
138 | 128 |
139 | 129 |
140 /* Audio driver bootstrap functions */ | |
141 | |
142 static int | 130 static int |
143 Audio_Available(void) | 131 PAUDIO_Available(void) |
144 { | 132 { |
145 int fd; | 133 int fd; |
146 int available; | 134 int available; |
147 | 135 |
148 available = 0; | 136 available = 0; |
152 close(fd); | 140 close(fd); |
153 } | 141 } |
154 return (available); | 142 return (available); |
155 } | 143 } |
156 | 144 |
157 static void | |
158 Audio_DeleteDevice(SDL_AudioDevice * device) | |
159 { | |
160 SDL_free(device->hidden); | |
161 SDL_free(device); | |
162 } | |
163 | |
164 static SDL_AudioDevice * | |
165 Audio_CreateDevice(int devindex) | |
166 { | |
167 SDL_AudioDevice *this; | |
168 | |
169 /* Initialize all variables that we clean on shutdown */ | |
170 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); | |
171 if (this) { | |
172 SDL_memset(this, 0, (sizeof *this)); | |
173 this->hidden = (struct SDL_PrivateAudioData *) | |
174 SDL_malloc((sizeof *this->hidden)); | |
175 } | |
176 if ((this == NULL) || (this->hidden == NULL)) { | |
177 SDL_OutOfMemory(); | |
178 if (this) { | |
179 SDL_free(this); | |
180 } | |
181 return (0); | |
182 } | |
183 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
184 audio_fd = -1; | |
185 | |
186 /* Set the function pointers */ | |
187 this->OpenAudio = Paud_OpenAudio; | |
188 this->WaitAudio = Paud_WaitAudio; | |
189 this->PlayAudio = Paud_PlayAudio; | |
190 this->GetAudioBuf = Paud_GetAudioBuf; | |
191 this->CloseAudio = Paud_CloseAudio; | |
192 | |
193 this->free = Audio_DeleteDevice; | |
194 | |
195 return this; | |
196 } | |
197 | |
198 AudioBootStrap Paud_bootstrap = { | |
199 Paud_DRIVER_NAME, "AIX Paudio", | |
200 Audio_Available, Audio_CreateDevice, 0 | |
201 }; | |
202 | 145 |
203 /* This function waits until it is possible to write a full sound buffer */ | 146 /* This function waits until it is possible to write a full sound buffer */ |
204 static void | 147 static void |
205 Paud_WaitAudio(_THIS) | 148 PAUDIO_WaitDevice(_THIS) |
206 { | 149 { |
207 fd_set fdset; | 150 fd_set fdset; |
208 | 151 |
209 /* See if we need to use timed audio synchronization */ | 152 /* See if we need to use timed audio synchronization */ |
210 if (frame_ticks) { | 153 if (this->hidden->frame_ticks) { |
211 /* Use timer for general audio synchronization */ | 154 /* Use timer for general audio synchronization */ |
212 Sint32 ticks; | 155 Sint32 ticks; |
213 | 156 |
214 ticks = ((Sint32) (next_frame - SDL_GetTicks())) - FUDGE_TICKS; | 157 ticks = ((Sint32)(this->hidden->next_frame-SDL_GetTicks()))-FUDGE_TICKS; |
215 if (ticks > 0) { | 158 if (ticks > 0) { |
216 SDL_Delay(ticks); | 159 SDL_Delay(ticks); |
217 } | 160 } |
218 } else { | 161 } else { |
219 audio_buffer paud_bufinfo; | 162 audio_buffer paud_bufinfo; |
220 | 163 |
221 /* Use select() for audio synchronization */ | 164 /* Use select() for audio synchronization */ |
222 struct timeval timeout; | 165 struct timeval timeout; |
223 FD_ZERO(&fdset); | 166 FD_ZERO(&fdset); |
224 FD_SET(audio_fd, &fdset); | 167 FD_SET(this->hidden->audio_fd, &fdset); |
225 | 168 |
226 if (ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { | 169 if (ioctl(this->hidden->audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { |
227 #ifdef DEBUG_AUDIO | 170 #ifdef DEBUG_AUDIO |
228 fprintf(stderr, "Couldn't get audio buffer information\n"); | 171 fprintf(stderr, "Couldn't get audio buffer information\n"); |
229 #endif | 172 #endif |
230 timeout.tv_sec = 10; | 173 timeout.tv_sec = 10; |
231 timeout.tv_usec = 0; | 174 timeout.tv_usec = 0; |
242 } | 185 } |
243 | 186 |
244 #ifdef DEBUG_AUDIO | 187 #ifdef DEBUG_AUDIO |
245 fprintf(stderr, "Waiting for audio to get ready\n"); | 188 fprintf(stderr, "Waiting for audio to get ready\n"); |
246 #endif | 189 #endif |
247 if (select(audio_fd + 1, NULL, &fdset, NULL, &timeout) <= 0) { | 190 if (select(this->hidden->audio_fd+1,NULL,&fdset,NULL,&timeout) <= 0) { |
248 const char *message = | 191 const char *message = |
249 "Audio timeout - buggy audio driver? (disabled)"; | 192 "Audio timeout - buggy audio driver? (disabled)"; |
250 /* | 193 /* |
251 * In general we should never print to the screen, | 194 * In general we should never print to the screen, |
252 * but in this case we have no other way of letting | 195 * but in this case we have no other way of letting |
253 * the user know what happened. | 196 * the user know what happened. |
254 */ | 197 */ |
255 fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); | 198 fprintf(stderr, "SDL: %s - %s\n", strerror(errno), message); |
256 this->enabled = 0; | 199 this->enabled = 0; |
257 /* Don't try to close - may hang */ | 200 /* Don't try to close - may hang */ |
258 audio_fd = -1; | 201 this->hidden->audio_fd = -1; |
259 #ifdef DEBUG_AUDIO | 202 #ifdef DEBUG_AUDIO |
260 fprintf(stderr, "Done disabling audio\n"); | 203 fprintf(stderr, "Done disabling audio\n"); |
261 #endif | 204 #endif |
262 } | 205 } |
263 #ifdef DEBUG_AUDIO | 206 #ifdef DEBUG_AUDIO |
265 #endif | 208 #endif |
266 } | 209 } |
267 } | 210 } |
268 | 211 |
269 static void | 212 static void |
270 Paud_PlayAudio(_THIS) | 213 PAUDIO_PlayDevice(_THIS) |
271 { | 214 { |
272 int written; | 215 int written = 0; |
216 const Uint8 *mixbuf = this->hidden->mixbuf; | |
217 const size_t mixlen = this->hidden->mixlen; | |
273 | 218 |
274 /* Write the audio data, checking for EAGAIN on broken audio drivers */ | 219 /* Write the audio data, checking for EAGAIN on broken audio drivers */ |
275 do { | 220 do { |
276 written = write(audio_fd, mixbuf, mixlen); | 221 written = write(this->hidden->audio_fd, mixbuf, mixlen); |
277 if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) { | 222 if ((written < 0) && ((errno == 0) || (errno == EAGAIN))) { |
278 SDL_Delay(1); /* Let a little CPU time go by */ | 223 SDL_Delay(1); /* Let a little CPU time go by */ |
279 } | 224 } |
280 } | 225 } |
281 while ((written < 0) && | 226 while ((written < 0) && |
282 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR))); | 227 ((errno == 0) || (errno == EAGAIN) || (errno == EINTR))); |
283 | 228 |
284 /* If timer synchronization is enabled, set the next write frame */ | 229 /* If timer synchronization is enabled, set the next write frame */ |
285 if (frame_ticks) { | 230 if (this->hidden->frame_ticks) { |
286 next_frame += frame_ticks; | 231 this->hidden->next_frame += this->hidden->frame_ticks; |
287 } | 232 } |
288 | 233 |
289 /* If we couldn't write, assume fatal error for now */ | 234 /* If we couldn't write, assume fatal error for now */ |
290 if (written < 0) { | 235 if (written < 0) { |
291 this->enabled = 0; | 236 this->enabled = 0; |
294 fprintf(stderr, "Wrote %d bytes of audio data\n", written); | 239 fprintf(stderr, "Wrote %d bytes of audio data\n", written); |
295 #endif | 240 #endif |
296 } | 241 } |
297 | 242 |
298 static Uint8 * | 243 static Uint8 * |
299 Paud_GetAudioBuf(_THIS) | 244 PAUDIO_GetDeviceBuf(_THIS) |
300 { | 245 { |
301 return mixbuf; | 246 return this->hidden->mixbuf; |
302 } | 247 } |
303 | 248 |
304 static void | 249 static void |
305 Paud_CloseAudio(_THIS) | 250 PAUDIO_CloseDevice(_THIS) |
306 { | 251 { |
307 if (mixbuf != NULL) { | 252 if (this->hidden != NULL) { |
308 SDL_FreeAudioMem(mixbuf); | 253 if (this->hidden->mixbuf != NULL) { |
309 mixbuf = NULL; | 254 SDL_FreeAudioMem(this->hidden->mixbuf); |
310 } | 255 this->hidden->mixbuf = NULL; |
311 if (audio_fd >= 0) { | 256 } |
312 close(audio_fd); | 257 if (this->hidden->audio_fd >= 0) { |
313 audio_fd = -1; | 258 close(this->hidden->audio_fd); |
259 this->hidden->audio_fd = -1; | |
260 } | |
261 SDL_free(this->hidden); | |
262 this->hidden = NULL; | |
314 } | 263 } |
315 } | 264 } |
316 | 265 |
317 static int | 266 static int |
318 Paud_OpenAudio(_THIS, SDL_AudioSpec * spec) | 267 PAUDIO_OpenDevice(_THIS, const char *devname, int iscapture) |
319 { | 268 { |
269 const char *workaround = SDL_getenv("SDL_DSP_NOSELECT"); | |
320 char audiodev[1024]; | 270 char audiodev[1024]; |
271 const char *err = NULL; | |
321 int format; | 272 int format; |
322 int bytes_per_sample; | 273 int bytes_per_sample; |
323 SDL_AudioFormat test_format; | 274 SDL_AudioFormat test_format; |
324 audio_init paud_init; | 275 audio_init paud_init; |
325 audio_buffer paud_bufinfo; | 276 audio_buffer paud_bufinfo; |
326 audio_status paud_status; | 277 audio_status paud_status; |
327 audio_control paud_control; | 278 audio_control paud_control; |
328 audio_change paud_change; | 279 audio_change paud_change; |
329 | 280 int fd = -1; |
330 /* Reset the timer synchronization flag */ | 281 |
331 frame_ticks = 0.0; | 282 /* Initialize all variables that we clean on shutdown */ |
283 this->hidden = (struct SDL_PrivateAudioData *) | |
284 SDL_malloc((sizeof *this->hidden)); | |
285 if (this->hidden == NULL) { | |
286 SDL_OutOfMemory(); | |
287 return 0; | |
288 } | |
289 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
332 | 290 |
333 /* Open the audio device */ | 291 /* Open the audio device */ |
334 audio_fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); | 292 fd = OpenAudioPath(audiodev, sizeof(audiodev), OPEN_FLAGS, 0); |
335 if (audio_fd < 0) { | 293 this->hidden->audio_fd = fd; |
294 if (fd < 0) { | |
295 PAUDIO_CloseDevice(this); | |
336 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); | 296 SDL_SetError("Couldn't open %s: %s", audiodev, strerror(errno)); |
337 return -1; | 297 return 0; |
338 } | 298 } |
339 | 299 |
340 /* | 300 /* |
341 * We can't set the buffer size - just ask the device for the maximum | 301 * We can't set the buffer size - just ask the device for the maximum |
342 * that we can have. | 302 * that we can have. |
343 */ | 303 */ |
344 if (ioctl(audio_fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { | 304 if (ioctl(fd, AUDIO_BUFFER, &paud_bufinfo) < 0) { |
305 PAUDIO_CloseDevice(this); | |
345 SDL_SetError("Couldn't get audio buffer information"); | 306 SDL_SetError("Couldn't get audio buffer information"); |
346 return -1; | 307 return 0; |
347 } | 308 } |
348 | 309 |
349 mixbuf = NULL; | 310 if (this->spec.channels > 1) |
350 | 311 this->spec.channels = 2; |
351 if (spec->channels > 1) | |
352 spec->channels = 2; | |
353 else | 312 else |
354 spec->channels = 1; | 313 this->spec.channels = 1; |
355 | 314 |
356 /* | 315 /* |
357 * Fields in the audio_init structure: | 316 * Fields in the audio_init structure: |
358 * | 317 * |
359 * Ignored by us: | 318 * Ignored by us: |
396 * * CONFLICT - conflict with open's flags | 355 * * CONFLICT - conflict with open's flags |
397 * * OVERLOADED - out of DSP MIPS or memory | 356 * * OVERLOADED - out of DSP MIPS or memory |
398 * paud.position_resolution; * smallest increment for position | 357 * paud.position_resolution; * smallest increment for position |
399 */ | 358 */ |
400 | 359 |
401 paud_init.srate = spec->freq; | 360 paud_init.srate = this->spec.freq; |
402 paud_init.mode = PCM; | 361 paud_init.mode = PCM; |
403 paud_init.operation = PLAY; | 362 paud_init.operation = PLAY; |
404 paud_init.channels = spec->channels; | 363 paud_init.channels = this->spec.channels; |
405 | 364 |
406 /* Try for a closest match on audio format */ | 365 /* Try for a closest match on audio format */ |
407 format = 0; | 366 format = 0; |
408 for (test_format = SDL_FirstAudioFormat(spec->format); | 367 for (test_format = SDL_FirstAudioFormat(this->spec.format); |
409 !format && test_format;) { | 368 !format && test_format;) { |
410 #ifdef DEBUG_AUDIO | 369 #ifdef DEBUG_AUDIO |
411 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); | 370 fprintf(stderr, "Trying format 0x%4.4x\n", test_format); |
412 #endif | 371 #endif |
413 switch (test_format) { | 372 switch (test_format) { |
456 } | 415 } |
457 if (format == 0) { | 416 if (format == 0) { |
458 #ifdef DEBUG_AUDIO | 417 #ifdef DEBUG_AUDIO |
459 fprintf(stderr, "Couldn't find any hardware audio formats\n"); | 418 fprintf(stderr, "Couldn't find any hardware audio formats\n"); |
460 #endif | 419 #endif |
420 PAUDIO_CloseDevice(this); | |
461 SDL_SetError("Couldn't find any hardware audio formats"); | 421 SDL_SetError("Couldn't find any hardware audio formats"); |
462 return -1; | 422 return 0; |
463 } | 423 } |
464 spec->format = test_format; | 424 this->spec.format = test_format; |
465 | 425 |
466 /* | 426 /* |
467 * We know the buffer size and the max number of subsequent writes | 427 * We know the buffer size and the max number of subsequent writes |
468 * that can be pending. If more than one can pend, allow the application | 428 * that can be pending. If more than one can pend, allow the application |
469 * to do something like double buffering between our write buffer and | 429 * to do something like double buffering between our write buffer and |
470 * the device's own buffer that we are filling with write() anyway. | 430 * the device's own buffer that we are filling with write() anyway. |
471 * | 431 * |
472 * We calculate spec->samples like this because SDL_CalculateAudioSpec() | 432 * We calculate this->spec.samples like this because |
473 * will give put paud_bufinfo.write_buf_cap (or paud_bufinfo.write_buf_cap/2) | 433 * SDL_CalculateAudioSpec() will give put paud_bufinfo.write_buf_cap |
474 * into spec->size in return. | 434 * (or paud_bufinfo.write_buf_cap/2) into this->spec.size in return. |
475 */ | 435 */ |
476 if (paud_bufinfo.request_buf_cap == 1) { | 436 if (paud_bufinfo.request_buf_cap == 1) { |
477 spec->samples = paud_bufinfo.write_buf_cap | 437 this->spec.samples = paud_bufinfo.write_buf_cap |
478 / bytes_per_sample / spec->channels; | 438 / bytes_per_sample / this->spec.channels; |
479 } else { | 439 } else { |
480 spec->samples = paud_bufinfo.write_buf_cap | 440 this->spec.samples = paud_bufinfo.write_buf_cap |
481 / bytes_per_sample / spec->channels / 2; | 441 / bytes_per_sample / this->spec.channels / 2; |
482 } | 442 } |
483 paud_init.bsize = bytes_per_sample * spec->channels; | 443 paud_init.bsize = bytes_per_sample * this->spec.channels; |
484 | 444 |
485 SDL_CalculateAudioSpec(spec); | 445 SDL_CalculateAudioSpec(&this->spec); |
486 | 446 |
487 /* | 447 /* |
488 * The AIX paud device init can't modify the values of the audio_init | 448 * The AIX paud device init can't modify the values of the audio_init |
489 * structure that we pass to it. So we don't need any recalculation | 449 * structure that we pass to it. So we don't need any recalculation |
490 * of this stuff and no reinit call as in linux dsp and dma code. | 450 * of this stuff and no reinit call as in linux dsp and dma code. |
491 * | 451 * |
492 * /dev/paud supports all of the encoding formats, so we don't need | 452 * /dev/paud supports all of the encoding formats, so we don't need |
493 * to do anything like reopening the device, either. | 453 * to do anything like reopening the device, either. |
494 */ | 454 */ |
495 if (ioctl(audio_fd, AUDIO_INIT, &paud_init) < 0) { | 455 if (ioctl(fd, AUDIO_INIT, &paud_init) < 0) { |
496 switch (paud_init.rc) { | 456 switch (paud_init.rc) { |
497 case 1: | 457 case 1: |
498 SDL_SetError | 458 err = "Couldn't set audio format: DSP can't do play requests"; |
499 ("Couldn't set audio format: DSP can't do play requests"); | |
500 return -1; | |
501 break; | 459 break; |
502 case 2: | 460 case 2: |
503 SDL_SetError | 461 err = "Couldn't set audio format: DSP can't do record requests"; |
504 ("Couldn't set audio format: DSP can't do record requests"); | |
505 return -1; | |
506 break; | 462 break; |
507 case 4: | 463 case 4: |
508 SDL_SetError("Couldn't set audio format: request was invalid"); | 464 err = "Couldn't set audio format: request was invalid"; |
509 return -1; | |
510 break; | 465 break; |
511 case 5: | 466 case 5: |
512 SDL_SetError | 467 err = "Couldn't set audio format: conflict with open's flags"; |
513 ("Couldn't set audio format: conflict with open's flags"); | |
514 return -1; | |
515 break; | 468 break; |
516 case 6: | 469 case 6: |
517 SDL_SetError | 470 err = "Couldn't set audio format: out of DSP MIPS or memory"; |
518 ("Couldn't set audio format: out of DSP MIPS or memory"); | |
519 return -1; | |
520 break; | 471 break; |
521 default: | 472 default: |
522 SDL_SetError | 473 err = "Couldn't set audio format: not documented in sys/audio.h"; |
523 ("Couldn't set audio format: not documented in sys/audio.h"); | 474 break; |
524 return -1; | 475 } |
525 break; | 476 } |
526 } | 477 |
478 if (err != NULL) { | |
479 PAUDIO_CloseDevice(this); | |
480 SDL_SetError("Paudio: %s", err); | |
481 return 0; | |
527 } | 482 } |
528 | 483 |
529 /* Allocate mixing buffer */ | 484 /* Allocate mixing buffer */ |
530 mixlen = spec->size; | 485 this->hidden->mixlen = this->spec.size; |
531 mixbuf = (Uint8 *) SDL_AllocAudioMem(mixlen); | 486 this->hidden->mixbuf = (Uint8 *) SDL_AllocAudioMem(this->hidden->mixlen); |
532 if (mixbuf == NULL) { | 487 if (this->hidden->mixbuf == NULL) { |
533 return -1; | 488 PAUDIO_CloseDevice(this); |
534 } | 489 SDL_OutOfMemory(); |
535 SDL_memset(mixbuf, spec->silence, spec->size); | 490 return 0; |
491 } | |
492 SDL_memset(this->hidden->mixbuf, this->spec.silence, this->spec.size); | |
536 | 493 |
537 /* | 494 /* |
538 * Set some paramters: full volume, first speaker that we can find. | 495 * Set some paramters: full volume, first speaker that we can find. |
539 * Ignore the other settings for now. | 496 * Ignore the other settings for now. |
540 */ | 497 */ |
549 paud_change.bass = AUDIO_IGNORE; /* the new bass state */ | 506 paud_change.bass = AUDIO_IGNORE; /* the new bass state */ |
550 paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ | 507 paud_change.pitch = AUDIO_IGNORE; /* the new pitch state */ |
551 | 508 |
552 paud_control.ioctl_request = AUDIO_CHANGE; | 509 paud_control.ioctl_request = AUDIO_CHANGE; |
553 paud_control.request_info = (char *) &paud_change; | 510 paud_control.request_info = (char *) &paud_change; |
554 if (ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0) { | 511 if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) { |
555 #ifdef DEBUG_AUDIO | 512 #ifdef DEBUG_AUDIO |
556 fprintf(stderr, "Can't change audio display settings\n"); | 513 fprintf(stderr, "Can't change audio display settings\n"); |
557 #endif | 514 #endif |
558 } | 515 } |
559 | 516 |
561 * Tell the device to expect data. Actual start will wait for | 518 * Tell the device to expect data. Actual start will wait for |
562 * the first write() call. | 519 * the first write() call. |
563 */ | 520 */ |
564 paud_control.ioctl_request = AUDIO_START; | 521 paud_control.ioctl_request = AUDIO_START; |
565 paud_control.position = 0; | 522 paud_control.position = 0; |
566 if (ioctl(audio_fd, AUDIO_CONTROL, &paud_control) < 0) { | 523 if (ioctl(fd, AUDIO_CONTROL, &paud_control) < 0) { |
524 PAUDIO_CloseDevice(this); | |
567 #ifdef DEBUG_AUDIO | 525 #ifdef DEBUG_AUDIO |
568 fprintf(stderr, "Can't start audio play\n"); | 526 fprintf(stderr, "Can't start audio play\n"); |
569 #endif | 527 #endif |
570 SDL_SetError("Can't start audio play"); | 528 SDL_SetError("Can't start audio play"); |
571 return -1; | 529 return 0; |
572 } | 530 } |
573 | 531 |
574 /* Check to see if we need to use select() workaround */ | 532 /* Check to see if we need to use select() workaround */ |
575 { | 533 if (workaround != NULL) { |
576 char *workaround; | 534 this->hidden->frame_ticks = (float) (this->spec.samples * 1000) / |
577 workaround = SDL_getenv("SDL_DSP_NOSELECT"); | 535 this->spec.freq; |
578 if (workaround) { | 536 this->hidden->next_frame = SDL_GetTicks() + this->hidden->frame_ticks; |
579 frame_ticks = (float) (spec->samples * 1000) / spec->freq; | 537 } |
580 next_frame = SDL_GetTicks() + frame_ticks; | |
581 } | |
582 } | |
583 | |
584 /* Get the parent process id (we're the parent of the audio thread) */ | |
585 parent = getpid(); | |
586 | 538 |
587 /* We're ready to rock and roll. :-) */ | 539 /* We're ready to rock and roll. :-) */ |
588 return 0; | 540 return 1; |
589 } | 541 } |
542 | |
543 static int | |
544 PAUDIO_Init(SDL_AudioDriverImpl *impl) | |
545 { | |
546 /* Set the function pointers */ | |
547 impl->OpenDevice = DSP_OpenDevice; | |
548 impl->PlayDevice = DSP_PlayDevice; | |
549 impl->PlayDevice = DSP_WaitDevice; | |
550 impl->GetDeviceBuf = DSP_GetDeviceBuf; | |
551 impl->CloseDevice = DSP_CloseDevice; | |
552 impl->OnlyHasDefaultOutputDevice = 1; /* !!! FIXME: add device enum! */ | |
553 | |
554 return 1; | |
555 } | |
556 | |
557 AudioBootStrap PAUDIO_bootstrap = { | |
558 PAUDIO_DRIVER_NAME, "AIX Paudio", | |
559 PAUDIO_Available, PAUDIO_Init, 0 | |
560 }; | |
590 | 561 |
591 /* vi: set ts=4 sw=4 expandtab: */ | 562 /* vi: set ts=4 sw=4 expandtab: */ |