pulse: implement custom mainloop poll function

Implement setting a custom poll function. When there is a custom
function, just poll the epoll fd in it.

Fixes #276
This commit is contained in:
Wim Taymans 2020-09-07 15:50:58 +02:00
parent b6e84ded75
commit f541bf9037
2 changed files with 40 additions and 3 deletions

View file

@ -27,6 +27,7 @@
#include <spa/utils/ringbuffer.h> #include <spa/utils/ringbuffer.h>
#include <spa/param/audio/format-utils.h> #include <spa/param/audio/format-utils.h>
#include <pulse/mainloop.h>
#include <pulse/stream.h> #include <pulse/stream.h>
#include <pulse/format.h> #include <pulse/format.h>
#include <pulse/subscribe.h> #include <pulse/subscribe.h>
@ -219,6 +220,10 @@ struct pa_mainloop {
int timeout; int timeout;
int n_events; int n_events;
int fd;
pa_poll_func poll_func;
void *poll_func_userdata;
}; };
struct param { struct param {

View file

@ -18,12 +18,14 @@
*/ */
#include <errno.h> #include <errno.h>
#include <poll.h>
#include <pipewire/log.h> #include <pipewire/log.h>
#include <pipewire/loop.h> #include <pipewire/loop.h>
#include <pulse/mainloop.h> #include <pulse/mainloop.h>
#include <pulse/xmalloc.h> #include <pulse/xmalloc.h>
#include <pulse/timeval.h>
#include "internal.h" #include "internal.h"
@ -265,6 +267,7 @@ pa_mainloop *pa_mainloop_new(void)
if (loop->loop == NULL) if (loop->loop == NULL)
goto no_loop; goto no_loop;
loop->fd = pw_loop_get_fd(loop->loop);
loop->event = pw_loop_add_event(loop->loop, do_stop, loop); loop->event = pw_loop_add_event(loop->loop, do_stop, loop);
loop->api = api; loop->api = api;
loop->api.userdata = loop->loop; loop->api.userdata = loop->loop;
@ -293,16 +296,44 @@ int pa_mainloop_prepare(pa_mainloop *m, int timeout)
return 0; return 0;
} }
static int usec_to_timeout(pa_usec_t u)
{
if (u == PA_USEC_INVALID)
return -1;
return (u + PA_USEC_PER_MSEC - 1) / PA_USEC_PER_MSEC;
}
/** Execute the previously prepared poll. Returns a negative value on error.*/ /** Execute the previously prepared poll. Returns a negative value on error.*/
SPA_EXPORT SPA_EXPORT
int pa_mainloop_poll(pa_mainloop *m) int pa_mainloop_poll(pa_mainloop *m)
{ {
int res; int res;
bool do_iterate;
if (m->quit) if (m->quit)
return -2; return -2;
if (m->poll_func) {
struct pollfd fds[1];
fds[0].fd = m->fd;
fds[0].events = POLLIN;
fds[0].revents = 0;
res = m->poll_func(fds, 1,
usec_to_timeout(m->timeout),
m->poll_func_userdata);
do_iterate = res == 1 && SPA_FLAG_IS_SET(fds[0].revents, POLLIN);
} else {
do_iterate = true;
}
if (do_iterate) {
pw_loop_enter(m->loop);
res = pw_loop_iterate(m->loop, m->timeout); res = pw_loop_iterate(m->loop, m->timeout);
pw_loop_leave(m->loop);
}
if (res < 0) { if (res < 0) {
if (res == -EINTR) if (res == -EINTR)
res = 0; res = 0;
@ -394,10 +425,11 @@ void pa_mainloop_wakeup(pa_mainloop *m)
SPA_EXPORT SPA_EXPORT
void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata) void pa_mainloop_set_poll_func(pa_mainloop *m, pa_poll_func poll_func, void *userdata)
{ {
pw_log_warn("Not Implemented"); pa_assert(m);
m->poll_func = poll_func;
m->poll_func_userdata = userdata;
} }
struct once_info { struct once_info {
void (*callback)(pa_mainloop_api*m, void *userdata); void (*callback)(pa_mainloop_api*m, void *userdata);
void *userdata; void *userdata;