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 /src/lib/ecore_audio/ecore_audio_pulse_ml.c | |
parent | 01e4c9597e344ce4e34f7889883452ae0dd0a928 (diff) |
ecore_audio: Add pulseaudio output for eo
Signed-off-by: Daniel Willmann <d.willmann@samsung.com>
Diffstat (limited to '')
-rw-r--r-- | src/lib/ecore_audio/ecore_audio_pulse_ml.c | 308 |
1 files changed, 308 insertions, 0 deletions
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 */ | ||
24 | struct 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 | |||
36 | static Ecore_Fd_Handler_Flags | ||
37 | map_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 | |||
42 | static 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 | |||
74 | static 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 | |||
89 | static 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 | |||
96 | static void | ||
97 | _ecore_pa_io_free(pa_io_event *event) | ||
98 | { | ||
99 | ecore_main_fd_handler_del(event->handler); | ||
100 | free(event); | ||
101 | } | ||
102 | |||
103 | static 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 */ | ||
110 | struct 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 | |||
122 | Eina_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 | |||
132 | pa_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 | |||
157 | void | ||
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 | |||
191 | void | ||
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 | |||
202 | void | ||
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 */ | ||
209 | struct 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 | |||
220 | Eina_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 | |||
231 | pa_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 | |||
246 | void | ||
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 | |||
260 | void | ||
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 | |||
271 | void | ||
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 | |||
277 | static 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 */ | ||
285 | const 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 | */ | ||