/src/lib/ecore_audio/ecore_audio_pulse_ml.c

https://github.com/Enlightenment/efl · C · 355 lines · 279 code · 66 blank · 10 comment · 35 complexity · 8d6d25e928604dd9a2aac11486940cc0 MD5 · raw file

  1. #ifdef HAVE_CONFIG_H
  2. #include <config.h>
  3. #endif
  4. #include <stdlib.h>
  5. #include <stdio.h>
  6. #include <string.h>
  7. #ifdef HAVE_FEATURES_H
  8. #include <features.h>
  9. #endif
  10. #include <ctype.h>
  11. #include <errno.h>
  12. #include <pulse/pulseaudio.h>
  13. #include <sys/time.h>
  14. #include <sys/types.h>
  15. #include <sys/socket.h>
  16. #include "ecore_audio_private.h"
  17. /* Ecore mainloop integration start */
  18. struct pa_io_event
  19. {
  20. pa_mainloop_api *mainloop;
  21. Ecore_Fd_Handler *handler;
  22. void *userdata;
  23. pa_io_event_flags_t flags;
  24. pa_io_event_cb_t callback;
  25. pa_io_event_destroy_cb_t destroy_callback;
  26. };
  27. static Ecore_Fd_Handler_Flags
  28. map_flags_to_ecore(pa_io_event_flags_t flags)
  29. {
  30. 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));
  31. }
  32. static Eina_Bool
  33. _ecore_io_wrapper(void *data, Ecore_Fd_Handler *handler)
  34. {
  35. char buf[64];
  36. pa_io_event_flags_t flags = 0;
  37. pa_io_event *event = (pa_io_event *)data;
  38. int fd = 0;
  39. char *disp = NULL;
  40. fd = ecore_main_fd_handler_fd_get(handler);
  41. if (fd < 0) return ECORE_CALLBACK_RENEW;
  42. if (ecore_main_fd_handler_active_get(handler, ECORE_FD_READ))
  43. {
  44. flags |= PA_IO_EVENT_INPUT;
  45. /* Check for HUP and report */
  46. if (recv(fd, buf, 64, MSG_PEEK))
  47. {
  48. if (errno == ESHUTDOWN || errno == ECONNRESET || errno == ECONNABORTED || errno == ENETRESET)
  49. {
  50. DBG("HUP condition detected");
  51. flags |= PA_IO_EVENT_HANGUP;
  52. }
  53. }
  54. }
  55. if (ecore_main_fd_handler_active_get(handler, ECORE_FD_WRITE))
  56. flags |= PA_IO_EVENT_OUTPUT;
  57. if (ecore_main_fd_handler_active_get(handler, ECORE_FD_ERROR))
  58. flags |= PA_IO_EVENT_ERROR;
  59. if (getenv("WAYLAND_DISPLAY"))
  60. {
  61. disp = eina_strdup(getenv("DISPLAY"));
  62. unsetenv("DISPLAY");
  63. }
  64. event->callback(event->mainloop, event, fd, flags, event->userdata);
  65. if (disp) setenv("DISPLAY", disp, 1);
  66. free(disp);
  67. return ECORE_CALLBACK_RENEW;
  68. }
  69. static pa_io_event *
  70. _ecore_pa_io_new(pa_mainloop_api *api, int fd, pa_io_event_flags_t flags, pa_io_event_cb_t cb, void *userdata)
  71. {
  72. pa_io_event *event;
  73. event = calloc(1, sizeof(pa_io_event));
  74. if (!event)
  75. {
  76. ERR("Failed to allocate memory!");
  77. return NULL;
  78. }
  79. event->mainloop = api;
  80. event->userdata = userdata;
  81. event->callback = cb;
  82. event->flags = flags;
  83. event->handler = ecore_main_fd_handler_add(fd, map_flags_to_ecore(flags), _ecore_io_wrapper, event, NULL, NULL);
  84. return event;
  85. }
  86. static void
  87. _ecore_pa_io_enable(pa_io_event *event, pa_io_event_flags_t flags)
  88. {
  89. event->flags = flags;
  90. ecore_main_fd_handler_active_set(event->handler, map_flags_to_ecore(flags));
  91. }
  92. static void
  93. _ecore_pa_io_free(pa_io_event *event)
  94. {
  95. ecore_main_fd_handler_del(event->handler);
  96. free(event);
  97. }
  98. static void
  99. _ecore_pa_io_set_destroy(pa_io_event *event, pa_io_event_destroy_cb_t cb)
  100. {
  101. event->destroy_callback = cb;
  102. }
  103. /* Timed events */
  104. struct pa_time_event
  105. {
  106. pa_mainloop_api *mainloop;
  107. Ecore_Timer *timer;
  108. struct timeval tv;
  109. void *userdata;
  110. pa_time_event_cb_t callback;
  111. pa_time_event_destroy_cb_t destroy_callback;
  112. Eina_Bool in_event : 1;
  113. Eina_Bool dead : 1;
  114. };
  115. void
  116. _ecore_pa_time_free(pa_time_event *event)
  117. {
  118. event->dead = 1;
  119. if (event->in_event) return;
  120. if (event->timer)
  121. ecore_timer_del(event->timer);
  122. event->timer = NULL;
  123. free(event);
  124. }
  125. Eina_Bool
  126. _ecore_time_wrapper(void *data)
  127. {
  128. pa_time_event *event = (pa_time_event *)data;
  129. char *disp = NULL;
  130. if (getenv("WAYLAND_DISPLAY"))
  131. {
  132. disp = eina_strdup(getenv("DISPLAY"));
  133. unsetenv("DISPLAY");
  134. }
  135. event->in_event = 1;
  136. event->callback(event->mainloop, event, &event->tv, event->userdata);
  137. if (disp) setenv("DISPLAY", disp, 1);
  138. free(disp);
  139. event->in_event = 0;
  140. event->timer = NULL;
  141. if (event->dead)
  142. _ecore_pa_time_free(event);
  143. return ECORE_CALLBACK_CANCEL;
  144. }
  145. pa_time_event *
  146. _ecore_pa_time_new(pa_mainloop_api *api, const struct timeval *tv, pa_time_event_cb_t cb, void *userdata)
  147. {
  148. pa_time_event *event;
  149. struct timeval now;
  150. double interval;
  151. event = calloc(1, sizeof(pa_time_event));
  152. if (!event)
  153. {
  154. ERR("Failed to allocate memory!");
  155. return NULL;
  156. }
  157. event->mainloop = api;
  158. event->userdata = userdata;
  159. event->callback = cb;
  160. event->tv = *tv;
  161. if (gettimeofday(&now, NULL) == -1)
  162. {
  163. ERR("Failed to get the current time!");
  164. free(event);
  165. return NULL;
  166. }
  167. interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
  168. event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);
  169. return event;
  170. }
  171. void
  172. _ecore_pa_time_restart(pa_time_event *event, const struct timeval *tv)
  173. {
  174. struct timeval now;
  175. double interval;
  176. /* If tv is NULL disable timer */
  177. if (!tv)
  178. {
  179. ecore_timer_del(event->timer);
  180. event->timer = NULL;
  181. return;
  182. }
  183. event->tv = *tv;
  184. if (gettimeofday(&now, NULL) == -1)
  185. {
  186. ERR("Failed to get the current time!");
  187. return;
  188. }
  189. interval = (tv->tv_sec - now.tv_sec) + (tv->tv_usec - now.tv_usec) / 1000;
  190. if (!event->timer)
  191. {
  192. event->timer = ecore_timer_add(interval, _ecore_time_wrapper, event);
  193. }
  194. else
  195. {
  196. ecore_timer_interval_set(event->timer, interval);
  197. ecore_timer_reset(event->timer);
  198. }
  199. }
  200. void
  201. _ecore_pa_time_set_destroy(pa_time_event *event, pa_time_event_destroy_cb_t cb)
  202. {
  203. event->destroy_callback = cb;
  204. }
  205. /* Deferred events */
  206. struct pa_defer_event
  207. {
  208. pa_mainloop_api *mainloop;
  209. Ecore_Idler *idler;
  210. void *userdata;
  211. pa_defer_event_cb_t callback;
  212. pa_defer_event_destroy_cb_t destroy_callback;
  213. };
  214. Eina_Bool
  215. _ecore_defer_wrapper(void *data)
  216. {
  217. pa_defer_event *event = (pa_defer_event *)data;
  218. event->idler = NULL;
  219. event->callback(event->mainloop, event, event->userdata);
  220. return ECORE_CALLBACK_CANCEL;
  221. }
  222. pa_defer_event *
  223. _ecore_pa_defer_new(pa_mainloop_api *api, pa_defer_event_cb_t cb, void *userdata)
  224. {
  225. pa_defer_event *event;
  226. event = calloc(1, sizeof(pa_defer_event));
  227. if (!event)
  228. {
  229. ERR("Failed to allocate memory!");
  230. return NULL;
  231. }
  232. event->mainloop = api;
  233. event->userdata = userdata;
  234. event->callback = cb;
  235. event->idler = ecore_idler_add(_ecore_defer_wrapper, event);
  236. return event;
  237. }
  238. void
  239. _ecore_pa_defer_enable(pa_defer_event *event, int b)
  240. {
  241. if (!b && event->idler)
  242. {
  243. ecore_idler_del(event->idler);
  244. event->idler = NULL;
  245. }
  246. else if (b && !event->idler)
  247. {
  248. event->idler = ecore_idler_add(_ecore_defer_wrapper, event);
  249. }
  250. }
  251. void
  252. _ecore_pa_defer_free(pa_defer_event *event)
  253. {
  254. if (event->idler)
  255. ecore_idler_del(event->idler);
  256. event->idler = NULL;
  257. free(event);
  258. }
  259. void
  260. _ecore_pa_defer_set_destroy(pa_defer_event *event, pa_defer_event_destroy_cb_t cb)
  261. {
  262. event->destroy_callback = cb;
  263. }
  264. static void
  265. _ecore_pa_quit(pa_mainloop_api *api EINA_UNUSED, int retval EINA_UNUSED)
  266. {
  267. /* FIXME: Need to clean up timers, etc.? */
  268. WRN("Not quitting mainloop, although PA requested it");
  269. }
  270. /* Function table for PA mainloop integration */
  271. const pa_mainloop_api functable = {
  272. .userdata = NULL,
  273. .io_new = _ecore_pa_io_new,
  274. .io_enable = _ecore_pa_io_enable,
  275. .io_free = _ecore_pa_io_free,
  276. .io_set_destroy = _ecore_pa_io_set_destroy,
  277. .time_new = _ecore_pa_time_new,
  278. .time_restart = _ecore_pa_time_restart,
  279. .time_free = _ecore_pa_time_free,
  280. .time_set_destroy = _ecore_pa_time_set_destroy,
  281. .defer_new = _ecore_pa_defer_new,
  282. .defer_enable = _ecore_pa_defer_enable,
  283. .defer_free = _ecore_pa_defer_free,
  284. .defer_set_destroy = _ecore_pa_defer_set_destroy,
  285. .quit = _ecore_pa_quit,
  286. };
  287. /* *****************************************************
  288. * Ecore mainloop integration end
  289. */