diff options
author | Daniel Willmann <d.willmann@samsung.com> | 2013-04-17 18:31:38 +0100 |
---|---|---|
committer | Daniel Willmann <d.willmann@samsung.com> | 2013-04-18 19:14:32 +0100 |
commit | 72556567385540aaf98cb9848fd5ecbff1bcad67 (patch) | |
tree | 106ca27e7cb53ba82a6d5ed9a3da44a345838669 | |
parent | 01e4c9597e344ce4e34f7889883452ae0dd0a928 (diff) | |
download | efl-72556567385540aaf98cb9848fd5ecbff1bcad67.tar.gz |
ecore_audio: Add pulseaudio output for eo
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
-rw-r--r-- | src/Makefile_Ecore_Audio.am | 3 | ||||
-rw-r--r-- | src/lib/ecore_audio/Ecore_Audio.h | 2 | ||||
-rw-r--r-- | src/lib/ecore_audio/ecore_audio_obj_out_pulse.c | 271 | ||||
-rw-r--r-- | src/lib/ecore_audio/ecore_audio_obj_out_pulse.h | 57 | ||||
-rw-r--r-- | src/lib/ecore_audio/ecore_audio_private.h | 14 | ||||
-rw-r--r-- | src/lib/ecore_audio/ecore_audio_pulse_ml.c | 308 |
6 files changed, 641 insertions, 14 deletions
diff --git a/src/Makefile_Ecore_Audio.am b/src/Makefile_Ecore_Audio.am index 7e062702f2..ded4d35785 100644 --- a/src/Makefile_Ecore_Audio.am +++ b/src/Makefile_Ecore_Audio.am @@ -13,6 +13,7 @@ lib/ecore_audio/ecore_audio_obj_out.h \ lib/ecore_audio/ecore_audio_obj_in_sndfile.h \ lib/ecore_audio/ecore_audio_obj_out_sndfile.h \ lib/ecore_audio/ecore_audio_obj_in_tone.h \ +lib/ecore_audio/ecore_audio_obj_out_pulse.h \ lib/ecore_audio/ecore_audio_protected.h @@ -24,6 +25,8 @@ lib/ecore_audio/ecore_audio_obj_out.c \ lib/ecore_audio/ecore_audio_obj_in_sndfile.c \ lib/ecore_audio/ecore_audio_obj_out_sndfile.c \ lib/ecore_audio/ecore_audio_obj_in_tone.c \ +lib/ecore_audio/ecore_audio_pulse_ml.c \ +lib/ecore_audio/ecore_audio_obj_out_pulse.c \ lib/ecore_audio/ecore_audio_private.h lib_ecore_audio_libecore_audio_la_CPPFLAGS = @ECORE_AUDIO_CFLAGS@ diff --git a/src/lib/ecore_audio/Ecore_Audio.h b/src/lib/ecore_audio/Ecore_Audio.h index 8a542176e1..b87f6479cc 100644 --- a/src/lib/ecore_audio/Ecore_Audio.h +++ b/src/lib/ecore_audio/Ecore_Audio.h @@ -576,4 +576,6 @@ EAPI void ecore_audio_input_callback_setup(Ecore_Audio_Object *in #include <ecore_audio_obj_in_tone.h> +#include <ecore_audio_obj_out_pulse.h> + #endif diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c new file mode 100644 index 0000000000..4a3f9f86b5 --- /dev/null +++ b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.c @@ -0,0 +1,271 @@ +#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 <pulse/pulseaudio.h> + +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> + +extern pa_mainloop_api functable; + +EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID = EO_NOOP; + +#define MY_CLASS ECORE_AUDIO_OBJ_OUT_PULSE_CLASS +#define MY_CLASS_NAME "ecore_audio_obj_out_pulse" + +const Eo_Event_Description _ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY; +#define ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY (&(_ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY)) + +struct _Ecore_Audio_Pulse_Class { + pa_mainloop_api *api; + pa_context *context; + pa_context_state_t state; + Eina_List *outputs; +}; + +static struct _Ecore_Audio_Pulse_Class class_vars = { + .api = &functable, +}; + +struct _Ecore_Audio_Pulse +{ + char *foo; +}; + +typedef struct _Ecore_Audio_Pulse Ecore_Audio_Pulse; + +static void _volume_set(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list) +{ + Eo *in; + pa_stream *stream; + Eina_List *input; + uint32_t idx; + pa_cvolume pa_volume; + Ecore_Audio_Output *out_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_OUT_CLASS); + + double volume = va_arg(*list, double); + + if (volume < 0) + volume = 0; + + pa_cvolume_set(&pa_volume, 2, volume * PA_VOLUME_NORM); + + 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("pulse_data", (void **)&stream)); + idx = pa_stream_get_index(stream); + pa_operation_unref(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) +{ + Eo *in = data; + + void *buf; + ssize_t bread; + + buf = malloc(len); + + eo_do(in, ecore_audio_obj_in_read(buf, len, &bread)); + pa_stream_write(stream, buf, bread, free, 0, PA_SEEK_RELATIVE); + if (bread < len) + { + //in->ended = EINA_TRUE; + pa_operation_unref(pa_stream_drain(stream, NULL, NULL)); + } +} + +static Eina_Bool _update_samplerate_cb(void *data, Eo *eo_obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Eo *out = data; + pa_stream *stream; + int samplerate; + double speed; + + eo_do(eo_obj, ecore_audio_obj_in_samplerate_get(&samplerate)); + eo_do(eo_obj, ecore_audio_obj_in_speed_get(&speed)); + + eo_do(eo_obj, eo_base_data_get("pulse_data", &stream)); + + pa_operation_unref(pa_stream_update_sample_rate(stream, samplerate * speed, NULL, NULL)); +} + +static void _input_attach_internal(Eo *eo_obj, Eo *in) +{ + const char *name; + pa_sample_spec ss; + double speed; + pa_stream *stream; + Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS); + + ss.format = PA_SAMPLE_FLOAT32LE; + eo_do(in, ecore_audio_obj_in_samplerate_get(&ss.rate)); + eo_do(in, ecore_audio_obj_in_speed_get(&speed)); + eo_do(in, ecore_audio_obj_in_channels_get(&ss.channels)); + eo_do(in, ecore_audio_obj_name_get(&name)); + + ss.rate = ss.rate * speed; + + stream = pa_stream_new(class_vars.context, name, &ss, NULL); + if (!stream) { + ERR("Could not create stream"); + return; + } + + eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_attach(in)); + + 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("pulse_data", stream, NULL)); + + //FIXME: Handle paused state + + pa_stream_set_write_callback(stream, _write_cb, in); + pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_VARIABLE_RATE, NULL, NULL); +} + +static Eina_Bool _delayed_attach_cb(void *data, Eo *eo_obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED) +{ + Eo *in = data; + eo_do(eo_obj, eo_event_callback_del(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, _delayed_attach_cb, in)); + + _input_attach_internal(eo_obj, in); + + return EINA_TRUE; +} + +static void _input_attach(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list) +{ + Eo *in = va_arg(*list, Eo *); + + if (class_vars.state != PA_CONTEXT_READY) { + DBG("Delaying input_attach because PA context is not ready."); + eo_do(eo_obj, eo_event_callback_add(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, _delayed_attach_cb, in)); + } else { + _input_attach_internal(eo_obj, in); + } +} + +static void _drain_cb(pa_stream *stream, int success EINA_UNUSED, void *data EINA_UNUSED) +{ + pa_stream_disconnect(stream); + pa_stream_unref(stream); +} + +static void _input_detach(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list) +{ + pa_stream *stream; + + Eo *in = va_arg(*list, Eo *); + + eo_do(in, eo_base_data_get("pulse_data", (void **)&stream)); + + pa_stream_set_write_callback(stream, NULL, NULL); + pa_operation_unref(pa_stream_drain(stream, _drain_cb, NULL)); + + eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_detach(in)); +} + +static void _state_cb(pa_context *context, void *data EINA_UNUSED) +{ + Eina_List *out; + Eo *eo_obj; + pa_context_state_t state; + + state = pa_context_get_state(context); + + if (state == PA_CONTEXT_READY) { + DBG("PA context ready."); + EINA_LIST_FOREACH(class_vars.outputs, out, eo_obj) { + eo_do(eo_obj, eo_event_callback_call(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, NULL, NULL)); + } + } else { + DBG("Connection state %i", state); + } + + class_vars.state = state; +} + +static void _constructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED) +{ + int argc; + char **argv; + + eo_do_super(eo_obj, MY_CLASS, eo_constructor()); + + if (!class_vars.context) { + 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"); + } else { + class_vars.context = 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); + } + + class_vars.outputs = eina_list_append(class_vars.outputs, eo_obj); +} + +static void _destructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED) +{ + eo_do_super(eo_obj, MY_CLASS, eo_destructor()); + + class_vars.outputs = eina_list_remove(class_vars.outputs, eo_obj); +} + +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_Event_Description *event_desc[] = { + ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, + NULL +}; + + +static const Eo_Class_Description class_desc = { + EO_VERSION, + MY_CLASS_NAME, + EO_CLASS_TYPE_REGULAR, + EO_CLASS_DESCRIPTION_OPS(&ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID, op_desc, ECORE_AUDIO_OBJ_OUT_PULSE_SUB_ID_LAST), + event_desc, + sizeof(Ecore_Audio_Pulse), + _class_constructor, + NULL +}; + +EO_DEFINE_CLASS(ecore_audio_obj_out_pulse_class_get, &class_desc, ECORE_AUDIO_OBJ_OUT_CLASS, NULL); diff --git a/src/lib/ecore_audio/ecore_audio_obj_out_pulse.h b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.h new file mode 100644 index 0000000000..f89413b8a4 --- /dev/null +++ b/src/lib/ecore_audio/ecore_audio_obj_out_pulse.h @@ -0,0 +1,57 @@ +#ifndef ECORE_AUDIO_OUT_PULSE_H +#define ECORE_AUDIO_OUT_PULSE_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_pulse.h + * @brief Audio Module + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/** + * @addtogroup Ecore_Audio_Group + * @{ + */ + +#define ECORE_AUDIO_OBJ_OUT_PULSE_CLASS ecore_audio_obj_out_pulse_class_get() + +const Eo_Class *ecore_audio_obj_out_pulse_class_get() EINA_CONST; + +extern EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID; + +enum _Ecore_Audio_Obj_Out_Pulse_Sub_Ids +{ + ECORE_AUDIO_OBJ_OUT_PULSE_SUB_ID_LAST +}; + +#define ECORE_AUDIO_OBJ_OUT_PULSE_ID(sub_id) (ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID + EO_TYPECHECK(enum _Ecore_Audio_Obj_Out_Pulse_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 ef08b74a9b..7868b08b5f 100644 --- a/src/lib/ecore_audio/ecore_audio_private.h +++ b/src/lib/ecore_audio/ecore_audio_private.h @@ -155,20 +155,6 @@ void ecore_audio_alsa_shutdown(void); #endif /* HAVE_ALSA */ #ifdef HAVE_PULSE -/* PA mainloop integration */ -struct _Ecore_Audio_Pa_Private -{ - pa_mainloop_api api; - pa_context *context; - pa_context_state_t state; -}; - -/* ecore_audio_pulse */ -struct _Ecore_Audio_Pulse -{ - pa_stream *stream; -}; - Ecore_Audio_Module *ecore_audio_pulse_init(void); void ecore_audio_pulse_shutdown(void); #endif /* HAVE_PULSE */ diff --git a/src/lib/ecore_audio/ecore_audio_pulse_ml.c b/src/lib/ecore_audio/ecore_audio_pulse_ml.c new file mode 100644 index 0000000000..67dd96b132 --- /dev/null +++ b/src/lib/ecore_audio/ecore_audio_pulse_ml.c @@ -0,0 +1,308 @@ +#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 <ctype.h> +#include <errno.h> + +#include <pulse/pulseaudio.h> + +#include <sys/time.h> +#include <sys/types.h> +#include <sys/socket.h> + +#include "ecore_audio_private.h" + +/* Ecore mainloop integration start */ +struct pa_io_event +{ + pa_mainloop_api *mainloop; + Ecore_Fd_Handler *handler; + + void *userdata; + + pa_io_event_flags_t flags; + pa_io_event_cb_t callback; + pa_io_event_destroy_cb_t destroy_callback; +}; + +static Ecore_Fd_Handler_Flags +map_flags_to_ecore(pa_io_event_flags_t flags) +{ + return (Ecore_Fd_Handler_Flags)((flags & PA_IO_EVENT_INPUT ? ECORE_FD_READ : 0) | (flags & PA_IO_EVENT_OUTPUT ? ECORE_FD_WRITE : 0) | (flags & PA_IO_EVENT_ERROR ? ECORE_FD_ERROR : 0) | (flags & PA_IO_EVENT_HANGUP ? ECORE_FD_READ : 0)); +} + +static Eina_Bool +_ecore_io_wrapper(void *data, Ecore_Fd_Handler *handler) +{ + char buf[64]; + pa_io_event_flags_t flags = 0; + pa_io_event *event = (pa_io_event *)data; + + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ)) + { + flags |= PA_IO_EVENT_INPUT; + + /* Check for HUP and report */ + if (recv(ecore_main_fd_handler_fd_get(handler), buf, 64, MSG_PEEK)) + { + if (errno == ESHUTDOWN || errno == ECONNRESET || errno == ECONNABORTED || errno == ENETRESET) + { + DBG("HUP condition detected"); + flags |= PA_IO_EVENT_HANGUP; + } + } + } + + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE)) + flags |= PA_IO_EVENT_OUTPUT; + if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR)) + flags |= PA_IO_EVENT_ERROR; + + event->callback(event->mainloop, event, ecore_main_fd_handler_fd_get(handler), flags, event->userdata); + + return ECORE_CALLBACK_RENEW; +} + +static pa_io_event * +_ecore_pa_io_new(pa_mainloop_api *api, int fd, pa_io_event_flags_t flags, pa_io_event_cb_t cb, void *userdata) +{ + pa_io_event *event; + + event = calloc(1, sizeof(pa_io_event)); + event->mainloop = api; + event->userdata = userdata; + event->callback = cb; + event->flags = flags; + event->handler = ecore_main_fd_handler_add(fd, map_flags_to_ecore(flags), _ecore_io_wrapper, event, NULL, NULL); + + return event; +} + +static void +_ecore_pa_io_enable(pa_io_event *event, pa_io_event_flags_t flags) +{ + event->flags = flags; + ecore_main_fd_handler_active_set(event->handler, map_flags_to_ecore(flags)); +} + +static void +_ecore_pa_io_free(pa_io_event *event) +{ + ecore_main_fd_handler_del(event->handler); + free(event); +} + +static void +_ecore_pa_io_set_destroy(pa_io_event *event, pa_io_event_destroy_cb_t cb) +{ + event->destroy_callback = cb; +} + +/* Timed events */ +struct pa_time_event +{ + pa_mainloop_api *mainloop; + Ecore_Timer *timer; + struct timeval tv; + + void *userdata; + + pa_time_event_cb_t callback; + pa_time_event_destroy_cb_t destroy_callback; +}; + +Eina_Bool +_ecore_time_wrapper(void *data) +{ + pa_time_event *event = (pa_time_event *)data; + + event->callback(event->mainloop, event, &event->tv, event->userdata); + + return ECORE_CALLBACK_CANCEL; +} + +pa_time_event * +_ecore_pa_time_new(pa_mainloop_api *api, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata) +{ + pa_time_event *event; + struct timeval now; + double interval; + + event = calloc(1, sizeof(pa_time_event)); + event->mainloop = api; + event->userdata = userdata; + event->callback = cb; + event->tv = *tv; + + if (gettimeofday(&now, NULL) == -1) + { + ERR("Failed to get the current time!"); + return NULL; + } + + interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000; + event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event); + + return event; +} + +void +_ecore_pa_time_restart(pa_time_event *event, const struct timeval *tv) +{ + struct timeval now; + double interval; + + /* If tv is NULL disable timer */ + if (!tv) + { + ecore_timer_del(event->timer); + event->timer = NULL; + return; + } + + event->tv = *tv; + + if (gettimeofday(&now, NULL) == -1) + { + ERR("Failed to get the current time!"); + return; + } + + interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000; + if (event->timer) + { + event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event); + } + else + { + ecore_timer_interval_set(event->timer, interval); + ecore_timer_reset(event->timer); + } +} + +void +_ecore_pa_time_free(pa_time_event *event) +{ + if (event->timer) + ecore_timer_del(event->timer); + + event->timer = NULL; + + free(event); +} + +void +_ecore_pa_time_set_destroy(pa_time_event *event, pa_time_event_destroy_cb_t cb) +{ + event->destroy_callback = cb; +} + +/* Deferred events */ +struct pa_defer_event +{ + pa_mainloop_api *mainloop; + Ecore_Idler *idler; + + void *userdata; + + pa_defer_event_cb_t callback; + pa_defer_event_destroy_cb_t destroy_callback; +}; + +Eina_Bool +_ecore_defer_wrapper(void *data) +{ + pa_defer_event *event = (pa_defer_event *)data; + + event->idler = NULL; + event->callback(event->mainloop, event, event->userdata); + + return ECORE_CALLBACK_CANCEL; +} + +pa_defer_event * +_ecore_pa_defer_new(pa_mainloop_api *api, pa_defer_event_cb_t cb, void *userdata) +{ + pa_defer_event *event; + + event = calloc(1, sizeof(pa_defer_event)); + event->mainloop = api; + event->userdata = userdata; + event->callback = cb; + + event->idler = ecore_idler_add(_ecore_defer_wrapper, event); + + return event; +} + +void +_ecore_pa_defer_enable(pa_defer_event *event, int b) +{ + if (!b && event->idler) + { + ecore_idler_del(event->idler); + event->idler = NULL; + } + else if (b && !event->idler) + { + event->idler = ecore_idler_add(_ecore_defer_wrapper, event); + } +} + +void +_ecore_pa_defer_free(pa_defer_event *event) +{ + if (event->idler) + ecore_idler_del(event->idler); + + event->idler = NULL; + + free(event); +} + +void +_ecore_pa_defer_set_destroy(pa_defer_event *event, pa_defer_event_destroy_cb_t cb) +{ + event->destroy_callback = cb; +} + +static void +_ecore_pa_quit(pa_mainloop_api *api EINA_UNUSED, int retval EINA_UNUSED) +{ + /* FIXME: Need to clean up timers, etc.? */ + WRN("Not quitting mainloop, although PA requested it"); +} + +/* Function table for PA mainloop integration */ +const pa_mainloop_api functable = { + .userdata = NULL, + + .io_new = _ecore_pa_io_new, + .io_enable = _ecore_pa_io_enable, + .io_free = _ecore_pa_io_free, + .io_set_destroy = _ecore_pa_io_set_destroy, + + .time_new = _ecore_pa_time_new, + .time_restart = _ecore_pa_time_restart, + .time_free = _ecore_pa_time_free, + .time_set_destroy = _ecore_pa_time_set_destroy, + + .defer_new = _ecore_pa_defer_new, + .defer_enable = _ecore_pa_defer_enable, + .defer_free = _ecore_pa_defer_free, + .defer_set_destroy = _ecore_pa_defer_set_destroy, + + .quit = _ecore_pa_quit, +}; + +/* ***************************************************** + * Ecore mainloop integration end + */ |