summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wtaymans@redhat.com>2016-11-21 12:54:40 +0100
committerWim Taymans <wtaymans@redhat.com>2016-11-21 12:54:40 +0100
commit3dcbf4b2283b5a4d88289d015e7305e343e7b581 (patch)
treede0b92b407fd60275732700730d0674747dd8823
parentd250ed42e6e5839471e07ef4fd78f41ce8c5ca7b (diff)
Move suspend on idle in module
Move suspend-on-idle code from the node to a module Add some more SpaLoop API
-rw-r--r--pinos/client/loop.c12
-rw-r--r--pinos/client/loop.h7
-rw-r--r--pinos/modules/meson.build9
-rw-r--r--pinos/modules/module-autolink.c6
-rw-r--r--pinos/modules/module-suspend-on-idle.c216
-rw-r--r--pinos/server/core.c1
-rw-r--r--pinos/server/core.h3
-rw-r--r--pinos/server/data-loop.c4
-rw-r--r--pinos/server/link.c4
-rw-r--r--pinos/server/node.c100
-rw-r--r--pinos/server/node.h11
-rw-r--r--pinos/server/port.c2
-rw-r--r--spa/include/spa/loop.h98
13 files changed, 363 insertions, 110 deletions
diff --git a/pinos/client/loop.c b/pinos/client/loop.c
index 87d0c602..141ddef6 100644
--- a/pinos/client/loop.c
+++ b/pinos/client/loop.c
@@ -284,11 +284,17 @@ pinos_loop_set_hooks (PinosLoop *loop,
}
void
-pinos_loop_set_thread (PinosLoop *loop,
- void *thread)
+pinos_loop_enter_thread (PinosLoop *loop)
{
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
- impl->thread = *((pthread_t*)thread);
+ impl->thread = pthread_self();
+}
+
+void
+pinos_loop_leave_thread (PinosLoop *loop)
+{
+ PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
+ impl->thread = 0;
}
SpaResult
diff --git a/pinos/client/loop.h b/pinos/client/loop.h
index 6c802987..6e010e2c 100644
--- a/pinos/client/loop.h
+++ b/pinos/client/loop.h
@@ -30,9 +30,6 @@ extern "C" {
typedef struct _PinosLoop PinosLoop;
-typedef bool (*PinosCheckfunc) (PinosLoop *loop,
- void *data);
-
typedef void (*PinosLoopHook) (PinosLoop *loop,
void *data);
@@ -72,8 +69,8 @@ void pinos_loop_set_hooks (PinosLoop *loop,
PinosLoopHook pre_func,
PinosLoopHook post_func,
void *data);
-void pinos_loop_set_thread (PinosLoop *loop,
- void *thread);
+void pinos_loop_enter_thread (PinosLoop *loop);
+void pinos_loop_leave_thread (PinosLoop *loop);
SpaResult pinos_loop_iterate (PinosLoop *loop,
int timeout);
diff --git a/pinos/modules/meson.build b/pinos/modules/meson.build
index 4dbd56fc..f3b728a9 100644
--- a/pinos/modules/meson.build
+++ b/pinos/modules/meson.build
@@ -23,3 +23,12 @@ pinos_module_protocol_dbus = shared_library('pinos-module-protocol-dbus', [ 'mod
install_dir : '@0@/pinos-0.1'.format(get_option('libdir')),
dependencies : [gobject_dep, gmodule_dep, glib_dep, gio_dep, mathlib, dl_lib, pinos_dep, pinoscore_dep],
)
+
+pinos_module_suspend_on_idle = shared_library('pinos-module-suspend-on-idle', [ 'module-suspend-on-idle.c' ],
+ c_args : pinos_module_c_args,
+ include_directories : [configinc, pinosinc, spa_inc],
+ link_with : spalib,
+ install : true,
+ install_dir : '@0@/pinos-0.1'.format(get_option('libdir')),
+ dependencies : [mathlib, dl_lib, pinos_dep, pinoscore_dep],
+)
diff --git a/pinos/modules/module-autolink.c b/pinos/modules/module-autolink.c
index 7a30caaf..f86e6943 100644
--- a/pinos/modules/module-autolink.c
+++ b/pinos/modules/module-autolink.c
@@ -96,7 +96,7 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
error:
{
- pinos_node_report_error (node, error);
+ pinos_node_update_state (node, PINOS_NODE_STATE_ERROR, error);
return;
}
}
@@ -128,9 +128,9 @@ on_link_state_changed (PinosListener *listener,
pinos_log_debug ("module %p: link %p: state error: %s", impl, link, link->error);
if (link->input && link->input->node)
- pinos_node_report_error (link->input->node, strdup (link->error));
+ pinos_node_update_state (link->input->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
if (link->output && link->output->node)
- pinos_node_report_error (link->output->node, strdup (link->error));
+ pinos_node_update_state (link->output->node, PINOS_NODE_STATE_ERROR, strdup (link->error));
break;
}
diff --git a/pinos/modules/module-suspend-on-idle.c b/pinos/modules/module-suspend-on-idle.c
new file mode 100644
index 00000000..47549349
--- /dev/null
+++ b/pinos/modules/module-suspend-on-idle.c
@@ -0,0 +1,216 @@
+/* Pinos
+ * Copyright (C) 2015 Wim Taymans <wim.taymans@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include <string.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "config.h"
+
+#include "pinos/server/core.h"
+#include "pinos/server/module.h"
+
+#define MODULE_URI "http://pinos.org/ns/module-suspend-on-idle"
+#define MODULE_PREFIX MODULE_URI "#"
+
+typedef struct {
+ PinosCore *core;
+ PinosProperties *properties;
+ PinosGlobal *global;
+
+ struct {
+ uint32_t module;
+ } uri;
+
+ PinosListener global_added;
+ PinosListener global_removed;
+ PinosListener node_state_request;
+ PinosListener node_state_changed;
+
+ SpaList node_list;
+} ModuleImpl;
+
+typedef struct {
+ ModuleImpl *impl;
+ PinosNode *node;
+ SpaList link;
+ PinosSource *timeout;
+ guint idle_timeout;
+} NodeInfo;
+
+static NodeInfo *
+find_node_info (ModuleImpl *impl, PinosNode *node)
+{
+ NodeInfo *info;
+
+ spa_list_for_each (info, &impl->node_list, link) {
+ if (info->node == node)
+ return info;
+ }
+ return NULL;
+}
+
+static void
+remove_idle_timeout (NodeInfo *info)
+{
+ if (info->idle_timeout) {
+ g_source_remove (info->idle_timeout);
+ info->idle_timeout = 0;
+ }
+}
+
+static bool
+idle_timeout (NodeInfo *info)
+{
+ info->idle_timeout = 0;
+ pinos_log_debug ("module %p: node %p idle timeout", info->impl, info->node);
+ pinos_node_set_state (info->node, PINOS_NODE_STATE_SUSPENDED);
+ return G_SOURCE_REMOVE;
+}
+
+static void
+on_node_state_request (PinosListener *listener,
+ PinosNode *node,
+ PinosNodeState state)
+{
+ ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, node_state_changed);
+ NodeInfo *info;
+
+ if ((info = find_node_info (impl, node)) == NULL)
+ return;
+
+ remove_idle_timeout (info);
+}
+
+static void
+on_node_state_changed (PinosListener *listener,
+ PinosNode *node,
+ PinosNodeState old,
+ PinosNodeState state)
+{
+ ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, node_state_changed);
+ NodeInfo *info;
+
+ if ((info = find_node_info (impl, node)) == NULL)
+ return;
+
+ if (state != PINOS_NODE_STATE_IDLE) {
+ remove_idle_timeout (info);
+ } else {
+ pinos_log_debug ("module %p: node %p became idle", impl, node);
+ info->idle_timeout = g_timeout_add_seconds (3,
+ (GSourceFunc) idle_timeout,
+ info);
+ }
+}
+
+static void
+on_global_added (PinosListener *listener,
+ PinosCore *core,
+ PinosGlobal *global)
+{
+ ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_added);
+
+ if (global->type == impl->core->registry.uri.node) {
+ PinosNode *node = global->object;
+ NodeInfo *info;
+
+ info = calloc (1, sizeof (NodeInfo));
+ info->impl = impl;
+ info->node = node;
+ info->timeout = NULL;
+ spa_list_insert (impl->node_list.prev, &info->link);
+ }
+}
+
+static void
+on_global_removed (PinosListener *listener,
+ PinosCore *core,
+ PinosGlobal *global)
+{
+ ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, global_removed);
+
+ if (global->type == impl->core->registry.uri.node) {
+ PinosNode *node = global->object;
+ NodeInfo *info;
+
+ if ((info = find_node_info (impl, node))) {
+ remove_idle_timeout (info);
+ spa_list_remove (&info->link);
+ free (info);
+ }
+ }
+}
+
+
+/**
+ * module_new:
+ * @core: #PinosCore
+ * @properties: #PinosProperties
+ *
+ * Make a new #ModuleImpl object with given @properties
+ *
+ * Returns: a new #ModuleImpl
+ */
+static ModuleImpl *
+module_new (PinosCore *core,
+ PinosProperties *properties)
+{
+ ModuleImpl *impl;
+
+ impl = calloc (1, sizeof (ModuleImpl));
+ pinos_log_debug ("module %p: new", impl);
+
+ impl->core = core;
+ impl->properties = properties;
+
+ spa_list_init (&impl->node_list);
+
+ 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->node_state_request, &impl->node_state_request, on_node_state_request);
+ pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed);
+
+ impl->uri.module = spa_id_map_get_id (core->registry.map, MODULE_URI);
+
+ impl->global = pinos_core_add_global (core,
+ impl->uri.module,
+ impl);
+ return impl;
+}
+
+#if 0
+static void
+module_destroy (ModuleImpl *impl)
+{
+ pinos_log_debug ("module %p: destroy", impl);
+
+ pinos_global_destroy (impl->global);
+
+ pinos_signal_remove (&impl->node_state_changed);
+ free (impl);
+}
+#endif
+
+bool
+pinos__module_init (PinosModule * module, const char * args)
+{
+ module_new (module->core, NULL);
+ return TRUE;
+}
diff --git a/pinos/server/core.c b/pinos/server/core.c
index 5b020a2e..57c43611 100644
--- a/pinos/server/core.c
+++ b/pinos/server/core.c
@@ -64,6 +64,7 @@ pinos_core_new (PinosMainLoop *main_loop)
pinos_signal_init (&this->destroy_signal);
pinos_signal_init (&this->global_added);
pinos_signal_init (&this->global_removed);
+ pinos_signal_init (&this->node_state_request);
pinos_signal_init (&this->node_state_changed);
pinos_signal_init (&this->port_added);
pinos_signal_init (&this->port_removed);
diff --git a/pinos/server/core.h b/pinos/server/core.h
index 88550425..b82acc28 100644
--- a/pinos/server/core.h
+++ b/pinos/server/core.h
@@ -76,6 +76,9 @@ struct _PinosCore {
PinosCore *core,
PinosGlobal *global));
+ PINOS_SIGNAL (node_state_request, (PinosListener *listener,
+ PinosNode *object,
+ PinosNodeState state));
PINOS_SIGNAL (node_state_changed, (PinosListener *listener,
PinosNode *object,
PinosNodeState old,
diff --git a/pinos/server/data-loop.c b/pinos/server/data-loop.c
index f9d97def..358cbe35 100644
--- a/pinos/server/data-loop.c
+++ b/pinos/server/data-loop.c
@@ -96,11 +96,14 @@ do_loop (void *user_data)
make_realtime (this);
pinos_log_debug ("data-loop %p: enter thread", this);
+ pinos_loop_enter_thread (impl->this.loop);
+
while (impl->running) {
if ((res = pinos_loop_iterate (this->loop, -1)) < 0)
pinos_log_warn ("data-loop %p: iterate error %d", this, res);
}
pinos_log_debug ("data-loop %p: leave thread", this);
+ pinos_loop_leave_thread (impl->this.loop);
return NULL;
}
@@ -169,7 +172,6 @@ pinos_data_loop_start (PinosDataLoop *loop)
impl->running = false;
return SPA_RESULT_ERROR;
}
- pinos_loop_set_thread (impl->this.loop, &impl->thread);
}
return SPA_RESULT_OK;
}
diff --git a/pinos/server/link.c b/pinos/server/link.c
index a6b25960..bf9c6002 100644
--- a/pinos/server/link.c
+++ b/pinos/server/link.c
@@ -748,7 +748,7 @@ do_link_remove_done (SpaLoop *loop,
if (this->input->node->n_used_input_links == 0 &&
this->input->node->n_used_output_links == 0)
- pinos_node_report_idle (this->input->node);
+ pinos_node_set_state (this->input->node, PINOS_NODE_STATE_IDLE);
clear_port_buffers (this, this->input);
this->input = NULL;
@@ -759,7 +759,7 @@ do_link_remove_done (SpaLoop *loop,
if (this->output->node->n_used_input_links == 0 &&
this->output->node->n_used_output_links == 0)
- pinos_node_report_idle (this->output->node);
+ pinos_node_set_state (this->output->node, PINOS_NODE_STATE_IDLE);
clear_port_buffers (this, this->output);
this->output = NULL;
diff --git a/pinos/server/node.c b/pinos/server/node.c
index bd20d94f..3e4a9a48 100644
--- a/pinos/server/node.c
+++ b/pinos/server/node.c
@@ -37,8 +37,6 @@ typedef struct
uint32_t seq;
bool async_init;
-
- guint idle_timeout;
} PinosNodeImpl;
static void init_complete (PinosNode *this);
@@ -396,7 +394,7 @@ init_complete (PinosNode *this)
pinos_log_debug ("node %p: init completed", this);
impl->async_init = false;
- pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED);
+ pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL);
}
void
@@ -631,30 +629,19 @@ pinos_node_get_free_port (PinosNode *node,
}
static void
-remove_idle_timeout (PinosNode *node)
-{
- PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
-
- if (impl->idle_timeout) {
- g_source_remove (impl->idle_timeout);
- impl->idle_timeout = 0;
- }
-}
-
-static void
on_state_complete (PinosNode *node,
gpointer data,
SpaResult res)
{
PinosNodeState state = GPOINTER_TO_INT (data);
+ char *error = NULL;
pinos_log_debug ("node %p: state complete %d", node, res);
if (SPA_RESULT_IS_ERROR (res)) {
- char *error;
asprintf (&error, "error changing node state: %d", res);
- pinos_node_report_error (node, error);
- } else
- pinos_node_update_state (node, state);
+ state = PINOS_NODE_STATE_ERROR;
+ }
+ pinos_node_update_state (node, state, error);
}
/**
@@ -672,7 +659,7 @@ pinos_node_set_state (PinosNode *node,
{
SpaResult res = SPA_RESULT_OK;
- remove_idle_timeout (node);
+ pinos_signal_emit (&node->core->node_state_request, node, state);
pinos_log_debug ("node %p: set state %s", node, pinos_node_state_as_string (state));
@@ -715,13 +702,15 @@ pinos_node_set_state (PinosNode *node,
* pinos_node_update_state:
* @node: a #PinosNode
* @state: a #PinosNodeState
+ * @error: error when @state is #PINOS_NODE_STATE_ERROR
*
* Update the state of a node. This method is used from
* inside @node itself.
*/
void
pinos_node_update_state (PinosNode *node,
- PinosNodeState state)
+ PinosNodeState state,
+ char *error)
{
PinosNodeState old;
@@ -731,75 +720,10 @@ pinos_node_update_state (PinosNode *node,
pinos_node_state_as_string (old),
pinos_node_state_as_string (state));
+ if (node->error)
+ free (node->error);
+ node->error = error;
node->state = state;
pinos_signal_emit (&node->core->node_state_changed, node, old, state);
}
}
-
-/**
- * pinos_node_report_error:
- * @node: a #PinosNode
- * @error: an error message
- *
- * Report an error from within @node.
- */
-void
-pinos_node_report_error (PinosNode *node,
- char *error)
-{
- PinosNodeState old;
-
- free (node->error);
- remove_idle_timeout (node);
- node->error = error;
- old = node->state;
- node->state = PINOS_NODE_STATE_ERROR;
- pinos_log_debug ("node %p: got error state %s", node, error);
- pinos_signal_emit (&node->core->node_state_changed, node, old, node->state);
-}
-
-static bool
-idle_timeout (PinosNode *node)
-{
- PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
-
- impl->idle_timeout = 0;
- pinos_log_debug ("node %p: idle timeout", node);
- pinos_node_set_state (node, PINOS_NODE_STATE_SUSPENDED);
-
- return G_SOURCE_REMOVE;
-}
-
-/**
- * pinos_node_report_idle:
- * @node: a #PinosNode
- *
- * Mark @node as being idle. This will start a timeout that will
- * set the node to SUSPENDED.
- */
-void
-pinos_node_report_idle (PinosNode *node)
-{
- PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
-
- pinos_log_debug ("node %p: report idle", node);
- pinos_node_set_state (node, PINOS_NODE_STATE_IDLE);
-
- impl->idle_timeout = g_timeout_add_seconds (3,
- (GSourceFunc) idle_timeout,
- node);
-}
-
-/**
- * pinos_node_report_busy:
- * @node: a #PinosNode
- *
- * Mark @node as being busy. This will set the state of the node
- * to the RUNNING state.
- */
-void
-pinos_node_report_busy (PinosNode *node)
-{
- pinos_log_debug ("node %p: report busy", node);
- pinos_node_set_state (node, PINOS_NODE_STATE_RUNNING);
-}
diff --git a/pinos/server/node.h b/pinos/server/node.h
index 6507779f..4947f065 100644
--- a/pinos/server/node.h
+++ b/pinos/server/node.h
@@ -103,12 +103,11 @@ void pinos_node_set_data_loop (PinosNode *node,
PinosPort * pinos_node_get_free_port (PinosNode *node,
PinosDirection direction);
-SpaResult pinos_node_set_state (PinosNode *node, PinosNodeState state);
-void pinos_node_update_state (PinosNode *node, PinosNodeState state);
-
-void pinos_node_report_error (PinosNode *node, char *error);
-void pinos_node_report_idle (PinosNode *node);
-void pinos_node_report_busy (PinosNode *node);
+SpaResult pinos_node_set_state (PinosNode *node,
+ PinosNodeState state);
+void pinos_node_update_state (PinosNode *node,
+ PinosNodeState state,
+ char *error);
#ifdef __cplusplus
}
diff --git a/pinos/server/port.c b/pinos/server/port.c
index 77eaa830..8700f077 100644
--- a/pinos/server/port.c
+++ b/pinos/server/port.c
@@ -238,7 +238,7 @@ do_remove_link_done (SpaLoop *loop,
if (node->n_used_output_links == 0 &&
node->n_used_input_links == 0) {
- pinos_node_report_idle (node);
+ pinos_node_update_state (node, PINOS_NODE_STATE_IDLE, NULL);
}
if (!port->allocated) {
diff --git a/spa/include/spa/loop.h b/spa/include/spa/loop.h
index 22338dc1..d661e769 100644
--- a/spa/include/spa/loop.h
+++ b/spa/include/spa/loop.h
@@ -26,11 +26,15 @@ extern "C" {
typedef struct _SpaLoop SpaLoop;
typedef struct _SpaSource SpaSource;
+typedef struct _SpaLoopControl SpaLoopControl;
+typedef struct _SpaLoopUtils SpaLoopUtils;
#define SPA_LOOP_URI "http://spaplug.in/ns/loop"
#define SPA_LOOP_PREFIX SPA_LOOP_URI "#"
#define SPA_LOOP__MainLoop SPA_LOOP_PREFIX "MainLoop"
#define SPA_LOOP__DataLoop SPA_LOOP_PREFIX "DataLoop"
+#define SPA_LOOP__Control SPA_LOOP_PREFIX "Control"
+#define SPA_LOOP__Utils SPA_LOOP_PREFIX "Utils"
#include <spa/defs.h>
@@ -62,7 +66,7 @@ typedef SpaResult (*SpaInvokeFunc) (SpaLoop *loop,
/**
* SpaLoop:
*
- * Register sources to an event loop
+ * Register sources and work items to an event loop
*/
struct _SpaLoop {
/* the total size of this structure. This can be used to expand this
@@ -88,6 +92,98 @@ struct _SpaLoop {
#define spa_loop_remove_source(l,...) (l)->remove_source(__VA_ARGS__)
#define spa_loop_invoke(l,...) (l)->invoke((l),__VA_ARGS__)
+typedef void (*SpaLoopHook) (SpaLoopControl *ctrl,
+ void *data);
+/**
+ * SpaLoopControl:
+ *
+ * Control an event loop
+ */
+struct _SpaLoopControl {
+ /* the total size of this structure. This can be used to expand this
+ * structure in the future */
+ size_t size;
+
+ int (*get_fd) (SpaLoopControl *ctrl);
+
+ SpaResult (*set_hooks) (SpaLoopControl *ctrl,
+ SpaLoopHook pre_hook,
+ SpaLoopHook post_hook,
+ void *data);
+
+ SpaResult (*enter) (SpaLoopControl *ctrl);
+ SpaResult (*leave) (SpaLoopControl *ctrl);
+
+ SpaResult (*iterate) (SpaLoopControl *ctrl,
+ int timeout);
+};
+
+#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_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__)
+
+
+typedef void (*SpaSourceIOFunc) (SpaSource *source,
+ int fd,
+ SpaIO mask,
+ void *data);
+typedef void (*SpaSourceIdleFunc) (SpaSource *source,
+ void *data);
+typedef void (*SpaSourceEventFunc) (SpaSource *source,
+ void *data);
+typedef void (*SpaSourceTimerFunc) (SpaSource *source,
+ void *data);
+typedef void (*SpaSourceSignalFunc) (SpaSource *source,
+ int signal_number,
+ void *data);
+
+/**
+ * SpaLoopUtils:
+ *
+ * Create sources for an event loop
+ */
+struct _SpaLoopUtils {
+ /* the total size of this structure. This can be used to expand this
+ * structure in the future */
+ size_t size;
+
+ SpaSource * (*add_io) (SpaLoopUtils *utils,
+ int fd,
+ SpaIO mask,
+ SpaSourceIOFunc func,
+ void *data);
+ SpaResult (*update_io) (SpaSource *source,
+ SpaIO mask);
+
+ SpaSource * (*add_idle) (SpaLoopUtils *utils,
+ SpaSourceIdleFunc func,
+ void *data);
+ SpaResult (*enable_idle) (SpaSource *source,
+ bool enabled);
+
+ SpaSource * (*add_event) (SpaLoopUtils *utils,
+ SpaSourceEventFunc func,
+ void *data);
+ SpaResult (*signal_event) (SpaSource *source);
+
+ SpaSource * (*add_timer) (SpaLoopUtils *utils,
+ SpaSourceTimerFunc func,
+ void *data);
+ SpaResult (*update_timer) (SpaSource *source,
+ struct timespec *value,
+ struct timespec *interval,
+ bool absolute);
+ SpaSource * (*add_signal) (SpaLoopUtils *utils,
+ int signal_number,
+ SpaSourceSignalFunc func,
+ void *data);
+
+ SpaSource * (*destroy_source) (SpaSource *source);
+};
+
+
#ifdef __cplusplus
} /* extern "C" */
#endif