ecore_audio: Add rudimentary ALSA support
authorDaniel Willmann <d.willmann@samsung.com>
Fri, 14 Dec 2012 23:38:21 +0000 (23:38 +0000)
committerDaniel Willmann <daniel@totalueberwachung.de>
Fri, 14 Dec 2012 23:38:21 +0000 (23:38 +0000)
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 <d.willmann@samsung.com>
SVN revision: 80999

src/lib/ecore_audio/ecore_audio.c
src/lib/ecore_audio/ecore_audio_alsa.c [new file with mode: 0644]
src/lib/ecore_audio/ecore_audio_private.h

index 6d53b65..1a1e863 100644 (file)
@@ -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 (file)
index 0000000..b0f48c6
--- /dev/null
@@ -0,0 +1,174 @@
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#ifdef HAVE_ALSA
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_FEATURES_H
+#include <features.h>
+#endif
+#include <ctype.h>
+#include <errno.h>
+
+#include <alsa/asoundlib.h>
+
+#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 */
index 8f24e07..7f0ee5c 100644 (file)
@@ -9,6 +9,10 @@
 #include <config.h>
 #endif
 
+#ifdef HAVE_ALSA
+#include <alsa/asoundlib.h>
+#endif
+
 #ifdef HAVE_PULSE
 #include <pulse/pulseaudio.h>
 #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