From 308e64094b1048cc87a0fc90dc08d739a1de7a53 Mon Sep 17 00:00:00 2001 From: twinaphex Date: Fri, 21 Jun 2013 18:56:39 +0200 Subject: [PATCH] (ALSA QSA) Add preliminary ALSA QSA driver based on CatalystG's audio driver for PCSX ReARMed - still broken - exits at 'Error: Channel Parameter Error - no such process' --- blackberry-qnx/alsa_qsa.c | 182 ++++++++++++++++++++++++++++++++++++++ driver.c | 2 + driver.h | 2 + griffin/griffin.c | 4 + 4 files changed, 190 insertions(+) create mode 100644 blackberry-qnx/alsa_qsa.c diff --git a/blackberry-qnx/alsa_qsa.c b/blackberry-qnx/alsa_qsa.c new file mode 100644 index 0000000000..2d53502cf7 --- /dev/null +++ b/blackberry-qnx/alsa_qsa.c @@ -0,0 +1,182 @@ +/* RetroArch - A frontend for libretro. + * Copyright (C) 2010-2013 - Hans-Kristian Arntzen + * + * RetroArch is free software: you can redistribute it and/or modify it under the terms + * of the GNU General Public License as published by the Free Software Found- + * ation, either version 3 of the License, or (at your option) any later version. + * + * RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR + * PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with RetroArch. + * If not, see . + */ + +#include "../general.h" +#include "../driver.h" + +#define ALSA_PCM_NEW_HW_PARAMS_API +#define ALSA_PCM_NEW_SW_PARAMS_API +#include + +typedef struct alsa +{ + snd_pcm_t *pcm; + size_t buffer_size; + snd_pcm_channel_status_t status; + bool nonblock; + bool has_float; + bool can_pause; + bool is_paused; +} alsa_t; + +static void *alsa_qsa_init(const char *device, unsigned rate, unsigned latency) +{ + (void)device; + (void)rate; + (void)latency; + + int err, card, dev; + snd_pcm_channel_params_t params; + snd_pcm_channel_setup_t setup; + + alsa_t *alsa = (alsa_t*)calloc(1, sizeof(alsa_t)); + if (!alsa) + return NULL; + + if ((err = snd_pcm_open_preferred(&alsa->pcm, &card, &dev, + SND_PCM_OPEN_PLAYBACK)) < 0) + { + RARCH_ERR("Audio open error: %s\n", snd_strerror(err)); + goto error; + } + + if((err = snd_pcm_nonblock_mode(alsa->pcm, 1)) < 0) + { + RARCH_ERR("Can't set blocking mode: %s\n", snd_strerror(err)); + goto error; + } + + if ((err = snd_pcm_plugin_set_disable (alsa->pcm, PLUGIN_DISABLE_MMAP)) < 0) + { + RARCH_ERR("Can't disable MMAP plugin: %s\n", snd_strerror(err)); + goto error; + } + + params.channel = SND_PCM_CHANNEL_PLAYBACK; + params.mode = SND_PCM_MODE_BLOCK; + + params.format.interleave = 1; + params.format.format = SND_PCM_SFMT_S16_LE; + params.format.rate = rate; + params.format.voices = 2; + + params.start_mode = SND_PCM_START_DATA; + params.stop_mode = SND_PCM_STOP_STOP; + + params.buf.block.frag_size = 4096; + params.buf.block.frags_min = 1; + params.buf.block.frags_max = 19; + + if ((err = snd_pcm_plugin_params(alsa->pcm, ¶ms)) < 0) + { + RARCH_ERR("Channel Parameter Error: %s\n", snd_strerror(err)); + goto error; + } + + setup.channel = SND_PCM_CHANNEL_PLAYBACK; + + if ((err = snd_pcm_plugin_setup(alsa->pcm, &setup)) < 0) + { + RARCH_ERR("Channel Parameter Read Back Error: %s\n", snd_strerror(err)); + goto error; + } + + alsa->buffer_size = setup.buf.block.frag_size * 19; + RARCH_LOG("ALSA buffer size: %d\n", alsa->buffer_size); + + if ((err = snd_pcm_plugin_prepare(alsa->pcm, SND_PCM_CHANNEL_PLAYBACK)) < 0) + { + RARCH_ERR("Channel Prepare Error: %s\n", snd_strerror(err)); + goto error; + } + + alsa->has_float = false; + + return alsa; + +error: + return (void*)-1; +} + +static void alsa_qsa_free(void *data) +{ + alsa_t *alsa = (alsa_t*)data; + + if (alsa->pcm != NULL) + { + snd_pcm_close(alsa->pcm); + alsa->pcm = NULL; + } +} + +static ssize_t alsa_qsa_write(void *data, const void *buf, size_t size) +{ + alsa_t *alsa = (alsa_t*)data; + + int err = snd_pcm_plugin_write(alsa->pcm, buf, size); + + return size; +} + +static bool alsa_qsa_stop(void *data) +{ + alsa_t *alsa = (alsa_t*)data; + + if (alsa->can_pause && !alsa->is_paused) + { + /* TODO */ + return false; + } + else return true; +} + +static bool alsa_qsa_start(void *data) +{ + (void)data; + return true; +} + +static void alsa_qsa_set_nonblock_state(void *data, bool state) +{ + alsa_t *alsa = (alsa_t*)data; + + int err; + + if((err = snd_pcm_nonblock_mode(alsa->pcm, state)) < 0) + { + RARCH_ERR("Can't set blocking mode to %d: %s\n", state, + snd_strerror(err)); + return; + } + + alsa->nonblock = state; +} + +static bool alsa_qsa_use_float(void *data) +{ + alsa_t *alsa = (alsa_t*)data; + return alsa->has_float; +} + +const audio_driver_t audio_alsa = { + alsa_qsa_init, + alsa_qsa_write, + alsa_qsa_stop, + alsa_qsa_start, + alsa_qsa_set_nonblock_state, + alsa_qsa_free, + alsa_qsa_use_float, + "alsa", +}; diff --git a/driver.c b/driver.c index 3ede83fd0b..1df27f5d99 100644 --- a/driver.c +++ b/driver.c @@ -37,8 +37,10 @@ static const audio_driver_t *audio_drivers[] = { #ifdef HAVE_ALSA &audio_alsa, +#ifndef __QNX__ &audio_alsathread, #endif +#endif #if defined(HAVE_OSS) || defined(HAVE_OSS_BSD) &audio_oss, #endif diff --git a/driver.h b/driver.h index 59c87b0957..88176ff817 100644 --- a/driver.h +++ b/driver.h @@ -488,7 +488,9 @@ extern driver_t driver; extern const audio_driver_t audio_rsound; extern const audio_driver_t audio_oss; extern const audio_driver_t audio_alsa; +#ifndef __QNX__ extern const audio_driver_t audio_alsathread; +#endif extern const audio_driver_t audio_roar; extern const audio_driver_t audio_openal; extern const audio_driver_t audio_opensl; diff --git a/griffin/griffin.c b/griffin/griffin.c index 1a4c34cedf..d420276399 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -328,9 +328,13 @@ AUDIO #endif #ifdef HAVE_ALSA +#ifdef __QNX__ +#include "../blackberry-qnx/alsa_qsa.c" +#else #include "../audio/alsa.c" #include "../audio/alsathread.c" #endif +#endif #ifdef HAVE_AL #include "../audio/openal.c"