From eb15fa9e9c87bfe95062ed12be2fb383e0ee9e43 Mon Sep 17 00:00:00 2001 From: Daniel Willmann Date: Fri, 14 Dec 2012 23:38:21 +0000 Subject: [PATCH] ecore_audio: Add rudimentary ALSA support By rudimentary I mean I barely got it to work. For my particular test case. It will not work for you and needs lots of love until it can be used. Signed-off-by: Daniel Willmann SVN revision: 80999 --- src/lib/ecore_audio/ecore_audio.c | 8 + src/lib/ecore_audio/ecore_audio_alsa.c | 174 ++++++++++++++++++++++ src/lib/ecore_audio/ecore_audio_private.h | 18 +++ 3 files changed, 200 insertions(+) create mode 100644 src/lib/ecore_audio/ecore_audio_alsa.c diff --git a/src/lib/ecore_audio/ecore_audio.c b/src/lib/ecore_audio/ecore_audio.c index 6d53b65d5e..1a1e86376c 100644 --- a/src/lib/ecore_audio/ecore_audio.c +++ b/src/lib/ecore_audio/ecore_audio.c @@ -76,6 +76,11 @@ ecore_audio_init(void) ECORE_AUDIO_OUTPUT_INPUT_ADDED = ecore_event_type_new(); ECORE_AUDIO_OUTPUT_INPUT_REMOVED = ecore_event_type_new(); +#ifdef HAVE_ALSA + mod = ecore_audio_alsa_init(); + if (mod) + ecore_audio_modules = eina_list_append(ecore_audio_modules, mod); +#endif #ifdef HAVE_PULSE mod = ecore_audio_pulse_init(); if (mod) @@ -107,6 +112,9 @@ ecore_audio_shutdown(void) /* FIXME: Shutdown all the inputs and outputs first */ +#ifdef HAVE_ALSA + ecore_audio_alsa_shutdown(); +#endif #ifdef HAVE_PULSE ecore_audio_pulse_shutdown(); #endif diff --git a/src/lib/ecore_audio/ecore_audio_alsa.c b/src/lib/ecore_audio/ecore_audio_alsa.c new file mode 100644 index 0000000000..b0f48c6b5e --- /dev/null +++ b/src/lib/ecore_audio/ecore_audio_alsa.c @@ -0,0 +1,174 @@ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_ALSA + +#include +#include +#include + +#ifdef HAVE_FEATURES_H +#include +#endif +#include +#include + +#include + +#include "ecore_audio_private.h" + +static Ecore_Audio_Module *alsa_module = NULL; + +static Ecore_Audio_Object * +_alsa_output_new(Ecore_Audio_Object *output) +{ + int ret; + Ecore_Audio_Output *out = (Ecore_Audio_Output *)output; + struct _Ecore_Audio_Alsa *alsa; + + alsa = calloc(1, sizeof(struct _Ecore_Audio_Alsa)); + if (!alsa) + { + ERR("Could not allocate memory for private structure."); + free(out); + return NULL; + } + + out->module_data = alsa; + + ret = snd_pcm_open(&alsa->handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK); + if (ret < 0) + { + ERR("Could not open playback: %s", snd_strerror(ret)); + goto err; + } + + /* XXX: Make configurable */ + ret = snd_pcm_set_params(alsa->handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, 2, 44100, 1, 500000); + if (ret < 0) + { + ERR("Could not set parameters: %s", snd_strerror(ret)); + goto err; + } + + return output; + +err: + free(out->module_data); + return NULL; +} + +static void +_alsa_output_del(Ecore_Audio_Object *output) +{ + free(output->module_data); +} + +static Eina_Bool +_alsa_output_async_cb(Ecore_Audio_Object *output) +{ + unsigned char *data; + int size, ret; + snd_pcm_sframes_t avail; + Ecore_Audio_Output *out = output; + Ecore_Audio_Input *in = eina_list_data_get(out->inputs); + struct _Ecore_Audio_Alsa *alsa = (struct _Ecore_Audio_Alsa *)output->module_data; + + /* XXX: Error handling! */ + avail = snd_pcm_avail_update(alsa->handle); + ERR("Aval: %i", avail); + if (!avail) + return EINA_TRUE; + if (avail < 0) + goto recover; + + data = calloc(1, sizeof(float) * avail * 8); + + size = in->module->in_ops->input_read((Ecore_Audio_Object *)in, data, avail*8); + ERR("Read: %i", size); + + ret = snd_pcm_writei(alsa->handle, data, size/8); + ERR("Written: %i", ret); + if (ret < 0) { +recover: + ERR(snd_strerror(ret)); + snd_pcm_recover(alsa->handle, ret, 0); + } + + return EINA_TRUE; +} + +static void +_alsa_output_add_input(Ecore_Audio_Object *output, Ecore_Audio_Object *input) +{ + Ecore_Audio_Module *outmod = output->module; + Ecore_Audio_Module *inmod = input->module; + struct _Ecore_Audio_Alsa *alsa = (struct _Ecore_Audio_Alsa *)output->module_data; + + ecore_timer_add(0.3, _alsa_output_async_cb, output); +} + +static struct input_api inops = { +}; + +static struct output_api outops = { + .output_new = _alsa_output_new, + .output_del = _alsa_output_del, +// .output_volume_set = _alsa_output_volume_set, + .output_add_input = _alsa_output_add_input, +// .output_del_input = _alsa_output_del_input, +// .output_update_input_format = _alsa_output_update_input_format, +}; + +/* externally accessible functions */ + +/** + * @addtogroup Ecore_Audio_Group Ecore_Audio_alsa - Ecore internal ALSA audio functions + * + * @{ + */ + +/** + * @brief Initialize the Ecore_Audio ALSA module. + * + * @return the initialized module success, NULL on error. + * + */ +Ecore_Audio_Module * +ecore_audio_alsa_init(void) +{ + alsa_module = calloc(1, sizeof(Ecore_Audio_Module)); + if (!alsa_module) + { + ERR("Could not allocate memory for the module."); + return NULL; + } + + ECORE_MAGIC_SET(alsa_module, ECORE_MAGIC_AUDIO_MODULE); + alsa_module->type = ECORE_AUDIO_TYPE_ALSA; + alsa_module->name = "alsa"; + alsa_module->inputs = NULL; + alsa_module->outputs = NULL; + alsa_module->in_ops = &inops; + alsa_module->out_ops = &outops; + + return alsa_module; +} + +/** + * @brief Shut down the Ecore_Audio ALSA module + */ +void +ecore_audio_alsa_shutdown(void) +{ + free(alsa_module); + alsa_module = NULL; +} + +/** + * @} + */ + +#endif /* HAVE_ALSA */ diff --git a/src/lib/ecore_audio/ecore_audio_private.h b/src/lib/ecore_audio/ecore_audio_private.h index 8f24e07989..7f0ee5c511 100644 --- a/src/lib/ecore_audio/ecore_audio_private.h +++ b/src/lib/ecore_audio/ecore_audio_private.h @@ -9,6 +9,10 @@ #include #endif +#ifdef HAVE_ALSA +#include +#endif + #ifdef HAVE_PULSE #include #endif @@ -297,6 +301,20 @@ struct _Ecore_Audio_Callback { extern Eina_List *ecore_audio_modules; +#ifdef HAVE_ALSA +/* ecore_audio_alsa */ +struct _Ecore_Audio_Alsa +{ + ECORE_MAGIC; + snd_pcm_t *handle; + unsigned int channels; + unsigned int samplerate; +}; + +Ecore_Audio_Module *ecore_audio_alsa_init(void); +void ecore_audio_alsa_shutdown(void); +#endif /* HAVE_ALSA */ + #ifdef HAVE_PULSE /* PA mainloop integration */ struct _Ecore_Audio_Pa_Private