comparison src/audio/nto/SDL_nto_audio.c @ 1668:4da1ee79c9af SDL-1.3

more tweaking indent options
author Sam Lantinga <slouken@libsdl.org>
date Mon, 29 May 2006 04:04:35 +0000
parents 782fd950bd46
children
comparison
equal deleted inserted replaced
1667:1fddae038bc8 1668:4da1ee79c9af
68 {"Vortex 8820", QSA_MMAP_WORKAROUND}, 68 {"Vortex 8820", QSA_MMAP_WORKAROUND},
69 {"Vortex 8830", QSA_MMAP_WORKAROUND}, 69 {"Vortex 8830", QSA_MMAP_WORKAROUND},
70 }; 70 };
71 71
72 /* Audio driver functions */ 72 /* Audio driver functions */
73 static void NTO_ThreadInit (_THIS); 73 static void NTO_ThreadInit(_THIS);
74 static int NTO_OpenAudio (_THIS, SDL_AudioSpec * spec); 74 static int NTO_OpenAudio(_THIS, SDL_AudioSpec * spec);
75 static void NTO_WaitAudio (_THIS); 75 static void NTO_WaitAudio(_THIS);
76 static void NTO_PlayAudio (_THIS); 76 static void NTO_PlayAudio(_THIS);
77 static Uint8 *NTO_GetAudioBuf (_THIS); 77 static Uint8 *NTO_GetAudioBuf(_THIS);
78 static void NTO_CloseAudio (_THIS); 78 static void NTO_CloseAudio(_THIS);
79 79
80 /* card names check to apply the workarounds */ 80 /* card names check to apply the workarounds */
81 static int 81 static int
82 NTO_CheckBuggyCards (_THIS, unsigned long checkfor) 82 NTO_CheckBuggyCards(_THIS, unsigned long checkfor)
83 { 83 {
84 char scardname[33]; 84 char scardname[33];
85 int it; 85 int it;
86 86
87 if (snd_card_get_name (cardno, scardname, 32) < 0) { 87 if (snd_card_get_name(cardno, scardname, 32) < 0) {
88 return 0; 88 return 0;
89 } 89 }
90 90
91 for (it = 0; it < QSA_WA_CARDS; it++) { 91 for (it = 0; it < QSA_WA_CARDS; it++) {
92 if (SDL_strcmp (buggycards[it].cardname, scardname) == 0) { 92 if (SDL_strcmp(buggycards[it].cardname, scardname) == 0) {
93 if (buggycards[it].bugtype == checkfor) { 93 if (buggycards[it].bugtype == checkfor) {
94 return 1; 94 return 1;
95 } 95 }
96 } 96 }
97 } 97 }
98 98
99 return 0; 99 return 0;
100 } 100 }
101 101
102 static void 102 static void
103 NTO_ThreadInit (_THIS) 103 NTO_ThreadInit(_THIS)
104 { 104 {
105 int status; 105 int status;
106 struct sched_param param; 106 struct sched_param param;
107 107
108 /* increasing default 10 priority to 25 to avoid jerky sound */ 108 /* increasing default 10 priority to 25 to avoid jerky sound */
109 status = SchedGet (0, 0, &param); 109 status = SchedGet(0, 0, &param);
110 param.sched_priority = param.sched_curpriority + 15; 110 param.sched_priority = param.sched_curpriority + 15;
111 status = SchedSet (0, 0, SCHED_NOCHANGE, &param); 111 status = SchedSet(0, 0, SCHED_NOCHANGE, &param);
112 } 112 }
113 113
114 /* PCM transfer channel parameters initialize function */ 114 /* PCM transfer channel parameters initialize function */
115 static void 115 static void
116 NTO_InitAudioParams (snd_pcm_channel_params_t * cpars) 116 NTO_InitAudioParams(snd_pcm_channel_params_t * cpars)
117 { 117 {
118 SDL_memset (cpars, 0, sizeof (snd_pcm_channel_params_t)); 118 SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t));
119 119
120 cpars->channel = SND_PCM_CHANNEL_PLAYBACK; 120 cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
121 cpars->mode = SND_PCM_MODE_BLOCK; 121 cpars->mode = SND_PCM_MODE_BLOCK;
122 cpars->start_mode = SND_PCM_START_DATA; 122 cpars->start_mode = SND_PCM_START_DATA;
123 cpars->stop_mode = SND_PCM_STOP_STOP; 123 cpars->stop_mode = SND_PCM_STOP_STOP;
129 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; 129 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN;
130 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; 130 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX;
131 } 131 }
132 132
133 static int 133 static int
134 NTO_AudioAvailable (void) 134 NTO_AudioAvailable(void)
135 { 135 {
136 /* See if we can open a nonblocking channel. 136 /* See if we can open a nonblocking channel.
137 Return value '1' means we can. 137 Return value '1' means we can.
138 Return value '0' means we cannot. */ 138 Return value '0' means we cannot. */
139 139
142 snd_pcm_t *handle; 142 snd_pcm_t *handle;
143 143
144 available = 0; 144 available = 0;
145 handle = NULL; 145 handle = NULL;
146 146
147 rval = snd_pcm_open_preferred (&handle, NULL, NULL, OPEN_FLAGS); 147 rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS);
148 148
149 if (rval >= 0) { 149 if (rval >= 0) {
150 available = 1; 150 available = 1;
151 151
152 if ((rval = snd_pcm_close (handle)) < 0) { 152 if ((rval = snd_pcm_close(handle)) < 0) {
153 SDL_SetError 153 SDL_SetError
154 ("NTO_AudioAvailable(): snd_pcm_close failed: %s\n", 154 ("NTO_AudioAvailable(): snd_pcm_close failed: %s\n",
155 snd_strerror (rval)); 155 snd_strerror(rval));
156 available = 0; 156 available = 0;
157 } 157 }
158 } else { 158 } else {
159 SDL_SetError 159 SDL_SetError
160 ("NTO_AudioAvailable(): there are no available audio devices.\n"); 160 ("NTO_AudioAvailable(): there are no available audio devices.\n");
162 162
163 return (available); 163 return (available);
164 } 164 }
165 165
166 static void 166 static void
167 NTO_DeleteAudioDevice (SDL_AudioDevice * device) 167 NTO_DeleteAudioDevice(SDL_AudioDevice * device)
168 { 168 {
169 if ((device) && (device->hidden)) { 169 if ((device) && (device->hidden)) {
170 SDL_free (device->hidden); 170 SDL_free(device->hidden);
171 } 171 }
172 if (device) { 172 if (device) {
173 SDL_free (device); 173 SDL_free(device);
174 } 174 }
175 } 175 }
176 176
177 static SDL_AudioDevice * 177 static SDL_AudioDevice *
178 NTO_CreateAudioDevice (int devindex) 178 NTO_CreateAudioDevice(int devindex)
179 { 179 {
180 SDL_AudioDevice *this; 180 SDL_AudioDevice *this;
181 181
182 /* Initialize all variables that we clean on shutdown */ 182 /* Initialize all variables that we clean on shutdown */
183 this = (SDL_AudioDevice *) SDL_malloc (sizeof (SDL_AudioDevice)); 183 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice));
184 if (this) { 184 if (this) {
185 SDL_memset (this, 0, sizeof (SDL_AudioDevice)); 185 SDL_memset(this, 0, sizeof(SDL_AudioDevice));
186 this->hidden = (struct SDL_PrivateAudioData *) 186 this->hidden = (struct SDL_PrivateAudioData *)
187 SDL_malloc (sizeof (struct SDL_PrivateAudioData)); 187 SDL_malloc(sizeof(struct SDL_PrivateAudioData));
188 } 188 }
189 if ((this == NULL) || (this->hidden == NULL)) { 189 if ((this == NULL) || (this->hidden == NULL)) {
190 SDL_OutOfMemory (); 190 SDL_OutOfMemory();
191 if (this) { 191 if (this) {
192 SDL_free (this); 192 SDL_free(this);
193 } 193 }
194 return (0); 194 return (0);
195 } 195 }
196 SDL_memset (this->hidden, 0, sizeof (struct SDL_PrivateAudioData)); 196 SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData));
197 audio_handle = NULL; 197 audio_handle = NULL;
198 198
199 /* Set the function pointers */ 199 /* Set the function pointers */
200 this->ThreadInit = NTO_ThreadInit; 200 this->ThreadInit = NTO_ThreadInit;
201 this->OpenAudio = NTO_OpenAudio; 201 this->OpenAudio = NTO_OpenAudio;
215 NTO_CreateAudioDevice 215 NTO_CreateAudioDevice
216 }; 216 };
217 217
218 /* This function waits until it is possible to write a full sound buffer */ 218 /* This function waits until it is possible to write a full sound buffer */
219 static void 219 static void
220 NTO_WaitAudio (_THIS) 220 NTO_WaitAudio(_THIS)
221 { 221 {
222 fd_set wfds; 222 fd_set wfds;
223 int selectret; 223 int selectret;
224 224
225 FD_ZERO (&wfds); 225 FD_ZERO(&wfds);
226 FD_SET (audio_fd, &wfds); 226 FD_SET(audio_fd, &wfds);
227 227
228 do { 228 do {
229 selectret = select (audio_fd + 1, NULL, &wfds, NULL, NULL); 229 selectret = select(audio_fd + 1, NULL, &wfds, NULL, NULL);
230 switch (selectret) { 230 switch (selectret) {
231 case -1: 231 case -1:
232 case 0: 232 case 0:
233 SDL_SetError ("NTO_WaitAudio(): select() failed: %s\n", 233 SDL_SetError("NTO_WaitAudio(): select() failed: %s\n",
234 strerror (errno)); 234 strerror(errno));
235 return; 235 return;
236 default: 236 default:
237 if (FD_ISSET (audio_fd, &wfds)) { 237 if (FD_ISSET(audio_fd, &wfds)) {
238 return; 238 return;
239 } 239 }
240 break; 240 break;
241 } 241 }
242 } 242 }
243 while (1); 243 while (1);
244 } 244 }
245 245
246 static void 246 static void
247 NTO_PlayAudio (_THIS) 247 NTO_PlayAudio(_THIS)
248 { 248 {
249 int written, rval; 249 int written, rval;
250 int towrite; 250 int towrite;
251 void *pcmbuffer; 251 void *pcmbuffer;
252 252
257 towrite = this->spec.size; 257 towrite = this->spec.size;
258 pcmbuffer = pcm_buf; 258 pcmbuffer = pcm_buf;
259 259
260 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ 260 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */
261 do { 261 do {
262 written = snd_pcm_plugin_write (audio_handle, pcm_buf, towrite); 262 written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite);
263 if (written != towrite) { 263 if (written != towrite) {
264 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { 264 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
265 /* Let a little CPU time go by and try to write again */ 265 /* Let a little CPU time go by and try to write again */
266 SDL_Delay (1); 266 SDL_Delay(1);
267 /* if we wrote some data */ 267 /* if we wrote some data */
268 towrite -= written; 268 towrite -= written;
269 pcmbuffer += written * this->spec.channels; 269 pcmbuffer += written * this->spec.channels;
270 continue; 270 continue;
271 } else { 271 } else {
272 if ((errno == EINVAL) || (errno == EIO)) { 272 if ((errno == EINVAL) || (errno == EIO)) {
273 SDL_memset (&cstatus, 0, sizeof (cstatus)); 273 SDL_memset(&cstatus, 0, sizeof(cstatus));
274 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; 274 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
275 if ((rval = 275 if ((rval =
276 snd_pcm_plugin_status (audio_handle, 276 snd_pcm_plugin_status(audio_handle, &cstatus)) < 0) {
277 &cstatus)) < 0) {
278 SDL_SetError 277 SDL_SetError
279 ("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", 278 ("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n",
280 snd_strerror (rval)); 279 snd_strerror(rval));
281 return; 280 return;
282 } 281 }
283 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) 282 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN)
284 || (cstatus.status == SND_PCM_STATUS_READY)) { 283 || (cstatus.status == SND_PCM_STATUS_READY)) {
285 if ((rval = 284 if ((rval =
286 snd_pcm_plugin_prepare (audio_handle, 285 snd_pcm_plugin_prepare(audio_handle,
287 SND_PCM_CHANNEL_PLAYBACK)) 286 SND_PCM_CHANNEL_PLAYBACK))
288 < 0) { 287 < 0) {
289 SDL_SetError 288 SDL_SetError
290 ("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", 289 ("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n",
291 snd_strerror (rval)); 290 snd_strerror(rval));
292 return; 291 return;
293 } 292 }
294 } 293 }
295 continue; 294 continue;
296 } else { 295 } else {
312 311
313 return; 312 return;
314 } 313 }
315 314
316 static Uint8 * 315 static Uint8 *
317 NTO_GetAudioBuf (_THIS) 316 NTO_GetAudioBuf(_THIS)
318 { 317 {
319 return pcm_buf; 318 return pcm_buf;
320 } 319 }
321 320
322 static void 321 static void
323 NTO_CloseAudio (_THIS) 322 NTO_CloseAudio(_THIS)
324 { 323 {
325 int rval; 324 int rval;
326 325
327 this->enabled = 0; 326 this->enabled = 0;
328 327
329 if (audio_handle != NULL) { 328 if (audio_handle != NULL) {
330 if ((rval = 329 if ((rval =
331 snd_pcm_plugin_flush (audio_handle, 330 snd_pcm_plugin_flush(audio_handle,
332 SND_PCM_CHANNEL_PLAYBACK)) < 0) { 331 SND_PCM_CHANNEL_PLAYBACK)) < 0) {
333 SDL_SetError 332 SDL_SetError
334 ("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n", 333 ("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n",
335 snd_strerror (rval)); 334 snd_strerror(rval));
336 return; 335 return;
337 } 336 }
338 if ((rval = snd_pcm_close (audio_handle)) < 0) { 337 if ((rval = snd_pcm_close(audio_handle)) < 0) {
339 SDL_SetError ("NTO_CloseAudio(): snd_pcm_close failed: %s\n", 338 SDL_SetError("NTO_CloseAudio(): snd_pcm_close failed: %s\n",
340 snd_strerror (rval)); 339 snd_strerror(rval));
341 return; 340 return;
342 } 341 }
343 audio_handle = NULL; 342 audio_handle = NULL;
344 } 343 }
345 } 344 }
346 345
347 static int 346 static int
348 NTO_OpenAudio (_THIS, SDL_AudioSpec * spec) 347 NTO_OpenAudio(_THIS, SDL_AudioSpec * spec)
349 { 348 {
350 int rval; 349 int rval;
351 int format; 350 int format;
352 Uint16 test_format; 351 Uint16 test_format;
353 int found; 352 int found;
354 353
355 audio_handle = NULL; 354 audio_handle = NULL;
356 this->enabled = 0; 355 this->enabled = 0;
357 356
358 if (pcm_buf != NULL) { 357 if (pcm_buf != NULL) {
359 SDL_FreeAudioMem (pcm_buf); 358 SDL_FreeAudioMem(pcm_buf);
360 pcm_buf = NULL; 359 pcm_buf = NULL;
361 } 360 }
362 361
363 /* initialize channel transfer parameters to default */ 362 /* initialize channel transfer parameters to default */
364 NTO_InitAudioParams (&cparams); 363 NTO_InitAudioParams(&cparams);
365 364
366 /* Open the audio device */ 365 /* Open the audio device */
367 rval = 366 rval =
368 snd_pcm_open_preferred (&audio_handle, &cardno, &deviceno, 367 snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS);
369 OPEN_FLAGS);
370 if (rval < 0) { 368 if (rval < 0) {
371 SDL_SetError ("NTO_OpenAudio(): snd_pcm_open failed: %s\n", 369 SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n",
372 snd_strerror (rval)); 370 snd_strerror(rval));
373 return (-1); 371 return (-1);
374 } 372 }
375 373
376 if (!NTO_CheckBuggyCards (this, QSA_MMAP_WORKAROUND)) { 374 if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) {
377 /* enable count status parameter */ 375 /* enable count status parameter */
378 if ((rval = 376 if ((rval =
379 snd_pcm_plugin_set_disable (audio_handle, 377 snd_pcm_plugin_set_disable(audio_handle,
380 PLUGIN_DISABLE_MMAP)) < 0) { 378 PLUGIN_DISABLE_MMAP)) < 0) {
381 SDL_SetError ("snd_pcm_plugin_set_disable failed: %s\n", 379 SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n",
382 snd_strerror (rval)); 380 snd_strerror(rval));
383 return (-1); 381 return (-1);
384 } 382 }
385 } 383 }
386 384
387 /* Try for a closest match on audio format */ 385 /* Try for a closest match on audio format */
388 format = 0; 386 format = 0;
389 /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */ 387 /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */
390 found = 0; 388 found = 0;
391 389
392 for (test_format = SDL_FirstAudioFormat (spec->format); !found;) { 390 for (test_format = SDL_FirstAudioFormat(spec->format); !found;) {
393 /* if match found set format to equivalent ALSA format */ 391 /* if match found set format to equivalent ALSA format */
394 switch (test_format) { 392 switch (test_format) {
395 case AUDIO_U8: 393 case AUDIO_U8:
396 format = SND_PCM_SFMT_U8; 394 format = SND_PCM_SFMT_U8;
397 found = 1; 395 found = 1;
419 default: 417 default:
420 break; 418 break;
421 } 419 }
422 420
423 if (!found) { 421 if (!found) {
424 test_format = SDL_NextAudioFormat (); 422 test_format = SDL_NextAudioFormat();
425 } 423 }
426 } 424 }
427 425
428 /* assumes test_format not 0 on success */ 426 /* assumes test_format not 0 on success */
429 if (test_format == 0) { 427 if (test_format == 0) {
442 440
443 /* Set rate */ 441 /* Set rate */
444 cparams.format.rate = spec->freq; 442 cparams.format.rate = spec->freq;
445 443
446 /* Setup the transfer parameters according to cparams */ 444 /* Setup the transfer parameters according to cparams */
447 rval = snd_pcm_plugin_params (audio_handle, &cparams); 445 rval = snd_pcm_plugin_params(audio_handle, &cparams);
448 if (rval < 0) { 446 if (rval < 0) {
449 SDL_SetError 447 SDL_SetError
450 ("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", 448 ("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n",
451 snd_strerror (rval)); 449 snd_strerror(rval));
452 return (-1); 450 return (-1);
453 } 451 }
454 452
455 /* Make sure channel is setup right one last time */ 453 /* Make sure channel is setup right one last time */
456 SDL_memset (&csetup, 0x00, sizeof (csetup)); 454 SDL_memset(&csetup, 0x00, sizeof(csetup));
457 csetup.channel = SND_PCM_CHANNEL_PLAYBACK; 455 csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
458 if (snd_pcm_plugin_setup (audio_handle, &csetup) < 0) { 456 if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) {
459 SDL_SetError ("NTO_OpenAudio(): Unable to setup playback channel\n"); 457 SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n");
460 return -1; 458 return -1;
461 } 459 }
462 460
463 461
464 /* Calculate the final parameters for this audio specification */ 462 /* Calculate the final parameters for this audio specification */
465 SDL_CalculateAudioSpec (spec); 463 SDL_CalculateAudioSpec(spec);
466 464
467 pcm_len = spec->size; 465 pcm_len = spec->size;
468 466
469 if (pcm_len == 0) { 467 if (pcm_len == 0) {
470 pcm_len = 468 pcm_len =
471 csetup.buf.block.frag_size * spec->channels * 469 csetup.buf.block.frag_size * spec->channels *
472 (snd_pcm_format_width (format) / 8); 470 (snd_pcm_format_width(format) / 8);
473 } 471 }
474 472
475 /* Allocate memory to the audio buffer and initialize with silence (Note that 473 /* Allocate memory to the audio buffer and initialize with silence (Note that
476 buffer size must be a multiple of fragment size, so find closest multiple) 474 buffer size must be a multiple of fragment size, so find closest multiple)
477 */ 475 */
478 pcm_buf = (Uint8 *) SDL_AllocAudioMem (pcm_len); 476 pcm_buf = (Uint8 *) SDL_AllocAudioMem(pcm_len);
479 if (pcm_buf == NULL) { 477 if (pcm_buf == NULL) {
480 SDL_SetError ("NTO_OpenAudio(): pcm buffer allocation failed\n"); 478 SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n");
481 return (-1); 479 return (-1);
482 } 480 }
483 SDL_memset (pcm_buf, spec->silence, pcm_len); 481 SDL_memset(pcm_buf, spec->silence, pcm_len);
484 482
485 /* get the file descriptor */ 483 /* get the file descriptor */
486 if ((audio_fd = 484 if ((audio_fd =
487 snd_pcm_file_descriptor (audio_handle, 485 snd_pcm_file_descriptor(audio_handle,
488 SND_PCM_CHANNEL_PLAYBACK)) < 0) { 486 SND_PCM_CHANNEL_PLAYBACK)) < 0) {
489 SDL_SetError 487 SDL_SetError
490 ("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", 488 ("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n",
491 snd_strerror (rval)); 489 snd_strerror(rval));
492 return (-1); 490 return (-1);
493 } 491 }
494 492
495 /* Trigger audio playback */ 493 /* Trigger audio playback */
496 rval = snd_pcm_plugin_prepare (audio_handle, SND_PCM_CHANNEL_PLAYBACK); 494 rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK);
497 if (rval < 0) { 495 if (rval < 0) {
498 SDL_SetError ("snd_pcm_plugin_prepare failed: %s\n", 496 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n",
499 snd_strerror (rval)); 497 snd_strerror(rval));
500 return (-1); 498 return (-1);
501 } 499 }
502 500
503 this->enabled = 1; 501 this->enabled = 1;
504 502
505 /* Get the parent process id (we're the parent of the audio thread) */ 503 /* Get the parent process id (we're the parent of the audio thread) */
506 parent = getpid (); 504 parent = getpid();
507 505
508 /* We're really ready to rock and roll. :-) */ 506 /* We're really ready to rock and roll. :-) */
509 return (0); 507 return (0);
510 } 508 }
511 509