31 #include "../../SDL_internal.h" 33 #if SDL_AUDIO_DRIVER_QSA 39 #include <sys/types.h> 42 #include <sys/select.h> 43 #include <sys/neutrino.h> 44 #include <sys/asoundlib.h> 48 #include "../../core/unix/SDL_poll.h" 49 #include "../SDL_audio_c.h" 53 #define DEFAULT_CPARAMS_RATE 44100 54 #define DEFAULT_CPARAMS_VOICES 1 56 #define DEFAULT_CPARAMS_FRAG_SIZE 4096 57 #define DEFAULT_CPARAMS_FRAGS_MIN 1 58 #define DEFAULT_CPARAMS_FRAGS_MAX 1 61 #define QSA_MAX_DEVICES 32 62 #define QSA_MAX_NAME_LENGTH 81+16 64 typedef struct _QSA_Device
66 char name[QSA_MAX_NAME_LENGTH];
71 QSA_Device qsa_playback_device[QSA_MAX_DEVICES];
74 QSA_Device qsa_capture_device[QSA_MAX_DEVICES];
78 QSA_SetError(
const char *fn,
int status)
80 return SDL_SetError(
"QSA: %s() failed: %s", fn, snd_strerror(status));
88 struct sched_param
param;
89 if (SchedGet(0, 0, &
param) != -1) {
90 param.sched_priority =
param.sched_curpriority + 15;
91 SchedSet(0, 0, SCHED_NOCHANGE, &
param);
97 QSA_InitAudioParams(snd_pcm_channel_params_t * cpars)
100 cpars->channel = SND_PCM_CHANNEL_PLAYBACK;
101 cpars->mode = SND_PCM_MODE_BLOCK;
102 cpars->start_mode = SND_PCM_START_DATA;
103 cpars->stop_mode = SND_PCM_STOP_STOP;
104 cpars->format.format = SND_PCM_SFMT_S16_LE;
105 cpars->format.interleave = 1;
106 cpars->format.rate = DEFAULT_CPARAMS_RATE;
107 cpars->format.voices = DEFAULT_CPARAMS_VOICES;
108 cpars->buf.block.frag_size = DEFAULT_CPARAMS_FRAG_SIZE;
109 cpars->buf.block.frags_min = DEFAULT_CPARAMS_FRAGS_MIN;
110 cpars->buf.block.frags_max = DEFAULT_CPARAMS_FRAGS_MAX;
115 QSA_WaitDevice(
_THIS)
123 result =
SDL_IOReady(this->hidden->audio_fd, !this->hidden->iscapture, 2 * 1000);
126 SDL_SetError(
"QSA: SDL_IOReady() failed: %s", strerror(errno));
130 this->hidden->timeout_on_wait = 1;
133 this->hidden->timeout_on_wait = 0;
139 QSA_PlayDevice(
_THIS)
141 snd_pcm_channel_status_t cstatus;
152 pcmbuffer = this->hidden->pcm_buf;
157 snd_pcm_plugin_write(this->hidden->audio_handle, pcmbuffer,
159 if (written != towrite) {
162 if ((errno == EAGAIN) && (written == 0)) {
163 if (this->hidden->timeout_on_wait != 0) {
170 if ((errno == EAGAIN) || (errno == EWOULDBLOCK)) {
179 if ((errno == EINVAL) || (errno == EIO)) {
181 if (!this->hidden->iscapture) {
182 cstatus.channel = SND_PCM_CHANNEL_PLAYBACK;
184 cstatus.channel = SND_PCM_CHANNEL_CAPTURE;
188 snd_pcm_plugin_status(this->hidden->audio_handle,
191 QSA_SetError(
"snd_pcm_plugin_status", status);
195 if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) ||
196 (cstatus.status == SND_PCM_STATUS_READY)) {
197 if (!this->hidden->iscapture) {
199 snd_pcm_plugin_prepare(this->hidden->
201 SND_PCM_CHANNEL_PLAYBACK);
204 snd_pcm_plugin_prepare(this->hidden->
206 SND_PCM_CHANNEL_CAPTURE);
209 QSA_SetError(
"snd_pcm_plugin_prepare", status);
232 QSA_GetDeviceBuf(
_THIS)
234 return this->hidden->pcm_buf;
238 QSA_CloseDevice(
_THIS)
240 if (this->hidden->audio_handle !=
NULL) {
241 if (!this->hidden->iscapture) {
243 snd_pcm_plugin_flush(this->hidden->audio_handle,
244 SND_PCM_CHANNEL_PLAYBACK);
247 snd_pcm_plugin_flush(this->hidden->audio_handle,
248 SND_PCM_CHANNEL_CAPTURE);
250 snd_pcm_close(this->hidden->audio_handle);
258 QSA_OpenDevice(
_THIS,
void *
handle,
const char *devname,
int iscapture)
260 const QSA_Device *
device = (
const QSA_Device *) handle;
265 snd_pcm_channel_setup_t csetup;
266 snd_pcm_channel_params_t cparams;
274 if (this->hidden ==
NULL) {
279 QSA_InitAudioParams(&cparams);
284 if (device !=
NULL) {
286 this->hidden->deviceno = device->deviceno;
287 this->hidden->cardno = device->cardno;
288 status = snd_pcm_open(&this->hidden->audio_handle,
289 device->cardno, device->deviceno,
290 iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
293 status = snd_pcm_open_preferred(&this->hidden->audio_handle,
294 &this->hidden->cardno,
295 &this->hidden->deviceno,
296 iscapture ? SND_PCM_OPEN_CAPTURE : SND_PCM_OPEN_PLAYBACK);
301 this->hidden->audio_handle =
NULL;
302 return QSA_SetError(
"snd_pcm_open", status);
312 switch (test_format) {
315 format = SND_PCM_SFMT_U8;
321 format = SND_PCM_SFMT_S8;
327 format = SND_PCM_SFMT_S16_LE;
333 format = SND_PCM_SFMT_S16_BE;
339 format = SND_PCM_SFMT_U16_LE;
345 format = SND_PCM_SFMT_U16_BE;
351 format = SND_PCM_SFMT_S32_LE;
357 format = SND_PCM_SFMT_S32_BE;
363 format = SND_PCM_SFMT_FLOAT_LE;
369 format = SND_PCM_SFMT_FLOAT_BE;
385 if (test_format == 0) {
386 return SDL_SetError(
"QSA: Couldn't find any hardware audio formats");
392 cparams.format.format =
format;
398 cparams.format.rate = this->
spec.
freq;
401 status = snd_pcm_plugin_params(this->hidden->audio_handle, &cparams);
403 return QSA_SetError(
"snd_pcm_plugin_params", status);
408 if (!this->hidden->iscapture) {
409 csetup.channel = SND_PCM_CHANNEL_PLAYBACK;
411 csetup.channel = SND_PCM_CHANNEL_CAPTURE;
415 if (snd_pcm_plugin_setup(this->hidden->audio_handle, &csetup) < 0) {
422 this->hidden->pcm_len = this->
spec.
size;
424 if (this->hidden->pcm_len == 0) {
425 this->hidden->pcm_len =
427 (snd_pcm_format_width(format) / 8);
435 this->hidden->pcm_buf =
437 if (this->hidden->pcm_buf ==
NULL) {
440 SDL_memset(this->hidden->pcm_buf, this->spec.silence,
441 this->hidden->pcm_len);
444 if (!this->hidden->iscapture) {
445 this->hidden->audio_fd =
446 snd_pcm_file_descriptor(this->hidden->audio_handle,
447 SND_PCM_CHANNEL_PLAYBACK);
449 this->hidden->audio_fd =
450 snd_pcm_file_descriptor(this->hidden->audio_handle,
451 SND_PCM_CHANNEL_CAPTURE);
454 if (this->hidden->audio_fd < 0) {
455 return QSA_SetError(
"snd_pcm_file_descriptor", status);
459 if (!this->hidden->iscapture) {
462 snd_pcm_plugin_prepare(this->hidden->audio_handle,
463 SND_PCM_CHANNEL_PLAYBACK);
467 snd_pcm_plugin_prepare(this->hidden->audio_handle,
468 SND_PCM_CHANNEL_CAPTURE);
472 return QSA_SetError(
"snd_pcm_plugin_prepare", status);
480 QSA_DetectDevices(
void)
502 for (it = 0; it < cards; it++) {
506 snd_card_get_longname(it,
508 [qsa_playback_devices].
name,
509 QSA_MAX_NAME_LENGTH);
514 sprintf(qsa_playback_device[qsa_playback_devices].
name +
516 [qsa_playback_devices].
name),
" d%d",
520 qsa_playback_device[qsa_playback_devices].cardno = it;
524 snd_pcm_open(&handle, it, devices,
525 SND_PCM_OPEN_PLAYBACK);
527 qsa_playback_device[qsa_playback_devices].deviceno =
529 status = snd_pcm_close(handle);
532 qsa_playback_devices++;
536 if (status == -ENOENT) {
545 if (qsa_playback_devices >= QSA_MAX_DEVICES) {
552 if (qsa_playback_devices >= QSA_MAX_DEVICES) {
560 for (it = 0; it < cards; it++) {
564 snd_card_get_longname(it,
566 [qsa_capture_devices].
name,
567 QSA_MAX_NAME_LENGTH);
572 sprintf(qsa_capture_device[qsa_capture_devices].
name +
574 [qsa_capture_devices].
name),
" d%d",
578 qsa_capture_device[qsa_capture_devices].cardno = it;
582 snd_pcm_open(&handle, it, devices,
583 SND_PCM_OPEN_CAPTURE);
585 qsa_capture_device[qsa_capture_devices].deviceno =
587 status = snd_pcm_close(handle);
590 qsa_capture_devices++;
594 if (status == -ENOENT) {
600 if (qsa_capture_devices >= QSA_MAX_DEVICES) {
610 if (qsa_capture_devices >= QSA_MAX_DEVICES) {
618 QSA_Deinitialize(
void)
624 qsa_playback_devices = 0;
625 qsa_capture_devices = 0;
634 qsa_playback_devices = 0;
635 qsa_capture_devices = 0;
661 "qsa",
"QNX QSA Audio", QSA_Init, 0
SDL_AudioFormat SDL_FirstAudioFormat(SDL_AudioFormat format)
int SDL_IOReady(int fd, SDL_bool forWrite, int timeoutMS)
void(* DetectDevices)(void)
int ProvidesOwnCallbackThread
void(* PlayDevice)(_THIS)
void(* WaitDevice)(_THIS)
void SDL_OpenedAudioDeviceDisconnected(SDL_AudioDevice *device)
Uint16 SDL_AudioFormat
Audio format flags.
void(* UnlockDevice)(_THIS)
int OnlyHasDefaultCaptureDevice
SDL_AudioFormat SDL_NextAudioFormat(void)
GLuint const GLchar * name
GLint GLint GLsizei GLsizei GLsizei GLint GLenum format
static SDL_AudioDeviceID device
void(* ThreadInit)(_THIS)
int OnlyHasDefaultOutputDevice
EGLImageKHR EGLint EGLint * handle
AudioBootStrap QSAAUDIO_bootstrap
void(* Deinitialize)(void)
void SDL_CalculateAudioSpec(SDL_AudioSpec *spec)
void(* LockDevice)(_THIS)
GLenum GLenum GLsizei const GLuint GLboolean enabled
int(* OpenDevice)(_THIS, void *handle, const char *devname, int iscapture)
#define SDL_OutOfMemory()
void(* CloseDevice)(_THIS)
Uint8 *(* GetDeviceBuf)(_THIS)
void SDL_AddAudioDevice(const int iscapture, const char *name, void *handle)