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

@ -41,13 +41,6 @@ reset_alsa_sink_props (SpaALSAProps *props)
props->min_latency = default_min_latency;
}
static void
update_state (SpaALSASink *this, SpaNodeState state)
{
spa_log_info (this->log, "update state %d", state);
this->node.state = state;
}
static SpaResult
spa_alsa_sink_node_get_props (SpaNode *node,
SpaProps **props)
@ -348,11 +341,7 @@ spa_alsa_sink_node_port_set_format (SpaNode *node,
PROP (&f[1], this->type.alloc_param_meta_enable.ringbufferAlign, SPA_POD_TYPE_INT, 16));
this->params[2] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
this->info.extra = NULL;
update_state (this, SPA_NODE_STATE_READY);
}
else
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}
@ -451,7 +440,6 @@ spa_alsa_sink_node_port_use_buffers (SpaNode *node,
if (n_buffers == 0) {
spa_alsa_pause (this, false);
spa_alsa_clear_buffers (this);
update_state (this, SPA_NODE_STATE_READY);
return SPA_RESULT_OK;
}
@ -480,8 +468,6 @@ spa_alsa_sink_node_port_use_buffers (SpaNode *node,
}
this->n_buffers = n_buffers;
update_state (this, SPA_NODE_STATE_PAUSED);
return SPA_RESULT_OK;
}
@ -552,14 +538,10 @@ spa_alsa_sink_node_port_send_command (SpaNode *node,
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
res = spa_alsa_pause (this, false);
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
update_state (this, SPA_NODE_STATE_STREAMING);
}
res = spa_alsa_start (this, false);
}
else
res = SPA_RESULT_NOT_IMPLEMENTED;
@ -578,21 +560,25 @@ spa_alsa_sink_node_process_input (SpaNode *node)
this = SPA_CONTAINER_OF (node, SpaALSASink, node);
if ((input = this->io) == NULL)
if ((input = this->io) == NULL) {
return SPA_RESULT_OK;
}
if (!this->have_format) {
spa_log_error (this->log, "alsa-sink %p: no format", this);
input->status = SPA_RESULT_NO_FORMAT;
return SPA_RESULT_ERROR;
}
if (input->buffer_id >= this->n_buffers) {
spa_log_error (this->log, "alsa-sink %p: invalid buffer %u", this, input->buffer_id);
input->status = SPA_RESULT_INVALID_BUFFER_ID;
return SPA_RESULT_ERROR;
}
b = &this->buffers[input->buffer_id];
if (!b->outstanding) {
spa_log_error (this->log, "alsa-sink %p: buffer %u in use", this, input->buffer_id);
input->buffer_id = SPA_ID_INVALID;
input->status = SPA_RESULT_INVALID_BUFFER_ID;
return SPA_RESULT_ERROR;
@ -621,7 +607,6 @@ spa_alsa_sink_node_process_output (SpaNode *node)
static const SpaNode alsasink_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_alsa_sink_node_get_props,
spa_alsa_sink_node_set_props,
spa_alsa_sink_node_send_command,
@ -725,8 +710,6 @@ alsa_sink_init (const SpaHandleFactory *factory,
}
}
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}

View file

@ -32,12 +32,6 @@
typedef struct _SpaALSAState SpaALSASource;
static void
update_state (SpaALSASource *this, SpaNodeState state)
{
this->node.state = state;
}
static const char default_device[] = "hw:0";
static const uint32_t default_min_latency = 1024;
@ -123,9 +117,7 @@ do_start (SpaLoop *loop,
SpaALSASource *this = user_data;
SpaResult res;
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
update_state (this, SPA_NODE_STATE_STREAMING);
}
res = spa_alsa_start (this, false);
if (async) {
SpaEventNodeAsyncComplete ac = SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (this->type.event_node.AsyncComplete,
@ -151,9 +143,7 @@ do_pause (SpaLoop *loop,
SpaALSASource *this = user_data;
SpaResult res;
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
res = spa_alsa_pause (this, false);
if (async) {
SpaEventNodeAsyncComplete ac = SPA_EVENT_NODE_ASYNC_COMPLETE_INIT (this->type.event_node.AsyncComplete,
@ -390,10 +380,6 @@ spa_alsa_source_node_port_set_format (SpaNode *node,
this->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
this->info.extra = NULL;
update_state (this, SPA_NODE_STATE_READY);
} else {
update_state (this, SPA_NODE_STATE_CONFIGURE);
}
return SPA_RESULT_OK;
@ -517,11 +503,6 @@ spa_alsa_source_node_port_use_buffers (SpaNode *node,
}
this->n_buffers = n_buffers;
if (this->n_buffers > 0)
update_state (this, SPA_NODE_STATE_PAUSED);
else
update_state (this, SPA_NODE_STATE_READY);
return SPA_RESULT_OK;
}
@ -609,13 +590,9 @@ spa_alsa_source_node_port_send_command (SpaNode *node,
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
if (SPA_RESULT_IS_OK (res = spa_alsa_pause (this, false))) {
update_state (this, SPA_NODE_STATE_PAUSED);
}
res = spa_alsa_pause (this, false);
} else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
if (SPA_RESULT_IS_OK (res = spa_alsa_start (this, false))) {
update_state (this, SPA_NODE_STATE_STREAMING);
}
res = spa_alsa_start (this, false);
} else
res = SPA_RESULT_NOT_IMPLEMENTED;
@ -648,7 +625,6 @@ spa_alsa_source_node_process_output (SpaNode *node)
static const SpaNode alsasource_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_alsa_source_node_get_props,
spa_alsa_source_node_set_props,
spa_alsa_source_node_send_command,
@ -800,9 +776,6 @@ alsa_source_init (const SpaHandleFactory *factory,
snprintf (this->props.device, 63, "%s", info->items[i].value);
}
}
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}

View file

@ -332,18 +332,16 @@ pull_frames_queue (SpaALSAState *state,
snd_pcm_uframes_t frames)
{
snd_pcm_uframes_t total_frames = 0, to_write = frames;
SpaPortIO *io = state->io;
if (spa_list_is_empty (&state->ready)) {
SpaEvent event = SPA_EVENT_INIT (state->type.event_node.NeedInput);
SpaPortIO *io;
if ((io = state->io)) {
io->flags = SPA_PORT_IO_FLAG_RANGE;
io->status = SPA_RESULT_OK;
io->range.offset = state->sample_count * state->frame_size;
io->range.min_size = state->threshold * state->frame_size;
io->range.max_size = frames * state->frame_size;
}
io->flags = SPA_PORT_IO_FLAG_RANGE;
io->status = SPA_RESULT_OK;
io->range.offset = state->sample_count * state->frame_size;
io->range.min_size = state->threshold * state->frame_size;
io->range.max_size = frames * state->frame_size;
state->event_cb (&state->node, &event, state->user_data);
}
while (!spa_list_is_empty (&state->ready) && to_write > 0) {
@ -375,7 +373,6 @@ pull_frames_queue (SpaALSAState *state,
spa_log_trace (state->log, "alsa-util %p: reuse buffer %u", state, b->outbuf->id);
state->event_cb (&state->node, (SpaEvent *)&rb, state->user_data);
state->ready_offset = 0;
}
total_frames += n_frames;

View file

@ -25,6 +25,7 @@
#include <spa/type-map.h>
#include <spa/node.h>
#include <spa/audio/format-utils.h>
#include <spa/format-builder.h>
#include <lib/props.h>
#define MAX_BUFFERS 64
@ -40,14 +41,14 @@ typedef struct {
} MixerBuffer;
typedef struct {
bool valid;
SpaPortIO *io;
bool have_format;
SpaAudioInfo format;
SpaPortInfo info;
SpaPortIO *io;
MixerBuffer buffers[MAX_BUFFERS];
uint32_t n_buffers;
SpaList queue;
size_t queued_offset;
size_t queued_bytes;
@ -55,9 +56,11 @@ typedef struct {
typedef struct {
uint32_t node;
uint32_t format;
SpaTypeMediaType media_type;
SpaTypeMediaSubtype media_subtype;
SpaTypeFormatAudio format_audio;
SpaTypeAudioFormat audio_format;
SpaTypeCommandNode command_node;
} Type;
@ -65,9 +68,11 @@ static inline void
init_type (Type *type, SpaTypeMap *map)
{
type->node = spa_type_map_get_id (map, SPA_TYPE__Node);
type->format = spa_type_map_get_id (map, SPA_TYPE__Format);
spa_type_media_type_map (map, &type->media_type);
spa_type_media_subtype_map (map, &type->media_subtype);
spa_type_format_audio_map (map, &type->format_audio);
spa_type_audio_format_map (map, &type->audio_format);
spa_type_command_node_map (map, &type->command_node);
}
@ -87,20 +92,36 @@ struct _SpaAudioMixer {
SpaAudioMixerPort in_ports[MAX_PORTS];
SpaAudioMixerPort out_ports[1];
bool have_format;
SpaAudioInfo format;
uint8_t format_buffer[4096];
bool started;
#define STATE_ERROR 0
#define STATE_IN 1
#define STATE_OUT 2
int state;
};
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !this->in_ports[(p)].valid)
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && this->in_ports[(p)].valid)
#define CHECK_PORT_NUM(this,d,p) (((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS) || \
((d) == SPA_DIRECTION_OUTPUT && (p) == 0))
#define CHECK_FREE_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && !this->in_ports[(p)].io)
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) < MAX_PORTS && this->in_ports[(p)].io)
#define CHECK_OUT_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
#define CHECK_PORT(this,d,p) (CHECK_OUT_PORT(this,d,p) || CHECK_IN_PORT (this,d,p))
enum {
PROP_ID_LAST,
};
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_U_MM(f,key,type,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_MIN_MAX,type,3,__VA_ARGS__)
#define PROP_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
#define PROP_U_EN(f,key,type,n,...) \
SPA_POD_PROP (f,key,SPA_POD_PROP_FLAG_UNSET | \
SPA_POD_PROP_RANGE_ENUM,type,n,__VA_ARGS__)
static SpaResult
spa_audiomixer_node_get_props (SpaNode *node,
@ -116,12 +137,6 @@ spa_audiomixer_node_set_props (SpaNode *node,
return SPA_RESULT_NOT_IMPLEMENTED;
}
static void
update_state (SpaAudioMixer *this, SpaNodeState state)
{
this->node.state = state;
}
static SpaResult
spa_audiomixer_node_send_command (SpaNode *node,
SpaCommand *command)
@ -134,10 +149,10 @@ spa_audiomixer_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaAudioMixer, node);
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
update_state (this, SPA_NODE_STATE_STREAMING);
this->started = true;
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
this->started = false;
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
@ -199,7 +214,7 @@ spa_audiomixer_node_get_port_ids (SpaNode *node,
if (input_ids) {
for (i = 0, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) {
if (this->in_ports[i].valid)
if (this->in_ports[i].io)
input_ids[idx++] = i;
}
}
@ -222,7 +237,6 @@ spa_audiomixer_node_add_port (SpaNode *node,
spa_return_val_if_fail (CHECK_FREE_IN_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
this->in_ports[port_id].valid = true;
this->port_count++;
spa_list_init (&this->in_ports[port_id].queue);
@ -247,13 +261,12 @@ spa_audiomixer_node_remove_port (SpaNode *node,
spa_return_val_if_fail (CHECK_IN_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
this->in_ports[port_id].valid = false;
this->port_count--;
io = this->in_ports[port_id].io;
if (io && io->buffer_id) {
if (io && io->buffer_id)
this->port_queued--;
}
this->in_ports[port_id].io = NULL;
this->port_count--;
return SPA_RESULT_OK;
}
@ -268,6 +281,12 @@ spa_audiomixer_node_port_enum_formats (SpaNode *node,
uint32_t index)
{
SpaAudioMixer *this;
SpaResult res;
SpaFormat *fmt;
uint8_t buffer[256];
SpaPODBuilder b = { NULL, };
SpaPODFrame f[2];
uint32_t count, match;
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
@ -276,13 +295,30 @@ spa_audiomixer_node_port_enum_formats (SpaNode *node,
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
switch (index) {
count = match = filter ? 0 : index;
next:
spa_pod_builder_init (&b, buffer, sizeof (buffer));
switch (count++) {
case 0:
spa_pod_builder_format (&b, &f[0], this->type.format,
this->type.media_type.audio, this->type.media_subtype.raw,
PROP (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, this->type.audio_format.S16),
PROP_U_MM (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, 44100, 1, INT32_MAX),
PROP_U_MM (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, 2, 1, INT32_MAX));
break;
default:
return SPA_RESULT_ENUM_END;
}
*format = NULL;
fmt = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
if ((res = spa_format_filter (fmt, filter, &b)) != SPA_RESULT_OK || match++ != index)
goto next;
*format = SPA_POD_BUILDER_DEREF (&b, 0, SpaFormat);
return SPA_RESULT_OK;
}
@ -330,16 +366,10 @@ spa_audiomixer_node_port_set_format (SpaNode *node,
if (!spa_format_audio_raw_parse (format, &info.info.raw, &this->type.format_audio))
return SPA_RESULT_INVALID_MEDIA_TYPE;
port->format = info;
this->format = info;
port->have_format = true;
}
if (port->have_format) {
update_state (this, SPA_NODE_STATE_READY);
}
else
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}
@ -351,6 +381,8 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
{
SpaAudioMixer *this;
SpaAudioMixerPort *port;
SpaPODBuilder b = { NULL, };
SpaPODFrame f[2];
spa_return_val_if_fail (node != NULL, SPA_RESULT_INVALID_ARGUMENTS);
spa_return_val_if_fail (format != NULL, SPA_RESULT_INVALID_ARGUMENTS);
@ -364,7 +396,13 @@ spa_audiomixer_node_port_get_format (SpaNode *node,
if (!port->have_format)
return SPA_RESULT_NO_FORMAT;
*format = NULL;
spa_pod_builder_init (&b, this->format_buffer, sizeof (this->format_buffer));
spa_pod_builder_format (&b, &f[0], this->type.format,
this->type.media_type.audio, this->type.media_subtype.raw,
PROP (&f[1], this->type.format_audio.format, SPA_POD_TYPE_ID, this->format.info.raw.format),
PROP (&f[1], this->type.format_audio.rate, SPA_POD_TYPE_INT, this->format.info.raw.rate),
PROP (&f[1], this->type.format_audio.channels, SPA_POD_TYPE_INT, this->format.info.raw.channels));
*format = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaFormat);
return SPA_RESULT_OK;
}
@ -453,15 +491,11 @@ spa_audiomixer_node_port_use_buffers (SpaNode *node,
default:
break;
}
spa_list_insert (port->queue.prev, &b->link);
if (!b->outstanding)
spa_list_insert (port->queue.prev, &b->link);
}
port->n_buffers = n_buffers;
if (port->n_buffers > 0) {
update_state (this, SPA_NODE_STATE_PAUSED);
} else {
update_state (this, SPA_NODE_STATE_READY);
}
return SPA_RESULT_OK;
}
@ -490,7 +524,7 @@ spa_audiomixer_node_port_set_io (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaAudioMixer, node);
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT);
port = direction == SPA_DIRECTION_INPUT ? &this->in_ports[port_id] : &this->out_ports[port_id];
port->io = io;
@ -504,11 +538,15 @@ recycle_buffer (SpaAudioMixer *this, uint32_t id)
SpaAudioMixerPort *port = &this->out_ports[0];
MixerBuffer *b = &port->buffers[id];
if (b->outstanding) {
spa_list_insert (port->queue.prev, &b->link);
b->outstanding = false;
spa_log_trace (this->log, "audiomixer %p: recycle buffer %d", this, id);
if (!b->outstanding) {
spa_log_warn (this->log, "audiomixer %p: buffer %d not outstanding", this, id);
return;
}
spa_list_insert (port->queue.prev, &b->link);
b->outstanding = false;
spa_log_trace (this->log, "audiomixer %p: recycle buffer %d", this, id);
}
static SpaResult
@ -542,7 +580,7 @@ static void
add_port_data (SpaAudioMixer *this, MixerBuffer *out, SpaAudioMixerPort *port, int layer)
{
int i;
uint16_t *op, *ip;
int16_t *op, *ip;
size_t os, is, chunk;
MixerBuffer *b = spa_list_first (&port->queue, MixerBuffer, link);
@ -559,7 +597,7 @@ add_port_data (SpaAudioMixer *this, MixerBuffer *out, SpaAudioMixerPort *port, i
}
else {
for (i = 0; i < chunk / 2; i++)
op[i] += ip[i];
op[i] = SPA_CLAMP (op[i] + ip[i], INT16_MIN, INT16_MAX);
}
port->queued_offset += chunk;
@ -596,56 +634,66 @@ spa_audiomixer_node_process_input (SpaNode *node)
SpaAudioMixerPort *port = &this->in_ports[i];
SpaPortIO *input;
if (!port->valid || (input = port->io) == NULL)
if ((input = port->io) == NULL)
continue;
if (input->buffer_id != SPA_ID_INVALID) {
MixerBuffer *b = &port->buffers[input->buffer_id];
if (!b->outstanding) {
spa_log_warn (this->log, "audiomixer %p: buffer was not outstanding %d", this, input->buffer_id);
continue;
}
if (spa_list_is_empty (&port->queue)) {
port->queued_bytes = 0;
port->queued_offset = 0;
}
spa_log_trace (this->log, "audiomixer %p: queue buffer %d on port %p", this, b->outbuf->id, port);
spa_list_insert (port->queue.prev, &b->link);
b->outstanding = false;
port->queued_bytes += b->outbuf->datas[0].chunk->size;
spa_log_trace (this->log, "audiomixer %p: queue buffer %d on port %p %zd %zd",
this, b->outbuf->id, port, port->queued_bytes, min_queued);
input->buffer_id = SPA_ID_INVALID;
}
if (min_queued == -1 || port->queued_bytes < min_queued)
if (min_queued == -1 || (port->queued_bytes > 0 && port->queued_bytes < min_queued))
min_queued = port->queued_bytes;
input->status = SPA_RESULT_OK;
}
if (min_queued != -1) {
if (min_queued > 0) {
MixerBuffer *outbuf;
SpaPortIO *output;
int j;
int layer;
if (spa_list_is_empty (&outport->queue))
return SPA_RESULT_OUT_OF_BUFFERS;
outbuf = spa_list_first (&outport->queue, MixerBuffer, link);
spa_list_remove (&outbuf->link);
spa_log_trace (this->log, "audiomixer %p: dequeue output buffer %d", this, outbuf->outbuf->id);
spa_log_trace (this->log, "audiomixer %p: dequeue output buffer %d %zd", this, outbuf->outbuf->id, min_queued);
outbuf->outstanding = true;
outbuf->outbuf->datas[0].chunk->offset = 0;
outbuf->outbuf->datas[0].chunk->size = min_queued;
outbuf->outbuf->datas[0].chunk->stride = 0;
for (j = 0, i = 0; i < MAX_PORTS; i++) {
for (layer = 0, i = 0; i < MAX_PORTS; i++) {
SpaAudioMixerPort *port = &this->in_ports[i];
if (!port->valid || port->io == NULL ||
spa_list_is_empty (&port->queue))
if (port->io == NULL)
continue;
add_port_data (this, outbuf, port, j++);
if (spa_list_is_empty (&port->queue)) {
spa_log_warn (this->log, "audiomixer %p: underrun stream %d", this, i);
continue;
}
add_port_data (this, outbuf, port, layer++);
}
output = outport->io;
output->buffer_id = outbuf->outbuf->id;
output->state = SPA_RESULT_OK;
output->status = SPA_RESULT_OK;
this->state = STATE_OUT;
}
return this->state == STATE_IN ? SPA_RESULT_NEED_INPUT : SPA_RESULT_HAVE_OUTPUT;
@ -672,7 +720,7 @@ spa_audiomixer_node_process_output (SpaNode *node)
for (i = 0; i < MAX_PORTS; i++) {
SpaPortIO *input;
if (!this->in_ports[i].valid || (input = this->in_ports[i].io) == NULL)
if ((input = this->in_ports[i].io) == NULL)
continue;
input->flags = output->flags;
@ -690,7 +738,6 @@ spa_audiomixer_node_process_output (SpaNode *node)
static const SpaNode audiomixer_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_audiomixer_node_get_props,
spa_audiomixer_node_set_props,
spa_audiomixer_node_send_command,
@ -772,7 +819,7 @@ spa_audiomixer_init (const SpaHandleFactory *factory,
this->node = audiomixer_node;
this->out_ports[0].valid = true;
this->out_ports[0].io = NULL;
this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS |
SPA_PORT_INFO_FLAG_NO_REF;
spa_list_init (&this->out_ports[0].queue);

View file

@ -336,12 +336,6 @@ audiotestsrc_on_output (SpaSource *source)
send_have_output (this);
}
static void
update_state (SpaAudioTestSrc *this, SpaNodeState state)
{
this->node.state = state;
}
static SpaResult
spa_audiotestsrc_node_send_command (SpaNode *node,
SpaCommand *command)
@ -375,7 +369,6 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
this->started = true;
set_timer (this, true);
update_state (this, SPA_NODE_STATE_STREAMING);
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
if (!this->have_format)
@ -389,7 +382,6 @@ spa_audiotestsrc_node_send_command (SpaNode *node,
this->started = false;
set_timer (this, false);
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
@ -605,10 +597,7 @@ spa_audiotestsrc_node_port_set_format (SpaNode *node,
this->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
this->info.extra = NULL;
update_state (this, SPA_NODE_STATE_READY);
}
else
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}
@ -729,12 +718,6 @@ spa_audiotestsrc_node_port_use_buffers (SpaNode *node,
}
this->n_buffers = n_buffers;
if (this->n_buffers > 0) {
update_state (this, SPA_NODE_STATE_PAUSED);
} else {
update_state (this, SPA_NODE_STATE_READY);
}
return SPA_RESULT_OK;
}
@ -853,7 +836,6 @@ spa_audiotestsrc_node_process_output (SpaNode *node)
static const SpaNode audiotestsrc_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_audiotestsrc_node_get_props,
spa_audiotestsrc_node_set_props,
spa_audiotestsrc_node_send_command,
@ -1029,8 +1011,6 @@ audiotestsrc_init (const SpaHandleFactory *factory,
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
this->node.state = SPA_NODE_STATE_CONFIGURE;
spa_log_info (this->log, "audiotestsrc %p: initialized, async=%d", this, this->async);
return SPA_RESULT_OK;

View file

@ -47,7 +47,7 @@ typedef struct {
bool have_buffers;
FFMpegBuffer buffers[MAX_BUFFERS];
SpaPortInfo info;
void *io;
SpaPortIO *io;
} SpaFFMpegPort;
typedef struct {
@ -81,6 +81,8 @@ struct _SpaFFMpegDec {
SpaFFMpegPort in_ports[1];
SpaFFMpegPort out_ports[1];
bool started;
};
enum {
@ -101,12 +103,6 @@ spa_ffmpeg_dec_node_set_props (SpaNode *node,
return SPA_RESULT_NOT_IMPLEMENTED;
}
static void
update_state (SpaFFMpegDec *this, SpaNodeState state)
{
this->node.state = state;
}
static SpaResult
spa_ffmpeg_dec_node_send_command (SpaNode *node,
SpaCommand *command)
@ -119,10 +115,10 @@ spa_ffmpeg_dec_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaFFMpegDec, node);
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
update_state (this, SPA_NODE_STATE_STREAMING);
this->started = true;
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
this->started = false;
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
@ -454,7 +450,6 @@ spa_ffmpeg_dec_node_port_send_command (SpaNode *node,
static const SpaNode ffmpeg_dec_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_ffmpeg_dec_node_get_props,
spa_ffmpeg_dec_node_set_props,
spa_ffmpeg_dec_node_send_command,

View file

@ -86,18 +86,10 @@ struct _SpaFFMpegEnc {
SpaFFMpegPort in_ports[1];
SpaFFMpegPort out_ports[1];
};
enum {
PROP_ID_LAST,
bool started;
};
static void
update_state (SpaFFMpegEnc *this, SpaNodeState state)
{
this->node.state = state;
}
static SpaResult
spa_ffmpeg_enc_node_get_props (SpaNode *node,
SpaProps **props)
@ -124,10 +116,10 @@ spa_ffmpeg_enc_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaFFMpegEnc, node);
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
update_state (this, SPA_NODE_STATE_STREAMING);
this->started = true;
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
this->started = false;
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
@ -461,7 +453,6 @@ spa_ffmpeg_enc_node_process_output (SpaNode *node)
static const SpaNode ffmpeg_enc_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_ffmpeg_enc_node_get_props,
spa_ffmpeg_enc_node_set_props,
spa_ffmpeg_enc_node_send_command,
@ -534,7 +525,5 @@ spa_ffmpeg_enc_init (SpaHandle *handle,
this->in_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
this->out_ports[0].info.flags = SPA_PORT_INFO_FLAG_NONE;
this->node.state = SPA_NODE_STATE_CONFIGURE;
return SPA_RESULT_OK;
}

View file

@ -137,7 +137,7 @@ typedef struct {
SpaPortInfo info;
SpaAllocParam *params[2];
uint8_t params_buffer[1024];
void *io;
SpaPortIO *io;
int64_t last_ticks;
int64_t last_monotonic;
@ -163,14 +163,8 @@ struct _SpaV4l2Source {
SpaV4l2State state[1];
};
#define CHECK_PORT(this, direction, port_id) ((direction) == SPA_DIRECTION_OUTPUT && (port_id) == 0)
#define CHECK_PORT(this,direction,port_id) ((direction) == SPA_DIRECTION_OUTPUT && (port_id) == 0)
static void
update_state (SpaV4l2Source *this, SpaNodeState state)
{
spa_log_info (this->log, "state: %d", state);
this->node.state = state;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
@ -249,7 +243,6 @@ do_pause_done (SpaLoop *loop,
if (SPA_RESULT_IS_OK (ac->body.res.value)) {
state->started = false;
update_state (this, SPA_NODE_STATE_PAUSED);
}
this->event_cb (&this->node, (SpaEvent *)ac, this->user_data);
@ -300,7 +293,6 @@ do_start_done (SpaLoop *loop,
if (SPA_RESULT_IS_OK (ac->body.res.value)) {
state->started = true;
update_state (this, SPA_NODE_STATE_STREAMING);
}
this->event_cb (&this->node, (SpaEvent *)ac, this->user_data);
@ -515,7 +507,6 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
spa_v4l2_clear_buffers (this);
spa_v4l2_close (this);
state->have_format = false;
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
} else {
info.media_type = SPA_FORMAT_MEDIA_TYPE (format);
@ -572,7 +563,6 @@ spa_v4l2_source_node_port_set_format (SpaNode *node,
if (!(flags & SPA_PORT_FORMAT_FLAG_TEST_ONLY)) {
state->current_format = info;
state->have_format = true;
update_state (this, SPA_NODE_STATE_READY);
}
return SPA_RESULT_OK;
@ -706,12 +696,6 @@ spa_v4l2_source_node_port_use_buffers (SpaNode *node,
if ((res = spa_v4l2_use_buffers (this, buffers, n_buffers)) < 0)
return res;
}
if (state->n_buffers)
update_state (this, SPA_NODE_STATE_PAUSED);
else
update_state (this, SPA_NODE_STATE_READY);
return SPA_RESULT_OK;
}
@ -742,13 +726,6 @@ spa_v4l2_source_node_port_alloc_buffers (SpaNode *node,
res = spa_v4l2_alloc_buffers (this, params, n_params, buffers, n_buffers);
if (state->n_buffers) {
if (state->started)
update_state (this, SPA_NODE_STATE_STREAMING);
else
update_state (this, SPA_NODE_STATE_PAUSED);
}
return res;
}
@ -850,7 +827,6 @@ spa_v4l2_source_node_process_output (SpaNode *node)
static const SpaNode v4l2source_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_v4l2_source_node_get_props,
spa_v4l2_source_node_set_props,
spa_v4l2_source_node_send_command,
@ -1006,8 +982,6 @@ v4l2_source_init (const SpaHandleFactory *factory,
strncpy (this->props.device, str, 63);
}
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}

View file

@ -85,6 +85,7 @@ typedef struct {
} SpaVideoTestSrcProps;
#define MAX_BUFFERS 16
#define MAX_PORTS 1
typedef struct _VTSBuffer VTSBuffer;
@ -137,7 +138,8 @@ struct _SpaVideoTestSrc {
SpaList empty;
};
#define CHECK_PORT(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) == 0)
#define CHECK_PORT_NUM(this,d,p) ((d) == SPA_DIRECTION_OUTPUT && (p) < MAX_PORTS)
#define CHECK_PORT(this,d,p) (CHECK_PORT_NUM(this,d,p) && this->io)
#define DEFAULT_LIVE true
#define DEFAULT_PATTERN pattern_smpte_snow
@ -276,6 +278,7 @@ videotestsrc_make_buffer (SpaVideoTestSrc *this)
if (spa_list_is_empty (&this->empty)) {
set_timer (this, false);
spa_log_error (this->log, "videotestsrc %p: out of buffers", this);
return SPA_RESULT_OUT_OF_BUFFERS;
}
b = spa_list_first (&this->empty, VTSBuffer, link);
@ -321,13 +324,6 @@ videotestsrc_on_output (SpaSource *source)
send_have_output (this);
}
static void
update_state (SpaVideoTestSrc *this, SpaNodeState state)
{
this->node.state = state;
spa_log_info (this->log, "videotestsrc %p: update state %d", this, state);
}
static SpaResult
spa_videotestsrc_node_send_command (SpaNode *node,
SpaCommand *command)
@ -361,7 +357,6 @@ spa_videotestsrc_node_send_command (SpaNode *node,
this->started = true;
set_timer (this, true);
update_state (this, SPA_NODE_STATE_STREAMING);
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
if (!this->have_format)
@ -375,7 +370,6 @@ spa_videotestsrc_node_send_command (SpaNode *node,
this->started = false;
set_timer (this, false);
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
@ -592,10 +586,7 @@ spa_videotestsrc_node_port_set_format (SpaNode *node,
this->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
this->info.extra = NULL;
update_state (this, SPA_NODE_STATE_READY);
}
else
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}
@ -715,12 +706,6 @@ spa_videotestsrc_node_port_use_buffers (SpaNode *node,
}
this->n_buffers = n_buffers;
if (this->n_buffers > 0) {
update_state (this, SPA_NODE_STATE_PAUSED);
} else {
update_state (this, SPA_NODE_STATE_READY);
}
return SPA_RESULT_OK;
}
@ -759,7 +744,7 @@ spa_videotestsrc_node_port_set_io (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaVideoTestSrc, node);
spa_return_val_if_fail (CHECK_PORT (this, direction, port_id), SPA_RESULT_INVALID_PORT);
spa_return_val_if_fail (CHECK_PORT_NUM (this, direction, port_id), SPA_RESULT_INVALID_PORT);
this->io = io;
@ -839,7 +824,6 @@ spa_videotestsrc_node_process_output (SpaNode *node)
static const SpaNode videotestsrc_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_videotestsrc_node_get_props,
spa_videotestsrc_node_set_props,
spa_videotestsrc_node_send_command,
@ -1015,8 +999,6 @@ videotestsrc_init (const SpaHandleFactory *factory,
if (this->props.live)
this->info.flags |= SPA_PORT_INFO_FLAG_LIVE;
this->node.state = SPA_NODE_STATE_CONFIGURE;
spa_log_info (this->log, "videotestsrc %p: initialized, async=%d", this, this->async);
return SPA_RESULT_OK;

View file

@ -55,7 +55,7 @@ typedef struct {
SpaVolumeBuffer buffers[MAX_BUFFERS];
uint32_t n_buffers;
void *io;
SpaPortIO *io;
SpaList empty;
} SpaVolumePort;
@ -113,6 +113,8 @@ struct _SpaVolume {
SpaVolumePort in_ports[1];
SpaVolumePort out_ports[1];
bool started;
};
#define CHECK_IN_PORT(this,d,p) ((d) == SPA_DIRECTION_INPUT && (p) == 0)
@ -129,12 +131,6 @@ reset_volume_props (SpaVolumeProps *props)
props->mute = DEFAULT_MUTE;
}
static void
update_state (SpaVolume *this, SpaNodeState state)
{
this->node.state = state;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_MM(f,key,type,...) \
@ -203,10 +199,10 @@ spa_volume_node_send_command (SpaNode *node,
this = SPA_CONTAINER_OF (node, SpaVolume, node);
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
update_state (this, SPA_NODE_STATE_STREAMING);
this->started = true;
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
update_state (this, SPA_NODE_STATE_PAUSED);
this->started = false;
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
@ -410,10 +406,7 @@ spa_volume_node_port_set_format (SpaNode *node,
port->params[1] = SPA_POD_BUILDER_DEREF (&b, f[0].ref, SpaAllocParam);
port->info.extra = NULL;
update_state (this, SPA_NODE_STATE_READY);
}
else
update_state (this, SPA_NODE_STATE_CONFIGURE);
return SPA_RESULT_OK;
}
@ -535,11 +528,6 @@ spa_volume_node_port_use_buffers (SpaNode *node,
}
port->n_buffers = n_buffers;
if (port->n_buffers > 0) {
update_state (this, SPA_NODE_STATE_PAUSED);
} else {
update_state (this, SPA_NODE_STATE_READY);
}
return SPA_RESULT_OK;
}
@ -747,7 +735,6 @@ spa_volume_node_process_output (SpaNode *node)
static const SpaNode volume_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_volume_node_get_props,
spa_volume_node_set_props,
spa_volume_node_send_command,

View file

@ -123,12 +123,6 @@ struct _SpaXvSink {
#include "xv-utils.c"
static void
update_state (SpaXvSink *this, SpaNodeState state)
{
this->node.state = state;
}
#define PROP(f,key,type,...) \
SPA_POD_PROP (f,key,0,type,1,__VA_ARGS__)
#define PROP_R(f,key,type,...) \
@ -191,13 +185,9 @@ spa_xv_sink_node_send_command (SpaNode *node,
if (SPA_COMMAND_TYPE (command) == this->type.command_node.Start) {
spa_xv_start (this);
update_state (this, SPA_NODE_STATE_STREAMING);
}
else if (SPA_COMMAND_TYPE (command) == this->type.command_node.Pause) {
spa_xv_stop (this);
update_state (this, SPA_NODE_STATE_PAUSED);
}
else
return SPA_RESULT_NOT_IMPLEMENTED;
@ -489,7 +479,6 @@ spa_xv_sink_node_process_output (SpaNode *node)
static const SpaNode xvsink_node = {
sizeof (SpaNode),
NULL,
SPA_NODE_STATE_INIT,
spa_xv_sink_node_get_props,
spa_xv_sink_node_set_props,
spa_xv_sink_node_send_command,