diff --git a/configure.ac b/configure.ac index 630417a0b5..aba9f8cf13 100644 --- a/configure.ac +++ b/configure.ac @@ -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]) diff --git a/src/Makefile_Ecore_Audio.am b/src/Makefile_Ecore_Audio.am index 99f1ba4838..55c439fc79 100644 --- a/src/Makefile_Ecore_Audio.am +++ b/src/Makefile_Ecore_Audio.am @@ -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@ diff --git a/src/lib/ecore_audio/ecore_audio.c b/src/lib/ecore_audio/ecore_audio.c index 4d38c13ada..d09d656008 100644 --- a/src/lib/ecore_audio/ecore_audio.c +++ b/src/lib/ecore_audio/ecore_audio.c @@ -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 */ /** * @} diff --git a/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c b/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c index cefe28b021..1117a65f14 100644 --- a/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c +++ b/src/lib/ecore_audio/ecore_audio_obj_in_sndfile.c @@ -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); diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c index 7c6db021a7..e665df7da0 100644 --- a/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c +++ b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c @@ -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); diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c b/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c index e24cfeb0f7..6143b4b02d 100644 --- a/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c +++ b/src/lib/ecore_audio/ecore_audio_obj_out_sndfile.c @@ -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); diff --git a/src/lib/ecore_audio/ecore_audio_private.h b/src/lib/ecore_audio/ecore_audio_private.h index 13a7b6ae4c..6cf19a7921 100644 --- a/src/lib/ecore_audio/ecore_audio_private.h +++ b/src/lib/ecore_audio/ecore_audio_private.h @@ -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);