mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	loop: build loop with SPA interface
This commit is contained in:
		
							parent
							
								
									80deb6b387
								
							
						
					
					
						commit
						f42268b9a5
					
				
					 6 changed files with 429 additions and 446 deletions
				
			
		| 
						 | 
					@ -35,20 +35,20 @@
 | 
				
			||||||
#include <pinos/client/loop.h>
 | 
					#include <pinos/client/loop.h>
 | 
				
			||||||
#include <pinos/client/log.h>
 | 
					#include <pinos/client/log.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct _PinosSource {
 | 
					typedef struct {
 | 
				
			||||||
  SpaSource source;
 | 
					  SpaSource source;
 | 
				
			||||||
  SpaList link;
 | 
					  SpaList link;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool close;
 | 
					  bool close;
 | 
				
			||||||
  union {
 | 
					  union {
 | 
				
			||||||
    PinosSourceIOFunc io;
 | 
					    SpaSourceIOFunc io;
 | 
				
			||||||
    PinosSourceIdleFunc idle;
 | 
					    SpaSourceIdleFunc idle;
 | 
				
			||||||
    PinosSourceEventFunc event;
 | 
					    SpaSourceEventFunc event;
 | 
				
			||||||
    PinosSourceTimerFunc timer;
 | 
					    SpaSourceTimerFunc timer;
 | 
				
			||||||
    PinosSourceSignalFunc signal;
 | 
					    SpaSourceSignalFunc signal;
 | 
				
			||||||
  } func;
 | 
					  } func;
 | 
				
			||||||
  int signal_number;
 | 
					  int signal_number;
 | 
				
			||||||
};
 | 
					} SpaSourceImpl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#define DATAS_SIZE (4096 * 8)
 | 
					#define DATAS_SIZE (4096 * 8)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -66,20 +66,21 @@ typedef struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaList source_list;
 | 
					  SpaList source_list;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PinosLoopHook  pre_func;
 | 
					  SpaLoopHook    pre_func;
 | 
				
			||||||
  PinosLoopHook  post_func;
 | 
					  SpaLoopHook    post_func;
 | 
				
			||||||
  void          *hook_data;
 | 
					  void          *hook_data;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  int            epoll_fd;
 | 
				
			||||||
  pthread_t      thread;
 | 
					  pthread_t      thread;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaLoop loop;
 | 
					  SpaLoop        loop;
 | 
				
			||||||
 | 
					  SpaLoopControl control;
 | 
				
			||||||
 | 
					  SpaLoopUtils   utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PinosSource  *event;
 | 
					  SpaSource     *event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaRingbuffer buffer;
 | 
					  SpaRingbuffer  buffer;
 | 
				
			||||||
  uint8_t       buffer_data[DATAS_SIZE];
 | 
					  uint8_t        buffer_data[DATAS_SIZE];
 | 
				
			||||||
 | 
					 | 
				
			||||||
  int epoll_fd;
 | 
					 | 
				
			||||||
} PinosLoopImpl;
 | 
					} PinosLoopImpl;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static SpaResult
 | 
					static SpaResult
 | 
				
			||||||
| 
						 | 
					@ -189,7 +190,7 @@ loop_invoke (SpaLoop       *loop,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    spa_ringbuffer_write_advance (&impl->buffer, item->item_size);
 | 
					    spa_ringbuffer_write_advance (&impl->buffer, item->item_size);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pinos_source_event_signal (impl->event);
 | 
					    pinos_loop_signal_event (&impl->this, impl->event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    if (seq != SPA_ID_INVALID)
 | 
					    if (seq != SPA_ID_INVALID)
 | 
				
			||||||
      res = SPA_RESULT_RETURN_ASYNC (seq);
 | 
					      res = SPA_RESULT_RETURN_ASYNC (seq);
 | 
				
			||||||
| 
						 | 
					@ -200,8 +201,8 @@ loop_invoke (SpaLoop       *loop,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
event_func (PinosSource *source,
 | 
					event_func (SpaSource *source,
 | 
				
			||||||
            void        *data)
 | 
					            void      *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosLoopImpl *impl = data;
 | 
					  PinosLoopImpl *impl = data;
 | 
				
			||||||
  size_t offset;
 | 
					  size_t offset;
 | 
				
			||||||
| 
						 | 
					@ -213,6 +214,342 @@ event_func (PinosSource *source,
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int
 | 
				
			||||||
 | 
					loop_get_fd (SpaLoopControl *ctrl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return impl->epoll_fd;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					loop_set_hooks (SpaLoopControl *ctrl,
 | 
				
			||||||
 | 
					                SpaLoopHook     pre_func,
 | 
				
			||||||
 | 
					                SpaLoopHook     post_func,
 | 
				
			||||||
 | 
					                void           *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  impl->pre_func = pre_func;
 | 
				
			||||||
 | 
					  impl->post_func = post_func;
 | 
				
			||||||
 | 
					  impl->hook_data = data;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					loop_enter (SpaLoopControl  *ctrl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
 | 
				
			||||||
 | 
					  impl->thread = pthread_self();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					loop_leave (SpaLoopControl  *ctrl)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
 | 
				
			||||||
 | 
					  impl->thread = 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaResult
 | 
				
			||||||
 | 
					loop_iterate (SpaLoopControl *ctrl,
 | 
				
			||||||
 | 
					              int             timeout)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (ctrl, PinosLoopImpl, control);
 | 
				
			||||||
 | 
					  struct epoll_event ep[32];
 | 
				
			||||||
 | 
					  int i, nfds, save_errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (SPA_UNLIKELY (impl->pre_func))
 | 
				
			||||||
 | 
					    impl->pre_func (ctrl, impl->hook_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (SPA_UNLIKELY ((nfds = epoll_wait (impl->epoll_fd, ep, SPA_N_ELEMENTS (ep), timeout)) < 0))
 | 
				
			||||||
 | 
					    save_errno = errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (SPA_UNLIKELY (impl->post_func))
 | 
				
			||||||
 | 
					    impl->post_func (ctrl, impl->hook_data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (SPA_UNLIKELY (nfds < 0)) {
 | 
				
			||||||
 | 
					    errno = save_errno;
 | 
				
			||||||
 | 
					    return SPA_RESULT_ERRNO;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for (i = 0; i < nfds; i++) {
 | 
				
			||||||
 | 
					    SpaSource *source = ep[i].data.ptr;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source->rmask = 0;
 | 
				
			||||||
 | 
					    if (ep[i].events & EPOLLIN)
 | 
				
			||||||
 | 
					      source->rmask |= SPA_IO_IN;
 | 
				
			||||||
 | 
					    if (ep[i].events & EPOLLOUT)
 | 
				
			||||||
 | 
					      source->rmask |= SPA_IO_OUT;
 | 
				
			||||||
 | 
					    if (ep[i].events & EPOLLHUP)
 | 
				
			||||||
 | 
					      source->rmask |= SPA_IO_HUP;
 | 
				
			||||||
 | 
					    if (ep[i].events & EPOLLERR)
 | 
				
			||||||
 | 
					      source->rmask |= SPA_IO_ERR;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    source->func (source);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					  return SPA_RESULT_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					source_io_func (SpaSource *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
 | 
				
			||||||
 | 
					  s->func.io (source, source->fd, source->rmask, source->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaSource *
 | 
				
			||||||
 | 
					loop_add_io (SpaLoopUtils    *utils,
 | 
				
			||||||
 | 
					             int              fd,
 | 
				
			||||||
 | 
					             SpaIO            mask,
 | 
				
			||||||
 | 
					             bool             close,
 | 
				
			||||||
 | 
					             SpaSourceIOFunc  func,
 | 
				
			||||||
 | 
					             void            *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
 | 
				
			||||||
 | 
					  SpaSourceImpl *source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source = calloc (1, sizeof (SpaSourceImpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source->source.loop = &impl->loop;
 | 
				
			||||||
 | 
					  source->source.func = source_io_func;
 | 
				
			||||||
 | 
					  source->source.data = data;
 | 
				
			||||||
 | 
					  source->source.fd = fd;
 | 
				
			||||||
 | 
					  source->source.mask = mask;
 | 
				
			||||||
 | 
					  source->close = close;
 | 
				
			||||||
 | 
					  source->func.io = func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_loop_add_source (&impl->loop, &source->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_insert (&impl->source_list, &source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return &source->source;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaResult
 | 
				
			||||||
 | 
					loop_update_io (SpaSource *source,
 | 
				
			||||||
 | 
					                SpaIO        mask)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  source->mask = mask;
 | 
				
			||||||
 | 
					  return spa_loop_update_source (source->loop, source);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					source_idle_func (SpaSource *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
 | 
				
			||||||
 | 
					  s->func.idle (source, source->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaSource *
 | 
				
			||||||
 | 
					loop_add_idle (SpaLoopUtils      *utils,
 | 
				
			||||||
 | 
					               SpaSourceIdleFunc  func,
 | 
				
			||||||
 | 
					               void              *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
 | 
				
			||||||
 | 
					  SpaSourceImpl *source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source = calloc (1, sizeof (SpaSourceImpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source->source.loop = &impl->loop;
 | 
				
			||||||
 | 
					  source->source.func = source_idle_func;
 | 
				
			||||||
 | 
					  source->source.data = data;
 | 
				
			||||||
 | 
					  source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
 | 
				
			||||||
 | 
					  source->close = true;
 | 
				
			||||||
 | 
					  source->source.mask = SPA_IO_IN;
 | 
				
			||||||
 | 
					  source->func.idle = func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_loop_add_source (&impl->loop, &source->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_insert (&impl->source_list, &source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_loop_utils_enable_idle (&impl->utils, &source->source, true);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return &source->source;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					loop_enable_idle (SpaSource *source,
 | 
				
			||||||
 | 
					                  bool       enabled)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint64_t count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (enabled) {
 | 
				
			||||||
 | 
					    count = 1;
 | 
				
			||||||
 | 
					    if (write (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
				
			||||||
 | 
					      pinos_log_warn ("loop %p: failed to write idle fd: %s", source, strerror (errno));
 | 
				
			||||||
 | 
					  } else {
 | 
				
			||||||
 | 
					    if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
				
			||||||
 | 
					      pinos_log_warn ("loop %p: failed to read idle fd: %s", source, strerror (errno));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					source_event_func (SpaSource *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
 | 
				
			||||||
 | 
					  uint64_t count;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
				
			||||||
 | 
					    pinos_log_warn ("loop %p: failed to read event fd: %s", source, strerror (errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  s->func.event (source, source->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaSource *
 | 
				
			||||||
 | 
					loop_add_event (SpaLoopUtils       *utils,
 | 
				
			||||||
 | 
					                SpaSourceEventFunc  func,
 | 
				
			||||||
 | 
					                void               *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
 | 
				
			||||||
 | 
					  SpaSourceImpl *source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source = calloc (1, sizeof (SpaSourceImpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source->source.loop = &impl->loop;
 | 
				
			||||||
 | 
					  source->source.func = source_event_func;
 | 
				
			||||||
 | 
					  source->source.data = data;
 | 
				
			||||||
 | 
					  source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
 | 
				
			||||||
 | 
					  source->source.mask = SPA_IO_IN;
 | 
				
			||||||
 | 
					  source->close = true;
 | 
				
			||||||
 | 
					  source->func.event = func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_loop_add_source (&impl->loop, &source->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_insert (&impl->source_list, &source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return &source->source;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					loop_signal_event (SpaSource *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  uint64_t count = 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (write (source->fd, &count, sizeof(uint64_t)) != sizeof(uint64_t))
 | 
				
			||||||
 | 
					    pinos_log_warn ("loop %p: failed to write event fd: %s", source, strerror (errno));
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					source_timer_func (SpaSource *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
 | 
				
			||||||
 | 
					  uint64_t expires;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (read (source->fd, &expires, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
				
			||||||
 | 
					    pinos_log_warn ("loop %p: failed to read timer fd: %s", source, strerror (errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  s->func.timer (source, source->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaSource *
 | 
				
			||||||
 | 
					loop_add_timer (SpaLoopUtils       *utils,
 | 
				
			||||||
 | 
					                SpaSourceTimerFunc  func,
 | 
				
			||||||
 | 
					                void               *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
 | 
				
			||||||
 | 
					  SpaSourceImpl *source;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source = calloc (1, sizeof (SpaSourceImpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source->source.loop = &impl->loop;
 | 
				
			||||||
 | 
					  source->source.func = source_timer_func;
 | 
				
			||||||
 | 
					  source->source.data = data;
 | 
				
			||||||
 | 
					  source->source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
 | 
				
			||||||
 | 
					  source->source.mask = SPA_IO_IN;
 | 
				
			||||||
 | 
					  source->close = true;
 | 
				
			||||||
 | 
					  source->func.timer = func;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_loop_add_source (&impl->loop, &source->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_insert (&impl->source_list, &source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return &source->source;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaResult
 | 
				
			||||||
 | 
					loop_update_timer (SpaSource       *source,
 | 
				
			||||||
 | 
					                   struct timespec *value,
 | 
				
			||||||
 | 
					                   struct timespec *interval,
 | 
				
			||||||
 | 
					                   bool             absolute)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  struct itimerspec its;
 | 
				
			||||||
 | 
					  int flags = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_zero (its);
 | 
				
			||||||
 | 
					  if (value)
 | 
				
			||||||
 | 
					    its.it_value = *value;
 | 
				
			||||||
 | 
					  if (interval)
 | 
				
			||||||
 | 
					    its.it_interval = *interval;
 | 
				
			||||||
 | 
					  if (absolute)
 | 
				
			||||||
 | 
					    flags |= TFD_TIMER_ABSTIME;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (timerfd_settime (source->fd, flags, &its, NULL) < 0)
 | 
				
			||||||
 | 
					    return SPA_RESULT_ERRNO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return SPA_RESULT_OK;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					source_signal_func (SpaSource *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
 | 
				
			||||||
 | 
					  struct signalfd_siginfo signal_info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (read (source->fd, &signal_info, sizeof (signal_info)) != sizeof (signal_info))
 | 
				
			||||||
 | 
					    pinos_log_warn ("loop %p: failed to read signal fd: %s", source, strerror (errno));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  s->func.signal (source, s->signal_number, source->data);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static SpaSource *
 | 
				
			||||||
 | 
					loop_add_signal (SpaLoopUtils        *utils,
 | 
				
			||||||
 | 
					                 int                  signal_number,
 | 
				
			||||||
 | 
					                 SpaSourceSignalFunc  func,
 | 
				
			||||||
 | 
					                 void                *data)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (utils, PinosLoopImpl, utils);
 | 
				
			||||||
 | 
					  SpaSourceImpl *source;
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					  sigset_t mask;
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source = calloc (1, sizeof (SpaSourceImpl));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  source->source.loop = &impl->loop;
 | 
				
			||||||
 | 
					  source->source.func = source_signal_func;
 | 
				
			||||||
 | 
					  source->source.data = data;
 | 
				
			||||||
 | 
					#if 0
 | 
				
			||||||
 | 
					  sigemptyset (&mask);
 | 
				
			||||||
 | 
					  sigaddset (&mask, signal_number);
 | 
				
			||||||
 | 
					  source->source.fd = signalfd (-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
 | 
				
			||||||
 | 
					  sigprocmask (SIG_BLOCK, &mask, NULL);
 | 
				
			||||||
 | 
					#endif
 | 
				
			||||||
 | 
					  source->source.mask = SPA_IO_IN;
 | 
				
			||||||
 | 
					  source->close = true;
 | 
				
			||||||
 | 
					  source->func.signal = func;
 | 
				
			||||||
 | 
					  source->signal_number = signal_number;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_loop_add_source (&impl->loop, &source->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_insert (&impl->source_list, &source->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return &source->source;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void
 | 
				
			||||||
 | 
					loop_destroy_source (SpaSource *source)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  SpaSourceImpl *s = SPA_CONTAINER_OF (source, SpaSourceImpl, source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_list_remove (&s->link);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  spa_loop_remove_source (source->loop, source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  if (source->fd != -1 && s->close)
 | 
				
			||||||
 | 
					    close (source->fd);
 | 
				
			||||||
 | 
					  free (s);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
PinosLoop *
 | 
					PinosLoop *
 | 
				
			||||||
pinos_loop_new (void)
 | 
					pinos_loop_new (void)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
| 
						 | 
					@ -239,11 +576,32 @@ pinos_loop_new (void)
 | 
				
			||||||
  impl->loop.invoke = loop_invoke;
 | 
					  impl->loop.invoke = loop_invoke;
 | 
				
			||||||
  this->loop = &impl->loop;
 | 
					  this->loop = &impl->loop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  impl->control.size = sizeof (SpaLoopControl);
 | 
				
			||||||
 | 
					  impl->control.get_fd = loop_get_fd;
 | 
				
			||||||
 | 
					  impl->control.set_hooks = loop_set_hooks;
 | 
				
			||||||
 | 
					  impl->control.enter = loop_enter;
 | 
				
			||||||
 | 
					  impl->control.leave = loop_leave;
 | 
				
			||||||
 | 
					  impl->control.iterate = loop_iterate;
 | 
				
			||||||
 | 
					  this->control = &impl->control;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  impl->utils.size = sizeof (SpaLoopUtils);
 | 
				
			||||||
 | 
					  impl->utils.add_io = loop_add_io;
 | 
				
			||||||
 | 
					  impl->utils.update_io = loop_update_io;
 | 
				
			||||||
 | 
					  impl->utils.add_idle = loop_add_idle;
 | 
				
			||||||
 | 
					  impl->utils.enable_idle = loop_enable_idle;
 | 
				
			||||||
 | 
					  impl->utils.add_event = loop_add_event;
 | 
				
			||||||
 | 
					  impl->utils.signal_event = loop_signal_event;
 | 
				
			||||||
 | 
					  impl->utils.add_timer = loop_add_timer;
 | 
				
			||||||
 | 
					  impl->utils.update_timer = loop_update_timer;
 | 
				
			||||||
 | 
					  impl->utils.add_signal = loop_add_signal;
 | 
				
			||||||
 | 
					  impl->utils.destroy_source = loop_destroy_source;
 | 
				
			||||||
 | 
					  this->utils = &impl->utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  spa_ringbuffer_init (&impl->buffer, DATAS_SIZE);
 | 
					  spa_ringbuffer_init (&impl->buffer, DATAS_SIZE);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  impl->event = pinos_loop_add_event (this,
 | 
					  impl->event = loop_add_event (&impl->utils,
 | 
				
			||||||
                                      event_func,
 | 
					                                event_func,
 | 
				
			||||||
                                      impl);
 | 
					                                impl);
 | 
				
			||||||
  return this;
 | 
					  return this;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -251,347 +609,13 @@ void
 | 
				
			||||||
pinos_loop_destroy (PinosLoop *loop)
 | 
					pinos_loop_destroy (PinosLoop *loop)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
				
			||||||
  PinosSource *source, *tmp;
 | 
					  SpaSourceImpl *source, *tmp;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_signal_emit (&loop->destroy_signal, loop);
 | 
					  pinos_signal_emit (&loop->destroy_signal, loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  spa_list_for_each_safe (source, tmp, &impl->source_list, link)
 | 
					  spa_list_for_each_safe (source, tmp, &impl->source_list, link)
 | 
				
			||||||
    pinos_source_destroy (source);
 | 
					    loop_destroy_source (&source->source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  close (impl->epoll_fd);
 | 
					  close (impl->epoll_fd);
 | 
				
			||||||
  free (impl);
 | 
					  free (impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
int
 | 
					 | 
				
			||||||
pinos_loop_get_fd (PinosLoop *loop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return impl->epoll_fd;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
pinos_loop_set_hooks (PinosLoop     *loop,
 | 
					 | 
				
			||||||
                      PinosLoopHook  pre_func,
 | 
					 | 
				
			||||||
                      PinosLoopHook  post_func,
 | 
					 | 
				
			||||||
                      void          *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  impl->pre_func = pre_func;
 | 
					 | 
				
			||||||
  impl->post_func = post_func;
 | 
					 | 
				
			||||||
  impl->hook_data = data;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
pinos_loop_enter_thread (PinosLoop  *loop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  impl->thread = pthread_self();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
pinos_loop_leave_thread (PinosLoop  *loop)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  impl->thread = 0;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SpaResult
 | 
					 | 
				
			||||||
pinos_loop_iterate (PinosLoop *loop,
 | 
					 | 
				
			||||||
                    int        timeout)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  struct epoll_event ep[32];
 | 
					 | 
				
			||||||
  int i, nfds, save_errno;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (SPA_UNLIKELY (impl->pre_func))
 | 
					 | 
				
			||||||
    impl->pre_func (loop, impl->hook_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (SPA_UNLIKELY ((nfds = epoll_wait(impl->epoll_fd, ep, SPA_N_ELEMENTS (ep), timeout)) < 0))
 | 
					 | 
				
			||||||
    save_errno = errno;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (SPA_UNLIKELY (impl->post_func))
 | 
					 | 
				
			||||||
    impl->post_func (loop, impl->hook_data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (SPA_UNLIKELY (nfds < 0)) {
 | 
					 | 
				
			||||||
    errno = save_errno;
 | 
					 | 
				
			||||||
    return SPA_RESULT_ERRNO;
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (i = 0; i < nfds; i++) {
 | 
					 | 
				
			||||||
    SpaSource *source = ep[i].data.ptr;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    source->rmask = 0;
 | 
					 | 
				
			||||||
    if (ep[i].events & EPOLLIN)
 | 
					 | 
				
			||||||
      source->rmask |= SPA_IO_IN;
 | 
					 | 
				
			||||||
    if (ep[i].events & EPOLLOUT)
 | 
					 | 
				
			||||||
      source->rmask |= SPA_IO_OUT;
 | 
					 | 
				
			||||||
    if (ep[i].events & EPOLLHUP)
 | 
					 | 
				
			||||||
      source->rmask |= SPA_IO_HUP;
 | 
					 | 
				
			||||||
    if (ep[i].events & EPOLLERR)
 | 
					 | 
				
			||||||
      source->rmask |= SPA_IO_ERR;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    source->func (source);
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
  return SPA_RESULT_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
source_io_func (SpaSource *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
 | 
					 | 
				
			||||||
  s->func.io (s, s->source.fd, s->source.rmask, s->source.data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *
 | 
					 | 
				
			||||||
pinos_loop_add_io (PinosLoop         *loop,
 | 
					 | 
				
			||||||
                   int                fd,
 | 
					 | 
				
			||||||
                   SpaIO              mask,
 | 
					 | 
				
			||||||
                   bool               close,
 | 
					 | 
				
			||||||
                   PinosSourceIOFunc  func,
 | 
					 | 
				
			||||||
                   void              *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  PinosSource *source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source = calloc (1, sizeof (PinosSource));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source->source.loop = loop->loop;
 | 
					 | 
				
			||||||
  source->source.func = source_io_func;
 | 
					 | 
				
			||||||
  source->source.data = data;
 | 
					 | 
				
			||||||
  source->source.fd = fd;
 | 
					 | 
				
			||||||
  source->source.mask = mask;
 | 
					 | 
				
			||||||
  source->close = close;
 | 
					 | 
				
			||||||
  source->func.io = func;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_loop_add_source (loop->loop, &source->source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_list_insert (&impl->source_list, &source->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return source;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SpaResult
 | 
					 | 
				
			||||||
pinos_source_io_update (PinosSource *source,
 | 
					 | 
				
			||||||
                        SpaIO        mask)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  source->source.mask = mask;
 | 
					 | 
				
			||||||
  return spa_loop_update_source (source->source.loop, &source->source);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
source_idle_func (SpaSource *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
 | 
					 | 
				
			||||||
  s->func.idle (s, s->source.data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *
 | 
					 | 
				
			||||||
pinos_loop_add_idle (PinosLoop           *loop,
 | 
					 | 
				
			||||||
                     PinosSourceIdleFunc  func,
 | 
					 | 
				
			||||||
                     void                *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  PinosSource *source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source = calloc (1, sizeof (PinosSource));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source->source.loop = loop->loop;
 | 
					 | 
				
			||||||
  source->source.func = source_idle_func;
 | 
					 | 
				
			||||||
  source->source.data = data;
 | 
					 | 
				
			||||||
  source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
 | 
					 | 
				
			||||||
  source->close = true;
 | 
					 | 
				
			||||||
  source->source.mask = SPA_IO_IN;
 | 
					 | 
				
			||||||
  source->func.idle = func;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_loop_add_source (loop->loop, &source->source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_list_insert (&impl->source_list, &source->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pinos_source_idle_enable (source, true);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return source;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
pinos_source_idle_enable (PinosSource          *source,
 | 
					 | 
				
			||||||
                          bool                  enabled)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  uint64_t count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (enabled) {
 | 
					 | 
				
			||||||
    count = 1;
 | 
					 | 
				
			||||||
    if (write (source->source.fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
					 | 
				
			||||||
      pinos_log_warn ("loop %p: failed to write idle fd: %s", source, strerror (errno));
 | 
					 | 
				
			||||||
  } else {
 | 
					 | 
				
			||||||
    if (read (source->source.fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
					 | 
				
			||||||
      pinos_log_warn ("loop %p: failed to read idle fd: %s", source, strerror (errno));
 | 
					 | 
				
			||||||
  }
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
source_event_func (SpaSource *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
 | 
					 | 
				
			||||||
  uint64_t count;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (read (source->fd, &count, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
					 | 
				
			||||||
    pinos_log_warn ("loop %p: failed to read event fd: %s", source, strerror (errno));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  s->func.event (s, s->source.data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *
 | 
					 | 
				
			||||||
pinos_loop_add_event (PinosLoop            *loop,
 | 
					 | 
				
			||||||
                      PinosSourceEventFunc  func,
 | 
					 | 
				
			||||||
                      void                 *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  PinosSource *source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source = calloc (1, sizeof (PinosSource));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source->source.loop = loop->loop;
 | 
					 | 
				
			||||||
  source->source.func = source_event_func;
 | 
					 | 
				
			||||||
  source->source.data = data;
 | 
					 | 
				
			||||||
  source->source.fd = eventfd (0, EFD_CLOEXEC | EFD_NONBLOCK);
 | 
					 | 
				
			||||||
  source->source.mask = SPA_IO_IN;
 | 
					 | 
				
			||||||
  source->close = true;
 | 
					 | 
				
			||||||
  source->func.event = func;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_loop_add_source (loop->loop, &source->source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_list_insert (&impl->source_list, &source->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return source;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
pinos_source_event_signal (PinosSource *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  uint64_t count = 1;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (write (source->source.fd, &count, sizeof(uint64_t)) != sizeof(uint64_t))
 | 
					 | 
				
			||||||
    pinos_log_warn ("loop %p: failed to write event fd: %s", source, strerror (errno));
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
source_timer_func (SpaSource *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
 | 
					 | 
				
			||||||
  uint64_t expires;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (read (source->fd, &expires, sizeof (uint64_t)) != sizeof (uint64_t))
 | 
					 | 
				
			||||||
    pinos_log_warn ("loop %p: failed to read timer fd: %s", source, strerror (errno));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  s->func.timer (s, s->source.data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *
 | 
					 | 
				
			||||||
pinos_loop_add_timer (PinosLoop            *loop,
 | 
					 | 
				
			||||||
                      PinosSourceTimerFunc  func,
 | 
					 | 
				
			||||||
                      void                 *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  PinosSource *source;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source = calloc (1, sizeof (PinosSource));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source->source.loop = loop->loop;
 | 
					 | 
				
			||||||
  source->source.func = source_timer_func;
 | 
					 | 
				
			||||||
  source->source.data = data;
 | 
					 | 
				
			||||||
  source->source.fd = timerfd_create (CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
 | 
					 | 
				
			||||||
  source->source.mask = SPA_IO_IN;
 | 
					 | 
				
			||||||
  source->close = true;
 | 
					 | 
				
			||||||
  source->func.timer = func;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_loop_add_source (loop->loop, &source->source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_list_insert (&impl->source_list, &source->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return source;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
SpaResult
 | 
					 | 
				
			||||||
pinos_source_timer_update (PinosSource          *source,
 | 
					 | 
				
			||||||
                           struct timespec      *value,
 | 
					 | 
				
			||||||
                           struct timespec      *interval,
 | 
					 | 
				
			||||||
                           bool                  absolute)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  struct itimerspec its;
 | 
					 | 
				
			||||||
  int flags = 0;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_zero (its);
 | 
					 | 
				
			||||||
  if (value)
 | 
					 | 
				
			||||||
    its.it_value = *value;
 | 
					 | 
				
			||||||
  if (interval)
 | 
					 | 
				
			||||||
    its.it_interval = *interval;
 | 
					 | 
				
			||||||
  if (absolute)
 | 
					 | 
				
			||||||
    flags |= TFD_TIMER_ABSTIME;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (timerfd_settime (source->source.fd, flags, &its, NULL) < 0)
 | 
					 | 
				
			||||||
    return SPA_RESULT_ERRNO;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return SPA_RESULT_OK;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
static void
 | 
					 | 
				
			||||||
source_signal_func (SpaSource *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosSource *s = SPA_CONTAINER_OF (source, PinosSource, source);
 | 
					 | 
				
			||||||
  struct signalfd_siginfo signal_info;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (read (source->fd, &signal_info, sizeof (signal_info)) != sizeof (signal_info))
 | 
					 | 
				
			||||||
    pinos_log_warn ("loop %p: failed to read signal fd: %s", source, strerror (errno));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  s->func.signal (s, s->signal_number, s->source.data);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *
 | 
					 | 
				
			||||||
pinos_loop_add_signal (PinosLoop             *loop,
 | 
					 | 
				
			||||||
                       int                    signal_number,
 | 
					 | 
				
			||||||
                       PinosSourceSignalFunc  func,
 | 
					 | 
				
			||||||
                       void                  *data)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
 | 
					 | 
				
			||||||
  PinosSource *source;
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
  sigset_t mask;
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source = calloc (1, sizeof (PinosSource));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  source->source.loop = loop->loop;
 | 
					 | 
				
			||||||
  source->source.func = source_signal_func;
 | 
					 | 
				
			||||||
  source->source.data = data;
 | 
					 | 
				
			||||||
#if 0
 | 
					 | 
				
			||||||
  sigemptyset (&mask);
 | 
					 | 
				
			||||||
  sigaddset (&mask, signal_number);
 | 
					 | 
				
			||||||
  source->source.fd = signalfd (-1, &mask, SFD_CLOEXEC | SFD_NONBLOCK);
 | 
					 | 
				
			||||||
  sigprocmask (SIG_BLOCK, &mask, NULL);
 | 
					 | 
				
			||||||
#endif
 | 
					 | 
				
			||||||
  source->source.mask = SPA_IO_IN;
 | 
					 | 
				
			||||||
  source->close = true;
 | 
					 | 
				
			||||||
  source->func.signal = func;
 | 
					 | 
				
			||||||
  source->signal_number = signal_number;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_loop_add_source (loop->loop, &source->source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_list_insert (&impl->source_list, &source->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  return source;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void
 | 
					 | 
				
			||||||
pinos_source_destroy (PinosSource *source)
 | 
					 | 
				
			||||||
{
 | 
					 | 
				
			||||||
  spa_list_remove (&source->link);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  spa_loop_remove_source (source->source.loop, &source->source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  if (source->source.fd != -1 && source->close)
 | 
					 | 
				
			||||||
    close (source->source.fd);
 | 
					 | 
				
			||||||
  free (source);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -30,31 +30,15 @@ extern "C" {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct _PinosLoop PinosLoop;
 | 
					typedef struct _PinosLoop PinosLoop;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (*PinosLoopHook)    (PinosLoop *loop,
 | 
					 | 
				
			||||||
                                  void      *data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef struct _PinosSource PinosSource;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
typedef void (*PinosSourceIOFunc)     (PinosSource *source,
 | 
					 | 
				
			||||||
                                       int          fd,
 | 
					 | 
				
			||||||
                                       SpaIO        mask,
 | 
					 | 
				
			||||||
                                       void        *data);
 | 
					 | 
				
			||||||
typedef void (*PinosSourceIdleFunc)   (PinosSource *source,
 | 
					 | 
				
			||||||
                                       void        *data);
 | 
					 | 
				
			||||||
typedef void (*PinosSourceEventFunc)  (PinosSource *source,
 | 
					 | 
				
			||||||
                                       void        *data);
 | 
					 | 
				
			||||||
typedef void (*PinosSourceTimerFunc)  (PinosSource *source,
 | 
					 | 
				
			||||||
                                       void        *data);
 | 
					 | 
				
			||||||
typedef void (*PinosSourceSignalFunc) (PinosSource *source,
 | 
					 | 
				
			||||||
                                       int          signal_number,
 | 
					 | 
				
			||||||
                                       void        *data);
 | 
					 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
 * PinosLoop:
 | 
					 * PinosLoop:
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * Pinos loop interface.
 | 
					 * Pinos loop interface.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
struct _PinosLoop {
 | 
					struct _PinosLoop {
 | 
				
			||||||
  SpaLoop *loop;
 | 
					  SpaLoop        *loop;
 | 
				
			||||||
 | 
					  SpaLoopControl *control;
 | 
				
			||||||
 | 
					  SpaLoopUtils   *utils;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PINOS_SIGNAL  (destroy_signal,   (PinosListener *listener,
 | 
					  PINOS_SIGNAL  (destroy_signal,   (PinosListener *listener,
 | 
				
			||||||
                                    PinosLoop     *loop));
 | 
					                                    PinosLoop     *loop));
 | 
				
			||||||
| 
						 | 
					@ -63,56 +47,27 @@ struct _PinosLoop {
 | 
				
			||||||
PinosLoop *    pinos_loop_new             (void);
 | 
					PinosLoop *    pinos_loop_new             (void);
 | 
				
			||||||
void           pinos_loop_destroy         (PinosLoop *loop);
 | 
					void           pinos_loop_destroy         (PinosLoop *loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int            pinos_loop_get_fd          (PinosLoop *loop);
 | 
					#define pinos_loop_add_source(l,...)      spa_loop_add_source((l)->loop,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define pinos_loop_update_source(l,...)   spa_loop_update_source(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define pinos_loop_remove_source(l,...)   spa_loop_remove_source(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define pinos_loop_invoke(l,...)          spa_loop_invoke((l)->loop,__VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void           pinos_loop_set_hooks       (PinosLoop     *loop,
 | 
					#define pinos_loop_get_fd(l)              spa_loop_control_get_fd((l)->control)
 | 
				
			||||||
                                           PinosLoopHook  pre_func,
 | 
					#define pinos_loop_set_hooks(l,...)       spa_loop_control_set_hooks((l)->control,__VA_ARGS__)
 | 
				
			||||||
                                           PinosLoopHook  post_func,
 | 
					#define pinos_loop_enter(l)               spa_loop_control_enter((l)->control)
 | 
				
			||||||
                                           void          *data);
 | 
					#define pinos_loop_iterate(l,...)         spa_loop_control_iterate((l)->control,__VA_ARGS__)
 | 
				
			||||||
void           pinos_loop_enter_thread    (PinosLoop     *loop);
 | 
					#define pinos_loop_leave(l)               spa_loop_control_leave((l)->control)
 | 
				
			||||||
void           pinos_loop_leave_thread    (PinosLoop     *loop);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
SpaResult      pinos_loop_iterate         (PinosLoop     *loop,
 | 
					#define pinos_loop_add_io(l,...)          spa_loop_utils_add_io((l)->utils,__VA_ARGS__)
 | 
				
			||||||
                                           int            timeout);
 | 
					#define pinos_loop_update_io(l,...)       spa_loop_utils_update_io((l)->utils,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define pinos_loop_add_idle(l,...)        spa_loop_utils_add_idle((l)->utils,__VA_ARGS__)
 | 
				
			||||||
#define pinos_loop_add_source(l,s)        ((l)->loop->add_source((l)->loop,s);
 | 
					#define pinos_loop_enable_idle(l,...)     spa_loop_utils_enable_idle((l)->utils,__VA_ARGS__)
 | 
				
			||||||
#define pinos_loop_update_source(l,s)     ((l)->loop->update_source(s);
 | 
					#define pinos_loop_add_event(l,...)       spa_loop_utils_add_event((l)->utils,__VA_ARGS__)
 | 
				
			||||||
#define pinos_loop_remove_source(l,s)     ((l)->loop->remove_source(s);
 | 
					#define pinos_loop_signal_event(l,...)    spa_loop_utils_signal_event((l)->utils,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define pinos_loop_add_timer(l,...)       spa_loop_utils_add_timer((l)->utils,__VA_ARGS__)
 | 
				
			||||||
PinosSource *  pinos_loop_add_io          (PinosLoop            *loop,
 | 
					#define pinos_loop_update_timer(l,...)    spa_loop_utils_update_timer((l)->utils,__VA_ARGS__)
 | 
				
			||||||
                                           int                   fd,
 | 
					#define pinos_loop_add_signal(l,...)      spa_loop_utils_add_signal((l)->utils,__VA_ARGS__)
 | 
				
			||||||
                                           SpaIO                 mask,
 | 
					#define pinos_loop_destroy_source(l,...)  spa_loop_utils_destroy_source((l)->utils,__VA_ARGS__)
 | 
				
			||||||
                                           bool                  close,
 | 
					 | 
				
			||||||
                                           PinosSourceIOFunc     func,
 | 
					 | 
				
			||||||
                                           void                 *data);
 | 
					 | 
				
			||||||
SpaResult      pinos_source_io_update     (PinosSource          *source,
 | 
					 | 
				
			||||||
                                           SpaIO                 mask);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *  pinos_loop_add_idle        (PinosLoop            *loop,
 | 
					 | 
				
			||||||
                                           PinosSourceIdleFunc   func,
 | 
					 | 
				
			||||||
                                           void                 *data);
 | 
					 | 
				
			||||||
void           pinos_source_idle_enable   (PinosSource          *source,
 | 
					 | 
				
			||||||
                                           bool                  enabled);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *  pinos_loop_add_event       (PinosLoop            *loop,
 | 
					 | 
				
			||||||
                                           PinosSourceEventFunc  func,
 | 
					 | 
				
			||||||
                                           void                 *data);
 | 
					 | 
				
			||||||
void           pinos_source_event_signal  (PinosSource          *source);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *  pinos_loop_add_timer       (PinosLoop            *loop,
 | 
					 | 
				
			||||||
                                           PinosSourceTimerFunc  func,
 | 
					 | 
				
			||||||
                                           void                 *data);
 | 
					 | 
				
			||||||
SpaResult      pinos_source_timer_update  (PinosSource          *source,
 | 
					 | 
				
			||||||
                                           struct timespec      *value,
 | 
					 | 
				
			||||||
                                           struct timespec      *interval,
 | 
					 | 
				
			||||||
                                           bool                  absolute);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
PinosSource *  pinos_loop_add_signal      (PinosLoop            *loop,
 | 
					 | 
				
			||||||
                                           int                   signal_number,
 | 
					 | 
				
			||||||
                                           PinosSourceSignalFunc func,
 | 
					 | 
				
			||||||
                                           void                 *data);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void           pinos_source_destroy       (PinosSource          *source);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -52,9 +52,6 @@ struct _PinosProtocolDBus {
 | 
				
			||||||
  PinosGlobal *global;
 | 
					  PinosGlobal *global;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PinosProperties *properties;
 | 
					  PinosProperties *properties;
 | 
				
			||||||
 | 
					 | 
				
			||||||
  PINOS_SIGNAL (destroy_signal, (PinosListener      *listener,
 | 
					 | 
				
			||||||
                                 PinosProtocolDBus  *proto));
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef struct {
 | 
					typedef struct {
 | 
				
			||||||
| 
						 | 
					@ -654,8 +651,6 @@ pinos_protocol_dbus_new (PinosCore       *core,
 | 
				
			||||||
  spa_list_init (&impl->client_list);
 | 
					  spa_list_init (&impl->client_list);
 | 
				
			||||||
  spa_list_init (&impl->object_list);
 | 
					  spa_list_init (&impl->object_list);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_signal_init (&this->destroy_signal);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pinos_signal_add (&core->global_added, &impl->global_added, on_global_added);
 | 
					  pinos_signal_add (&core->global_added, &impl->global_added, on_global_added);
 | 
				
			||||||
  pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed);
 | 
					  pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed);
 | 
				
			||||||
  pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed);
 | 
					  pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed);
 | 
				
			||||||
| 
						 | 
					@ -679,8 +674,6 @@ pinos_protocol_dbus_destroy (PinosProtocolDBus *proto)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_log_debug ("protocol-dbus %p: destroy", impl);
 | 
					  pinos_log_debug ("protocol-dbus %p: destroy", impl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_signal_emit (&proto->destroy_signal, proto);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  pinos_global_destroy (proto->global);
 | 
					  pinos_global_destroy (proto->global);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  spa_list_for_each_safe (object, tmp, &impl->object_list, link)
 | 
					  spa_list_for_each_safe (object, tmp, &impl->object_list, link)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -50,7 +50,7 @@ typedef struct {
 | 
				
			||||||
  ModuleImpl  *impl;
 | 
					  ModuleImpl  *impl;
 | 
				
			||||||
  PinosNode   *node;
 | 
					  PinosNode   *node;
 | 
				
			||||||
  SpaList      link;
 | 
					  SpaList      link;
 | 
				
			||||||
  PinosSource *timeout;
 | 
					  SpaSource   *timeout;
 | 
				
			||||||
  guint        idle_timeout;
 | 
					  guint        idle_timeout;
 | 
				
			||||||
} NodeInfo;
 | 
					} NodeInfo;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,7 +36,7 @@ typedef struct
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosDataLoop this;
 | 
					  PinosDataLoop this;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  PinosSource *event;
 | 
					  SpaSource *event;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  bool running;
 | 
					  bool running;
 | 
				
			||||||
  pthread_t thread;
 | 
					  pthread_t thread;
 | 
				
			||||||
| 
						 | 
					@ -96,22 +96,22 @@ do_loop (void *user_data)
 | 
				
			||||||
  make_realtime (this);
 | 
					  make_realtime (this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_log_debug ("data-loop %p: enter thread", this);
 | 
					  pinos_log_debug ("data-loop %p: enter thread", this);
 | 
				
			||||||
  pinos_loop_enter_thread (impl->this.loop);
 | 
					  pinos_loop_enter (impl->this.loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (impl->running) {
 | 
					  while (impl->running) {
 | 
				
			||||||
    if ((res = pinos_loop_iterate (this->loop, -1)) < 0)
 | 
					    if ((res = pinos_loop_iterate (this->loop, -1)) < 0)
 | 
				
			||||||
      pinos_log_warn ("data-loop %p: iterate error %d", this, res);
 | 
					      pinos_log_warn ("data-loop %p: iterate error %d", this, res);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  pinos_log_debug ("data-loop %p: leave thread", this);
 | 
					  pinos_log_debug ("data-loop %p: leave thread", this);
 | 
				
			||||||
  pinos_loop_leave_thread (impl->this.loop);
 | 
					  pinos_loop_leave (impl->this.loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return NULL;
 | 
					  return NULL;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void
 | 
					static void
 | 
				
			||||||
do_stop (PinosSource *source,
 | 
					do_stop (SpaSource *source,
 | 
				
			||||||
         void        *data)
 | 
					         void      *data)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosDataLoopImpl *impl = data;
 | 
					  PinosDataLoopImpl *impl = data;
 | 
				
			||||||
  impl->running = false;
 | 
					  impl->running = false;
 | 
				
			||||||
| 
						 | 
					@ -153,7 +153,7 @@ pinos_data_loop_destroy (PinosDataLoop *loop)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_data_loop_stop (loop);
 | 
					  pinos_data_loop_stop (loop);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_source_destroy (impl->event);
 | 
					  pinos_loop_destroy_source (loop->loop, impl->event);
 | 
				
			||||||
  pinos_loop_destroy (loop->loop);
 | 
					  pinos_loop_destroy (loop->loop);
 | 
				
			||||||
  free (impl);
 | 
					  free (impl);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -181,7 +181,7 @@ pinos_data_loop_stop (PinosDataLoop *loop)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  PinosDataLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosDataLoopImpl, this);
 | 
					  PinosDataLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosDataLoopImpl, this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pinos_source_event_signal (impl->event);
 | 
					  pinos_loop_signal_event (impl->this.loop, impl->event);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pthread_join (impl->thread, NULL);
 | 
					  pthread_join (impl->thread, NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -106,13 +106,13 @@ struct _SpaLoopControl {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int          (*get_fd)            (SpaLoopControl *ctrl);
 | 
					  int          (*get_fd)            (SpaLoopControl *ctrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaResult    (*set_hooks)         (SpaLoopControl *ctrl,
 | 
					  void         (*set_hooks)         (SpaLoopControl *ctrl,
 | 
				
			||||||
                                     SpaLoopHook     pre_hook,
 | 
					                                     SpaLoopHook     pre_hook,
 | 
				
			||||||
                                     SpaLoopHook     post_hook,
 | 
					                                     SpaLoopHook     post_hook,
 | 
				
			||||||
                                     void           *data);
 | 
					                                     void           *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaResult    (*enter)             (SpaLoopControl *ctrl);
 | 
					  void         (*enter)             (SpaLoopControl *ctrl);
 | 
				
			||||||
  SpaResult    (*leave)             (SpaLoopControl *ctrl);
 | 
					  void         (*leave)             (SpaLoopControl *ctrl);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaResult    (*iterate)           (SpaLoopControl *ctrl,
 | 
					  SpaResult    (*iterate)           (SpaLoopControl *ctrl,
 | 
				
			||||||
                                     int             timeout);
 | 
					                                     int             timeout);
 | 
				
			||||||
| 
						 | 
					@ -121,8 +121,8 @@ struct _SpaLoopControl {
 | 
				
			||||||
#define spa_loop_control_get_fd(l)             (l)->get_fd(l)
 | 
					#define spa_loop_control_get_fd(l)             (l)->get_fd(l)
 | 
				
			||||||
#define spa_loop_control_set_hooks(l,...)      (l)->set_hook((l),__VA_ARGS__)
 | 
					#define spa_loop_control_set_hooks(l,...)      (l)->set_hook((l),__VA_ARGS__)
 | 
				
			||||||
#define spa_loop_control_enter(l)              (l)->enter(l)
 | 
					#define spa_loop_control_enter(l)              (l)->enter(l)
 | 
				
			||||||
#define spa_loop_control_leave(l)              (l)->leave(l)
 | 
					 | 
				
			||||||
#define spa_loop_control_iterate(l,...)        (l)->iterate((l),__VA_ARGS__)
 | 
					#define spa_loop_control_iterate(l,...)        (l)->iterate((l),__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_control_leave(l)              (l)->leave(l)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
typedef void (*SpaSourceIOFunc)     (SpaSource *source,
 | 
					typedef void (*SpaSourceIOFunc)     (SpaSource *source,
 | 
				
			||||||
| 
						 | 
					@ -152,6 +152,7 @@ struct _SpaLoopUtils {
 | 
				
			||||||
  SpaSource *  (*add_io)            (SpaLoopUtils       *utils,
 | 
					  SpaSource *  (*add_io)            (SpaLoopUtils       *utils,
 | 
				
			||||||
                                     int                 fd,
 | 
					                                     int                 fd,
 | 
				
			||||||
                                     SpaIO               mask,
 | 
					                                     SpaIO               mask,
 | 
				
			||||||
 | 
					                                     bool                close,
 | 
				
			||||||
                                     SpaSourceIOFunc     func,
 | 
					                                     SpaSourceIOFunc     func,
 | 
				
			||||||
                                     void               *data);
 | 
					                                     void               *data);
 | 
				
			||||||
  SpaResult    (*update_io)         (SpaSource          *source,
 | 
					  SpaResult    (*update_io)         (SpaSource          *source,
 | 
				
			||||||
| 
						 | 
					@ -160,13 +161,13 @@ struct _SpaLoopUtils {
 | 
				
			||||||
  SpaSource *  (*add_idle)          (SpaLoopUtils       *utils,
 | 
					  SpaSource *  (*add_idle)          (SpaLoopUtils       *utils,
 | 
				
			||||||
                                     SpaSourceIdleFunc   func,
 | 
					                                     SpaSourceIdleFunc   func,
 | 
				
			||||||
                                     void               *data);
 | 
					                                     void               *data);
 | 
				
			||||||
  SpaResult    (*enable_idle)       (SpaSource          *source,
 | 
					  void         (*enable_idle)       (SpaSource          *source,
 | 
				
			||||||
                                     bool                enabled);
 | 
					                                     bool                enabled);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaSource *  (*add_event)         (SpaLoopUtils       *utils,
 | 
					  SpaSource *  (*add_event)         (SpaLoopUtils       *utils,
 | 
				
			||||||
                                     SpaSourceEventFunc  func,
 | 
					                                     SpaSourceEventFunc  func,
 | 
				
			||||||
                                     void               *data);
 | 
					                                     void               *data);
 | 
				
			||||||
  SpaResult    (*signal_event)      (SpaSource          *source);
 | 
					  void         (*signal_event)      (SpaSource          *source);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaSource *  (*add_timer)         (SpaLoopUtils       *utils,
 | 
					  SpaSource *  (*add_timer)         (SpaLoopUtils       *utils,
 | 
				
			||||||
                                     SpaSourceTimerFunc  func,
 | 
					                                     SpaSourceTimerFunc  func,
 | 
				
			||||||
| 
						 | 
					@ -180,9 +181,19 @@ struct _SpaLoopUtils {
 | 
				
			||||||
                                     SpaSourceSignalFunc func,
 | 
					                                     SpaSourceSignalFunc func,
 | 
				
			||||||
                                     void               *data);
 | 
					                                     void               *data);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  SpaSource *  (*destroy_source)    (SpaSource          *source);
 | 
					  void         (*destroy_source)    (SpaSource          *source);
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#define spa_loop_utils_add_io(l,...)             (l)->add_io(l,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_update_io(l,...)          (l)->update_io(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_add_idle(l,...)           (l)->add_idle(l,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_enable_idle(l,...)        (l)->enable_idle(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_add_event(l,...)          (l)->add_event(l,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_signal_event(l,...)       (l)->signal_event(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_add_timer(l,...)          (l)->add_timer(l,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_update_timer(l,...)       (l)->update_timer(__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_add_signal(l,...)         (l)->add_signal(l,__VA_ARGS__)
 | 
				
			||||||
 | 
					#define spa_loop_utils_destroy_source(l,...)     (l)->destroy_source(__VA_ARGS__)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#ifdef __cplusplus
 | 
					#ifdef __cplusplus
 | 
				
			||||||
}  /* extern "C" */
 | 
					}  /* extern "C" */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue