1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2006 Lennart Poettering 5 6 PulseAudio is free software; you can redistribute it and/or modify 7 it under the terms of the GNU Lesser General Public License as 8 published by the Free Software Foundation; either version 2.1 of the 9 License, or (at your option) any later version. 10 11 PulseAudio is distributed in the hope that it will be useful, but 12 WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 18***/ 19 20#ifdef HAVE_CONFIG_H 21#include <config.h> 22#endif 23 24#include <pulse/timeval.h> 25#include <pulse/xmalloc.h> 26 27#include <pulsecore/macro.h> 28 29#include "avahi-wrap.h" 30 31typedef struct { 32 AvahiPoll api; 33 pa_mainloop_api *mainloop; 34} pa_avahi_poll; 35 36struct AvahiWatch { 37 pa_io_event *io_event; 38 pa_avahi_poll *avahi_poll; 39 AvahiWatchEvent current_event; 40 AvahiWatchCallback callback; 41 void *userdata; 42}; 43 44static AvahiWatchEvent translate_io_flags_back(pa_io_event_flags_t e) { 45 return 46 (e & PA_IO_EVENT_INPUT ? AVAHI_WATCH_IN : 0) | 47 (e & PA_IO_EVENT_OUTPUT ? AVAHI_WATCH_OUT : 0) | 48 (e & PA_IO_EVENT_ERROR ? AVAHI_WATCH_ERR : 0) | 49 (e & PA_IO_EVENT_HANGUP ? AVAHI_WATCH_HUP : 0); 50} 51 52static pa_io_event_flags_t translate_io_flags(AvahiWatchEvent e) { 53 return 54 (e & AVAHI_WATCH_IN ? PA_IO_EVENT_INPUT : 0) | 55 (e & AVAHI_WATCH_OUT ? PA_IO_EVENT_OUTPUT : 0) | 56 (e & AVAHI_WATCH_ERR ? PA_IO_EVENT_ERROR : 0) | 57 (e & AVAHI_WATCH_HUP ? PA_IO_EVENT_HANGUP : 0); 58} 59 60static void watch_callback(pa_mainloop_api*a, pa_io_event* e, int fd, pa_io_event_flags_t events, void *userdata) { 61 AvahiWatch *w = userdata; 62 63 pa_assert(a); 64 pa_assert(e); 65 pa_assert(w); 66 67 w->current_event = translate_io_flags_back(events); 68 w->callback(w, fd, w->current_event, w->userdata); 69 w->current_event = 0; 70} 71 72static AvahiWatch* watch_new(const AvahiPoll *api, int fd, AvahiWatchEvent event, AvahiWatchCallback callback, void *userdata) { 73 pa_avahi_poll *p; 74 AvahiWatch *w; 75 76 pa_assert(api); 77 pa_assert(fd >= 0); 78 pa_assert(callback); 79 pa_assert_se(p = api->userdata); 80 81 w = pa_xnew(AvahiWatch, 1); 82 w->avahi_poll = p; 83 w->current_event = 0; 84 w->callback = callback; 85 w->userdata = userdata; 86 w->io_event = p->mainloop->io_new(p->mainloop, fd, translate_io_flags(event), watch_callback, w); 87 88 return w; 89} 90 91static void watch_update(AvahiWatch *w, AvahiWatchEvent event) { 92 pa_assert(w); 93 94 w->avahi_poll->mainloop->io_enable(w->io_event, translate_io_flags(event)); 95} 96 97static AvahiWatchEvent watch_get_events(AvahiWatch *w) { 98 pa_assert(w); 99 100 return w->current_event; 101} 102 103static void watch_free(AvahiWatch *w) { 104 pa_assert(w); 105 106 w->avahi_poll->mainloop->io_free(w->io_event); 107 pa_xfree(w); 108} 109 110struct AvahiTimeout { 111 pa_time_event *time_event; 112 pa_avahi_poll *avahi_poll; 113 AvahiTimeoutCallback callback; 114 void *userdata; 115}; 116 117static void timeout_callback(pa_mainloop_api*a, pa_time_event* e, const struct timeval *t, void *userdata) { 118 AvahiTimeout *to = userdata; 119 120 pa_assert(a); 121 pa_assert(e); 122 123 to->callback(to, to->userdata); 124} 125 126static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) { 127 pa_avahi_poll *p; 128 AvahiTimeout *t; 129 130 pa_assert(api); 131 pa_assert(callback); 132 pa_assert_se(p = api->userdata); 133 134 t = pa_xnew(AvahiTimeout, 1); 135 t->avahi_poll = p; 136 t->callback = callback; 137 t->userdata = userdata; 138 139 t->time_event = tv ? p->mainloop->time_new(p->mainloop, tv, timeout_callback, t) : NULL; 140 141 return t; 142} 143 144static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { 145 146 pa_assert(t); 147 148 if (t->time_event && tv) 149 t->avahi_poll->mainloop->time_restart(t->time_event, tv); 150 else if (!t->time_event && tv) 151 t->time_event = t->avahi_poll->mainloop->time_new(t->avahi_poll->mainloop, tv, timeout_callback, t); 152 else if (t->time_event && !tv) { 153 t->avahi_poll->mainloop->time_free(t->time_event); 154 t->time_event = NULL; 155 } 156} 157 158static void timeout_free(AvahiTimeout *t) { 159 pa_assert(t); 160 161 if (t->time_event) 162 t->avahi_poll->mainloop->time_free(t->time_event); 163 pa_xfree(t); 164} 165 166AvahiPoll* pa_avahi_poll_new(pa_mainloop_api *m) { 167 pa_avahi_poll *p; 168 169 pa_assert(m); 170 171 p = pa_xnew(pa_avahi_poll, 1); 172 173 p->api.userdata = p; 174 p->api.watch_new = watch_new; 175 p->api.watch_update = watch_update; 176 p->api.watch_get_events = watch_get_events; 177 p->api.watch_free = watch_free; 178 p->api.timeout_new = timeout_new; 179 p->api.timeout_update = timeout_update; 180 p->api.timeout_free = timeout_free; 181 p->mainloop = m; 182 183 return &p->api; 184} 185 186void pa_avahi_poll_free(AvahiPoll *api) { 187 pa_avahi_poll *p; 188 pa_assert(api); 189 pa_assert_se(p = api->userdata); 190 191 pa_xfree(p); 192} 193 194