node: remove node state

Remove the node state. The state of the node is based on the state
of the ports, which can be derived directly from calling the port
methods. Track this state in the Port instead.
Add a mixer module that puts a mixer in from of audio sinks. This allows
multiple clients to play on one sink (still has some bugs). do some
fixes in the mixer and the scheduler to make this work.
This commit is contained in:
Wim Taymans 2017-04-08 20:33:54 +02:00
parent 28389e05f3
commit d3682067fa
30 changed files with 618 additions and 509 deletions

View file

@ -428,16 +428,16 @@ on_context_data (SpaSource *source,
continue;
}
if (opcode >= proxy->iface->n_events) {
pinos_log_error ("context %p: invalid method %u", this, opcode);
pinos_log_error ("context %p: invalid method %u for %u", this, opcode, id);
continue;
}
demarshal = proxy->iface->events;
if (demarshal[opcode]) {
if (!demarshal[opcode] (proxy, message, size))
pinos_log_error ("context %p: invalid message received %u", this, opcode);
pinos_log_error ("context %p: invalid message received %u for %u", this, opcode, id);
} else
pinos_log_error ("context %p: function %d not implemented", this, opcode);
pinos_log_error ("context %p: function %d not implemented on %u", this, opcode, id);
}
}

View file

@ -157,8 +157,6 @@ typedef struct {
const SpaFormat *format,
const SpaProps *props,
const SpaPortInfo *info);
void (*state_change) (void *object,
SpaNodeState state);
void (*event) (void *object,
SpaEvent *event);
void (*destroy) (void *object);
@ -166,7 +164,6 @@ typedef struct {
#define pinos_client_node_do_update(r,...) ((PinosClientNodeMethods*)r->iface->methods)->update(r,__VA_ARGS__)
#define pinos_client_node_do_port_update(r,...) ((PinosClientNodeMethods*)r->iface->methods)->port_update(r,__VA_ARGS__)
#define pinos_client_node_do_state_change(r,...) ((PinosClientNodeMethods*)r->iface->methods)->state_change(r,__VA_ARGS__)
#define pinos_client_node_do_event(r,...) ((PinosClientNodeMethods*)r->iface->methods)->event(r,__VA_ARGS__)
#define pinos_client_node_do_destroy(r) ((PinosClientNodeMethods*)r->iface->methods)->destroy(r)

View file

@ -535,23 +535,6 @@ client_node_marshal_port_update (void *object,
pinos_connection_end_write (connection, proxy->id, 1, b.b.offset);
}
static void
client_node_marshal_state_change (void *object,
SpaNodeState state)
{
PinosProxy *proxy = object;
PinosConnection *connection = proxy->context->protocol_private;
Builder b = { { NULL, 0, 0, NULL, write_pod }, connection };
SpaPODFrame f;
core_update_map (proxy->context);
spa_pod_builder_struct (&b.b, &f,
SPA_POD_TYPE_INT, state);
pinos_connection_end_write (connection, proxy->id, 2, b.b.offset);
}
static void
client_node_marshal_event (void *object,
SpaEvent *event)
@ -566,7 +549,7 @@ client_node_marshal_event (void *object,
spa_pod_builder_struct (&b.b, &f,
SPA_POD_TYPE_POD, event);
pinos_connection_end_write (connection, proxy->id, 3, b.b.offset);
pinos_connection_end_write (connection, proxy->id, 2, b.b.offset);
}
static void
@ -581,7 +564,7 @@ client_node_marshal_destroy (void *object)
spa_pod_builder_struct (&b.b, &f, 0);
pinos_connection_end_write (connection, proxy->id, 4, b.b.offset);
pinos_connection_end_write (connection, proxy->id, 3, b.b.offset);
}
static bool
@ -1042,7 +1025,6 @@ static const PinosInterface pinos_protocol_native_client_registry_interface = {
static const PinosClientNodeMethods pinos_protocol_native_client_client_node_methods = {
&client_node_marshal_update,
&client_node_marshal_port_update,
&client_node_marshal_state_change,
&client_node_marshal_event,
&client_node_marshal_destroy
};
@ -1062,7 +1044,7 @@ static const PinosDemarshalFunc pinos_protocol_native_client_client_node_demarsh
};
static const PinosInterface pinos_protocol_native_client_client_node_interface = {
5, &pinos_protocol_native_client_client_node_methods,
4, &pinos_protocol_native_client_client_node_methods,
11, pinos_protocol_native_client_client_node_demarshal,
};

View file

@ -61,7 +61,7 @@ typedef struct
{
PinosStream this;
SpaNodeState node_state;
uint32_t port_state;
uint32_t n_possible_formats;
SpaFormat **possible_formats;
@ -224,7 +224,7 @@ pinos_stream_new (PinosContext *context,
this->state = PINOS_STREAM_STATE_UNCONNECTED;
impl->node_state = SPA_NODE_STATE_INIT;
impl->port_state = SPA_PORT_STATE_INIT;
pinos_array_init (&impl->mem_ids, 64);
pinos_array_ensure_size (&impl->mem_ids, sizeof (MemId) * 64);
pinos_array_init (&impl->buffer_ids, 32);
@ -304,7 +304,7 @@ pinos_stream_destroy (PinosStream *stream)
}
static void
add_node_update (PinosStream *stream, uint32_t change_mask, bool flush)
add_node_update (PinosStream *stream, uint32_t change_mask)
{
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
uint32_t max_input_ports = 0, max_output_ports = 0;
@ -322,19 +322,7 @@ add_node_update (PinosStream *stream, uint32_t change_mask, bool flush)
}
static void
add_state_change (PinosStream *stream, SpaNodeState state, bool flush)
{
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
if (impl->node_state != state) {
impl->node_state = state;
pinos_client_node_do_state_change (impl->node_proxy,
state);
}
}
static void
add_port_update (PinosStream *stream, uint32_t change_mask, bool flush)
add_port_update (PinosStream *stream, uint32_t change_mask)
{
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
@ -384,7 +372,7 @@ send_have_output (PinosStream *stream)
}
static void
add_request_clock_update (PinosStream *stream, bool flush)
add_request_clock_update (PinosStream *stream)
{
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
SpaEventNodeRequestClockUpdate rcu =
@ -397,8 +385,7 @@ add_request_clock_update (PinosStream *stream, bool flush)
static void
add_async_complete (PinosStream *stream,
uint32_t seq,
SpaResult res,
bool flush)
SpaResult res)
{
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
SpaEventNodeAsyncComplete ac =
@ -413,14 +400,12 @@ do_node_init (PinosStream *stream)
PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this);
add_node_update (stream, PINOS_MESSAGE_NODE_UPDATE_MAX_INPUTS |
PINOS_MESSAGE_NODE_UPDATE_MAX_OUTPUTS,
false);
PINOS_MESSAGE_NODE_UPDATE_MAX_OUTPUTS);
impl->port_info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
add_port_update (stream, PINOS_MESSAGE_PORT_UPDATE_POSSIBLE_FORMATS |
PINOS_MESSAGE_PORT_UPDATE_INFO,
false);
add_state_change (stream, SPA_NODE_STATE_CONFIGURE, true);
PINOS_MESSAGE_PORT_UPDATE_INFO);
add_async_complete (stream, 0, SPA_RESULT_OK);
}
static void
@ -428,8 +413,7 @@ on_timeout (SpaSource *source,
void *data)
{
PinosStream *stream = data;
add_request_clock_update (stream, true);
add_request_clock_update (stream);
}
static MemId *
@ -606,14 +590,12 @@ handle_node_command (PinosStream *stream,
impl->rtsocket_source,
SPA_IO_ERR | SPA_IO_HUP);
add_state_change (stream, SPA_NODE_STATE_PAUSED, false);
add_async_complete (stream, seq, SPA_RESULT_OK, true);
add_async_complete (stream, seq, SPA_RESULT_OK);
stream_set_state (stream, PINOS_STREAM_STATE_PAUSED, NULL);
}
else if (SPA_COMMAND_TYPE (command) == context->type.command_node.Start) {
pinos_log_debug ("stream %p: start %d %d", stream, seq, impl->direction);
add_state_change (stream, SPA_NODE_STATE_STREAMING, false);
add_async_complete (stream, seq, SPA_RESULT_OK, true);
add_async_complete (stream, seq, SPA_RESULT_OK);
pinos_loop_update_io (stream->context->loop,
impl->rtsocket_source,
@ -640,7 +622,7 @@ handle_node_command (PinosStream *stream,
}
else {
pinos_log_warn ("unhandled node command %d", SPA_COMMAND_TYPE (command));
add_async_complete (stream, seq, SPA_RESULT_NOT_IMPLEMENTED, true);
add_async_complete (stream, seq, SPA_RESULT_NOT_IMPLEMENTED);
}
return true;
}
@ -854,18 +836,14 @@ client_node_use_buffers (void *object,
pinos_signal_emit (&stream->add_buffer, stream, bid->id);
}
if (n_buffers) {
add_state_change (stream, SPA_NODE_STATE_PAUSED, false);
} else {
clear_mems (stream);
add_state_change (stream, SPA_NODE_STATE_READY, false);
}
add_async_complete (stream, seq, SPA_RESULT_OK, true);
add_async_complete (stream, seq, SPA_RESULT_OK);
if (n_buffers)
stream_set_state (stream, PINOS_STREAM_STATE_PAUSED, NULL);
else
else {
clear_mems (stream);
stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL);
}
}
static void
@ -1031,19 +1009,15 @@ pinos_stream_finish_format (PinosStream *stream,
if (SPA_RESULT_IS_OK (res)) {
add_port_update (stream, PINOS_MESSAGE_PORT_UPDATE_INFO |
PINOS_MESSAGE_PORT_UPDATE_FORMAT,
false);
if (impl->format) {
add_state_change (stream, SPA_NODE_STATE_READY, false);
} else {
PINOS_MESSAGE_PORT_UPDATE_FORMAT);
if (!impl->format)
clear_buffers (stream);
add_state_change (stream, SPA_NODE_STATE_CONFIGURE, false);
}
}
impl->port_info.params = NULL;
impl->port_info.n_params = 0;
add_async_complete (stream, impl->pending_seq, res, true);
add_async_complete (stream, impl->pending_seq, res);
impl->pending_seq = SPA_ID_INVALID;

View file

@ -57,7 +57,7 @@ transport_area_get_size (PinosTransportArea *area)
}
static void
transport_setup_area (void *p, PinosTransport *trans)
transport_setup_area (void *p, PinosTransport *trans, bool reset)
{
PinosTransportArea *a;
int i;
@ -66,36 +66,37 @@ transport_setup_area (void *p, PinosTransport *trans)
p = SPA_MEMBER (p, sizeof (PinosTransportArea), SpaPortIO);
trans->inputs = p;
for (i = 0; i < a->max_inputs; i++) {
trans->inputs[i].state = SPA_PORT_STATE_FLAG_NONE;
trans->inputs[i].flags = SPA_PORT_IO_FLAG_NONE;
trans->inputs[i].buffer_id = SPA_ID_INVALID;
trans->inputs[i].status = SPA_RESULT_OK;
}
p = SPA_MEMBER (p, a->max_inputs * sizeof (SpaPortIO), void);
trans->outputs = p;
for (i = 0; i < a->max_outputs; i++) {
trans->outputs[i].state = SPA_PORT_STATE_FLAG_NONE;
trans->outputs[i].flags = SPA_PORT_IO_FLAG_NONE;
trans->outputs[i].buffer_id = SPA_ID_INVALID;
trans->outputs[i].status = SPA_RESULT_OK;
}
p = SPA_MEMBER (p, a->max_outputs * sizeof (SpaPortIO), void);
trans->input_buffer = p;
spa_ringbuffer_init (trans->input_buffer, INPUT_BUFFER_SIZE);
p = SPA_MEMBER (p, sizeof (SpaRingbuffer), void);
trans->input_data = p;
p = SPA_MEMBER (p, INPUT_BUFFER_SIZE, void);
trans->output_buffer = p;
spa_ringbuffer_init (trans->output_buffer, OUTPUT_BUFFER_SIZE);
p = SPA_MEMBER (p, sizeof (SpaRingbuffer), void);
trans->output_data = p;
p = SPA_MEMBER (p, OUTPUT_BUFFER_SIZE, void);
if (reset) {
for (i = 0; i < a->max_inputs; i++) {
trans->inputs[i].flags = 0;
trans->inputs[i].buffer_id = SPA_ID_INVALID;
trans->inputs[i].status = SPA_RESULT_OK;
}
for (i = 0; i < a->max_outputs; i++) {
trans->outputs[i].flags = 0;
trans->outputs[i].buffer_id = SPA_ID_INVALID;
trans->outputs[i].status = SPA_RESULT_OK;
}
spa_ringbuffer_init (trans->input_buffer, INPUT_BUFFER_SIZE);
spa_ringbuffer_init (trans->output_buffer, OUTPUT_BUFFER_SIZE);
}
}
PinosTransport *
@ -127,7 +128,7 @@ pinos_transport_new (uint32_t max_inputs,
&impl->mem);
memcpy (impl->mem.ptr, &area, sizeof (PinosTransportArea));
transport_setup_area (impl->mem.ptr, trans);
transport_setup_area (impl->mem.ptr, trans, true);
return trans;
}
@ -158,7 +159,7 @@ pinos_transport_new_from_info (PinosTransportInfo *info)
impl->offset = info->offset;
transport_setup_area (impl->mem.ptr, trans);
transport_setup_area (impl->mem.ptr, trans, false);
tmp = trans->output_buffer;
trans->output_buffer = trans->input_buffer;

View file

@ -624,7 +624,7 @@ gst_pinos_sink_setcaps (GstBaseSink * bsink, GstCaps * caps)
if (!gst_buffer_pool_is_active (GST_BUFFER_POOL_CAST (pinossink->pool))) {
GstStructure *config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pinossink->pool));
gst_buffer_pool_config_set_params (config, caps, 8192, 8, 16);
gst_buffer_pool_config_set_params (config, caps, 8192, 16, 32);
gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pinossink->pool), config);
gst_buffer_pool_set_active (GST_BUFFER_POOL_CAST (pinossink->pool), TRUE);
}

View file

@ -24,6 +24,15 @@ pinos_module_autolink = shared_library('pinos-module-autolink', [ 'module-autoli
dependencies : [mathlib, dl_lib, pinos_dep, pinoscore_dep],
)
pinos_module_mixer = shared_library('pinos-module-mixer', [ 'module-mixer.c' ],
c_args : pinos_module_c_args,
include_directories : [configinc, 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],
)
pinos_module_protocol_dbus = shared_library('pinos-module-protocol-dbus', [ 'module-protocol-dbus.c', gdbus_target ],
c_args : pinos_module_c_args,
include_directories : [configinc, spa_inc],

View file

@ -0,0 +1,188 @@
/* Pinos
* Copyright (C) 2017 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 <dlfcn.h>
#include "config.h"
#include "pinos/server/core.h"
#include "pinos/server/module.h"
#define AUDIOMIXER_LIB "build/spa/plugins/audiomixer/libspa-audiomixer.so"
typedef struct {
PinosCore *core;
PinosProperties *properties;
void *hnd;
const SpaHandleFactory *factory;
PinosListener check_send;
PinosListener check_dispatch;
} ModuleImpl;
static const SpaHandleFactory *
find_factory (ModuleImpl *impl)
{
SpaEnumHandleFactoryFunc enum_func;
uint32_t index;
const SpaHandleFactory *factory = NULL;
SpaResult res;
if ((impl->hnd = dlopen (AUDIOMIXER_LIB, RTLD_NOW)) == NULL) {
pinos_log_error ("can't load %s: %s", AUDIOMIXER_LIB, dlerror());
return NULL;
}
if ((enum_func = dlsym (impl->hnd, "spa_enum_handle_factory")) == NULL) {
pinos_log_error ("can't find enum function");
goto no_symbol;
}
for (index = 0; ; index++) {
if ((res = enum_func (&factory, index)) < 0) {
if (res != SPA_RESULT_ENUM_END)
pinos_log_error ("can't enumerate factories: %d", res);
goto enum_failed;
}
if (strcmp (factory->name, "audiomixer") == 0)
break;
}
return factory;
enum_failed:
no_symbol:
dlclose (impl->hnd);
impl->hnd = NULL;
return NULL;
}
static PinosNode *
make_node (ModuleImpl *impl)
{
SpaHandle *handle;
SpaResult res;
void *iface;
SpaNode *spa_node;
SpaClock *spa_clock;
PinosNode *node;
handle = calloc (1, impl->factory->size);
if ((res = spa_handle_factory_init (impl->factory,
handle,
NULL,
impl->core->support,
impl->core->n_support)) < 0) {
pinos_log_error ("can't make factory instance: %d", res);
goto init_failed;
}
if ((res = spa_handle_get_interface (handle,
impl->core->type.spa_node,
&iface)) < 0) {
pinos_log_error ("can't get interface %d", res);
goto interface_failed;
}
spa_node = iface;
if ((res = spa_handle_get_interface (handle,
impl->core->type.spa_clock,
&iface)) < 0) {
iface = NULL;
}
spa_clock = iface;
node = pinos_node_new (impl->core,
"audiomixer",
false,
spa_node,
spa_clock,
NULL);
return node;
interface_failed:
spa_handle_clear (handle);
init_failed:
free (handle);
return NULL;
}
static ModuleImpl *
module_new (PinosCore *core,
PinosProperties *properties)
{
ModuleImpl *impl;
PinosNode *n;
impl = calloc (1, sizeof (ModuleImpl));
pinos_log_debug ("module %p: new", impl);
impl->core = core;
impl->properties = properties;
impl->factory = find_factory (impl);
spa_list_for_each (n, &core->node_list, link) {
const char *str;
char *error;
PinosNode *node;
PinosPort *ip, *op;
if (n->global == NULL)
continue;
if (n->properties == NULL)
continue;
if ((str = pinos_properties_get (n->properties, "media.class")) == NULL)
continue;
if (strcmp (str, "Audio/Sink") != 0)
continue;
if ((ip = pinos_node_get_free_port (n, PINOS_DIRECTION_INPUT)) == NULL)
continue;
node = make_node (impl);
op = pinos_node_get_free_port (node, PINOS_DIRECTION_OUTPUT);
if (op == NULL)
continue;
pinos_port_link (op, ip, NULL, NULL, &error);
}
return impl;
}
#if 0
static void
module_destroy (ModuleImpl *impl)
{
pinos_log_debug ("module %p: destroy", impl);
free (impl);
}
#endif
bool
pinos__module_init (PinosModule * module, const char * args)
{
module_new (module->core, NULL);
return true;
}

View file

@ -113,6 +113,7 @@ add_item (PinosSpaMonitor *this, SpaMonitorItem *item)
mitem->id = strdup (id);
mitem->node = pinos_node_new (impl->core,
name,
false,
node_iface,
clock_iface,
props);

View file

@ -113,6 +113,7 @@ pinos_spa_node_load (PinosCore *core,
this->node = pinos_node_new (core,
name,
false,
spa_node,
spa_clock,
properties);

View file

@ -75,7 +75,7 @@ typedef struct {
SpaFormat *format;
uint32_t n_formats;
SpaFormat **formats;
void *io;
SpaPortIO *io;
uint32_t n_buffers;
ProxyBuffer buffers[MAX_BUFFERS];
@ -129,15 +129,6 @@ typedef struct
int data_fd;
} PinosClientNodeImpl;
static void
send_async_complete (SpaProxy *this, uint32_t seq, SpaResult res)
{
PinosCore *core = this->pnode->core;
SpaEventNodeAsyncComplete ac = SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (core->type.event_node.AsyncComplete,
seq, res);
this->event_cb (&this->node, (SpaEvent *)&ac, this->user_data);
}
static SpaResult
clear_buffers (SpaProxy *this, SpaProxyPort *port)
{
@ -758,7 +749,6 @@ spa_proxy_node_port_reuse_buffer (SpaNode *node,
{
SpaProxy *this;
PinosNode *pnode;
//uint64_t cmd = 1;
if (node == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
@ -769,11 +759,11 @@ spa_proxy_node_port_reuse_buffer (SpaNode *node,
if (!CHECK_OUT_PORT (this, SPA_DIRECTION_OUTPUT, port_id))
return SPA_RESULT_INVALID_PORT;
spa_log_trace (this->log, "reuse buffer %d", buffer_id);
{
SpaEventNodeReuseBuffer rb = SPA_EVENT_NODE_REUSE_BUFFER_INIT (pnode->core->type.event_node.ReuseBuffer,
port_id, buffer_id);
pinos_transport_add_event (pnode->transport, (SpaEvent *)&rb);
//write (this->data_source.fd, &cmd, 8);
}
return SPA_RESULT_OK;
@ -815,15 +805,23 @@ static SpaResult
spa_proxy_node_process_output (SpaNode *node)
{
SpaProxy *this;
int i;
if (node == NULL)
return SPA_RESULT_INVALID_ARGUMENTS;
this = SPA_CONTAINER_OF (node, SpaProxy, node);
for (i = 0; i < MAX_OUTPUTS; i++) {
SpaPortIO *io = this->out_ports[i].io;
if (io && io->buffer_id != SPA_ID_INVALID) {
spa_proxy_node_port_reuse_buffer (node, i, io->buffer_id);
io->buffer_id = SPA_ID_INVALID;
}
}
send_need_input (this);
return SPA_RESULT_OK;
return SPA_RESULT_HAVE_OUTPUT;
}
static SpaResult
@ -893,22 +891,6 @@ client_node_port_update (void *object,
}
}
static void
client_node_state_change (void *object,
SpaNodeState state)
{
PinosResource *resource = object;
PinosClientNode *node = resource->object;
PinosClientNodeImpl *impl = SPA_CONTAINER_OF (node, PinosClientNodeImpl, this);
SpaProxy *this = &impl->proxy;
SpaNodeState old = this->node.state;
spa_log_info (this->log, "proxy %p: got node state change %d -> %d", this, old, state);
this->node.state = state;
if (old == SPA_NODE_STATE_INIT)
send_async_complete (this, 0, SPA_RESULT_OK);
}
static void
client_node_event (void *object,
SpaEvent *event)
@ -932,7 +914,6 @@ client_node_destroy (void *object)
static PinosClientNodeMethods client_node_methods = {
&client_node_update,
&client_node_port_update,
&client_node_state_change,
&client_node_event,
&client_node_destroy,
};
@ -965,7 +946,6 @@ proxy_on_data_fd_events (SpaSource *source)
static const SpaNode proxy_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_proxy_node_get_props,
spa_proxy_node_set_props,
spa_proxy_node_send_command,
@ -1153,6 +1133,7 @@ pinos_client_node_new (PinosClient *client,
this->node = pinos_node_new (client->core,
name,
true,
&impl->proxy.node,
NULL,
properties);

View file

@ -543,20 +543,22 @@ pinos_core_find_format (PinosCore *core,
SpaFormat **format_filterss,
char **error)
{
SpaNodeState out_state, in_state;
uint32_t out_state, in_state;
SpaResult res;
SpaFormat *filter = NULL, *format;
uint32_t iidx = 0, oidx = 0;
out_state = output->node->node->state;
in_state = input->node->node->state;
out_state = output->state;
in_state = input->state;
if (out_state > SPA_NODE_STATE_CONFIGURE && output->node->state == PINOS_NODE_STATE_IDLE)
out_state = SPA_NODE_STATE_CONFIGURE;
if (in_state > SPA_NODE_STATE_CONFIGURE && input->node->state == PINOS_NODE_STATE_IDLE)
in_state = SPA_NODE_STATE_CONFIGURE;
pinos_log_debug ("core %p: finding best format %d %d", core, out_state, in_state);
if (in_state == SPA_NODE_STATE_CONFIGURE && out_state > SPA_NODE_STATE_CONFIGURE) {
if (out_state > SPA_PORT_STATE_CONFIGURE && output->node->state == PINOS_NODE_STATE_IDLE)
out_state = SPA_PORT_STATE_CONFIGURE;
if (in_state > SPA_PORT_STATE_CONFIGURE && input->node->state == PINOS_NODE_STATE_IDLE)
in_state = SPA_PORT_STATE_CONFIGURE;
if (in_state == SPA_PORT_STATE_CONFIGURE && out_state > SPA_PORT_STATE_CONFIGURE) {
/* only input needs format */
if ((res = spa_node_port_get_format (output->node->node,
SPA_DIRECTION_OUTPUT,
@ -565,7 +567,7 @@ pinos_core_find_format (PinosCore *core,
asprintf (error, "error get output format: %d", res);
goto error;
}
} else if (out_state == SPA_NODE_STATE_CONFIGURE && in_state > SPA_NODE_STATE_CONFIGURE) {
} else if (out_state == SPA_PORT_STATE_CONFIGURE && in_state > SPA_PORT_STATE_CONFIGURE) {
/* only output needs format */
if ((res = spa_node_port_get_format (input->node->node,
SPA_DIRECTION_INPUT,
@ -574,7 +576,7 @@ pinos_core_find_format (PinosCore *core,
asprintf (error, "error get input format: %d", res);
goto error;
}
} else if (in_state == SPA_NODE_STATE_CONFIGURE && out_state == SPA_NODE_STATE_CONFIGURE) {
} else if (in_state == SPA_PORT_STATE_CONFIGURE && out_state == SPA_PORT_STATE_CONFIGURE) {
again:
/* both ports need a format */
pinos_log_debug ("core %p: finding best format", core);

View file

@ -76,14 +76,14 @@ pinos_link_update_state (PinosLink *link,
}
static SpaResult
do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
do_negotiate (PinosLink *this, uint32_t in_state, uint32_t out_state)
{
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
SpaResult res = SPA_RESULT_ERROR, res2;
SpaFormat *format;
char *error = NULL;
if (in_state != SPA_NODE_STATE_CONFIGURE && out_state != SPA_NODE_STATE_CONFIGURE)
if (in_state != SPA_PORT_STATE_CONFIGURE && out_state != SPA_PORT_STATE_CONFIGURE)
return SPA_RESULT_OK;
pinos_link_update_state (this, PINOS_LINK_STATE_NEGOTIATING, NULL);
@ -98,20 +98,20 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
if (format == NULL)
goto error;
if (out_state > SPA_NODE_STATE_CONFIGURE && this->output->node->state == PINOS_NODE_STATE_IDLE) {
if (out_state > SPA_PORT_STATE_CONFIGURE && this->output->node->state == PINOS_NODE_STATE_IDLE) {
pinos_node_set_state (this->output->node, PINOS_NODE_STATE_SUSPENDED);
out_state = SPA_NODE_STATE_CONFIGURE;
out_state = SPA_PORT_STATE_CONFIGURE;
}
if (in_state > SPA_NODE_STATE_CONFIGURE && this->input->node->state == PINOS_NODE_STATE_IDLE) {
if (in_state > SPA_PORT_STATE_CONFIGURE && this->input->node->state == PINOS_NODE_STATE_IDLE) {
pinos_node_set_state (this->input->node, PINOS_NODE_STATE_SUSPENDED);
in_state = SPA_NODE_STATE_CONFIGURE;
in_state = SPA_PORT_STATE_CONFIGURE;
}
pinos_log_debug ("link %p: doing set format", this);
if (pinos_log_level_enabled (SPA_LOG_LEVEL_DEBUG))
spa_debug_format (format, this->core->type.map);
if (out_state == SPA_NODE_STATE_CONFIGURE) {
if (out_state == SPA_PORT_STATE_CONFIGURE) {
pinos_log_debug ("link %p: doing set format on output", this);
if ((res = spa_node_port_set_format (this->output->node->node,
SPA_DIRECTION_OUTPUT,
@ -121,9 +121,10 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
asprintf (&error, "error set output format: %d", res);
goto error;
}
this->output->state = SPA_PORT_STATE_READY;
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
}
if (in_state == SPA_NODE_STATE_CONFIGURE) {
if (in_state == SPA_PORT_STATE_CONFIGURE) {
pinos_log_debug ("link %p: doing set format on input", this);
if ((res2 = spa_node_port_set_format (this->input->node->node,
SPA_DIRECTION_INPUT,
@ -133,6 +134,7 @@ do_negotiate (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
asprintf (&error, "error set input format: %d", res2);
goto error;
}
this->input->state = SPA_PORT_STATE_READY;
pinos_work_queue_add (impl->work, this->input->node, res2, NULL, NULL);
res = res2 != SPA_RESULT_OK ? res2 : res;
}
@ -322,7 +324,7 @@ alloc_buffers (PinosLink *this,
}
static SpaResult
do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
do_allocation (PinosLink *this, uint32_t in_state, uint32_t out_state)
{
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
SpaResult res;
@ -330,7 +332,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
SpaPortInfoFlags in_flags, out_flags;
char *error = NULL;
if (in_state != SPA_NODE_STATE_READY && out_state != SPA_NODE_STATE_READY)
if (in_state != SPA_PORT_STATE_READY && out_state != SPA_PORT_STATE_READY)
return SPA_RESULT_OK;
pinos_link_update_state (this, PINOS_LINK_STATE_ALLOCATING, NULL);
@ -361,7 +363,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
this->input->node->live = true;
}
if (in_state == SPA_NODE_STATE_READY && out_state == SPA_NODE_STATE_READY) {
if (in_state == SPA_PORT_STATE_READY && out_state == SPA_PORT_STATE_READY) {
if ((out_flags & SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS) &&
(in_flags & SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS)) {
out_flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
@ -383,10 +385,10 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
res = SPA_RESULT_ERROR;
goto error;
}
} else if (in_state == SPA_NODE_STATE_READY && out_state > SPA_NODE_STATE_READY) {
} else if (in_state == SPA_PORT_STATE_READY && out_state > SPA_PORT_STATE_READY) {
out_flags &= ~SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
in_flags &= ~SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
} else if (out_state == SPA_NODE_STATE_READY && in_state > SPA_NODE_STATE_READY) {
} else if (out_state == SPA_PORT_STATE_READY && in_state > SPA_PORT_STATE_READY) {
in_flags &= ~SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS;
out_flags &= ~SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS;
} else {
@ -505,6 +507,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
asprintf (&error, "error alloc output buffers: %d", res);
goto error;
}
this->output->state = SPA_PORT_STATE_PAUSED;
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
this->output->buffers = impl->buffers;
this->output->n_buffers = impl->n_buffers;
@ -521,6 +524,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
asprintf (&error, "error alloc input buffers: %d", res);
goto error;
}
this->input->state = SPA_PORT_STATE_PAUSED;
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
this->input->buffers = impl->buffers;
this->input->n_buffers = impl->n_buffers;
@ -541,6 +545,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
asprintf (&error, "error use input buffers: %d", res);
goto error;
}
this->input->state = SPA_PORT_STATE_PAUSED;
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
this->input->buffers = impl->buffers;
this->input->n_buffers = impl->n_buffers;
@ -556,6 +561,7 @@ do_allocation (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
asprintf (&error, "error use output buffers: %d", res);
goto error;
}
this->output->state = SPA_PORT_STATE_PAUSED;
pinos_work_queue_add (impl->work, this->output->node, res, NULL, NULL);
this->output->buffers = impl->buffers;
this->output->n_buffers = impl->n_buffers;
@ -581,24 +587,26 @@ error:
}
static SpaResult
do_start (PinosLink *this, SpaNodeState in_state, SpaNodeState out_state)
do_start (PinosLink *this, uint32_t in_state, uint32_t out_state)
{
SpaResult res = SPA_RESULT_OK;
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
if (in_state < SPA_NODE_STATE_PAUSED || out_state < SPA_NODE_STATE_PAUSED)
if (in_state < SPA_PORT_STATE_PAUSED || out_state < SPA_PORT_STATE_PAUSED)
return SPA_RESULT_OK;
else if (in_state == SPA_NODE_STATE_STREAMING && out_state == SPA_NODE_STATE_STREAMING) {
else if (in_state == SPA_PORT_STATE_STREAMING && out_state == SPA_PORT_STATE_STREAMING) {
pinos_link_update_state (this, PINOS_LINK_STATE_RUNNING, NULL);
} else {
pinos_link_update_state (this, PINOS_LINK_STATE_PAUSED, NULL);
if (in_state == SPA_NODE_STATE_PAUSED) {
if (in_state == SPA_PORT_STATE_PAUSED) {
res = pinos_node_set_state (this->input->node, PINOS_NODE_STATE_RUNNING);
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
this->input->state = SPA_PORT_STATE_STREAMING;
}
if (out_state == SPA_NODE_STATE_PAUSED) {
if (out_state == SPA_PORT_STATE_PAUSED) {
res = pinos_node_set_state (this->output->node, PINOS_NODE_STATE_RUNNING);
this->output->state = SPA_PORT_STATE_STREAMING;
pinos_work_queue_add (impl->work, this->input->node, res, NULL, NULL);
}
}
@ -611,7 +619,7 @@ check_states (PinosLink *this,
SpaResult res)
{
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
SpaNodeState in_state, out_state;
uint32_t in_state, out_state;
again:
if (this->state == PINOS_LINK_STATE_ERROR)
@ -624,8 +632,8 @@ again:
this->output->node->state == PINOS_NODE_STATE_ERROR)
return SPA_RESULT_ERROR;
in_state = this->input->node->node->state;
out_state = this->output->node->node->state;
in_state = this->input->state;
out_state = this->output->state;
pinos_log_debug ("link %p: input state %d, output state %d", this, in_state, out_state);
@ -638,9 +646,9 @@ again:
if ((res = do_start (this, in_state, out_state)) != SPA_RESULT_OK)
goto exit;
if (this->input->node->node->state != in_state)
if (this->input->state != in_state)
goto again;
if (this->output->node->node->state != out_state)
if (this->output->state != out_state)
goto again;
return SPA_RESULT_OK;
@ -737,6 +745,7 @@ pinos_link_activate (PinosLink *this)
{
PinosLinkImpl *impl = SPA_CONTAINER_OF (this, PinosLinkImpl, this);
pinos_log_debug ("link %p: activate", this);
pinos_work_queue_add (impl->work,
this,
SPA_RESULT_WAIT_SYNC,
@ -902,6 +911,7 @@ clear_port_buffers (PinosLink *link, PinosPort *port)
port->direction,
port->port_id,
NULL, 0);
port->state = SPA_PORT_STATE_READY;
port->buffers = NULL;
port->n_buffers = 0;
}

View file

@ -33,6 +33,9 @@ typedef struct
{
PinosNode this;
#define STATE_IN 0
#define STATE_OUT 1
int state;
PinosWorkQueue *work;
bool async_init;
@ -41,13 +44,14 @@ typedef struct
static void init_complete (PinosNode *this);
static void
update_port_ids (PinosNode *node, bool create)
update_port_ids (PinosNode *node)
{
PinosNodeImpl *impl = SPA_CONTAINER_OF (node, PinosNodeImpl, this);
uint32_t *input_port_ids, *output_port_ids;
uint32_t n_input_ports, n_output_ports, max_input_ports, max_output_ports;
uint32_t i;
SpaList *ports;
SpaResult res;
if (node->node == NULL)
return;
@ -58,6 +62,15 @@ update_port_ids (PinosNode *node, bool create)
&n_output_ports,
&max_output_ports);
node->transport = pinos_transport_new (max_input_ports,
max_output_ports);
node->input_port_map = calloc (max_input_ports, sizeof (PinosPort *));
node->output_port_map = calloc (max_output_ports, sizeof (PinosPort *));
node->transport->area->n_inputs = n_input_ports;
node->transport->area->n_outputs = n_output_ports;
input_port_ids = alloca (sizeof (uint32_t) * n_input_ports);
output_port_ids = alloca (sizeof (uint32_t) * n_output_ports);
@ -67,9 +80,6 @@ update_port_ids (PinosNode *node, bool create)
max_output_ports,
output_port_ids);
node->input_port_map = realloc (node->input_port_map, sizeof (PinosPort *) * max_input_ports);
node->output_port_map = realloc (node->output_port_map, sizeof (PinosPort *) * max_output_ports);
pinos_log_debug ("node %p: update_port ids %u/%u, %u/%u", node,
n_input_ports, max_input_ports, n_output_ports, max_output_ports);
@ -88,6 +98,10 @@ update_port_ids (PinosNode *node, bool create)
pinos_log_debug ("node %p: input port added %d", node, input_port_ids[i]);
np = pinos_port_new (node, PINOS_DIRECTION_INPUT, input_port_ids[i]);
np->io = &node->transport->inputs[np->port_id];
if ((res = spa_node_port_set_io (node->node, SPA_DIRECTION_INPUT, np->port_id, np->io)) < 0)
pinos_log_warn ("node %p: can't set input IO %d", node, res);
spa_list_insert (ports, &np->link);
ports = np->link.next;
node->input_port_map[np->port_id] = np;
@ -123,6 +137,10 @@ update_port_ids (PinosNode *node, bool create)
pinos_log_debug ("node %p: output port added %d", node, output_port_ids[i]);
np = pinos_port_new (node, PINOS_DIRECTION_OUTPUT, output_port_ids[i]);
np->io = &node->transport->outputs[np->port_id];
if ((res = spa_node_port_set_io (node->node, SPA_DIRECTION_OUTPUT, np->port_id, np->io)) < 0)
pinos_log_warn ("node %p: can't set output IO %d", node, res);
spa_list_insert (ports, &np->link);
ports = np->link.next;
node->output_port_map[np->port_id] = np;
@ -143,17 +161,6 @@ update_port_ids (PinosNode *node, bool create)
}
}
node->transport = pinos_transport_new (max_input_ports,
max_output_ports);
node->transport->area->n_inputs = n_input_ports;
node->transport->area->n_outputs = n_output_ports;
for (i = 0; i < max_input_ports; i++)
spa_node_port_set_io (node->node, SPA_DIRECTION_INPUT, i, &node->transport->inputs[i]);
for (i = 0; i < max_output_ports; i++)
spa_node_port_set_io (node->node, SPA_DIRECTION_OUTPUT, i, &node->transport->outputs[i]);
pinos_signal_emit (&node->transport_changed, node);
}
@ -162,9 +169,6 @@ pause_node (PinosNode *this)
{
SpaResult res;
if (this->node->state <= SPA_NODE_STATE_PAUSED)
return SPA_RESULT_OK;
pinos_log_debug ("node %p: pause node", this);
{
SpaCommand cmd = SPA_COMMAND_INIT (this->core->type.command_node.Pause);
@ -267,7 +271,8 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.NeedInput) {
SpaResult res;
int i;
bool processed = false;
this->sched_state = STATE_IN;
for (i = 0; i < this->transport->area->n_inputs; i++) {
PinosLink *link;
@ -276,8 +281,7 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
SpaPortIO *po;
pi = &this->transport->inputs[i];
if (pi->buffer_id != SPA_ID_INVALID)
continue;
pinos_log_trace ("node %p: need input port %d, %d", this, i, pi->buffer_id);
inport = this->input_port_map[i];
spa_list_for_each (link, &inport->rt.links, rt.input_link) {
@ -287,23 +291,58 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
outport = link->rt.output;
po = &outport->node->transport->outputs[outport->port_id];
if (po->buffer_id != SPA_ID_INVALID) {
processed = true;
if (outport->node->sched_state == STATE_IN) {
/* pull */
*po = *pi;
pi->buffer_id = SPA_ID_INVALID;
pinos_log_trace ("node %p: process output %p %d", outport->node, po, po->buffer_id);
res = spa_node_process_output (outport->node->node);
if (res == SPA_RESULT_NEED_INPUT) {
on_node_event (outport->node->node, event, outport->node);
if (outport->node->sched_state == STATE_OUT)
goto push;
}
else if (res == SPA_RESULT_HAVE_OUTPUT) {
outport->node->sched_state = STATE_OUT;
}
else
pinos_log_warn ("node %p: got process output %d", outport->node, res);
} else {
/* push */
push:
*pi = *po;
pinos_log_trace ("node %p: process output %p %d", outport->node, po, po->buffer_id);
res = spa_node_process_output (outport->node->node);
if (res == SPA_RESULT_HAVE_OUTPUT)
outport->node->sched_state = STATE_OUT;
else if (res == SPA_RESULT_NEED_INPUT)
outport->node->sched_state = STATE_IN;
else if (res < 0)
pinos_log_warn ("node %p: got process output %d", this, res);
}
if ((res = spa_node_process_output (outport->node->node)) < 0)
pinos_log_warn ("node %p: got process output %d", outport->node, res);
}
}
if (processed) {
if ((res = spa_node_process_input (this->node)) < 0)
pinos_log_warn ("node %p: got process input %d", this, res);
if (pi->buffer_id != SPA_ID_INVALID) {
pinos_log_trace ("node %p: process input", this);
res = spa_node_process_input (this->node);
if (res == SPA_RESULT_HAVE_OUTPUT)
this->sched_state = STATE_OUT;
else if (res == SPA_RESULT_NEED_INPUT)
this->sched_state = STATE_IN;
else if (res < 0)
pinos_log_warn ("node %p: got process input %d", this, res);
}
}
}
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.HaveOutput) {
SpaResult res;
int i;
bool processed = false;
for (i = 0; i < this->transport->area->n_outputs; i++) {
PinosLink *link;
@ -327,13 +366,36 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data)
if ((res = spa_node_process_input (inport->node->node)) < 0)
pinos_log_warn ("node %p: got process input %d", inport->node, res);
}
processed = true;
}
if (processed) {
if ((res = spa_node_process_output (this->node)) < 0)
pinos_log_warn ("node %p: got process output %d", this, res);
if ((res = spa_node_process_output (this->node)) < 0)
pinos_log_warn ("node %p: got process output %d", this, res);
}
#if 0
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.ReuseBuffer) {
SpaEventNodeReuseBuffer *rb = (SpaEventNodeReuseBuffer *) event;
int i;
pinos_log_trace ("node %p: reuse buffer %u", this, rb->body.buffer_id.value);
for (i = 0; i < this->transport->area->n_inputs; i++) {
PinosLink *link;
PinosPort *inport, *outport;
SpaPortIO *po;
inport = this->input_port_map[i];
spa_list_for_each (link, &inport->rt.links, rt.input_link) {
if (link->rt.input == NULL || link->rt.output == NULL)
continue;
outport = link->rt.output;
po = &outport->node->transport->outputs[outport->port_id];
po->buffer_id = rb->body.buffer_id.value;
}
}
}
#endif
else if (SPA_EVENT_TYPE (event) == this->core->type.event_node.RequestClockUpdate) {
send_clock_update (this);
}
@ -440,7 +502,7 @@ init_complete (PinosNode *this)
{
PinosNodeImpl *impl = SPA_CONTAINER_OF (this, PinosNodeImpl, this);
update_port_ids (this, false);
update_port_ids (this);
pinos_log_debug ("node %p: init completed", this);
impl->async_init = false;
@ -466,6 +528,7 @@ pinos_node_set_data_loop (PinosNode *node,
PinosNode *
pinos_node_new (PinosCore *core,
const char *name,
bool async,
SpaNode *node,
SpaClock *clock,
PinosProperties *properties)
@ -525,15 +588,15 @@ pinos_node_new (PinosCore *core,
this->node->info->items[i].value);
}
if (this->node->state > SPA_NODE_STATE_INIT) {
init_complete (this);
} else {
impl->async_init = true;
impl->async_init = async;
if (async) {
pinos_work_queue_add (impl->work,
this,
SPA_RESULT_RETURN_ASYNC (0),
(PinosWorkFunc) init_complete,
NULL);
} else {
init_complete (this);
}
return this;
@ -668,21 +731,27 @@ PinosPort *
pinos_node_get_free_port (PinosNode *node,
PinosDirection direction)
{
uint32_t n_ports, max_ports;
uint32_t *n_ports, max_ports;
SpaList *ports;
PinosPort *port = NULL, *p;
PinosPort *port = NULL, *p, **portmap;
SpaPortIO *io;
int i;
if (direction == PINOS_DIRECTION_INPUT) {
max_ports = node->transport->area->max_inputs;
n_ports = node->transport->area->n_inputs;
n_ports = &node->transport->area->n_inputs;
ports = &node->input_ports;
portmap = node->input_port_map;
io = node->transport->inputs;
} else {
max_ports = node->transport->area->max_outputs;
n_ports = node->transport->area->n_outputs;
n_ports = &node->transport->area->n_outputs;
ports = &node->output_ports;
portmap = node->output_port_map;
io = node->transport->outputs;
}
pinos_log_debug ("node %p: direction %d max %u, n %u", node, direction, max_ports, n_ports);
pinos_log_debug ("node %p: direction %d max %u, n %u", node, direction, max_ports, *n_ports);
spa_list_for_each (p, ports, link) {
if (spa_list_is_empty (&p->links)) {
@ -691,9 +760,26 @@ pinos_node_get_free_port (PinosNode *node,
}
}
if (port == NULL && !spa_list_is_empty (ports))
port = spa_list_first (ports, PinosPort, link);
if (port == NULL) {
/* no port, can we create one ? */
if (*n_ports < max_ports) {
for (i = 0; i < max_ports && port == NULL; i++) {
if (portmap[i] == NULL) {
pinos_log_debug ("node %p: creating port direction %d %u", node, direction, i);
port = portmap[i] = pinos_port_new (node, direction, i);
port->io = &io[i];
(*n_ports)++;
spa_node_add_port (node->node, direction, i);
spa_node_port_set_io (node->node, direction, i, port->io);
}
}
} else {
/* for output we can reuse an existing port */
if (direction == PINOS_DIRECTION_OUTPUT && !spa_list_is_empty (ports)) {
port = spa_list_first (ports, PinosPort, link);
}
}
}
return port;
}
@ -714,6 +800,22 @@ on_state_complete (PinosNode *node,
pinos_node_update_state (node, state, error);
}
static void
node_activate (PinosNode *this)
{
PinosPort *port;
spa_list_for_each (port, &this->input_ports, link) {
PinosLink *link;
spa_list_for_each (link, &port->links, input_link)
pinos_link_activate (link);
}
spa_list_for_each (port, &this->output_ports, link) {
PinosLink *link;
spa_list_for_each (link, &port->links, output_link)
pinos_link_activate (link);
}
}
/**
* pinos_node_set_state:
* @node: a #PinosNode
@ -747,6 +849,7 @@ pinos_node_set_state (PinosNode *node,
break;
case PINOS_NODE_STATE_RUNNING:
node_activate (node);
send_clock_update (node);
res = start_node (node);
break;

View file

@ -67,6 +67,7 @@ struct _PinosNode {
SpaNode *node;
bool live;
SpaClock *clock;
int sched_state;
SpaList resource_list;
@ -107,6 +108,7 @@ struct _PinosNode {
PinosNode * pinos_node_new (PinosCore *core,
const char *name,
bool async,
SpaNode *node,
SpaClock *clock,
PinosProperties *properties);

View file

@ -48,6 +48,7 @@ pinos_port_new (PinosNode *node,
this->node = node;
this->direction = direction;
this->port_id = port_id;
this->state = SPA_PORT_STATE_CONFIGURE;
spa_list_init (&this->links);
spa_list_init (&this->rt.links);
@ -200,6 +201,7 @@ static SpaResult
pinos_port_pause (PinosPort *port)
{
SpaCommand cmd = SPA_COMMAND_INIT (port->node->core->type.command_node.Pause);
port->state = SPA_PORT_STATE_PAUSED;
return spa_node_port_send_command (port->node->node,
port->direction,
port->port_id,
@ -239,6 +241,7 @@ do_remove_link_done (SpaLoop *loop,
port->direction,
port->port_id,
NULL, 0);
port->state = SPA_PORT_STATE_READY;
port->buffers = NULL;
port->n_buffers = 0;
}
@ -315,6 +318,7 @@ do_clear_buffers_done (SpaLoop *loop,
port->direction,
port->port_id,
NULL, 0);
port->state = SPA_PORT_STATE_READY;
port->buffers = NULL;
port->n_buffers = 0;

View file

@ -45,6 +45,8 @@ struct _PinosPort {
PinosNode *node;
PinosDirection direction;
uint32_t port_id;
uint32_t state;
SpaPortIO *io;
bool allocated;
PinosMemblock buffer_mem;

View file

@ -898,23 +898,6 @@ client_node_demarshal_port_update (void *object,
return true;
}
static bool
client_node_demarshal_state_change (void *object,
void *data,
size_t size)
{
PinosResource *resource = object;
SpaPODIter it;
uint32_t state;
if (!spa_pod_iter_struct (&it, data, size) ||
!spa_pod_iter_get (&it, SPA_POD_TYPE_INT, &state, 0))
return false;
((PinosClientNodeMethods*)resource->implementation)->state_change (resource, state);
return true;
}
static bool
client_node_demarshal_event (void *object,
void *data,
@ -1035,7 +1018,6 @@ const PinosInterface pinos_protocol_native_server_client_interface = {
static const PinosDemarshalFunc pinos_protocol_native_server_client_node_demarshal[] = {
&client_node_demarshal_update,
&client_node_demarshal_port_update,
&client_node_demarshal_state_change,
&client_node_demarshal_event,
&client_node_demarshal_destroy,
};
@ -1055,7 +1037,7 @@ static const PinosClientNodeEvents pinos_protocol_native_server_client_node_even
};
const PinosInterface pinos_protocol_native_server_client_node_interface = {
5, &pinos_protocol_native_server_client_node_demarshal,
4, &pinos_protocol_native_server_client_node_demarshal,
11, &pinos_protocol_native_server_client_node_events,
};