diff options
Diffstat (limited to 'osdep/poll_wrapper.c')
-rw-r--r-- | osdep/poll_wrapper.c | 89 |
1 files changed, 89 insertions, 0 deletions
diff --git a/osdep/poll_wrapper.c b/osdep/poll_wrapper.c new file mode 100644 index 0000000..3fe039b --- /dev/null +++ b/osdep/poll_wrapper.c @@ -0,0 +1,89 @@ +/* + * This file is part of mpv. + * + * mpv is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * mpv is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with mpv. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdlib.h> +#include <poll.h> +#include <sys/select.h> +#include <stdio.h> + +#include "common/common.h" +#include "config.h" +#include "poll_wrapper.h" +#include "timer.h" + + +int mp_poll(struct pollfd *fds, int nfds, int64_t timeout_ns) +{ +#if HAVE_PPOLL + struct timespec ts; + ts.tv_sec = timeout_ns / MP_TIME_S_TO_NS(1); + ts.tv_nsec = timeout_ns % MP_TIME_S_TO_NS(1); + struct timespec *tsp = timeout_ns >= 0 ? &ts : NULL; + return ppoll(fds, nfds, tsp, NULL); +#endif + // Round-up to 1ms for short timeouts (100us, 1000us] + if (timeout_ns > MP_TIME_US_TO_NS(100)) + timeout_ns = MPMAX(timeout_ns, MP_TIME_MS_TO_NS(1)); + if (timeout_ns > 0) + timeout_ns /= MP_TIME_MS_TO_NS(1); + return poll(fds, nfds, timeout_ns); +} + +// poll shim that supports device files on macOS. +int polldev(struct pollfd fds[], nfds_t nfds, int timeout) +{ +#ifdef __APPLE__ + int maxfd = 0; + fd_set readfds, writefds; + FD_ZERO(&readfds); + FD_ZERO(&writefds); + for (size_t i = 0; i < nfds; ++i) { + struct pollfd *fd = &fds[i]; + if (fd->fd > maxfd) { + maxfd = fd->fd; + } + if ((fd->events & POLLIN)) { + FD_SET(fd->fd, &readfds); + } + if ((fd->events & POLLOUT)) { + FD_SET(fd->fd, &writefds); + } + } + struct timeval _timeout = { + .tv_sec = timeout / 1000, + .tv_usec = (timeout % 1000) * 1000 + }; + int n = select(maxfd + 1, &readfds, &writefds, NULL, + timeout != -1 ? &_timeout : NULL); + if (n < 0) { + return n; + } + for (size_t i = 0; i < nfds; ++i) { + struct pollfd *fd = &fds[i]; + fd->revents = 0; + if (FD_ISSET(fd->fd, &readfds)) { + fd->revents |= POLLIN; + } + if (FD_ISSET(fd->fd, &writefds)) { + fd->revents |= POLLOUT; + } + } + return n; +#else + return poll(fds, nfds, timeout); +#endif +} |