comparison src/audio/paudio/SDL_paudio.c @ 2049:5f6550e5184f

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