mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
Move suspend on idle in module
Move suspend-on-idle code from the node to a module Add some more SpaLoop API
This commit is contained in:
parent
d250ed42e6
commit
3dcbf4b228
13 changed files with 363 additions and 110 deletions
|
|
@ -284,11 +284,17 @@ pinos_loop_set_hooks (PinosLoop *loop,
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pinos_loop_set_thread (PinosLoop *loop,
|
pinos_loop_enter_thread (PinosLoop *loop)
|
||||||
void *thread)
|
|
||||||
{
|
{
|
||||||
PinosLoopImpl *impl = SPA_CONTAINER_OF (loop, PinosLoopImpl, this);
|
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
|
SpaResult
|
||||||
|
|
|
||||||
|
|
@ -30,9 +30,6 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct _PinosLoop PinosLoop;
|
typedef struct _PinosLoop PinosLoop;
|
||||||
|
|
||||||
typedef bool (*PinosCheckfunc) (PinosLoop *loop,
|
|
||||||
void *data);
|
|
||||||
|
|
||||||
typedef void (*PinosLoopHook) (PinosLoop *loop,
|
typedef void (*PinosLoopHook) (PinosLoop *loop,
|
||||||
void *data);
|
void *data);
|
||||||
|
|
||||||
|
|
@ -72,8 +69,8 @@ void pinos_loop_set_hooks (PinosLoop *loop,
|
||||||
PinosLoopHook pre_func,
|
PinosLoopHook pre_func,
|
||||||
PinosLoopHook post_func,
|
PinosLoopHook post_func,
|
||||||
void *data);
|
void *data);
|
||||||
void pinos_loop_set_thread (PinosLoop *loop,
|
void pinos_loop_enter_thread (PinosLoop *loop);
|
||||||
void *thread);
|
void pinos_loop_leave_thread (PinosLoop *loop);
|
||||||
|
|
||||||
SpaResult pinos_loop_iterate (PinosLoop *loop,
|
SpaResult pinos_loop_iterate (PinosLoop *loop,
|
||||||
int timeout);
|
int timeout);
|
||||||
|
|
|
||||||
|
|
@ -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')),
|
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],
|
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],
|
||||||
|
)
|
||||||
|
|
|
||||||
|
|
@ -96,7 +96,7 @@ try_link_port (PinosNode *node, PinosPort *port, ModuleImpl *impl)
|
||||||
|
|
||||||
error:
|
error:
|
||||||
{
|
{
|
||||||
pinos_node_report_error (node, error);
|
pinos_node_update_state (node, PINOS_NODE_STATE_ERROR, error);
|
||||||
return;
|
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);
|
pinos_log_debug ("module %p: link %p: state error: %s", impl, link, link->error);
|
||||||
|
|
||||||
if (link->input && link->input->node)
|
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)
|
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;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
216
pinos/modules/module-suspend-on-idle.c
Normal file
216
pinos/modules/module-suspend-on-idle.c
Normal file
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -64,6 +64,7 @@ pinos_core_new (PinosMainLoop *main_loop)
|
||||||
pinos_signal_init (&this->destroy_signal);
|
pinos_signal_init (&this->destroy_signal);
|
||||||
pinos_signal_init (&this->global_added);
|
pinos_signal_init (&this->global_added);
|
||||||
pinos_signal_init (&this->global_removed);
|
pinos_signal_init (&this->global_removed);
|
||||||
|
pinos_signal_init (&this->node_state_request);
|
||||||
pinos_signal_init (&this->node_state_changed);
|
pinos_signal_init (&this->node_state_changed);
|
||||||
pinos_signal_init (&this->port_added);
|
pinos_signal_init (&this->port_added);
|
||||||
pinos_signal_init (&this->port_removed);
|
pinos_signal_init (&this->port_removed);
|
||||||
|
|
|
||||||
|
|
@ -76,6 +76,9 @@ struct _PinosCore {
|
||||||
PinosCore *core,
|
PinosCore *core,
|
||||||
PinosGlobal *global));
|
PinosGlobal *global));
|
||||||
|
|
||||||
|
PINOS_SIGNAL (node_state_request, (PinosListener *listener,
|
||||||
|
PinosNode *object,
|
||||||
|
PinosNodeState state));
|
||||||
PINOS_SIGNAL (node_state_changed, (PinosListener *listener,
|
PINOS_SIGNAL (node_state_changed, (PinosListener *listener,
|
||||||
PinosNode *object,
|
PinosNode *object,
|
||||||
PinosNodeState old,
|
PinosNodeState old,
|
||||||
|
|
|
||||||
|
|
@ -96,11 +96,14 @@ 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);
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
@ -169,7 +172,6 @@ pinos_data_loop_start (PinosDataLoop *loop)
|
||||||
impl->running = false;
|
impl->running = false;
|
||||||
return SPA_RESULT_ERROR;
|
return SPA_RESULT_ERROR;
|
||||||
}
|
}
|
||||||
pinos_loop_set_thread (impl->this.loop, &impl->thread);
|
|
||||||
}
|
}
|
||||||
return SPA_RESULT_OK;
|
return SPA_RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -748,7 +748,7 @@ do_link_remove_done (SpaLoop *loop,
|
||||||
|
|
||||||
if (this->input->node->n_used_input_links == 0 &&
|
if (this->input->node->n_used_input_links == 0 &&
|
||||||
this->input->node->n_used_output_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);
|
clear_port_buffers (this, this->input);
|
||||||
this->input = NULL;
|
this->input = NULL;
|
||||||
|
|
@ -759,7 +759,7 @@ do_link_remove_done (SpaLoop *loop,
|
||||||
|
|
||||||
if (this->output->node->n_used_input_links == 0 &&
|
if (this->output->node->n_used_input_links == 0 &&
|
||||||
this->output->node->n_used_output_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);
|
clear_port_buffers (this, this->output);
|
||||||
this->output = NULL;
|
this->output = NULL;
|
||||||
|
|
|
||||||
|
|
@ -37,8 +37,6 @@ typedef struct
|
||||||
uint32_t seq;
|
uint32_t seq;
|
||||||
|
|
||||||
bool async_init;
|
bool async_init;
|
||||||
|
|
||||||
guint idle_timeout;
|
|
||||||
} PinosNodeImpl;
|
} PinosNodeImpl;
|
||||||
|
|
||||||
static void init_complete (PinosNode *this);
|
static void init_complete (PinosNode *this);
|
||||||
|
|
@ -396,7 +394,7 @@ init_complete (PinosNode *this)
|
||||||
pinos_log_debug ("node %p: init completed", this);
|
pinos_log_debug ("node %p: init completed", this);
|
||||||
impl->async_init = false;
|
impl->async_init = false;
|
||||||
|
|
||||||
pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED);
|
pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -630,31 +628,20 @@ 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
|
static void
|
||||||
on_state_complete (PinosNode *node,
|
on_state_complete (PinosNode *node,
|
||||||
gpointer data,
|
gpointer data,
|
||||||
SpaResult res)
|
SpaResult res)
|
||||||
{
|
{
|
||||||
PinosNodeState state = GPOINTER_TO_INT (data);
|
PinosNodeState state = GPOINTER_TO_INT (data);
|
||||||
|
char *error = NULL;
|
||||||
|
|
||||||
pinos_log_debug ("node %p: state complete %d", node, res);
|
pinos_log_debug ("node %p: state complete %d", node, res);
|
||||||
if (SPA_RESULT_IS_ERROR (res)) {
|
if (SPA_RESULT_IS_ERROR (res)) {
|
||||||
char *error;
|
|
||||||
asprintf (&error, "error changing node state: %d", res);
|
asprintf (&error, "error changing node state: %d", res);
|
||||||
pinos_node_report_error (node, error);
|
state = PINOS_NODE_STATE_ERROR;
|
||||||
} else
|
}
|
||||||
pinos_node_update_state (node, state);
|
pinos_node_update_state (node, state, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -672,7 +659,7 @@ pinos_node_set_state (PinosNode *node,
|
||||||
{
|
{
|
||||||
SpaResult res = SPA_RESULT_OK;
|
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));
|
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:
|
* pinos_node_update_state:
|
||||||
* @node: a #PinosNode
|
* @node: a #PinosNode
|
||||||
* @state: a #PinosNodeState
|
* @state: a #PinosNodeState
|
||||||
|
* @error: error when @state is #PINOS_NODE_STATE_ERROR
|
||||||
*
|
*
|
||||||
* Update the state of a node. This method is used from
|
* Update the state of a node. This method is used from
|
||||||
* inside @node itself.
|
* inside @node itself.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
pinos_node_update_state (PinosNode *node,
|
pinos_node_update_state (PinosNode *node,
|
||||||
PinosNodeState state)
|
PinosNodeState state,
|
||||||
|
char *error)
|
||||||
{
|
{
|
||||||
PinosNodeState old;
|
PinosNodeState old;
|
||||||
|
|
||||||
|
|
@ -731,75 +720,10 @@ pinos_node_update_state (PinosNode *node,
|
||||||
pinos_node_state_as_string (old),
|
pinos_node_state_as_string (old),
|
||||||
pinos_node_state_as_string (state));
|
pinos_node_state_as_string (state));
|
||||||
|
|
||||||
|
if (node->error)
|
||||||
|
free (node->error);
|
||||||
|
node->error = error;
|
||||||
node->state = state;
|
node->state = state;
|
||||||
pinos_signal_emit (&node->core->node_state_changed, node, old, 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);
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -103,12 +103,11 @@ void pinos_node_set_data_loop (PinosNode *node,
|
||||||
PinosPort * pinos_node_get_free_port (PinosNode *node,
|
PinosPort * pinos_node_get_free_port (PinosNode *node,
|
||||||
PinosDirection direction);
|
PinosDirection direction);
|
||||||
|
|
||||||
SpaResult pinos_node_set_state (PinosNode *node, PinosNodeState state);
|
SpaResult pinos_node_set_state (PinosNode *node,
|
||||||
void pinos_node_update_state (PinosNode *node, PinosNodeState state);
|
PinosNodeState state);
|
||||||
|
void pinos_node_update_state (PinosNode *node,
|
||||||
void pinos_node_report_error (PinosNode *node, char *error);
|
PinosNodeState state,
|
||||||
void pinos_node_report_idle (PinosNode *node);
|
char *error);
|
||||||
void pinos_node_report_busy (PinosNode *node);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -238,7 +238,7 @@ do_remove_link_done (SpaLoop *loop,
|
||||||
|
|
||||||
if (node->n_used_output_links == 0 &&
|
if (node->n_used_output_links == 0 &&
|
||||||
node->n_used_input_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) {
|
if (!port->allocated) {
|
||||||
|
|
|
||||||
|
|
@ -26,11 +26,15 @@ extern "C" {
|
||||||
|
|
||||||
typedef struct _SpaLoop SpaLoop;
|
typedef struct _SpaLoop SpaLoop;
|
||||||
typedef struct _SpaSource SpaSource;
|
typedef struct _SpaSource SpaSource;
|
||||||
|
typedef struct _SpaLoopControl SpaLoopControl;
|
||||||
|
typedef struct _SpaLoopUtils SpaLoopUtils;
|
||||||
|
|
||||||
#define SPA_LOOP_URI "http://spaplug.in/ns/loop"
|
#define SPA_LOOP_URI "http://spaplug.in/ns/loop"
|
||||||
#define SPA_LOOP_PREFIX SPA_LOOP_URI "#"
|
#define SPA_LOOP_PREFIX SPA_LOOP_URI "#"
|
||||||
#define SPA_LOOP__MainLoop SPA_LOOP_PREFIX "MainLoop"
|
#define SPA_LOOP__MainLoop SPA_LOOP_PREFIX "MainLoop"
|
||||||
#define SPA_LOOP__DataLoop SPA_LOOP_PREFIX "DataLoop"
|
#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>
|
#include <spa/defs.h>
|
||||||
|
|
||||||
|
|
@ -62,7 +66,7 @@ typedef SpaResult (*SpaInvokeFunc) (SpaLoop *loop,
|
||||||
/**
|
/**
|
||||||
* SpaLoop:
|
* SpaLoop:
|
||||||
*
|
*
|
||||||
* Register sources to an event loop
|
* Register sources and work items to an event loop
|
||||||
*/
|
*/
|
||||||
struct _SpaLoop {
|
struct _SpaLoop {
|
||||||
/* the total size of this structure. This can be used to expand this
|
/* 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_remove_source(l,...) (l)->remove_source(__VA_ARGS__)
|
||||||
#define spa_loop_invoke(l,...) (l)->invoke((l),__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
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue