summaryrefslogtreecommitdiff
path: root/src/lib/ecore_audio
diff options
context:
space:
mode:
authorDaniel Willmann <d.willmann@samsung.com>2013-04-17 18:31:38 +0100
committerDaniel Willmann <d.willmann@samsung.com>2013-04-18 19:14:32 +0100
commit72556567385540aaf98cb9848fd5ecbff1bcad67 (patch)
tree106ca27e7cb53ba82a6d5ed9a3da44a345838669 /src/lib/ecore_audio
parent01e4c9597e344ce4e34f7889883452ae0dd0a928 (diff)
ecore_audio: Add pulseaudio output for eo
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
Diffstat (limited to 'src/lib/ecore_audio')
-rw-r--r--src/lib/ecore_audio/Ecore_Audio.h2
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_out_pulse.c271
-rw-r--r--src/lib/ecore_audio/ecore_audio_obj_out_pulse.h57
-rw-r--r--src/lib/ecore_audio/ecore_audio_private.h14
-rw-r--r--src/lib/ecore_audio/ecore_audio_pulse_ml.c308
5 files changed, 638 insertions, 14 deletions
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
576 576
577#include <ecore_audio_obj_in_tone.h> 577#include <ecore_audio_obj_in_tone.h>
578 578
579#include <ecore_audio_obj_out_pulse.h>
580
579#endif 581#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 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8
9#ifdef HAVE_FEATURES_H
10#include <features.h>
11#endif
12
13#include <Eo.h>
14#include "ecore_audio_private.h"
15#include <pulse/pulseaudio.h>
16
17#include <sys/time.h>
18#include <sys/types.h>
19#include <sys/socket.h>
20
21extern pa_mainloop_api functable;
22
23EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID = EO_NOOP;
24
25#define MY_CLASS ECORE_AUDIO_OBJ_OUT_PULSE_CLASS
26#define MY_CLASS_NAME "ecore_audio_obj_out_pulse"
27
28const Eo_Event_Description _ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY;
29#define ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY (&(_ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY))
30
31struct _Ecore_Audio_Pulse_Class {
32 pa_mainloop_api *api;
33 pa_context *context;
34 pa_context_state_t state;
35 Eina_List *outputs;
36};
37
38static struct _Ecore_Audio_Pulse_Class class_vars = {
39 .api = &functable,
40};
41
42struct _Ecore_Audio_Pulse
43{
44 char *foo;
45};
46
47typedef struct _Ecore_Audio_Pulse Ecore_Audio_Pulse;
48
49static void _volume_set(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
50{
51 Eo *in;
52 pa_stream *stream;
53 Eina_List *input;
54 uint32_t idx;
55 pa_cvolume pa_volume;
56 Ecore_Audio_Output *out_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_OUT_CLASS);
57
58 double volume = va_arg(*list, double);
59
60 if (volume < 0)
61 volume = 0;
62
63 pa_cvolume_set(&pa_volume, 2, volume * PA_VOLUME_NORM);
64
65 eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_volume_set(volume));
66
67 EINA_LIST_FOREACH(out_obj->inputs, input, in) {
68 eo_do(in, eo_base_data_get("pulse_data", (void **)&stream));
69 idx = pa_stream_get_index(stream);
70 pa_operation_unref(pa_context_set_sink_input_volume(class_vars.context, idx, &pa_volume, NULL, NULL));
71 }
72
73}
74
75static void _write_cb(pa_stream *stream, size_t len, void *data)
76{
77 Eo *in = data;
78
79 void *buf;
80 ssize_t bread;
81
82 buf = malloc(len);
83
84 eo_do(in, ecore_audio_obj_in_read(buf, len, &bread));
85 pa_stream_write(stream, buf, bread, free, 0, PA_SEEK_RELATIVE);
86 if (bread < len)
87 {
88 //in->ended = EINA_TRUE;
89 pa_operation_unref(pa_stream_drain(stream, NULL, NULL));
90 }
91}
92
93static Eina_Bool _update_samplerate_cb(void *data, Eo *eo_obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
94{
95 Eo *out = data;
96 pa_stream *stream;
97 int samplerate;
98 double speed;
99
100 eo_do(eo_obj, ecore_audio_obj_in_samplerate_get(&samplerate));
101 eo_do(eo_obj, ecore_audio_obj_in_speed_get(&speed));
102
103 eo_do(eo_obj, eo_base_data_get("pulse_data", &stream));
104
105 pa_operation_unref(pa_stream_update_sample_rate(stream, samplerate * speed, NULL, NULL));
106}
107
108static void _input_attach_internal(Eo *eo_obj, Eo *in)
109{
110 const char *name;
111 pa_sample_spec ss;
112 double speed;
113 pa_stream *stream;
114 Ecore_Audio_Object *ea_obj = eo_data_get(eo_obj, ECORE_AUDIO_OBJ_CLASS);
115
116 ss.format = PA_SAMPLE_FLOAT32LE;
117 eo_do(in, ecore_audio_obj_in_samplerate_get(&ss.rate));
118 eo_do(in, ecore_audio_obj_in_speed_get(&speed));
119 eo_do(in, ecore_audio_obj_in_channels_get(&ss.channels));
120 eo_do(in, ecore_audio_obj_name_get(&name));
121
122 ss.rate = ss.rate * speed;
123
124 stream = pa_stream_new(class_vars.context, name, &ss, NULL);
125 if (!stream) {
126 ERR("Could not create stream");
127 return;
128 }
129
130 eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_attach(in));
131
132 eo_do(in, eo_event_callback_add(ECORE_AUDIO_EV_IN_SAMPLERATE_CHANGED, _update_samplerate_cb, eo_obj));
133
134 eo_do(in, eo_base_data_set("pulse_data", stream, NULL));
135
136 //FIXME: Handle paused state
137
138 pa_stream_set_write_callback(stream, _write_cb, in);
139 pa_stream_connect_playback(stream, NULL, NULL, PA_STREAM_VARIABLE_RATE, NULL, NULL);
140}
141
142static Eina_Bool _delayed_attach_cb(void *data, Eo *eo_obj, const Eo_Event_Description *desc EINA_UNUSED, void *event_info EINA_UNUSED)
143{
144 Eo *in = data;
145 eo_do(eo_obj, eo_event_callback_del(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, _delayed_attach_cb, in));
146
147 _input_attach_internal(eo_obj, in);
148
149 return EINA_TRUE;
150}
151
152static void _input_attach(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
153{
154 Eo *in = va_arg(*list, Eo *);
155
156 if (class_vars.state != PA_CONTEXT_READY) {
157 DBG("Delaying input_attach because PA context is not ready.");
158 eo_do(eo_obj, eo_event_callback_add(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, _delayed_attach_cb, in));
159 } else {
160 _input_attach_internal(eo_obj, in);
161 }
162}
163
164static void _drain_cb(pa_stream *stream, int success EINA_UNUSED, void *data EINA_UNUSED)
165{
166 pa_stream_disconnect(stream);
167 pa_stream_unref(stream);
168}
169
170static void _input_detach(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list)
171{
172 pa_stream *stream;
173
174 Eo *in = va_arg(*list, Eo *);
175
176 eo_do(in, eo_base_data_get("pulse_data", (void **)&stream));
177
178 pa_stream_set_write_callback(stream, NULL, NULL);
179 pa_operation_unref(pa_stream_drain(stream, _drain_cb, NULL));
180
181 eo_do_super(eo_obj, MY_CLASS, ecore_audio_obj_out_input_detach(in));
182}
183
184static void _state_cb(pa_context *context, void *data EINA_UNUSED)
185{
186 Eina_List *out;
187 Eo *eo_obj;
188 pa_context_state_t state;
189
190 state = pa_context_get_state(context);
191
192 if (state == PA_CONTEXT_READY) {
193 DBG("PA context ready.");
194 EINA_LIST_FOREACH(class_vars.outputs, out, eo_obj) {
195 eo_do(eo_obj, eo_event_callback_call(ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY, NULL, NULL));
196 }
197 } else {
198 DBG("Connection state %i", state);
199 }
200
201 class_vars.state = state;
202}
203
204static void _constructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
205{
206 int argc;
207 char **argv;
208
209 eo_do_super(eo_obj, MY_CLASS, eo_constructor());
210
211 if (!class_vars.context) {
212 ecore_app_args_get(&argc, &argv);
213 if (!argc) {
214 DBG("Could not get program name, pulse outputs will be named ecore_audio");
215 class_vars.context = pa_context_new(class_vars.api, "ecore_audio");
216 } else {
217 class_vars.context = pa_context_new(class_vars.api, basename(argv[0]));
218 }
219 pa_context_set_state_callback(class_vars.context, _state_cb, NULL);
220 pa_context_connect(class_vars.context, NULL, PA_CONTEXT_NOFLAGS, NULL);
221 }
222
223 class_vars.outputs = eina_list_append(class_vars.outputs, eo_obj);
224}
225
226static void _destructor(Eo *eo_obj, void *_pd EINA_UNUSED, va_list *list EINA_UNUSED)
227{
228 eo_do_super(eo_obj, MY_CLASS, eo_destructor());
229
230 class_vars.outputs = eina_list_remove(class_vars.outputs, eo_obj);
231}
232
233static void _class_constructor(Eo_Class *klass)
234{
235 const Eo_Op_Func_Description func_desc[] = {
236 /* Virtual functions of parent class implemented in this class */
237 EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_CONSTRUCTOR), _constructor),
238 EO_OP_FUNC(EO_BASE_ID(EO_BASE_SUB_ID_DESTRUCTOR), _destructor),
239
240 EO_OP_FUNC(ECORE_AUDIO_OBJ_ID(ECORE_AUDIO_OBJ_SUB_ID_VOLUME_SET), _volume_set),
241
242 EO_OP_FUNC(ECORE_AUDIO_OBJ_OUT_ID(ECORE_AUDIO_OBJ_OUT_SUB_ID_INPUT_ATTACH), _input_attach),
243 EO_OP_FUNC(ECORE_AUDIO_OBJ_OUT_ID(ECORE_AUDIO_OBJ_OUT_SUB_ID_INPUT_DETACH), _input_detach),
244 EO_OP_FUNC_SENTINEL
245 };
246
247 eo_class_funcs_set(klass, func_desc);
248}
249
250static const Eo_Op_Description op_desc[] = {
251 EO_OP_DESCRIPTION_SENTINEL
252};
253
254static const Eo_Event_Description *event_desc[] = {
255 ECORE_AUDIO_EV_OUT_PULSE_CONTEXT_READY,
256 NULL
257};
258
259
260static const Eo_Class_Description class_desc = {
261 EO_VERSION,
262 MY_CLASS_NAME,
263 EO_CLASS_TYPE_REGULAR,
264 EO_CLASS_DESCRIPTION_OPS(&ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID, op_desc, ECORE_AUDIO_OBJ_OUT_PULSE_SUB_ID_LAST),
265 event_desc,
266 sizeof(Ecore_Audio_Pulse),
267 _class_constructor,
268 NULL
269};
270
271EO_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 @@
1#ifndef ECORE_AUDIO_OUT_PULSE_H
2#define ECORE_AUDIO_OUT_PULSE_H
3
4#include <Eina.h>
5#include <Eo.h>
6
7#ifdef EAPI
8#undef EAPI
9#endif
10
11#ifdef __GNUC__
12#if __GNUC__ >= 4
13#define EAPI __attribute__ ((visibility("default")))
14#else
15#define EAPI
16#endif
17#else
18#define EAPI
19#endif
20
21/**
22 * @file ecore_audio_obj_out_pulse.h
23 * @brief Audio Module
24 */
25
26#ifdef __cplusplus
27extern "C"
28{
29#endif
30
31/**
32 * @addtogroup Ecore_Audio_Group
33 * @{
34 */
35
36#define ECORE_AUDIO_OBJ_OUT_PULSE_CLASS ecore_audio_obj_out_pulse_class_get()
37
38const Eo_Class *ecore_audio_obj_out_pulse_class_get() EINA_CONST;
39
40extern EAPI Eo_Op ECORE_AUDIO_OBJ_OUT_PULSE_BASE_ID;
41
42enum _Ecore_Audio_Obj_Out_Pulse_Sub_Ids
43{
44 ECORE_AUDIO_OBJ_OUT_PULSE_SUB_ID_LAST
45};
46
47#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))
48
49/**
50 * @}
51 */
52
53#ifdef __cplusplus
54}
55#endif
56
57#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);
155#endif /* HAVE_ALSA */ 155#endif /* HAVE_ALSA */
156 156
157#ifdef HAVE_PULSE 157#ifdef HAVE_PULSE
158/* PA mainloop integration */
159struct _Ecore_Audio_Pa_Private
160{
161 pa_mainloop_api api;
162 pa_context *context;
163 pa_context_state_t state;
164};
165
166/* ecore_audio_pulse */
167struct _Ecore_Audio_Pulse
168{
169 pa_stream *stream;
170};
171
172Ecore_Audio_Module *ecore_audio_pulse_init(void); 158Ecore_Audio_Module *ecore_audio_pulse_init(void);
173void ecore_audio_pulse_shutdown(void); 159void ecore_audio_pulse_shutdown(void);
174#endif /* HAVE_PULSE */ 160#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 @@
1#ifdef HAVE_CONFIG_H
2#include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <stdio.h>
7#include <string.h>
8
9#ifdef HAVE_FEATURES_H
10#include <features.h>
11#endif
12#include <ctype.h>
13#include <errno.h>
14
15#include <pulse/pulseaudio.h>
16
17#include <sys/time.h>
18#include <sys/types.h>
19#include <sys/socket.h>
20
21#include "ecore_audio_private.h"
22
23/* Ecore mainloop integration start */
24struct pa_io_event
25{
26 pa_mainloop_api *mainloop;
27 Ecore_Fd_Handler *handler;
28
29 void *userdata;
30
31 pa_io_event_flags_t flags;
32 pa_io_event_cb_t callback;
33 pa_io_event_destroy_cb_t destroy_callback;
34};
35
36static Ecore_Fd_Handler_Flags
37map_flags_to_ecore(pa_io_event_flags_t flags)
38{
39 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));
40}
41
42static Eina_Bool
43_ecore_io_wrapper(void *data, Ecore_Fd_Handler *handler)
44{
45 char buf[64];
46 pa_io_event_flags_t flags = 0;
47 pa_io_event *event = (pa_io_event *)data;
48
49 if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
50 {
51 flags |= PA_IO_EVENT_INPUT;
52
53 /* Check for HUP and report */
54 if (recv(ecore_main_fd_handler_fd_get(handler), buf, 64, MSG_PEEK))
55 {
56 if (errno == ESHUTDOWN || errno == ECONNRESET || errno == ECONNABORTED || errno == ENETRESET)
57 {
58 DBG("HUP condition detected");
59 flags |= PA_IO_EVENT_HANGUP;
60 }
61 }
62 }
63
64 if (ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE))
65 flags |= PA_IO_EVENT_OUTPUT;
66 if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
67 flags |= PA_IO_EVENT_ERROR;
68
69 event->callback(event->mainloop, event, ecore_main_fd_handler_fd_get(handler), flags, event->userdata);
70
71 return ECORE_CALLBACK_RENEW;
72}
73
74static pa_io_event *
75_ecore_pa_io_new(pa_mainloop_api *api, int fd, pa_io_event_flags_t flags, pa_io_event_cb_t cb, void *userdata)
76{
77 pa_io_event *event;
78
79 event = calloc(1, sizeof(pa_io_event));
80 event->mainloop = api;
81 event->userdata = userdata;
82 event->callback = cb;
83 event->flags = flags;
84 event->handler = ecore_main_fd_handler_add(fd, map_flags_to_ecore(flags), _ecore_io_wrapper, event, NULL, NULL);
85
86 return event;
87}
88
89static void
90_ecore_pa_io_enable(pa_io_event *event, pa_io_event_flags_t flags)
91{
92 event->flags = flags;
93 ecore_main_fd_handler_active_set(event->handler, map_flags_to_ecore(flags));
94}
95
96static void
97_ecore_pa_io_free(pa_io_event *event)
98{
99 ecore_main_fd_handler_del(event->handler);
100 free(event);
101}
102
103static void
104_ecore_pa_io_set_destroy(pa_io_event *event, pa_io_event_destroy_cb_t cb)
105{
106 event->destroy_callback = cb;
107}
108
109/* Timed events */
110struct pa_time_event
111{
112 pa_mainloop_api *mainloop;
113 Ecore_Timer *timer;
114 struct timeval tv;
115
116 void *userdata;
117
118 pa_time_event_cb_t callback;
119 pa_time_event_destroy_cb_t destroy_callback;
120};
121
122Eina_Bool
123_ecore_time_wrapper(void *data)
124{
125 pa_time_event *event = (pa_time_event *)data;
126
127 event->callback(event->mainloop, event, &event->tv, event->userdata);
128
129 return ECORE_CALLBACK_CANCEL;
130}
131
132pa_time_event *
133_ecore_pa_time_new(pa_mainloop_api *api, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata)
134{
135 pa_time_event *event;
136 struct timeval now;
137 double interval;
138
139 event = calloc(1, sizeof(pa_time_event));
140 event->mainloop = api;
141 event->userdata = userdata;
142 event->callback = cb;
143 event->tv = *tv;
144
145 if (gettimeofday(&now, NULL) == -1)
146 {
147 ERR("Failed to get the current time!");
148 return NULL;
149 }
150
151 interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
152 event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);
153
154 return event;
155}
156
157void
158_ecore_pa_time_restart(pa_time_event *event, const struct timeval *tv)
159{
160 struct timeval now;
161 double interval;
162
163 /* If tv is NULL disable timer */
164 if (!tv)
165 {
166 ecore_timer_del(event->timer);
167 event->timer = NULL;
168 return;
169 }
170
171 event->tv = *tv;
172
173 if (gettimeofday(&now, NULL) == -1)
174 {
175 ERR("Failed to get the current time!");
176 return;
177 }
178
179 interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
180 if (event->timer)
181 {
182 event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);
183 }
184 else
185 {
186 ecore_timer_interval_set(event->timer, interval);
187 ecore_timer_reset(event->timer);
188 }
189}
190
191void
192_ecore_pa_time_free(pa_time_event *event)
193{
194 if (event->timer)
195 ecore_timer_del(event->timer);
196
197 event->timer = NULL;
198
199 free(event);
200}
201
202void
203_ecore_pa_time_set_destroy(pa_time_event *event, pa_time_event_destroy_cb_t cb)
204{
205 event->destroy_callback = cb;
206}
207
208/* Deferred events */
209struct pa_defer_event
210{
211 pa_mainloop_api *mainloop;
212 Ecore_Idler *idler;
213
214 void *userdata;
215
216 pa_defer_event_cb_t callback;
217 pa_defer_event_destroy_cb_t destroy_callback;
218};
219
220Eina_Bool
221_ecore_defer_wrapper(void *data)
222{
223 pa_defer_event *event = (pa_defer_event *)data;
224
225 event->idler = NULL;
226 event->callback(event->mainloop, event, event->userdata);
227
228 return ECORE_CALLBACK_CANCEL;
229}
230
231pa_defer_event *
232_ecore_pa_defer_new(pa_mainloop_api *api, pa_defer_event_cb_t cb, void *userdata)
233{
234 pa_defer_event *event;
235
236 event = calloc(1, sizeof(pa_defer_event));
237 event->mainloop = api;
238 event->userdata = userdata;
239 event->callback = cb;
240
241 event->idler = ecore_idler_add(_ecore_defer_wrapper, event);
242
243 return event;
244}
245
246void
247_ecore_pa_defer_enable(pa_defer_event *event, int b)
248{
249 if (!b && event->idler)
250 {
251 ecore_idler_del(event->idler);
252 event->idler = NULL;
253 }
254 else if (b && !event->idler)
255 {
256 event->idler = ecore_idler_add(_ecore_defer_wrapper, event);
257 }
258}
259
260void
261_ecore_pa_defer_free(pa_defer_event *event)
262{
263 if (event->idler)
264 ecore_idler_del(event->idler);
265
266 event->idler = NULL;
267
268 free(event);
269}
270
271void
272_ecore_pa_defer_set_destroy(pa_defer_event *event, pa_defer_event_destroy_cb_t cb)
273{
274 event->destroy_callback = cb;
275}
276
277static void
278_ecore_pa_quit(pa_mainloop_api *api EINA_UNUSED, int retval EINA_UNUSED)
279{
280 /* FIXME: Need to clean up timers, etc.? */
281 WRN("Not quitting mainloop, although PA requested it");
282}
283
284/* Function table for PA mainloop integration */
285const pa_mainloop_api functable = {
286 .userdata = NULL,
287
288 .io_new = _ecore_pa_io_new,
289 .io_enable = _ecore_pa_io_enable,
290 .io_free = _ecore_pa_io_free,
291 .io_set_destroy = _ecore_pa_io_set_destroy,
292
293 .time_new = _ecore_pa_time_new,
294 .time_restart = _ecore_pa_time_restart,
295 .time_free = _ecore_pa_time_free,
296 .time_set_destroy = _ecore_pa_time_set_destroy,
297
298 .defer_new = _ecore_pa_defer_new,
299 .defer_enable = _ecore_pa_defer_enable,
300 .defer_free = _ecore_pa_defer_free,
301 .defer_set_destroy = _ecore_pa_defer_set_destroy,
302
303 .quit = _ecore_pa_quit,
304};
305
306/* *****************************************************
307 * Ecore mainloop integration end
308 */