Mercurial > sdl-ios-xcode
comparison src/audio/nto/SDL_nto_audio.c @ 3829:d3171647e661 SDL-ryan-multiple-audio-device
Moved NTO audio driver to 1.3 API.
author | Ryan C. Gordon <icculus@icculus.org> |
---|---|
date | Sat, 07 Oct 2006 19:53:48 +0000 |
parents | c8b3d3d13ed1 |
children | 7df0d3efe682 |
comparison
equal
deleted
inserted
replaced
3828:efdfe292bd88 | 3829:d3171647e661 |
---|---|
67 {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, | 67 {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, |
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 |
73 static void NTO_ThreadInit(_THIS); | 73 static inline void |
74 static int NTO_OpenAudio(_THIS, SDL_AudioSpec * spec); | 74 NTO_SetError(const char *fn, int rval) |
75 static void NTO_WaitAudio(_THIS); | 75 { |
76 static void NTO_PlayAudio(_THIS); | 76 SDL_SetError("NTO: %s failed: %s", fn, snd_strerror(rval)); |
77 static Uint8 *NTO_GetAudioBuf(_THIS); | 77 } |
78 static void NTO_CloseAudio(_THIS); | 78 |
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(this->hidden->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) { |
100 } | 100 } |
101 | 101 |
102 static void | 102 static void |
103 NTO_ThreadInit(_THIS) | 103 NTO_ThreadInit(_THIS) |
104 { | 104 { |
105 int status; | |
106 struct sched_param param; | 105 struct sched_param param; |
106 int status = SchedGet(0, 0, ¶m); | |
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, ¶m); | |
110 param.sched_priority = param.sched_curpriority + 15; | 109 param.sched_priority = param.sched_curpriority + 15; |
111 status = SchedSet(0, 0, SCHED_NOCHANGE, ¶m); | 110 status = SchedSet(0, 0, SCHED_NOCHANGE, ¶m); |
112 } | 111 } |
113 | 112 |
114 /* PCM transfer channel parameters initialize function */ | 113 /* PCM transfer channel parameters initialize function */ |
129 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; | 128 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; |
130 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; | 129 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; |
131 } | 130 } |
132 | 131 |
133 static int | 132 static int |
134 NTO_AudioAvailable(void) | 133 NTO_Available(void) |
135 { | 134 { |
136 /* See if we can open a nonblocking channel. | 135 /* See if we can open a nonblocking channel. |
137 Return value '1' means we can. | 136 Return value '1' means we can. |
138 Return value '0' means we cannot. */ | 137 Return value '0' means we cannot. */ |
139 | 138 |
140 int available; | 139 int available = 0; |
141 int rval; | 140 snd_pcm_t *handle = NULL; |
142 snd_pcm_t *handle; | 141 int rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); |
143 | |
144 available = 0; | |
145 handle = NULL; | |
146 | |
147 rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); | |
148 | |
149 if (rval >= 0) { | 142 if (rval >= 0) { |
150 available = 1; | 143 available = 1; |
151 | |
152 if ((rval = snd_pcm_close(handle)) < 0) { | 144 if ((rval = snd_pcm_close(handle)) < 0) { |
153 SDL_SetError | |
154 ("NTO_AudioAvailable(): snd_pcm_close failed: %s\n", | |
155 snd_strerror(rval)); | |
156 available = 0; | 145 available = 0; |
157 } | 146 } |
158 } else { | |
159 SDL_SetError | |
160 ("NTO_AudioAvailable(): there are no available audio devices.\n"); | |
161 } | 147 } |
162 | 148 |
163 return (available); | 149 return (available); |
164 } | 150 } |
165 | 151 |
166 static void | |
167 NTO_DeleteAudioDevice(SDL_AudioDevice * device) | |
168 { | |
169 if ((device) && (device->hidden)) { | |
170 SDL_free(device->hidden); | |
171 } | |
172 if (device) { | |
173 SDL_free(device); | |
174 } | |
175 } | |
176 | |
177 static SDL_AudioDevice * | |
178 NTO_CreateAudioDevice(int devindex) | |
179 { | |
180 SDL_AudioDevice *this; | |
181 | |
182 /* Initialize all variables that we clean on shutdown */ | |
183 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); | |
184 if (this) { | |
185 SDL_memset(this, 0, sizeof(SDL_AudioDevice)); | |
186 this->hidden = (struct SDL_PrivateAudioData *) | |
187 SDL_malloc(sizeof(struct SDL_PrivateAudioData)); | |
188 } | |
189 if ((this == NULL) || (this->hidden == NULL)) { | |
190 SDL_OutOfMemory(); | |
191 if (this) { | |
192 SDL_free(this); | |
193 } | |
194 return (0); | |
195 } | |
196 SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); | |
197 audio_handle = NULL; | |
198 | |
199 /* Set the function pointers */ | |
200 this->ThreadInit = NTO_ThreadInit; | |
201 this->OpenAudio = NTO_OpenAudio; | |
202 this->WaitAudio = NTO_WaitAudio; | |
203 this->PlayAudio = NTO_PlayAudio; | |
204 this->GetAudioBuf = NTO_GetAudioBuf; | |
205 this->CloseAudio = NTO_CloseAudio; | |
206 | |
207 this->free = NTO_DeleteAudioDevice; | |
208 | |
209 return this; | |
210 } | |
211 | |
212 AudioBootStrap QNXNTOAUDIO_bootstrap = { | |
213 DRIVER_NAME, "QNX6 QSA-NTO Audio", | |
214 NTO_AudioAvailable, | |
215 NTO_CreateAudioDevice, | |
216 0 | |
217 }; | |
218 | 152 |
219 /* This function waits until it is possible to write a full sound buffer */ | 153 /* This function waits until it is possible to write a full sound buffer */ |
220 static void | 154 static void |
221 NTO_WaitAudio(_THIS) | 155 NTO_WaitDevice(_THIS) |
222 { | 156 { |
223 fd_set wfds; | 157 fd_set wfds; |
224 int selectret; | 158 int selectret; |
225 | 159 |
226 FD_ZERO(&wfds); | 160 FD_ZERO(&wfds); |
227 FD_SET(audio_fd, &wfds); | 161 FD_SET(this->hidden->audio_fd, &wfds); |
228 | 162 |
229 do { | 163 do { |
230 selectret = select(audio_fd + 1, NULL, &wfds, NULL, NULL); | 164 selectret = select(this->hidden->audio_fd+1, NULL, &wfds, NULL, NULL); |
231 switch (selectret) { | 165 switch (selectret) { |
232 case -1: | 166 case -1: |
233 case 0: | 167 case 0: |
234 SDL_SetError("NTO_WaitAudio(): select() failed: %s\n", | 168 SDL_SetError("NTO: select() failed: %s\n", strerror(errno)); |
235 strerror(errno)); | |
236 return; | 169 return; |
237 default: | 170 default: |
238 if (FD_ISSET(audio_fd, &wfds)) { | 171 if (FD_ISSET(this->hidden->audio_fd, &wfds)) { |
239 return; | 172 return; |
240 } | 173 } |
241 break; | 174 break; |
242 } | 175 } |
243 } | 176 } |
244 while (1); | 177 while (1); |
245 } | 178 } |
246 | 179 |
247 static void | 180 static void |
248 NTO_PlayAudio(_THIS) | 181 NTO_PlayDevice(_THIS) |
249 { | 182 { |
183 snd_pcm_channel_status_t cstatus; | |
250 int written, rval; | 184 int written, rval; |
251 int towrite; | 185 int towrite; |
252 void *pcmbuffer; | 186 void *pcmbuffer; |
253 | 187 |
254 if (!this->enabled) { | 188 if ((!this->enabled) || (!this->hidden)) { |
255 return; | 189 return; |
256 } | 190 } |
257 | 191 |
258 towrite = this->spec.size; | 192 towrite = this->spec.size; |
259 pcmbuffer = pcm_buf; | 193 pcmbuffer = this->hidden->pcm_buf; |
260 | 194 |
261 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ | 195 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ |
262 do { | 196 do { |
263 written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite); | 197 written = snd_pcm_plugin_write(this->hidden->audio_handle, |
198 pcmbuffer, towrite); | |
264 if (written != towrite) { | 199 if (written != towrite) { |
265 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { | 200 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { |
266 /* Let a little CPU time go by and try to write again */ | 201 /* Let a little CPU time go by and try to write again */ |
267 SDL_Delay(1); | 202 SDL_Delay(1); |
268 /* if we wrote some data */ | 203 /* if we wrote some data */ |
269 towrite -= written; | 204 towrite -= written; |
270 pcmbuffer += written * this->spec.channels; | 205 pcmbuffer += written * this->spec.channels; |
271 continue; | 206 continue; |
272 } else { | 207 } else if ((errno == EINVAL) || (errno == EIO)) { |
273 if ((errno == EINVAL) || (errno == EIO)) { | 208 SDL_memset(&cstatus, 0, sizeof (cstatus)); |
274 SDL_memset(&cstatus, 0, sizeof(cstatus)); | 209 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; |
275 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; | 210 rval = snd_pcm_plugin_status(this->hidden->audio_handle, |
276 if ((rval = | 211 &cstatus); |
277 snd_pcm_plugin_status(audio_handle, &cstatus)) < 0) { | 212 if (rval < 0) { |
278 SDL_SetError | 213 NTO_SetError("snd_pcm_plugin_status", rval); |
279 ("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", | 214 return; |
280 snd_strerror(rval)); | 215 } |
216 | |
217 if ( (cstatus.status == SND_PCM_STATUS_UNDERRUN) || | |
218 (cstatus.status == SND_PCM_STATUS_READY)) { | |
219 rval = snd_pcm_plugin_prepare(this->hidden->audio_handle, | |
220 SND_PCM_CHANNEL_PLAYBACK); | |
221 if (rval < 0) { | |
222 NTO_SetError("snd_pcm_plugin_prepare", rval); | |
281 return; | 223 return; |
282 } | 224 } |
283 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) | |
284 || (cstatus.status == SND_PCM_STATUS_READY)) { | |
285 if ((rval = | |
286 snd_pcm_plugin_prepare(audio_handle, | |
287 SND_PCM_CHANNEL_PLAYBACK)) | |
288 < 0) { | |
289 SDL_SetError | |
290 ("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", | |
291 snd_strerror(rval)); | |
292 return; | |
293 } | |
294 } | |
295 continue; | |
296 } else { | |
297 return; | |
298 } | 225 } |
226 continue; | |
227 } else { | |
228 return; | |
299 } | 229 } |
300 } else { | 230 } else { |
301 /* we wrote all remaining data */ | 231 /* we wrote all remaining data */ |
302 towrite -= written; | 232 towrite -= written; |
303 pcmbuffer += written * this->spec.channels; | 233 pcmbuffer += written * this->spec.channels; |
307 | 237 |
308 /* If we couldn't write, assume fatal error for now */ | 238 /* If we couldn't write, assume fatal error for now */ |
309 if (towrite != 0) { | 239 if (towrite != 0) { |
310 this->enabled = 0; | 240 this->enabled = 0; |
311 } | 241 } |
312 | |
313 return; | |
314 } | 242 } |
315 | 243 |
316 static Uint8 * | 244 static Uint8 * |
317 NTO_GetAudioBuf(_THIS) | 245 NTO_GetDeviceBuf(_THIS) |
318 { | 246 { |
319 return pcm_buf; | 247 return this->hidden->pcm_buf; |
320 } | 248 } |
321 | 249 |
322 static void | 250 static void |
323 NTO_CloseAudio(_THIS) | 251 NTO_CloseDevice(_THIS) |
324 { | 252 { |
325 int rval; | 253 if (this->hidden != NULL) { |
326 | 254 if (this->hidden->audio_handle != NULL) { |
327 this->enabled = 0; | 255 snd_pcm_plugin_flush(this->hidden->audio_handle, |
328 | 256 SND_PCM_CHANNEL_PLAYBACK); |
329 if (audio_handle != NULL) { | 257 snd_pcm_close(this->hidden->audio_handle); |
330 if ((rval = | 258 this->hidden->audio_handle = NULL; |
331 snd_pcm_plugin_flush(audio_handle, | 259 } |
332 SND_PCM_CHANNEL_PLAYBACK)) < 0) { | 260 if (this->hidden->pcm_buf != NULL) { |
333 SDL_SetError | 261 SDL_FreeAudioMem(this->hidden->pcm_buf); |
334 ("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n", | 262 this->hidden->pcm_buf = NULL; |
335 snd_strerror(rval)); | 263 } |
336 return; | 264 SDL_free(this->hidden); |
337 } | 265 this->hidden = NULL; |
338 if ((rval = snd_pcm_close(audio_handle)) < 0) { | |
339 SDL_SetError("NTO_CloseAudio(): snd_pcm_close failed: %s\n", | |
340 snd_strerror(rval)); | |
341 return; | |
342 } | |
343 audio_handle = NULL; | |
344 } | 266 } |
345 } | 267 } |
346 | 268 |
347 static int | 269 static int |
348 NTO_OpenAudio(_THIS, SDL_AudioSpec * spec) | 270 NTO_OpenDevice(_THIS, const char *devname, int iscapture) |
349 { | 271 { |
350 int rval; | 272 int rval = 0; |
351 int format; | 273 int format = 0; |
352 SDL_AudioFormat test_format; | 274 SDL_AudioFormat test_format = 0; |
353 int found; | 275 int found = 0; |
354 | 276 snd_pcm_channel_setup_t csetup; |
355 audio_handle = NULL; | 277 snd_pcm_channel_params_t cparams; |
356 this->enabled = 0; | 278 |
357 | 279 /* Initialize all variables that we clean on shutdown */ |
358 if (pcm_buf != NULL) { | 280 this->hidden = (struct SDL_PrivateAudioData *) |
359 SDL_FreeAudioMem(pcm_buf); | 281 SDL_malloc((sizeof *this->hidden)); |
360 pcm_buf = NULL; | 282 if (this->hidden == NULL) { |
361 } | 283 SDL_OutOfMemory(); |
284 return 0; | |
285 } | |
286 SDL_memset(this->hidden, 0, (sizeof *this->hidden)); | |
362 | 287 |
363 /* initialize channel transfer parameters to default */ | 288 /* initialize channel transfer parameters to default */ |
364 NTO_InitAudioParams(&cparams); | 289 NTO_InitAudioParams(&cparams); |
365 | 290 |
366 /* Open the audio device */ | 291 /* Open the audio device */ |
367 rval = | 292 rval = snd_pcm_open_preferred(&this->hidden->audio_handle, |
368 snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS); | 293 &this->hidden->cardno, |
294 &this->hidden->deviceno, OPEN_FLAGS); | |
295 | |
369 if (rval < 0) { | 296 if (rval < 0) { |
370 SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", | 297 NTO_CloseDevice(this); |
371 snd_strerror(rval)); | 298 NTO_SetError("snd_pcm_open", rval); |
372 return (-1); | 299 return 0; |
373 } | 300 } |
374 | 301 |
375 if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { | 302 if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { |
376 /* enable count status parameter */ | 303 /* enable count status parameter */ |
377 if ((rval = | 304 rval = snd_pcm_plugin_set_disable(this->hidden->audio_handle, |
378 snd_pcm_plugin_set_disable(audio_handle, | 305 PLUGIN_DISABLE_MMAP); |
379 PLUGIN_DISABLE_MMAP)) < 0) { | 306 if (rval < 0) { |
380 SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", | 307 NTO_CloseDevice(this); |
381 snd_strerror(rval)); | 308 NTO_SetError("snd_pcm_plugin_set_disable", rval); |
382 return (-1); | 309 return 0; |
383 } | 310 } |
384 } | 311 } |
385 | 312 |
386 /* Try for a closest match on audio format */ | 313 /* Try for a closest match on audio format */ |
387 format = 0; | 314 format = 0; |
388 /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */ | 315 /* can't use format as SND_PCM_SFMT_U8 = 0 in nto */ |
389 found = 0; | 316 found = 0; |
390 | 317 |
391 for (test_format = SDL_FirstAudioFormat(spec->format); !found;) { | 318 for (test_format = SDL_FirstAudioFormat(this->spec.format); !found;) { |
392 /* if match found set format to equivalent ALSA format */ | 319 /* if match found set format to equivalent ALSA format */ |
393 switch (test_format) { | 320 switch (test_format) { |
394 case AUDIO_U8: | 321 case AUDIO_U8: |
395 format = SND_PCM_SFMT_U8; | 322 format = SND_PCM_SFMT_U8; |
396 found = 1; | 323 found = 1; |
440 } | 367 } |
441 } | 368 } |
442 | 369 |
443 /* assumes test_format not 0 on success */ | 370 /* assumes test_format not 0 on success */ |
444 if (test_format == 0) { | 371 if (test_format == 0) { |
445 SDL_SetError | 372 NTO_CloseDevice(this); |
446 ("NTO_OpenAudio(): Couldn't find any hardware audio formats"); | 373 SDL_SetError("NTO: Couldn't find any hardware audio formats"); |
447 return (-1); | 374 return 0; |
448 } | 375 } |
449 | 376 |
450 spec->format = test_format; | 377 this->spec.format = test_format; |
451 | 378 |
452 /* Set the audio format */ | 379 /* Set the audio format */ |
453 cparams.format.format = format; | 380 cparams.format.format = format; |
454 | 381 |
455 /* Set mono or stereo audio (currently only two channels supported) */ | 382 /* Set mono or stereo audio (currently only two channels supported) */ |
456 cparams.format.voices = spec->channels; | 383 cparams.format.voices = this->spec.channels; |
457 | 384 |
458 /* Set rate */ | 385 /* Set rate */ |
459 cparams.format.rate = spec->freq; | 386 cparams.format.rate = this->spec.freq; |
460 | 387 |
461 /* Setup the transfer parameters according to cparams */ | 388 /* Setup the transfer parameters according to cparams */ |
462 rval = snd_pcm_plugin_params(audio_handle, &cparams); | 389 rval = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams); |
463 if (rval < 0) { | 390 if (rval < 0) { |
464 SDL_SetError | 391 NTO_CloseDevice(this); |
465 ("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", | 392 NTO_SetError("snd_pcm_channel_params", rval); |
466 snd_strerror(rval)); | 393 return 0; |
467 return (-1); | |
468 } | 394 } |
469 | 395 |
470 /* Make sure channel is setup right one last time */ | 396 /* Make sure channel is setup right one last time */ |
471 SDL_memset(&csetup, 0x00, sizeof(csetup)); | 397 SDL_memset(&csetup, '\0', sizeof (csetup)); |
472 csetup.channel = SND_PCM_CHANNEL_PLAYBACK; | 398 csetup.channel = SND_PCM_CHANNEL_PLAYBACK; |
473 if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) { | 399 if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) { |
474 SDL_SetError("NTO_OpenAudio(): Unable to setup playback channel\n"); | 400 NTO_CloseDevice(this); |
475 return -1; | 401 SDL_SetError("NTO: Unable to setup playback channel\n"); |
476 } | 402 return 0; |
477 | 403 } |
478 | 404 |
479 /* Calculate the final parameters for this audio specification */ | 405 /* Calculate the final parameters for this audio specification */ |
480 SDL_CalculateAudioSpec(spec); | 406 SDL_CalculateAudioSpec(&this->spec); |
481 | 407 |
482 pcm_len = spec->size; | 408 this->hidden->pcm_len = this->spec.size; |
483 | 409 |
484 if (pcm_len == 0) { | 410 if (this->hidden->pcm_len == 0) { |
485 pcm_len = | 411 this->hidden->pcm_len = |
486 csetup.buf.block.frag_size * spec->channels * | 412 csetup.buf.block.frag_size * this->spec.channels * |
487 (snd_pcm_format_width(format) / 8); | 413 (snd_pcm_format_width(format) / 8); |
488 } | 414 } |
489 | 415 |
490 /* Allocate memory to the audio buffer and initialize with silence (Note that | 416 /* |
491 buffer size must be a multiple of fragment size, so find closest multiple) | 417 * Allocate memory to the audio buffer and initialize with silence |
418 * (Note that buffer size must be a multiple of fragment size, so find | |
419 * closest multiple) | |
492 */ | 420 */ |
493 pcm_buf = (Uint8 *) SDL_AllocAudioMem(pcm_len); | 421 this->hidden->pcm_buf = (Uint8 *) SDL_AllocAudioMem(this->hidden->pcm_len); |
494 if (pcm_buf == NULL) { | 422 if (this->hidden->pcm_buf == NULL) { |
495 SDL_SetError("NTO_OpenAudio(): pcm buffer allocation failed\n"); | 423 NTO_CloseDevice(this); |
496 return (-1); | 424 SDL_OutOfMemory(); |
497 } | 425 return 0; |
498 SDL_memset(pcm_buf, spec->silence, pcm_len); | 426 } |
427 SDL_memset(this->hidden->pcm_buf,this->spec.silence,this->hidden->pcm_len); | |
499 | 428 |
500 /* get the file descriptor */ | 429 /* get the file descriptor */ |
501 if ((audio_fd = | 430 this->hidden->audio_fd = snd_pcm_file_descriptor(this->hidden->audio_handle, |
502 snd_pcm_file_descriptor(audio_handle, | 431 SND_PCM_CHANNEL_PLAYBACK); |
503 SND_PCM_CHANNEL_PLAYBACK)) < 0) { | 432 if (this->hidden->audio_fd < 0) { |
504 SDL_SetError | 433 NTO_CloseDevice(this); |
505 ("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", | 434 NTO_SetError("snd_pcm_file_descriptor", rval); |
506 snd_strerror(rval)); | 435 return 0; |
507 return (-1); | |
508 } | 436 } |
509 | 437 |
510 /* Trigger audio playback */ | 438 /* Trigger audio playback */ |
511 rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK); | 439 rval = snd_pcm_plugin_prepare(this->hidden->audio_handle, |
440 SND_PCM_CHANNEL_PLAYBACK); | |
512 if (rval < 0) { | 441 if (rval < 0) { |
513 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", | 442 NTO_CloseDevice(this); |
514 snd_strerror(rval)); | 443 NTO_SetError("snd_pcm_plugin_prepare", rval); |
515 return (-1); | 444 return 0; |
516 } | 445 } |
517 | |
518 this->enabled = 1; | |
519 | |
520 /* Get the parent process id (we're the parent of the audio thread) */ | |
521 parent = getpid(); | |
522 | 446 |
523 /* We're really ready to rock and roll. :-) */ | 447 /* We're really ready to rock and roll. :-) */ |
524 return (0); | 448 return 1; |
525 } | 449 } |
450 | |
451 AudioBootStrap QNXNTOAUDIO_bootstrap = { | |
452 DRIVER_NAME, "QNX6 QSA-NTO Audio", | |
453 NTO_AudioAvailable, NTO_Init, 0 | |
454 }; | |
526 | 455 |
527 /* vi: set ts=4 sw=4 expandtab: */ | 456 /* vi: set ts=4 sw=4 expandtab: */ |