Compare commits

...

6 Commits

Author SHA1 Message Date
Daniel Willmann 2eec30815d Alsa WIP work
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
2013-06-14 13:42:23 +01:00
Daniel Willmann 1c6aa0c865 ecore_audio: Support either pulseaudio or alsa in the examples and multisense
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
2013-06-14 13:32:39 +01:00
Daniel Willmann 3775167c3b ecore_audio: Correctly calculate pulse timers
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
2013-06-14 13:25:57 +01:00
Daniel Willmann d8bd4107c2 ecore_audio: Remove old structs that we don't need anymore
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
2013-06-14 13:25:57 +01:00
Daniel Willmann bb083ad3db 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>
2013-06-14 13:25:57 +01:00
Daniel Willmann 5d0daf9f3b ecore_audio: Remove includes of optional modules from public .h file
For now programs using pulse output need to include the respective .h
file themselves.

Make sure test, examples, multisense and pulse actually include the
needed headers

Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
2013-06-14 13:25:57 +01:00
13 changed files with 409 additions and 85 deletions

View File

@ -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"])

View File

@ -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

View File

@ -9,6 +9,7 @@
#include <fcntl.h>
#include <Ecore.h>
#include <Ecore_Audio.h>
#include <ecore_audio_obj_out_pulse.h>
#include <math.h>
Eo *in = NULL;

View File

@ -1,6 +1,8 @@
// Compile with:
// gcc -o ecore_audio_playback ecore_audio_playback.c `pkg-config --libs --cflags ecore eina ecore-audio`
#include <config.h>
#include <stdio.h>
#include <string.h>
#include <libgen.h>
@ -13,6 +15,17 @@
#include <Ecore_Audio.h>
#include <Eina.h>
#if 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
#warning "Need either pulse or alsa for output"
#define MY_CLASS ECORE_AUDIO_OBJ_OUT_CLASS
#endif
Eo *out = NULL;
double volume = 1;
Eina_List *inputs = NULL;
@ -307,7 +320,7 @@ main(int argc, const char *argv[])
printf("Start: %s (%0.2fs)\n", name, length);
out = eo_add(ECORE_AUDIO_OBJ_OUT_PULSE_CLASS, NULL);
out = eo_add(MY_CLASS, NULL);
eo_do(out, ecore_audio_obj_out_input_attach(in, &ret));
if (!ret)
printf("Could not attach input %s\n", name);

View File

@ -37,17 +37,6 @@ extern "C"
* @{
*/
/** @since 1.8
*/
enum _Ecore_Audio_Type {
ECORE_AUDIO_TYPE_PULSE, /**< Use Pulseaudio module */
ECORE_AUDIO_TYPE_ALSA, /**< Use ALSA module*/
ECORE_AUDIO_TYPE_SNDFILE, /**< Use libsndfile module */
ECORE_AUDIO_TYPE_TONE, /**< Use tone module */
ECORE_AUDIO_TYPE_CUSTOM, /**< Use custom module */
ECORE_AUDIO_MODULE_LAST, /**< Sentinel */
};
/**
* @since 1.8
*/
@ -72,15 +61,6 @@ enum _Ecore_Audio_Format {
typedef enum _Ecore_Audio_Format Ecore_Audio_Format;
/**< The format of the audio data */
/** @since 1.8
*/
typedef struct _Ecore_Audio_Module Ecore_Audio_Module;
/**< The audio module */
/** @since 1.8
*/
typedef struct _Ecore_Audio_Object Ecore_Audio_Object; /**< The audio object */
/*
* @since 1.8
*/
@ -210,8 +190,6 @@ EAPI int ecore_audio_shutdown(void);
#include <ecore_audio_obj_in_tone.h>
#include <ecore_audio_obj_out_pulse.h>
/**
* @}
*/

View File

@ -16,8 +16,6 @@
int _ecore_audio_log_dom = -1;
static int _ecore_audio_init_count = 0;
Eina_List *ecore_audio_modules;
/* externally accessible functions */
@ -44,8 +42,6 @@ ecore_audio_init(void)
}
DBG("Ecore_Audio init");
ecore_audio_modules = NULL;
eina_log_timing(_ecore_audio_log_dom,
EINA_LOG_STATE_STOP,
@ -67,8 +63,6 @@ ecore_audio_shutdown(void)
EINA_LOG_STATE_SHUTDOWN);
eina_list_free(ecore_audio_modules);
eina_log_domain_unregister(_ecore_audio_log_dom);
_ecore_audio_log_dom = -1;

View File

@ -0,0 +1,282 @@
#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_Idler *idler;
};
typedef struct _Ecore_Audio_Alsa_Data Ecore_Audio_Alsa_Data;
static Eina_Bool _close_cb(void *data)
{
snd_pcm_t *handle = data;
snd_pcm_close(handle);
return EINA_FALSE;
}
static void _delayed_close(snd_pcm_t *handle)
{
ecore_timer_add(2, _close_cb, handle);
}
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, channels;
eo_do(in, eo_base_data_get("alsa_data", (void **)&alsa));
eo_do(in, ecore_audio_obj_in_channels_get(&channels));
avail = snd_pcm_avail(alsa->handle);
if (avail < 1000)
return EINA_TRUE;
buf = calloc(1, sizeof(float) * avail * channels);
eo_do(in, ecore_audio_obj_in_read(buf, avail*channels, &bread));
ERR("ALSA: avail %i, read %i", avail, bread/channels);
if (bread == 0)
goto end;
ret = snd_pcm_writei(alsa->handle, buf, bread/channels);
if (ret < 0)
{
ERR("Error when writing: %s (avail %i, read %i)", snd_strerror(ret), avail, bread);
snd_pcm_recover(alsa->handle, ret, 0);
}
if (bread<avail*channels)
snd_pcm_start(alsa->handle);
ERR("Success: written %i", ret);
end:
free(buf);
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->idler = ecore_idler_add(_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_idler_del(alsa->idler);
_delayed_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);

View File

@ -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

View File

@ -12,6 +12,7 @@
#include <Eo.h>
#include "ecore_audio_private.h"
#include "ecore_audio_obj_out_pulse.h"
#include <pulse/pulseaudio.h>
#include <sys/time.h>

View File

@ -71,26 +71,10 @@ extern int _ecore_audio_log_dom;
* @{
*/
typedef struct _Ecore_Audio_Object Ecore_Audio_Object;
typedef struct _Ecore_Audio_Input Ecore_Audio_Input;
typedef struct _Ecore_Audio_Output Ecore_Audio_Output;
/**
* @brief The structure representing an Ecore_Audio module
*/
struct _Ecore_Audio_Module
{
ECORE_MAGIC;
Ecore_Audio_Type type;
char *name;
Eina_List *inputs;
Eina_List *outputs;
void *priv;
struct input_api *in_ops;
struct output_api *out_ops;
};
struct _Ecore_Audio_Vio_Internal {
Ecore_Audio_Vio *vio;
void *data;
@ -142,39 +126,6 @@ struct _Ecore_Audio_Input
Eina_Bool ended;
};
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
Ecore_Audio_Module *ecore_audio_pulse_init(void);
void ecore_audio_pulse_shutdown(void);
#endif /* HAVE_PULSE */
#ifdef HAVE_SNDFILE
/* ecore_audio_sndfile */
Ecore_Audio_Module *ecore_audio_sndfile_init(void);
void ecore_audio_sndfile_shutdown(void);
#endif /* HAVE_SNDFILE */
Ecore_Audio_Module *ecore_audio_tone_init(void);
void ecore_audio_tone_shutdown(void);
Ecore_Audio_Module *ecore_audio_custom_init(void);
void ecore_audio_custom_shutdown(void);
/**
* @}
*/

View File

@ -149,7 +149,7 @@ _ecore_pa_time_new(pa_mainloop_api *api, const struct timeval *tv, pa_time_event
return NULL;
}
interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000000.0;
event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);
return event;
@ -177,7 +177,7 @@ _ecore_pa_time_restart(pa_time_event *event, const struct timeval *tv)
return;
}
interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000000.0;
if (event->timer)
{
event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);

View File

@ -1,6 +1,21 @@
#include "edje_private.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef ENABLE_MULTISENSE
#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 or ALSA suport!"
#endif
#include <sndfile.h>
#include "Ecore_Audio.h"
@ -153,7 +168,7 @@ _edje_multisense_internal_sound_sample_play(Edje *ed, const char *sample_name, c
eo_event_callback_add(ECORE_AUDIO_EV_IN_STOPPED, _play_finished, NULL));
if (!out)
{
out = eo_add(ECORE_AUDIO_OBJ_OUT_PULSE_CLASS, NULL);
out = eo_add(MY_CLASS, NULL);
if (out) outs++;
}
if (!out)
@ -210,7 +225,7 @@ _edje_multisense_internal_sound_tone_play(Edje *ed, const char *tone_name, const
eo_do(in, eo_event_callback_add(ECORE_AUDIO_EV_IN_STOPPED, _play_finished, NULL));
if (!out)
out = eo_add(ECORE_AUDIO_OBJ_OUT_PULSE_CLASS, NULL);
out = eo_add(MY_CLASS, NULL);
eo_do(out, ecore_audio_obj_out_input_attach(in, &ret));
if (!ret) {

View File

@ -13,6 +13,12 @@
#include <Ecore.h>
#include <Ecore_Audio.h>
#ifdef HAVE_PULSE
#include <ecore_audio_obj_out_pulse.h>
#endif
#if 0