diff --git a/blackberry-qnx/alsa_qsa.c b/blackberry-qnx/alsa_qsa.c index b48f90c686..43fd9a0174 100644 --- a/blackberry-qnx/alsa_qsa.c +++ b/blackberry-qnx/alsa_qsa.c @@ -21,6 +21,9 @@ #define ALSA_PCM_NEW_SW_PARAMS_API #include +#define MAX_FRAG_SIZE 3072 +#define DEFAULT_RATE 48000 + typedef struct alsa { snd_pcm_t *pcm; @@ -29,14 +32,8 @@ typedef struct alsa bool has_float; bool can_pause; bool is_paused; - unsigned frame_bits; } alsa_t; -#define MAX_FRAG_SIZE 3072 -#define DEFAULT_RATE 48000 - -typedef long snd_pcm_sframes_t; - static void *alsa_qsa_init(const char *device, unsigned rate, unsigned latency) { (void)device; @@ -63,41 +60,28 @@ static void *alsa_qsa_init(const char *device, unsigned rate, unsigned latency) goto error; } - if ((err = snd_pcm_plugin_set_disable (alsa->pcm, PLUGIN_MMAP)) < 0) + if ((err = snd_pcm_plugin_set_disable (alsa->pcm, PLUGIN_DISABLE_MMAP)) < 0) { RARCH_ERR("[ALSA QSA]: Can't disable MMAP plugin: %s\n", snd_strerror(err)); goto error; } - if ((err = snd_pcm_plugin_set_enable (alsa->pcm, PLUGIN_ROUTING)) < 0) - { - RARCH_ERR("[ALSA QSA]: Can't enable routing: %s\n", snd_strerror(err)); - goto error; - } - memset(¶ms, 0, sizeof(params)); - - - params.mode = SND_PCM_MODE_BLOCK; params.channel = SND_PCM_CHANNEL_PLAYBACK; - params.start_mode = SND_PCM_START_FULL; + params.mode = SND_PCM_MODE_BLOCK; + + params.format.interleave = 1; + params.format.format = SND_PCM_SFMT_S16_LE; + params.format.rate = DEFAULT_RATE; + params.format.voices = 2; + + params.start_mode = SND_PCM_START_DATA; params.stop_mode = SND_PCM_STOP_STOP; params.buf.block.frag_size = MAX_FRAG_SIZE; params.buf.block.frags_min = 2; - params.buf.block.frags_max = 1; - params.format.interleave = 1; - params.format.rate = DEFAULT_RATE; - params.format.voices = 2; - - params.format.format = SND_PCM_SFMT_S16_LE; - alsa->frame_bits = 16 * 2; /* bits * channel */ - -#if 0 - /* TODO/FIXME - invalid argument? */ - snd_pcm_plugin_set_disable(alsa->pcm, PLUGIN_DISABLE_BUFFER_PARTIAL_BLOCKS); -#endif + params.buf.block.frags_max = 1; if ((err = snd_pcm_plugin_params(alsa->pcm, ¶ms)) < 0) { @@ -134,60 +118,41 @@ error: return (void*)-1; } -static inline snd_pcm_sframes_t snd_pcm_bytes_to_frames(alsa_t *alsa, ssize_t bytes) +static ssize_t alsa_qsa_write(void *data, const void *buf, size_t size) { - return bytes * 8 / alsa->frame_bits; -} - -static ssize_t alsa_qsa_write(void *data, const void *buf, size_t size_) -{ - int status; + int written, status; alsa_t *alsa = (alsa_t*)data; snd_pcm_channel_status_t cstatus = {0}; - snd_pcm_sframes_t written = 0; - snd_pcm_sframes_t size = snd_pcm_bytes_to_frames(alsa, size_); - bool eagain_retry = true; - while (size) + written = snd_pcm_plugin_write(alsa->pcm, buf, size); + + if (written != size) { - snd_pcm_sframes_t frames = snd_pcm_plugin_write(alsa->pcm, buf, size); + /* Check if samples playback got stuck somewhere in hardware or in */ + /* the audio device driver */ + if ((errno == EAGAIN) && (written == 0)) + return 0; - if (frames <= 0) + if ((errno == EINVAL) || (errno == EIO)) { - if (frames == -EAGAIN && !alsa->nonblock) // Definitely not supposed to happen. - { - RARCH_WARN("[ALSA]: poll() was signaled, but EAGAIN returned from write.\n" - "Your ALSA driver might be subtly broken.\n"); + cstatus.channel = SND_PCM_CHANNEL_PLAYBACK; + status = snd_pcm_plugin_status(alsa->pcm, &cstatus); - if (eagain_retry) - { - eagain_retry = false; - continue; - } - else - return written; - } - else if (frames == -EAGAIN) // Expected if we're running nonblock. + if (status > 0) + return 0; + + if ((cstatus.status == SND_PCM_STATUS_UNDERRUN) || + (cstatus.status == SND_PCM_STATUS_READY)) { - return written; + status = snd_pcm_plugin_prepare(alsa->pcm, SND_PCM_CHANNEL_PLAYBACK); + if (status < 0) + return 0; } - /* TODO/FIXME - implement check_pcm_status for checking against more errors? */ - else if (frames < 0) - { - RARCH_ERR("[ALSA]: Unknown error occured (%s).\n", snd_strerror(frames)); - return -1; - } - } - else - { - written += frames; - buf += (frames << 1) * (alsa->has_float ? sizeof(float) : sizeof(int16_t)); - size -= frames; } } - return written; -} + return written; + } static bool alsa_qsa_stop(void *data) { @@ -304,4 +269,3 @@ const audio_driver_t audio_alsa = { alsa_qsa_write_avail, alsa_qsa_buffer_size, }; -