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