ecore_audio - save 232k of real RAM by dlopening depednecies

so libpuls and libsndfile suck in dependencies. they suck in so much
that by the time linking is done we've written to about 230kb of
PRIVATE MEMORY as dirty pages in symbol tablesm global veriables etc.
etc. - this is just horrible. especially if an app never makes any
sound... it's just wasted memory. this stuff is invisible to normal
memory debug tools. so this begins to address things. please see
T4227. my numbers now put me at:

1780Kb total dirty writable mapped from library file pages. down from
2012Kb.

This fixes some memory bloat reported in the above ticket, but there
is more to fix for sure.

@fix
This commit is contained in:
Carsten Haitzler 2016-08-01 14:37:10 +09:00
parent e077e92372
commit d27f5fcab7
7 changed files with 308 additions and 45 deletions

View File

@ -3932,9 +3932,22 @@ EFL_INTERNAL_DEPEND_PKG([ECORE_AUDIO], [emile])
EFL_ADD_LIBS([ECORE_AUDIO], [-lm])
EFL_OPTIONAL_DEPEND_PKG([ECORE_AUDIO], [${want_alsa}], [ALSA], [alsa])
EFL_OPTIONAL_DEPEND_PKG([ECORE_AUDIO], [${want_pulseaudio}], [PULSE], [libpulse])
EFL_OPTIONAL_DEPEND_PKG([ECORE_AUDIO], [${want_sndfile}], [SNDFILE], [sndfile])
if test "x${want_alsa}" = "xyes" ; then
PKG_CHECK_MODULES([ECORE_AUDIO_ALSA], [alsa])
AC_DEFINE([HAVE_ALSA], [1], [Alsa support])
fi
if test "x${want_pulseaudio}" = "xyes" ; then
PKG_CHECK_MODULES([ECORE_AUDIO_PULSE], [libpulse])
AC_DEFINE([HAVE_PULSE], [1], [Pulseaudio support])
fi
if test "x${want_sndfile}" = "xyes" ; then
PKG_CHECK_MODULES([ECORE_AUDIO_SNDFILE], [sndfile])
AC_DEFINE([HAVE_SNDFILE], [1], [Sndfile support])
fi
dnl EFL_OPTIONAL_DEPEND_PKG([ECORE_AUDIO_ALSA], [${want_alsa}], [ALSA], [alsa])
dnl EFL_OPTIONAL_DEPEND_PKG([ECORE_AUDIO_PULSE], [${want_pulseaudio}], [PULSE], [libpulse])
dnl EFL_OPTIONAL_DEPEND_PKG([ECORE_AUDIO_SNDFILE], [${want_sndfile}], [SNDFILE], [sndfile])
EFL_EVAL_PKGS([ECORE_AUDIO])

View File

@ -53,8 +53,8 @@ lib/ecore_audio/ecore_audio_obj_out.c \
lib/ecore_audio/ecore_audio_obj_in_tone.c \
lib/ecore_audio/ecore_audio_private.h
lib_ecore_audio_libecore_audio_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_AUDIO_CFLAGS@
lib_ecore_audio_libecore_audio_la_LIBADD = @ECORE_AUDIO_LIBS@
lib_ecore_audio_libecore_audio_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @ECORE_AUDIO_CFLAGS@ @ECORE_AUDIO_ALSA_CFLAGS@ @ECORE_AUDIO_PULSE_CFLAGS@ @ECORE_AUDIO_SNDFILE_CFLAGS@
lib_ecore_audio_libecore_audio_la_LIBADD = @ECORE_AUDIO_LIBS@ @ECORE_AUDIO_ALSA_LIBS@
lib_ecore_audio_libecore_audio_la_DEPENDENCIES = @ECORE_AUDIO_INTERNAL_LIBS@
lib_ecore_audio_libecore_audio_la_LDFLAGS = @EFL_LTLIBRARY_FLAGS@

View File

@ -18,6 +18,12 @@ int _ecore_audio_log_dom = -1;
static int _ecore_audio_init_count = 0;
Eina_List *ecore_audio_modules;
#ifdef HAVE_PULSE
Ecore_Audio_Lib_Pulse *ecore_audio_pulse_lib = NULL;
#endif /* HAVE_PULSE */
#ifdef HAVE_SNDFILE
Ecore_Audio_Lib_Sndfile *ecore_audio_sndfile_lib = NULL;
#endif /* HAVE_SNDFILE */
/* externally accessible functions */
@ -61,6 +67,13 @@ ecore_audio_shutdown(void)
if (--_ecore_audio_init_count != 0)
return _ecore_audio_init_count;
#ifdef HAVE_SNDFILE
ecore_audio_sndfile_lib_unload();
#endif /* HAVE_SNDFILE */
#ifdef HAVE_PULSE
ecore_audio_pulse_lib_unload();
#endif /* HAVE_PULSE */
/* FIXME: Shutdown all the inputs and outputs first */
eina_log_timing(_ecore_audio_log_dom,
EINA_LOG_STATE_START,
@ -78,6 +91,168 @@ ecore_audio_shutdown(void)
return _ecore_audio_init_count;
}
#ifdef HAVE_PULSE
Eina_Bool
ecore_audio_pulse_lib_load(void)
{
if (ecore_audio_pulse_lib)
{
if (!ecore_audio_pulse_lib->mod)
{
ERR("Cannot find libpulse!");
return EINA_FALSE;
}
return EINA_TRUE;
}
ecore_audio_pulse_lib = calloc(1, sizeof(Ecore_Audio_Lib_Pulse));
if (!ecore_audio_pulse_lib) return EINA_FALSE;
# define LOAD(x) \
if (!ecore_audio_pulse_lib->mod) { \
if ((ecore_audio_pulse_lib->mod = eina_module_new(x))) { \
if (!eina_module_load(ecore_audio_pulse_lib->mod)) { \
eina_module_free(ecore_audio_pulse_lib->mod); \
ecore_audio_pulse_lib->mod = NULL; \
} \
} \
}
# if defined(_WIN32) || defined(__CYGWIN__)
LOAD("libpulse-0.dll");
LOAD("libpulse.dll");
LOAD("pulse.dll");
# elif defined(__APPLE__) && defined(__MACH__)
LOAD("libpulse.0.dylib");
LOAD("libpulse.0.so");
LOAD("libpulse.so.0");
# else
LOAD("libpulse.so.0");
# endif
# undef LOAD
if (!ecore_audio_pulse_lib->mod) return EINA_FALSE;
#define SYM(x) \
if (!(ecore_audio_pulse_lib->x = eina_module_symbol_get(ecore_audio_pulse_lib->mod, #x))) { \
ERR("libpulse - cannot find %s", #x); \
goto err; \
}
SYM(pa_context_new);
SYM(pa_context_connect);
SYM(pa_context_set_sink_input_volume);
SYM(pa_context_get_state);
SYM(pa_context_set_state_callback);
SYM(pa_operation_unref);
SYM(pa_cvolume_set);
SYM(pa_stream_new);
SYM(pa_stream_unref);
SYM(pa_stream_connect_playback);
SYM(pa_stream_disconnect);
SYM(pa_stream_drain);
SYM(pa_stream_cork);
SYM(pa_stream_write);
SYM(pa_stream_begin_write);
SYM(pa_stream_set_write_callback);
SYM(pa_stream_trigger);
SYM(pa_stream_update_sample_rate);
SYM(pa_stream_get_index);
#undef SYM
return EINA_TRUE;
err:
if (ecore_audio_pulse_lib->mod)
{
eina_module_free(ecore_audio_pulse_lib->mod);
ecore_audio_pulse_lib->mod = NULL;
}
return EINA_FALSE;
}
void
ecore_audio_pulse_lib_unload(void)
{
if (ecore_audio_pulse_lib)
{
if (ecore_audio_pulse_lib->mod)
eina_module_free(ecore_audio_pulse_lib->mod);
free(ecore_audio_pulse_lib);
ecore_audio_pulse_lib = NULL;
}
}
#endif /* HAVE_PULSE */
#ifdef HAVE_SNDFILE
Eina_Bool
ecore_audio_sndfile_lib_load(void)
{
if (ecore_audio_sndfile_lib)
{
if (!ecore_audio_sndfile_lib->mod)
{
ERR("Cannot find libsndfile!");
return EINA_FALSE;
}
return EINA_TRUE;
}
ecore_audio_sndfile_lib = calloc(1, sizeof(Ecore_Audio_Lib_Sndfile));
if (!ecore_audio_sndfile_lib) return EINA_FALSE;
# define LOAD(x) \
if (!ecore_audio_sndfile_lib->mod) { \
if ((ecore_audio_sndfile_lib->mod = eina_module_new(x))) { \
if (!eina_module_load(ecore_audio_sndfile_lib->mod)) { \
eina_module_free(ecore_audio_sndfile_lib->mod); \
ecore_audio_sndfile_lib->mod = NULL; \
} \
} \
}
# if defined(_WIN32) || defined(__CYGWIN__)
LOAD("libsndfile-1.dll");
LOAD("libsndfile.dll");
LOAD("sndfile.dll");
# elif defined(__APPLE__) && defined(__MACH__)
LOAD("libsndfile.1.dylib");
LOAD("libsndfile.1.so");
LOAD("libsndfile.so.1");
# else
LOAD("libsndfile.so.1");
# endif
# undef LOAD
if (!ecore_audio_sndfile_lib->mod) return EINA_FALSE;
#define SYM(x) \
if (!(ecore_audio_sndfile_lib->x = eina_module_symbol_get(ecore_audio_sndfile_lib->mod, #x))) { \
ERR("libsndfile - cannot find %s", #x); \
goto err; \
}
SYM(sf_open);
SYM(sf_open_virtual);
SYM(sf_close);
SYM(sf_read_float);
SYM(sf_write_float);
SYM(sf_write_sync);
SYM(sf_seek);
SYM(sf_strerror);
#undef SYM
return EINA_TRUE;
err:
if (ecore_audio_sndfile_lib->mod)
{
eina_module_free(ecore_audio_sndfile_lib->mod);
ecore_audio_sndfile_lib->mod = NULL;
}
return EINA_FALSE;
}
void
ecore_audio_sndfile_lib_unload(void)
{
if (ecore_audio_sndfile_lib)
{
if (ecore_audio_sndfile_lib->mod)
eina_module_free(ecore_audio_sndfile_lib->mod);
free(ecore_audio_sndfile_lib);
ecore_audio_sndfile_lib = NULL;
}
}
#endif /* HAVE_SNDFILE */
/**
* @}

View File

@ -30,7 +30,8 @@ typedef struct _Ecore_Audio_In_Sndfile_Data Ecore_Audio_In_Sndfile_Data;
EOLIAN static ssize_t
_ecore_audio_in_sndfile_ecore_audio_in_read_internal(Eo *eo_obj EINA_UNUSED, Ecore_Audio_In_Sndfile_Data *obj, void *data, size_t len)
{
return sf_read_float(obj->handle, data, len/4)*4;
if (!ESF_LOAD()) return 0;
return ESF_CALL(sf_read_float)(obj->handle, data, len/4)*4;
}
EOLIAN static double
@ -38,8 +39,9 @@ _ecore_audio_in_sndfile_ecore_audio_in_seek(Eo *eo_obj EINA_UNUSED, Ecore_Audio_
{
sf_count_t count, pos;
if (!ESF_LOAD()) return 0.0;
count = offs * obj->sfinfo.samplerate;
pos = sf_seek(obj->handle, count, mode);
pos = ESF_CALL(sf_seek)(obj->handle, count, mode);
return (double)pos / obj->sfinfo.samplerate;
}
@ -50,8 +52,9 @@ _ecore_audio_in_sndfile_ecore_audio_source_set(Eo *eo_obj, Ecore_Audio_In_Sndfil
Ecore_Audio_Object *ea_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
Ecore_Audio_Input *in_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);
if (!ESF_LOAD()) return EINA_FALSE;
if (obj->handle) {
sf_close(obj->handle);
ESF_CALL(sf_close)(obj->handle);
obj->handle = NULL;
}
@ -60,7 +63,7 @@ _ecore_audio_in_sndfile_ecore_audio_source_set(Eo *eo_obj, Ecore_Audio_In_Sndfil
if (!ea_obj->source)
return EINA_FALSE;
obj->handle = sf_open(ea_obj->source, SFM_READ, &obj->sfinfo);
obj->handle = ESF_CALL(sf_open)(ea_obj->source, SFM_READ, &obj->sfinfo);
if (!obj->handle) {
eina_stringshare_del(ea_obj->source);
@ -147,8 +150,9 @@ _ecore_audio_in_sndfile_ecore_audio_vio_set(Eo *eo_obj, Ecore_Audio_In_Sndfile_D
Ecore_Audio_Object *ea_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
Ecore_Audio_Input *in_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_IN_CLASS);
if (!ESF_LOAD()) return;
if (obj->handle) {
sf_close(obj->handle);
ESF_CALL(sf_close)(obj->handle);
obj->handle = NULL;
}
@ -170,7 +174,7 @@ _ecore_audio_in_sndfile_ecore_audio_vio_set(Eo *eo_obj, Ecore_Audio_In_Sndfile_D
ea_obj->vio->free_func = free_func;
in_obj->seekable = (vio->seek != NULL);
obj->handle = sf_open_virtual(&vio_wrapper, SFM_READ, &obj->sfinfo, eo_obj);
obj->handle = ESF_CALL(sf_open_virtual)(&vio_wrapper, SFM_READ, &obj->sfinfo, eo_obj);
if (!obj->handle) {
eina_stringshare_del(ea_obj->source);
@ -199,8 +203,9 @@ _ecore_audio_in_sndfile_eo_base_destructor(Eo *eo_obj, Ecore_Audio_In_Sndfile_Da
{
Ecore_Audio_Object *ea_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
if (!ESF_LOAD()) return;
if (obj->handle)
sf_close(obj->handle);
ESF_CALL(sf_close)(obj->handle);
if (ea_obj->vio)
_free_vio(ea_obj);

View File

@ -54,19 +54,19 @@ _ecore_audio_out_pulse_ecore_audio_volume_set(Eo *eo_obj, Ecore_Audio_Out_Pulse_
pa_cvolume pa_volume;
Ecore_Audio_Output *out_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OUT_CLASS);
if (!EPA_LOAD()) return;
if (volume < 0)
volume = 0;
pa_cvolume_set(&pa_volume, 2, volume * PA_VOLUME_NORM);
EPA_CALL(pa_cvolume_set)(&pa_volume, 2, volume * PA_VOLUME_NORM);
ecore_audio_obj_volume_set(eo_super(eo_obj, MY_CLASS), volume);
EINA_LIST_FOREACH(out_obj->inputs, input, in) {
stream = eo_key_data_get(in, "pulse_data");
idx = pa_stream_get_index(stream);
pa_operation_unref(pa_context_set_sink_input_volume(class_vars.context, idx, &pa_volume, NULL, NULL));
idx = EPA_CALL(pa_stream_get_index)(stream);
EPA_CALL(pa_operation_unref)(EPA_CALL(pa_context_set_sink_input_volume)(class_vars.context, idx, &pa_volume, NULL, NULL));
}
}
static void _write_cb(pa_stream *stream, size_t len, void *data)
@ -77,14 +77,15 @@ static void _write_cb(pa_stream *stream, size_t len, void *data)
ssize_t bread = 0;
size_t wlen = len;
pa_stream_begin_write(stream, &buf, &wlen);
if (!EPA_LOAD()) return;
EPA_CALL(pa_stream_begin_write)(stream, &buf, &wlen);
bread = ecore_audio_obj_in_read(in, buf, wlen);
pa_stream_write(stream, buf, bread, NULL, 0, PA_SEEK_RELATIVE);
EPA_CALL(pa_stream_write)(stream, buf, bread, NULL, 0, PA_SEEK_RELATIVE);
if (bread < (int)len)
{
pa_operation_unref(pa_stream_trigger(stream, NULL, NULL));
EPA_CALL(pa_operation_unref)(EPA_CALL(pa_stream_trigger)(stream, NULL, NULL));
}
}
@ -99,7 +100,7 @@ static void _update_samplerate_cb(void *data EINA_UNUSED, const Eo_Event *event)
stream = eo_key_data_get(event->object, "pulse_data");
pa_operation_unref(pa_stream_update_sample_rate(stream, samplerate * speed, NULL, NULL));
EPA_CALL(pa_operation_unref)(EPA_CALL(pa_stream_update_sample_rate)(stream, samplerate * speed, NULL, NULL));
}
static Eina_Bool _input_attach_internal(Eo *eo_obj, Eo *in)
@ -111,6 +112,7 @@ static Eina_Bool _input_attach_internal(Eo *eo_obj, Eo *in)
Eina_Bool ret = EINA_FALSE;
Ecore_Audio_Object *ea_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
if (!EPA_LOAD()) return EINA_FALSE;
ret = ecore_audio_obj_out_input_attach(eo_super(eo_obj, MY_CLASS), in);
if (!ret)
return EINA_FALSE;
@ -123,7 +125,7 @@ static Eina_Bool _input_attach_internal(Eo *eo_obj, Eo *in)
ss.rate = ss.rate * speed;
stream = pa_stream_new(class_vars.context, name, &ss, NULL);
stream = EPA_CALL(pa_stream_new)(class_vars.context, name, &ss, NULL);
if (!stream) {
ERR("Could not create stream");
ecore_audio_obj_out_input_detach(eo_super(eo_obj, MY_CLASS), in);
@ -135,11 +137,11 @@ static Eina_Bool _input_attach_internal(Eo *eo_obj, Eo *in)
eo_key_data_set(in, "pulse_data", stream);
pa_stream_set_write_callback(stream, _write_cb, in);
pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_VARIABLE_RATE, NULL, NULL);
EPA_CALL(pa_stream_set_write_callback)(stream, _write_cb, in);
EPA_CALL(pa_stream_connect_playback)(stream, NULL, NULL, PA_STREAM_VARIABLE_RATE, NULL, NULL);
if (ea_obj->paused)
pa_operation_unref(pa_stream_cork(stream, 1, NULL, NULL));
EPA_CALL(pa_operation_unref)(EPA_CALL(pa_stream_cork)(stream, 1, NULL, NULL));
return ret;
}
@ -169,8 +171,9 @@ _ecore_audio_out_pulse_ecore_audio_out_input_attach(Eo *eo_obj, Ecore_Audio_Out_
static void _drain_cb(pa_stream *stream, int success EINA_UNUSED, void *data EINA_UNUSED)
{
pa_stream_disconnect(stream);
pa_stream_unref(stream);
if (!EPA_LOAD()) return;
EPA_CALL(pa_stream_disconnect)(stream);
EPA_CALL(pa_stream_unref)(stream);
}
EOLIAN static Eina_Bool
@ -180,21 +183,22 @@ _ecore_audio_out_pulse_ecore_audio_out_input_detach(Eo *eo_obj, Ecore_Audio_Out_
Eina_Bool ret2 = EINA_FALSE;
pa_operation *op;
if (!EPA_LOAD()) return EINA_FALSE;
ret2 = ecore_audio_obj_out_input_detach(eo_super(eo_obj, MY_CLASS), in);
if (!ret2)
return EINA_FALSE;
stream = eo_key_data_get(in, "pulse_data");
pa_stream_set_write_callback(stream, NULL, NULL);
op = pa_stream_drain(stream, _drain_cb, NULL);
EPA_CALL(pa_stream_set_write_callback)(stream, NULL, NULL);
op = EPA_CALL(pa_stream_drain) (stream, _drain_cb, NULL);
if (!op)
{
ERR("Failed to drain PulseAudio stream.");
return EINA_FALSE;
}
pa_operation_unref(op);
EPA_CALL(pa_operation_unref)(op);
return EINA_TRUE;
}
@ -204,7 +208,8 @@ static void _state_cb(pa_context *context, void *data EINA_UNUSED)
Eo *eo_obj;
pa_context_state_t state;
state = pa_context_get_state(context);
if (!EPA_LOAD()) return;
state = EPA_CALL(pa_context_get_state)(context);
class_vars.state = state;
//ref everything in the list to be sure...
@ -263,6 +268,7 @@ _ecore_audio_out_pulse_eo_base_constructor(Eo *eo_obj, Ecore_Audio_Out_Pulse_Dat
char **argv;
Ecore_Audio_Output *out_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OUT_CLASS);
if (!EPA_LOAD()) return NULL;
eo_obj = eo_constructor(eo_super(eo_obj, MY_CLASS));
out_obj->need_writer = EINA_FALSE;
@ -271,12 +277,12 @@ _ecore_audio_out_pulse_eo_base_constructor(Eo *eo_obj, Ecore_Audio_Out_Pulse_Dat
ecore_app_args_get(&argc, &argv);
if (!argc) {
DBG("Could not get program name, pulse outputs will be named ecore_audio");
class_vars.context = pa_context_new(class_vars.api, "ecore_audio");
class_vars.context = EPA_CALL(pa_context_new)(class_vars.api, "ecore_audio");
} else {
class_vars.context = pa_context_new(class_vars.api, basename(argv[0]));
class_vars.context = EPA_CALL(pa_context_new)(class_vars.api, basename(argv[0]));
}
pa_context_set_state_callback(class_vars.context, _state_cb, NULL);
pa_context_connect(class_vars.context, NULL, PA_CONTEXT_NOFLAGS, NULL);
EPA_CALL(pa_context_set_state_callback)(class_vars.context, _state_cb, NULL);
EPA_CALL(pa_context_connect)(class_vars.context, NULL, PA_CONTEXT_NOFLAGS, NULL);
}
class_vars.outputs = eina_list_append(class_vars.outputs, eo_obj);

View File

@ -40,21 +40,22 @@ static Eina_Bool _write_cb(void *data)
ssize_t written, bread = 0;
float buf[1024];
if (!ESF_LOAD()) return EINA_FALSE;
/* TODO: Support mixing of multiple inputs */
in = eina_list_data_get(out_obj->inputs);
bread = ecore_audio_obj_in_read(in, buf, 4*1024);
if (bread == 0) {
sf_write_sync(obj->handle);
ESF_CALL(sf_write_sync)(obj->handle);
ea_obj->paused = EINA_TRUE;
out_obj->write_idler = NULL;
return EINA_FALSE;
}
written = sf_write_float(obj->handle, buf, bread/4)*4;
written = ESF_CALL(sf_write_float)(obj->handle, buf, bread/4)*4;
if (written != bread)
ERR("Short write! (%s)\n", sf_strerror(obj->handle));
ERR("Short write! (%s)\n", ESF_CALL(sf_strerror)(obj->handle));
return EINA_TRUE;
}
@ -66,6 +67,7 @@ _ecore_audio_out_sndfile_ecore_audio_out_input_attach(Eo *eo_obj, Ecore_Audio_Ou
Ecore_Audio_Output *out_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OUT_CLASS);
Eina_Bool ret2 = EINA_FALSE;
if (!ESF_LOAD()) return EINA_FALSE;
ret2 = ecore_audio_obj_out_input_attach(eo_super(eo_obj, MY_CLASS), in);
if (!ret2)
return EINA_FALSE;
@ -73,7 +75,7 @@ _ecore_audio_out_sndfile_ecore_audio_out_input_attach(Eo *eo_obj, Ecore_Audio_Ou
obj->sfinfo.samplerate = ecore_audio_obj_in_samplerate_get(in);
obj->sfinfo.channels = ecore_audio_obj_in_channels_get(in);
obj->handle = sf_open(ea_obj->source, SFM_WRITE, &obj->sfinfo);
obj->handle = ESF_CALL(sf_open)(ea_obj->source, SFM_WRITE, &obj->sfinfo);
if (!obj->handle) {
eina_stringshare_del(ea_obj->source);
@ -97,8 +99,9 @@ _ecore_audio_out_sndfile_ecore_audio_source_set(Eo *eo_obj, Ecore_Audio_Out_Sndf
{
Ecore_Audio_Object *ea_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_CLASS);
if (!ESF_LOAD()) return EINA_FALSE;
if (obj->handle) {
sf_close(obj->handle);
ESF_CALL(sf_close)(obj->handle);
obj->handle = NULL;
}
@ -177,8 +180,9 @@ _ecore_audio_out_sndfile_eo_base_destructor(Eo *eo_obj, Ecore_Audio_Out_Sndfile_
{
Ecore_Audio_Output *out_obj = eo_data_scope_get(eo_obj, ECORE_AUDIO_OUT_CLASS);
if (!ESF_LOAD()) return;
if (obj->handle)
sf_close(obj->handle);
ESF_CALL(sf_close)(obj->handle);
if (out_obj->write_idler)
ecore_idler_del(out_obj->write_idler);

View File

@ -144,6 +144,7 @@ struct _Ecore_Audio_Input
extern Eina_List *ecore_audio_modules;
//////////////////////////////////////////////////////////////////////////
#ifdef HAVE_ALSA
/* ecore_audio_alsa */
struct _Ecore_Audio_Alsa
@ -158,26 +159,85 @@ Ecore_Audio_Module *ecore_audio_alsa_init(void);
void ecore_audio_alsa_shutdown(void);
#endif /* HAVE_ALSA */
//////////////////////////////////////////////////////////////////////////
#ifdef HAVE_PULSE
typedef struct _Ecore_Audio_Lib_Pulse Ecore_Audio_Lib_Pulse;
struct _Ecore_Audio_Lib_Pulse
{
Eina_Module *mod;
pa_context *(*pa_context_new) (pa_mainloop_api *mainloop, const char *name);
int (*pa_context_connect) (pa_context *c, const char *server, pa_context_flags_t flags, const pa_spawn_api *api);
pa_operation *(*pa_context_set_sink_input_volume) (pa_context *c, uint32_t idx, const pa_cvolume *volume, pa_context_success_cb_t cb, void *userdata);
pa_context_state_t (*pa_context_get_state) (pa_context *c);
void (*pa_context_set_state_callback) (pa_context *c, pa_context_notify_cb_t cb, void *userdata);
void (*pa_operation_unref) (pa_operation *o);
pa_cvolume *(*pa_cvolume_set) (pa_cvolume *a, unsigned channels, pa_volume_t v);
pa_stream *(*pa_stream_new) (pa_context *c, const char *name, const pa_sample_spec *ss, const pa_channel_map *map);
void (*pa_stream_unref) (pa_stream *s);
int (*pa_stream_connect_playback) (pa_stream *s, const char *dev, const pa_buffer_attr *attr, pa_stream_flags_t flags, const pa_cvolume *volume, pa_stream *sync_stream);
int (*pa_stream_disconnect) (pa_stream *s);
pa_operation *(*pa_stream_drain) (pa_stream *s, pa_stream_success_cb_t cb, void *userdata);
pa_operation *(*pa_stream_cork) (pa_stream *s, int b, pa_stream_success_cb_t cb, void *userdata);
int (*pa_stream_write) (pa_stream *p, const void *data, size_t nbytes, pa_free_cb_t free_cb, int64_t offset, pa_seek_mode_t seek);
int (*pa_stream_begin_write) (pa_stream *p, void **data, size_t *nbytes);
void (*pa_stream_set_write_callback) (pa_stream *p, pa_stream_request_cb_t cb, void *userdata);
pa_operation *(*pa_stream_trigger) (pa_stream *s, pa_stream_success_cb_t cb, void *userdata);
pa_operation *(*pa_stream_update_sample_rate) (pa_stream *s, uint32_t rate, pa_stream_success_cb_t cb, void *userdata);
uint32_t (*pa_stream_get_index) (pa_stream *s);
};
#define EPA_CALL(x) ecore_audio_pulse_lib->x
#define EPA_LOAD() ecore_audio_pulse_lib_load()
extern Ecore_Audio_Lib_Pulse *ecore_audio_pulse_lib;
Eina_Bool ecore_audio_pulse_lib_load(void);
void ecore_audio_pulse_lib_unload(void);
/* These are unused from ecore_audio_pulse.c which isn't used
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);
typedef struct _Ecore_Audio_Lib_Sndfile Ecore_Audio_Lib_Sndfile;
struct _Ecore_Audio_Lib_Sndfile
{
Eina_Module *mod;
SNDFILE *(*sf_open) (const char *path, int mode, SF_INFO *sfinfo);
SNDFILE *(*sf_open_virtual) (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data);
int (*sf_close) (SNDFILE *sndfile);
sf_count_t (*sf_read_float) (SNDFILE *sndfile, float *ptr, sf_count_t items);
sf_count_t (*sf_write_float) (SNDFILE *sndfile, const float *ptr, sf_count_t items);
void (*sf_write_sync) (SNDFILE *sndfile);
sf_count_t (*sf_seek) (SNDFILE *sndfile, sf_count_t frames, int whence);
const char *(*sf_strerror) (SNDFILE *sndfile);
};
#define ESF_CALL(x) ecore_audio_sndfile_lib->x
#define ESF_LOAD() ecore_audio_sndfile_lib_load()
extern Ecore_Audio_Lib_Sndfile *ecore_audio_sndfile_lib;
Eina_Bool ecore_audio_sndfile_lib_load(void);
void ecore_audio_sndfile_lib_unload(void);
#endif /* HAVE_SNDFILE */
//////////////////////////////////////////////////////////////////////////
#ifdef HAVE_COREAUDIO
/* ecore_audio_core_audio */
Ecore_Audio_Module *ecore_audio_core_audio_init(void);
void ecore_audio_core_audio_shutdown(void);
#endif /* HAVE_COREAUDIO */
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);