Mercurial > sdl-ios-xcode
comparison src/audio/nto/SDL_nto_audio.c @ 1895:c121d94672cb
SDL 1.2 is moving to a branch, and SDL 1.3 is becoming the head.
author | Sam Lantinga <slouken@libsdl.org> |
---|---|
date | Mon, 10 Jul 2006 21:04:37 +0000 |
parents | d910939febfa |
children | 3b4ce57c6215 |
comparison
equal
deleted
inserted
replaced
1894:c69cee13dd76 | 1895:c121d94672cb |
---|---|
55 #define QSA_NO_WORKAROUNDS 0x00000000 | 55 #define QSA_NO_WORKAROUNDS 0x00000000 |
56 #define QSA_MMAP_WORKAROUND 0x00000001 | 56 #define QSA_MMAP_WORKAROUND 0x00000001 |
57 | 57 |
58 struct BuggyCards | 58 struct BuggyCards |
59 { | 59 { |
60 char* cardname; | 60 char *cardname; |
61 unsigned long bugtype; | 61 unsigned long bugtype; |
62 }; | 62 }; |
63 | 63 |
64 #define QSA_WA_CARDS 3 | 64 #define QSA_WA_CARDS 3 |
65 | 65 |
66 struct BuggyCards buggycards[QSA_WA_CARDS]= | 66 struct BuggyCards buggycards[QSA_WA_CARDS] = { |
67 { | 67 {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, |
68 {"Sound Blaster Live!", QSA_MMAP_WORKAROUND}, | 68 {"Vortex 8820", QSA_MMAP_WORKAROUND}, |
69 {"Vortex 8820", QSA_MMAP_WORKAROUND}, | 69 {"Vortex 8830", QSA_MMAP_WORKAROUND}, |
70 {"Vortex 8830", QSA_MMAP_WORKAROUND}, | |
71 }; | 70 }; |
72 | 71 |
73 /* Audio driver functions */ | 72 /* Audio driver functions */ |
74 static void NTO_ThreadInit(_THIS); | 73 static void NTO_ThreadInit(_THIS); |
75 static int NTO_OpenAudio(_THIS, SDL_AudioSpec* spec); | 74 static int NTO_OpenAudio(_THIS, SDL_AudioSpec * spec); |
76 static void NTO_WaitAudio(_THIS); | 75 static void NTO_WaitAudio(_THIS); |
77 static void NTO_PlayAudio(_THIS); | 76 static void NTO_PlayAudio(_THIS); |
78 static Uint8* NTO_GetAudioBuf(_THIS); | 77 static Uint8 *NTO_GetAudioBuf(_THIS); |
79 static void NTO_CloseAudio(_THIS); | 78 static void NTO_CloseAudio(_THIS); |
80 | 79 |
81 /* card names check to apply the workarounds */ | 80 /* card names check to apply the workarounds */ |
82 static int NTO_CheckBuggyCards(_THIS, unsigned long checkfor) | 81 static int |
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 { | |
89 return 0; | 88 return 0; |
90 } | 89 } |
91 | 90 |
92 for (it=0; it<QSA_WA_CARDS; it++) | 91 for (it = 0; it < QSA_WA_CARDS; it++) { |
93 { | 92 if (SDL_strcmp(buggycards[it].cardname, scardname) == 0) { |
94 if (SDL_strcmp(buggycards[it].cardname, scardname)==0) | 93 if (buggycards[it].bugtype == checkfor) { |
95 { | 94 return 1; |
96 if (buggycards[it].bugtype==checkfor) | 95 } |
97 { | 96 } |
98 return 1; | |
99 } | |
100 } | |
101 } | 97 } |
102 | 98 |
103 return 0; | 99 return 0; |
104 } | 100 } |
105 | 101 |
106 static void NTO_ThreadInit(_THIS) | 102 static void |
107 { | 103 NTO_ThreadInit(_THIS) |
108 int status; | 104 { |
109 struct sched_param param; | 105 int status; |
110 | 106 struct sched_param param; |
111 /* increasing default 10 priority to 25 to avoid jerky sound */ | 107 |
112 status=SchedGet(0, 0, ¶m); | 108 /* increasing default 10 priority to 25 to avoid jerky sound */ |
113 param.sched_priority=param.sched_curpriority+15; | 109 status = SchedGet(0, 0, ¶m); |
114 status=SchedSet(0, 0, SCHED_NOCHANGE, ¶m); | 110 param.sched_priority = param.sched_curpriority + 15; |
111 status = SchedSet(0, 0, SCHED_NOCHANGE, ¶m); | |
115 } | 112 } |
116 | 113 |
117 /* PCM transfer channel parameters initialize function */ | 114 /* PCM transfer channel parameters initialize function */ |
118 static void NTO_InitAudioParams(snd_pcm_channel_params_t* cpars) | 115 static void |
116 NTO_InitAudioParams(snd_pcm_channel_params_t * cpars) | |
119 { | 117 { |
120 SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t)); | 118 SDL_memset(cpars, 0, sizeof(snd_pcm_channel_params_t)); |
121 | 119 |
122 cpars->channel = SND_PCM_CHANNEL_PLAYBACK; | 120 cpars->channel = SND_PCM_CHANNEL_PLAYBACK; |
123 cpars->mode = SND_PCM_MODE_BLOCK; | 121 cpars->mode = SND_PCM_MODE_BLOCK; |
124 cpars->start_mode = SND_PCM_START_DATA; | 122 cpars->start_mode = SND_PCM_START_DATA; |
125 cpars->stop_mode = SND_PCM_STOP_STOP; | 123 cpars->stop_mode = SND_PCM_STOP_STOP; |
126 cpars->format.format = SND_PCM_SFMT_S16_LE; | 124 cpars->format.format = SND_PCM_SFMT_S16_LE; |
127 cpars->format.interleave = 1; | 125 cpars->format.interleave = 1; |
128 cpars->format.rate = DEFAULT_CPARAMS_RATE; | 126 cpars->format.rate = DEFAULT_CPARAMS_RATE; |
129 cpars->format.voices = DEFAULT_CPARAMS_VOICES; | 127 cpars->format.voices = DEFAULT_CPARAMS_VOICES; |
130 cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE; | 128 cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE; |
131 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; | 129 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN; |
132 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; | 130 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX; |
133 } | 131 } |
134 | 132 |
135 static int NTO_AudioAvailable(void) | 133 static int |
134 NTO_AudioAvailable(void) | |
136 { | 135 { |
137 /* See if we can open a nonblocking channel. | 136 /* See if we can open a nonblocking channel. |
138 Return value '1' means we can. | 137 Return value '1' means we can. |
139 Return value '0' means we cannot. */ | 138 Return value '0' means we cannot. */ |
140 | 139 |
141 int available; | 140 int available; |
142 int rval; | 141 int rval; |
143 snd_pcm_t* handle; | 142 snd_pcm_t *handle; |
144 | 143 |
145 available = 0; | 144 available = 0; |
146 handle = NULL; | 145 handle = NULL; |
147 | 146 |
148 rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); | 147 rval = snd_pcm_open_preferred(&handle, NULL, NULL, OPEN_FLAGS); |
149 | 148 |
150 if (rval >= 0) | 149 if (rval >= 0) { |
151 { | |
152 available = 1; | 150 available = 1; |
153 | 151 |
154 if ((rval = snd_pcm_close(handle)) < 0) | 152 if ((rval = snd_pcm_close(handle)) < 0) { |
155 { | 153 SDL_SetError |
156 SDL_SetError("NTO_AudioAvailable(): snd_pcm_close failed: %s\n", snd_strerror(rval)); | 154 ("NTO_AudioAvailable(): snd_pcm_close failed: %s\n", |
155 snd_strerror(rval)); | |
157 available = 0; | 156 available = 0; |
158 } | 157 } |
159 } | 158 } else { |
160 else | 159 SDL_SetError |
161 { | 160 ("NTO_AudioAvailable(): there are no available audio devices.\n"); |
162 SDL_SetError("NTO_AudioAvailable(): there are no available audio devices.\n"); | |
163 } | 161 } |
164 | 162 |
165 return (available); | 163 return (available); |
166 } | 164 } |
167 | 165 |
168 static void NTO_DeleteAudioDevice(SDL_AudioDevice *device) | 166 static void |
169 { | 167 NTO_DeleteAudioDevice(SDL_AudioDevice * device) |
170 if ((device)&&(device->hidden)) | 168 { |
171 { | 169 if ((device) && (device->hidden)) { |
172 SDL_free(device->hidden); | 170 SDL_free(device->hidden); |
173 } | 171 } |
174 if (device) | 172 if (device) { |
175 { | |
176 SDL_free(device); | 173 SDL_free(device); |
177 } | 174 } |
178 } | 175 } |
179 | 176 |
180 static SDL_AudioDevice* NTO_CreateAudioDevice(int devindex) | 177 static SDL_AudioDevice * |
178 NTO_CreateAudioDevice(int devindex) | |
181 { | 179 { |
182 SDL_AudioDevice *this; | 180 SDL_AudioDevice *this; |
183 | 181 |
184 /* Initialize all variables that we clean on shutdown */ | 182 /* Initialize all variables that we clean on shutdown */ |
185 this = (SDL_AudioDevice *)SDL_malloc(sizeof(SDL_AudioDevice)); | 183 this = (SDL_AudioDevice *) SDL_malloc(sizeof(SDL_AudioDevice)); |
186 if (this) | 184 if (this) { |
187 { | |
188 SDL_memset(this, 0, sizeof(SDL_AudioDevice)); | 185 SDL_memset(this, 0, sizeof(SDL_AudioDevice)); |
189 this->hidden = (struct SDL_PrivateAudioData *)SDL_malloc(sizeof(struct SDL_PrivateAudioData)); | 186 this->hidden = (struct SDL_PrivateAudioData *) |
190 } | 187 SDL_malloc(sizeof(struct SDL_PrivateAudioData)); |
191 if ((this == NULL) || (this->hidden == NULL)) | 188 } |
192 { | 189 if ((this == NULL) || (this->hidden == NULL)) { |
193 SDL_OutOfMemory(); | 190 SDL_OutOfMemory(); |
194 if (this) | 191 if (this) { |
195 { | |
196 SDL_free(this); | 192 SDL_free(this); |
197 } | 193 } |
198 return (0); | 194 return (0); |
199 } | 195 } |
200 SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); | 196 SDL_memset(this->hidden, 0, sizeof(struct SDL_PrivateAudioData)); |
201 audio_handle = NULL; | 197 audio_handle = NULL; |
202 | 198 |
211 this->free = NTO_DeleteAudioDevice; | 207 this->free = NTO_DeleteAudioDevice; |
212 | 208 |
213 return this; | 209 return this; |
214 } | 210 } |
215 | 211 |
216 AudioBootStrap QNXNTOAUDIO_bootstrap = | 212 AudioBootStrap QNXNTOAUDIO_bootstrap = { |
217 { | |
218 DRIVER_NAME, "QNX6 QSA-NTO Audio", | 213 DRIVER_NAME, "QNX6 QSA-NTO Audio", |
219 NTO_AudioAvailable, | 214 NTO_AudioAvailable, |
220 NTO_CreateAudioDevice | 215 NTO_CreateAudioDevice |
221 }; | 216 }; |
222 | 217 |
223 /* 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 */ |
224 static void NTO_WaitAudio(_THIS) | 219 static void |
220 NTO_WaitAudio(_THIS) | |
225 { | 221 { |
226 fd_set wfds; | 222 fd_set wfds; |
227 int selectret; | 223 int selectret; |
228 | 224 |
229 FD_ZERO(&wfds); | 225 FD_ZERO(&wfds); |
230 FD_SET(audio_fd, &wfds); | 226 FD_SET(audio_fd, &wfds); |
231 | 227 |
232 do { | 228 do { |
233 selectret=select(audio_fd + 1, NULL, &wfds, NULL, NULL); | 229 selectret = select(audio_fd + 1, NULL, &wfds, NULL, NULL); |
234 switch (selectret) | 230 switch (selectret) { |
235 { | 231 case -1: |
236 case -1: | 232 case 0: |
237 case 0: SDL_SetError("NTO_WaitAudio(): select() failed: %s\n", strerror(errno)); | 233 SDL_SetError("NTO_WaitAudio(): select() failed: %s\n", |
238 return; | 234 strerror(errno)); |
239 default: if (FD_ISSET(audio_fd, &wfds)) | 235 return; |
240 { | 236 default: |
241 return; | 237 if (FD_ISSET(audio_fd, &wfds)) { |
242 } | 238 return; |
243 break; | 239 } |
244 } | 240 break; |
245 } while(1); | 241 } |
246 } | 242 } |
247 | 243 while (1); |
248 static void NTO_PlayAudio(_THIS) | 244 } |
245 | |
246 static void | |
247 NTO_PlayAudio(_THIS) | |
249 { | 248 { |
250 int written, rval; | 249 int written, rval; |
251 int towrite; | 250 int towrite; |
252 void* pcmbuffer; | 251 void *pcmbuffer; |
253 | 252 |
254 if (!this->enabled) | 253 if (!this->enabled) { |
255 { | |
256 return; | 254 return; |
257 } | 255 } |
258 | 256 |
259 towrite = this->spec.size; | 257 towrite = this->spec.size; |
260 pcmbuffer = pcm_buf; | 258 pcmbuffer = pcm_buf; |
261 | 259 |
262 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ | 260 /* Write the audio data, checking for EAGAIN (buffer full) and underrun */ |
263 do { | 261 do { |
264 written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite); | 262 written = snd_pcm_plugin_write(audio_handle, pcm_buf, towrite); |
265 if (written != towrite) | 263 if (written != towrite) { |
266 { | 264 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) { |
267 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) | |
268 { | |
269 /* 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 */ |
270 SDL_Delay(1); | 266 SDL_Delay(1); |
271 /* if we wrote some data */ | 267 /* if we wrote some data */ |
272 towrite -= written; | 268 towrite -= written; |
273 pcmbuffer += written * this->spec.channels; | 269 pcmbuffer += written * this->spec.channels; |
274 continue; | 270 continue; |
275 } | 271 } else { |
276 else | 272 if ((errno == EINVAL) || (errno == EIO)) { |
277 { | |
278 if ((errno == EINVAL) || (errno == EIO)) | |
279 { | |
280 SDL_memset(&cstatus, 0, sizeof(cstatus)); | 273 SDL_memset(&cstatus, 0, sizeof(cstatus)); |
281 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; | 274 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; |
282 if ((rval = snd_pcm_plugin_status(audio_handle, &cstatus)) < 0) | 275 if ((rval = |
283 { | 276 snd_pcm_plugin_status(audio_handle, &cstatus)) < 0) { |
284 SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", snd_strerror(rval)); | 277 SDL_SetError |
278 ("NTO_PlayAudio(): snd_pcm_plugin_status failed: %s\n", | |
279 snd_strerror(rval)); | |
285 return; | 280 return; |
286 } | 281 } |
287 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || (cstatus.status == SND_PCM_STATUS_READY)) | 282 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) |
288 { | 283 || (cstatus.status == SND_PCM_STATUS_READY)) { |
289 if ((rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) | 284 if ((rval = |
290 { | 285 snd_pcm_plugin_prepare(audio_handle, |
291 SDL_SetError("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval)); | 286 SND_PCM_CHANNEL_PLAYBACK)) |
287 < 0) { | |
288 SDL_SetError | |
289 ("NTO_PlayAudio(): snd_pcm_plugin_prepare failed: %s\n", | |
290 snd_strerror(rval)); | |
292 return; | 291 return; |
293 } | 292 } |
294 } | 293 } |
295 continue; | 294 continue; |
296 } | 295 } else { |
297 else | |
298 { | |
299 return; | 296 return; |
300 } | 297 } |
301 } | 298 } |
302 } | 299 } else { |
303 else | |
304 { | |
305 /* we wrote all remaining data */ | 300 /* we wrote all remaining data */ |
306 towrite -= written; | 301 towrite -= written; |
307 pcmbuffer += written * this->spec.channels; | 302 pcmbuffer += written * this->spec.channels; |
308 } | 303 } |
309 } while ((towrite > 0) && (this->enabled)); | 304 } |
305 while ((towrite > 0) && (this->enabled)); | |
310 | 306 |
311 /* If we couldn't write, assume fatal error for now */ | 307 /* If we couldn't write, assume fatal error for now */ |
312 if (towrite != 0) | 308 if (towrite != 0) { |
313 { | |
314 this->enabled = 0; | 309 this->enabled = 0; |
315 } | 310 } |
316 | 311 |
317 return; | 312 return; |
318 } | 313 } |
319 | 314 |
320 static Uint8* NTO_GetAudioBuf(_THIS) | 315 static Uint8 * |
316 NTO_GetAudioBuf(_THIS) | |
321 { | 317 { |
322 return pcm_buf; | 318 return pcm_buf; |
323 } | 319 } |
324 | 320 |
325 static void NTO_CloseAudio(_THIS) | 321 static void |
322 NTO_CloseAudio(_THIS) | |
326 { | 323 { |
327 int rval; | 324 int rval; |
328 | 325 |
329 this->enabled = 0; | 326 this->enabled = 0; |
330 | 327 |
331 if (audio_handle != NULL) | 328 if (audio_handle != NULL) { |
332 { | 329 if ((rval = |
333 if ((rval = snd_pcm_plugin_flush(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) | 330 snd_pcm_plugin_flush(audio_handle, |
334 { | 331 SND_PCM_CHANNEL_PLAYBACK)) < 0) { |
335 SDL_SetError("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n", snd_strerror(rval)); | 332 SDL_SetError |
333 ("NTO_CloseAudio(): snd_pcm_plugin_flush failed: %s\n", | |
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 { | 338 SDL_SetError("NTO_CloseAudio(): snd_pcm_close failed: %s\n", |
340 SDL_SetError("NTO_CloseAudio(): snd_pcm_close failed: %s\n",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 NTO_OpenAudio(_THIS, SDL_AudioSpec* spec) | 346 static int |
347 NTO_OpenAudio(_THIS, SDL_AudioSpec * spec) | |
348 { | 348 { |
349 int rval; | 349 int rval; |
350 int format; | 350 int format; |
351 Uint16 test_format; | 351 Uint16 test_format; |
352 int found; | 352 int found; |
353 | 353 |
354 audio_handle = NULL; | 354 audio_handle = NULL; |
355 this->enabled = 0; | 355 this->enabled = 0; |
356 | 356 |
357 if (pcm_buf != NULL) | 357 if (pcm_buf != NULL) { |
358 { | 358 SDL_FreeAudioMem(pcm_buf); |
359 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 = snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS); | 366 rval = |
368 if (rval < 0) | 367 snd_pcm_open_preferred(&audio_handle, &cardno, &deviceno, OPEN_FLAGS); |
369 { | 368 if (rval < 0) { |
370 SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", snd_strerror(rval)); | 369 SDL_SetError("NTO_OpenAudio(): snd_pcm_open failed: %s\n", |
370 snd_strerror(rval)); | |
371 return (-1); | 371 return (-1); |
372 } | 372 } |
373 | 373 |
374 if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) | 374 if (!NTO_CheckBuggyCards(this, QSA_MMAP_WORKAROUND)) { |
375 { | |
376 /* enable count status parameter */ | 375 /* enable count status parameter */ |
377 if ((rval = snd_pcm_plugin_set_disable(audio_handle, PLUGIN_DISABLE_MMAP)) < 0) | 376 if ((rval = |
378 { | 377 snd_pcm_plugin_set_disable(audio_handle, |
379 SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", snd_strerror(rval)); | 378 PLUGIN_DISABLE_MMAP)) < 0) { |
379 SDL_SetError("snd_pcm_plugin_set_disable failed: %s\n", | |
380 snd_strerror(rval)); | |
380 return (-1); | 381 return (-1); |
381 } | 382 } |
382 } | 383 } |
383 | 384 |
384 /* Try for a closest match on audio format */ | 385 /* Try for a closest match on audio format */ |
385 format = 0; | 386 format = 0; |
386 /* 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 */ |
387 found = 0; | 388 found = 0; |
388 | 389 |
389 for (test_format=SDL_FirstAudioFormat(spec->format); !found ;) | 390 for (test_format = SDL_FirstAudioFormat(spec->format); !found;) { |
390 { | |
391 /* if match found set format to equivalent ALSA format */ | 391 /* if match found set format to equivalent ALSA format */ |
392 switch (test_format) | 392 switch (test_format) { |
393 { | 393 case AUDIO_U8: |
394 case AUDIO_U8: | 394 format = SND_PCM_SFMT_U8; |
395 format = SND_PCM_SFMT_U8; | 395 found = 1; |
396 found = 1; | 396 break; |
397 break; | 397 case AUDIO_S8: |
398 case AUDIO_S8: | 398 format = SND_PCM_SFMT_S8; |
399 format = SND_PCM_SFMT_S8; | 399 found = 1; |
400 found = 1; | 400 break; |
401 break; | 401 case AUDIO_S16LSB: |
402 case AUDIO_S16LSB: | 402 format = SND_PCM_SFMT_S16_LE; |
403 format = SND_PCM_SFMT_S16_LE; | 403 found = 1; |
404 found = 1; | 404 break; |
405 break; | 405 case AUDIO_S16MSB: |
406 case AUDIO_S16MSB: | 406 format = SND_PCM_SFMT_S16_BE; |
407 format = SND_PCM_SFMT_S16_BE; | 407 found = 1; |
408 found = 1; | 408 break; |
409 break; | 409 case AUDIO_U16LSB: |
410 case AUDIO_U16LSB: | 410 format = SND_PCM_SFMT_U16_LE; |
411 format = SND_PCM_SFMT_U16_LE; | 411 found = 1; |
412 found = 1; | 412 break; |
413 break; | 413 case AUDIO_U16MSB: |
414 case AUDIO_U16MSB: | 414 format = SND_PCM_SFMT_U16_BE; |
415 format = SND_PCM_SFMT_U16_BE; | 415 found = 1; |
416 found = 1; | 416 break; |
417 break; | 417 default: |
418 default: | 418 break; |
419 break; | 419 } |
420 } | 420 |
421 | 421 if (!found) { |
422 if (!found) | |
423 { | |
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) { |
430 { | 428 SDL_SetError |
431 SDL_SetError("NTO_OpenAudio(): Couldn't find any hardware audio formats"); | 429 ("NTO_OpenAudio(): Couldn't find any hardware audio formats"); |
432 return (-1); | 430 return (-1); |
433 } | 431 } |
434 | 432 |
435 spec->format = test_format; | 433 spec->format = test_format; |
436 | 434 |
437 /* Set the audio format */ | 435 /* Set the audio format */ |
438 cparams.format.format = format; | 436 cparams.format.format = format; |
439 | 437 |
440 /* Set mono or stereo audio (currently only two channels supported) */ | 438 /* Set mono or stereo audio (currently only two channels supported) */ |
441 cparams.format.voices = spec->channels; | 439 cparams.format.voices = spec->channels; |
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 { | 447 SDL_SetError |
450 SDL_SetError("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", snd_strerror(rval)); | 448 ("NTO_OpenAudio(): snd_pcm_channel_params failed: %s\n", |
449 snd_strerror(rval)); | |
451 return (-1); | 450 return (-1); |
452 } | 451 } |
453 | 452 |
454 /* Make sure channel is setup right one last time */ | 453 /* Make sure channel is setup right one last time */ |
455 SDL_memset(&csetup, 0x00, sizeof(csetup)); | 454 SDL_memset(&csetup, 0x00, sizeof(csetup)); |
456 csetup.channel = SND_PCM_CHANNEL_PLAYBACK; | 455 csetup.channel = SND_PCM_CHANNEL_PLAYBACK; |
457 if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) | 456 if (snd_pcm_plugin_setup(audio_handle, &csetup) < 0) { |
458 { | |
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 { | 468 pcm_len = |
471 pcm_len = csetup.buf.block.frag_size * spec->channels * (snd_pcm_format_width(format)/8); | 469 csetup.buf.block.frag_size * spec->channels * |
470 (snd_pcm_format_width(format) / 8); | |
472 } | 471 } |
473 | 472 |
474 /* 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 |
475 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) |
476 */ | 475 */ |
477 pcm_buf = (Uint8*)SDL_AllocAudioMem(pcm_len); | 476 pcm_buf = (Uint8 *) SDL_AllocAudioMem(pcm_len); |
478 if (pcm_buf == NULL) | 477 if (pcm_buf == NULL) { |
479 { | |
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 = snd_pcm_file_descriptor(audio_handle, SND_PCM_CHANNEL_PLAYBACK)) < 0) | 484 if ((audio_fd = |
487 { | 485 snd_pcm_file_descriptor(audio_handle, |
488 SDL_SetError("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", snd_strerror(rval)); | 486 SND_PCM_CHANNEL_PLAYBACK)) < 0) { |
487 SDL_SetError | |
488 ("NTO_OpenAudio(): snd_pcm_file_descriptor failed with error code: %s\n", | |
489 snd_strerror(rval)); | |
489 return (-1); | 490 return (-1); |
490 } | 491 } |
491 | 492 |
492 /* Trigger audio playback */ | 493 /* Trigger audio playback */ |
493 rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK); | 494 rval = snd_pcm_plugin_prepare(audio_handle, SND_PCM_CHANNEL_PLAYBACK); |
494 if (rval < 0) | 495 if (rval < 0) { |
495 { | 496 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", |
496 SDL_SetError("snd_pcm_plugin_prepare failed: %s\n", snd_strerror(rval)); | 497 snd_strerror(rval)); |
497 return (-1); | 498 return (-1); |
498 } | 499 } |
499 | 500 |
500 this->enabled = 1; | 501 this->enabled = 1; |
501 | 502 |
503 parent = getpid(); | 504 parent = getpid(); |
504 | 505 |
505 /* We're really ready to rock and roll. :-) */ | 506 /* We're really ready to rock and roll. :-) */ |
506 return (0); | 507 return (0); |
507 } | 508 } |
509 | |
510 /* vi: set ts=4 sw=4 expandtab: */ |