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;