aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDaniel Willmann <d.willmann@samsung.com>2013-05-14 13:39:06 +0100
committerDaniel Willmann <d.willmann@samsung.com>2013-06-14 13:25:57 +0100
commitbb083ad3db58a57d8e14accdcb9bbec4c4b985ad (patch)
tree8d7aa9de0dc3f7cf96c9095faaa77f32a52b0940
parentecore_audio: Remove includes of optional modules from public .h file (diff)
downloadefl-bb083ad3db58a57d8e14accdcb9bbec4c4b985ad.tar.gz
ecore_audio: Add alsa support
Add alsa .c and .h file for Ecore_Audio alsa support This is not well tested and thus disabled by default Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
-rw-r--r--configure.ac16
-rw-r--r--src/Makefile_Ecore_Audio.am8
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_out_alsa.c252
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_out_alsa.h63
-rw-r--r--src/lib/ecore_audio/ecore_audio_private.h8
-rw-r--r--src/lib/edje/edje_multisense.c3
6 files changed, 340 insertions, 10 deletions
diff --git a/configure.ac b/configure.ac
index 35f400c2c1..0431e1ef8d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2398,8 +2398,19 @@ EFL_LIB_START_OPTIONAL([Ecore_Audio], [test "${want_audio}" = "yes"])
### Additional options to configure
-# ALSA support is still not there, thus no option for it yet.
-want_alsa="no"
+# ALSA support is not well tested, disable by default
+AC_ARG_ENABLE([alsa],
+ [AC_HELP_STRING([--enable-alsa],
+ [enable alsa sound support. @<:@default=enabled@:>@])],
+ [
+ if test "x${enableval}" = "xyes" ; then
+ want_alsa="yes"
+ else
+ want_alsa="no"
+ fi
+ ],
+ [want_alsa="no"])
+
# sndfile is mandatory otherwise it won't read from/write to files.
# TODO: if confirmed sndfile is mandatory, remove this variable
@@ -2457,6 +2468,7 @@ EFL_ADD_FEATURE([ECORE_AUDIO], [sndfile])
### Checks for library functions
EFL_LIB_END_OPTIONAL([Ecore_Audio])
+AM_CONDITIONAL([HAVE_ECORE_AUDIO_ALSA], [test "x${want_alsa}" = "xyes"])
AM_CONDITIONAL([HAVE_ECORE_AUDIO_PULSE], [test "x${want_pulseaudio}" = "xyes"])
AM_CONDITIONAL([HAVE_ECORE_AUDIO_SNDFILE], [test "x${want_sndfile}" = "xyes"])
diff --git a/src/Makefile_Ecore_Audio.am b/src/Makefile_Ecore_Audio.am
index 35a414cc52..62f2485410 100644
--- a/src/Makefile_Ecore_Audio.am
+++ b/src/Makefile_Ecore_Audio.am
@@ -27,6 +27,14 @@ lib_ecore_audio_libecore_audio_la_LIBADD = @ECORE_AUDIO_LIBS@
lib_ecore_audio_libecore_audio_la_DEPENDENCIES = @ECORE_AUDIO_INTERNAL_LIBS@
lib_ecore_audio_libecore_audio_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@
+if HAVE_ECORE_AUDIO_ALSA
+dist_installed_ecoreaudiomainheaders_DATA += \
+lib/ecore_audio/ecore_audio_obj_out_alsa.h
+
+lib_ecore_audio_libecore_audio_la_SOURCES += \
+lib/ecore_audio/ecore_audio_obj_out_alsa.c
+endif
+
if HAVE_ECORE_AUDIO_PULSE
dist_installed_ecoreaudiomainheaders_DATA += \
lib/ecore_audio/ecore_audio_obj_out_pulse.h
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_alsa.c b/src/lib/ecore_audio/ecore_audio_obj_out_alsa.c
new file mode 100644
index 0000000000..38a5fd9ef9
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_out_alsa.c
@@ -0,0 +1,252 @@
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#ifdef HAVE_FEATURES_H
+#include <features.h>
+#endif
+
+#include <Eo.h>
+#include "ecore_audio_private.h"
+#include "ecore_audio_obj_out_alsa.h"
+#include <alsa/asoundlib.h>
+
+#include <ctype.h>
+#include <errno.h>
+
+EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_ALSA_BASE_ID = EO_NOOP;
+
+#define MY_CLASS ECORE_AUDIO_OBJ_OUT_ALSA_CLASS
+#define MY_CLASS_NAME "ecore_audio_obj_out_alsa"
+
+
+struct _Ecore_Audio_Alsa
+{
+ char *foo;
+};
+
+typedef struct _Ecore_Audio_Alsa Ecore_Audio_Alsa;
+
+struct _Ecore_Audio_Alsa_Data
+{
+ snd_pcm_t *handle;
+ Ecore_Timer *timer;
+};
+
+typedef struct _Ecore_Audio_Alsa_Data Ecore_Audio_Alsa_Data;
+
+static void _volume_set(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
+{
+ Eo *in;
+ Ecore_Audio_Alsa_Data *alsa;
+ Eina_List *input;
+ Ecore_Audio_Output *out_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OBJ_OUT_CLASS);
+
+ double volume = va_arg(*list, double);
+
+ if (volume < 0)
+ volume = 0;
+
+ eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_volume_set(volume));
+
+ EINA_LIST_FOREACH(out_obj->inputs, input, in) {
+ eo_do(in, eo_base_data_get("alsa_data", (void **)&alsa));
+ /* FIXME: Volume control */
+ }
+
+}
+
+static Eina_Bool _write_cb(void *data)
+{
+ Eo *in = data;
+
+ Ecore_Audio_Alsa_Data *alsa;
+ void *buf;
+
+ size_t avail;
+ ssize_t bread;
+ int ret;
+
+ eo_do(in, eo_base_data_get("alsa_data", (void **)&alsa));
+
+ avail = snd_pcm_avail_update(alsa->handle);
+
+ buf = calloc(1, sizeof(float) * avail * 8);
+
+ eo_do(in, ecore_audio_obj_in_read(buf, avail*8, &bread));
+
+ ret = snd_pcm_writei(alsa->handle, buf, bread/8);
+ if (ret < 0)
+ {
+ ERR("Error when writing: %s", snd_strerror(ret));
+ snd_pcm_recover(alsa->handle, ret, 0);
+ }
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool _update_samplerate_cb(void *data EINA_UNUSED, Eo *eo_obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
+{
+ Ecore_Audio_Alsa_Data *alsa;
+ int samplerate, channels;
+ int ret;
+ double speed;
+
+ eo_do(eo_obj, ecore_audio_obj_in_samplerate_get(&samplerate));
+ eo_do(eo_obj, ecore_audio_obj_in_channels_get(&channels));
+ eo_do(eo_obj, ecore_audio_obj_in_speed_get(&speed));
+
+ samplerate *= speed;
+
+ eo_do(eo_obj, eo_base_data_get("alsa_data", (void **)&alsa));
+
+ ret = snd_pcm_set_params(alsa->handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, channels, samplerate, 1, 500000);
+
+ return EINA_TRUE;
+}
+
+static Eina_Bool _input_attach_internal(Eo *eo_obj, Eo *in)
+{
+ Ecore_Audio_Alsa_Data *alsa;
+ const char *name;
+ double speed;
+ unsigned int samplerate, channels;
+ int ret;
+ Eina_Bool success;
+
+ Ecore_Audio_Object *ea_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
+
+ eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_attach(in, &success));
+ if (!success)
+ return EINA_FALSE;
+
+ eo_do(in, ecore_audio_obj_in_samplerate_get((int *)&samplerate));
+ eo_do(in, ecore_audio_obj_in_speed_get(&speed));
+ eo_do(in, ecore_audio_obj_in_channels_get((int *)&channels));
+ eo_do(in, ecore_audio_obj_name_get(&name));
+
+ samplerate *= speed;
+
+ alsa = calloc(1, sizeof(Ecore_Audio_Alsa_Data));
+
+ ret = snd_pcm_open(&alsa->handle, "default", SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK);
+ if (ret < 0)
+ {
+ ERR("Could not open for playback: %s", snd_strerror(ret));
+ ERR("Could not create stream");
+ free(alsa);
+ eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_detach(in, NULL));
+ return EINA_FALSE;
+ }
+
+ ret = snd_pcm_set_params(alsa->handle, SND_PCM_FORMAT_FLOAT, SND_PCM_ACCESS_RW_INTERLEAVED, channels, samplerate, 1, 500000);
+ if (ret < 0)
+ {
+ free(alsa);
+ ERR("Could not set parameters: %s", snd_strerror(ret));
+ snd_pcm_close(alsa->handle);
+ return EINA_FALSE;
+ }
+
+ eo_do(in, eo_event_callback_add(ECORE_AUDIO_EV_IN_SAMPLERATE_CHANGED, _update_samplerate_cb, eo_obj));
+
+ eo_do(in, eo_base_data_set("alsa_data", alsa, free));
+
+ if (ea_obj->paused)
+ return EINA_TRUE;
+
+ alsa->timer = ecore_timer_add(0.3, _write_cb, in);
+
+ return EINA_TRUE;
+}
+
+static void _input_attach(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
+{
+ Eina_Bool retval = EINA_TRUE;
+
+ Eo *in = va_arg(*list, Eo *);
+ Eina_Bool *ret = va_arg(*list, Eina_Bool *);
+
+ retval = _input_attach_internal(eo_obj, in);
+ if (ret)
+ *ret = retval;
+}
+
+static void _input_detach(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
+{
+ Ecore_Audio_Alsa_Data *alsa;
+ Eina_Bool ret2;
+
+ Eo *in = va_arg(*list, Eo *);
+ Eina_Bool *ret = va_arg(*list, Eina_Bool *);
+
+ if (ret)
+ *ret = EINA_FALSE;
+
+ eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_detach(in, &ret2));
+ if (!ret2)
+ return;
+
+ eo_do(in, eo_base_data_get("alsa_data", (void **)&alsa));
+
+ ecore_timer_del(alsa->timer);
+
+ snd_pcm_close(alsa->handle);
+
+ eo_do(in, eo_base_data_del("alsa_data"));
+
+ if (ret)
+ *ret = EINA_TRUE;
+}
+
+static void _constructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+ Ecore_Audio_Output *out_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OBJ_OUT_CLASS);
+
+ eo_do_super(eo_obj, MY_CLASS, eo_constructor());
+
+ out_obj->need_writer = EINA_FALSE;
+}
+
+static void _destructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
+{
+ eo_do_super(eo_obj, MY_CLASS, eo_destructor());
+}
+
+static void _class_constructor(Eo_Class *klass)
+{
+ const Eo_Op_Func_Description func_desc[] = {
+ /* Virtual functions of parent class implemented in this class */
+ EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
+ EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
+
+ EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_VOLUME_SET), _volume_set),
+
+ EO_OP_FUNC(ECORE_AUDIO_OBJ_OUT_ID(ECORE_AUDIO_OBJ_OUT_SUB_ID_INPUT_ATTACH), _input_attach),
+ EO_OP_FUNC(ECORE_AUDIO_OBJ_OUT_ID(ECORE_AUDIO_OBJ_OUT_SUB_ID_INPUT_DETACH), _input_detach),
+ EO_OP_FUNC_SENTINEL
+ };
+
+ eo_class_funcs_set(klass, func_desc);
+}
+
+static const Eo_Op_Description op_desc[] = {
+ EO_OP_DESCRIPTION_SENTINEL
+};
+
+static const Eo_Class_Description class_desc = {
+ EO_VERSION,
+ MY_CLASS_NAME,
+ EO_CLASS_TYPE_REGULAR,
+ EO_CLASS_DESCRIPTION_OPS(&ECORE_AUDIO_OBJ_OUT_ALSA_BASE_ID, op_desc, ECORE_AUDIO_OBJ_OUT_ALSA_SUB_ID_LAST),
+ NULL,
+ sizeof(Ecore_Audio_Alsa),
+ _class_constructor,
+ NULL
+};
+
+EO_DEFINE_CLASS(ecore_audio_obj_out_alsa_class_get, &class_desc, ECORE_AUDIO_OBJ_OUT_CLASS, NULL);
diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_alsa.h b/src/lib/ecore_audio/ecore_audio_obj_out_alsa.h
new file mode 100644
index 0000000000..0dd6524e31
--- /dev/null
+++ b/src/lib/ecore_audio/ecore_audio_obj_out_alsa.h
@@ -0,0 +1,63 @@
+#ifndef ECORE_AUDIO_OUT_ALSA_H
+#define ECORE_AUDIO_OUT_ALSA_H
+
+#include <Eina.h>
+#include <Eo.h>
+
+#ifdef EAPI
+#undef EAPI
+#endif
+
+#ifdef __GNUC__
+#if __GNUC__ >= 4
+#define EAPI __attribute__ ((visibility("default")))
+#else
+#define EAPI
+#endif
+#else
+#define EAPI
+#endif
+
+/**
+ * @file ecore_audio_obj_out_alsa.h
+ * @brief Ecore_Audio alsa output
+ */
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * @defgroup ecore_audio_obj_out_alsa - Ecore_Audio alsa output
+ * @intogroup Ecore_Audio_Group
+ * @{
+ */
+
+#define ECORE_AUDIO_OBJ_OUT_ALSA_CLASS ecore_audio_obj_out_alsa_class_get() /**< Ecore_Audio alsa output */
+
+/**
+ * @brief Get the Eo class ID
+ *
+ * @return The Eo class ID
+ */
+const Eo_Class *ecore_audio_obj_out_alsa_class_get() EINA_CONST;
+
+extern EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_ALSA_BASE_ID;
+
+enum _Ecore_Audio_Obj_Out_Alsa_Sub_Ids
+{
+ ECORE_AUDIO_OBJ_OUT_ALSA_SUB_ID_LAST
+};
+
+#define ECORE_AUDIO_OBJ_OUT_ALSA_ID(sub_id) (ECORE_AUDIO_OBJ_OUT_ALSA_BASE_ID + EO_TYPECHECK(enum _Ecore_Audio_Obj_Out_Alsa_Sub_Ids, sub_id))
+
+/**
+ * @}
+ */
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/src/lib/ecore_audio/ecore_audio_private.h b/src/lib/ecore_audio/ecore_audio_private.h
index 35afa85f4c..a28ca7c374 100644
--- a/src/lib/ecore_audio/ecore_audio_private.h
+++ b/src/lib/ecore_audio/ecore_audio_private.h
@@ -146,14 +146,6 @@ 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 */
diff --git a/src/lib/edje/edje_multisense.c b/src/lib/edje/edje_multisense.c
index a6860c933c..8bcbbf83c6 100644
--- a/src/lib/edje/edje_multisense.c
+++ b/src/lib/edje/edje_multisense.c
@@ -9,6 +9,9 @@
#ifdef HAVE_PULSE
#include "ecore_audio_obj_out_pulse.h"
#define MY_CLASS ECORE_AUDIO_OBJ_OUT_PULSE_CLASS
+#elif HAVE_ALSA
+#include "ecore_audio_obj_out_alsa.h"
+#define MY_CLASS ECORE_AUDIO_OBJ_OUT_ALSA_CLASS
#else
#error "Multisense needs Pulseaudio suport!"
#endif