diff options
29 files changed, 2264 insertions, 798 deletions
diff --git a/doc/design.txt b/doc/design.txt index c534bd0d..f7c3b8e8 100644 --- a/doc/design.txt +++ b/doc/design.txt @@ -395,44 +395,46 @@ communication channel node-update port-update - start-configure + state-configure 2) Set formats S->C CONFIGURE - add-port set-property enumerate ports + add-port + remove-port enumerate formats set-format - end-configure -3) Buffer requirements update C->S BUFFER_REQS +3) Buffer requirements update C->S Update port status - start-alloc + state-ready if enough formats are set -4) Start S->C ALLOC +4) Start S->C READY read port memory requirements add_mem + remove_mem add_buffer - pause/start + remove_buffer + start->streaming -5) Pause S->C PAUSED +5) Pause S->C STREAMING - start/stop + stop-streaming -5) data transfer C->S STARTED +5) data transfer C->S need-input + have-output + add_mem add_buffer process_buffer reuse_buffer remove_buffer remove_mem - have-output - pause/stop 6) data transfer S->C @@ -442,23 +444,17 @@ communication channel reuse_buffer remove_buffer remove_mem - pause/stop 7) format change C->S port-update - start-configure + state-configure 8) format change S->C - Send set-format change on ports - end-configure, back to 3 - -9) stop S->C ALLOC - - remove_buffer - remove_mem + Send set-format change on ports -> READY if new memory requirements + -> RUNNING if all ok -10) clear format S->C CONFIGURE +9) format-change to NULL -> CONFIGURE - format-change to NULL +10) ERROR diff --git a/pinos/Makefile.am b/pinos/Makefile.am index 2f3edc2e..28d7cc3f 100644 --- a/pinos/Makefile.am +++ b/pinos/Makefile.am @@ -42,7 +42,7 @@ SERVER_CFLAGS = -D__INCLUDED_FROM_PINOS AM_LIBADD = $(GLIB_LIBS) $(INTLLIBS) $(GST_LIBS) -L$(top_srcdir)/spa/build/lib/ -lspa-lib AM_LDADD = $(GLIB_LIBS) $(GST_LIBS) $(INTLLIBS) -L$(top_srcdir)/spa/build/lib/ -lspa-lib -AM_LDFLAGS = $(NODELETE_LDFLAGS) +AM_LDFLAGS = $(NODELETE_LDFLAGS) -Wl,-rpath=/home/wim/gst/head/pinos/spa/build/lib/ FOREIGN_CFLAGS = -w diff --git a/pinos/modules/spa/spa-alsa-sink.c b/pinos/modules/spa/spa-alsa-sink.c index 1b65145b..bb273029 100644 --- a/pinos/modules/spa/spa-alsa-sink.c +++ b/pinos/modules/spa/spa-alsa-sink.c @@ -52,8 +52,7 @@ typedef struct { struct _PinosSpaAlsaSinkPrivate { - SpaHandle *sink; - const SpaNode *sink_node; + SpaNode *sink; PinosProperties *props; PinosRingbuffer *ringbuffer; @@ -78,8 +77,9 @@ enum { G_DEFINE_TYPE (PinosSpaAlsaSink, pinos_spa_alsa_sink, PINOS_TYPE_NODE); static SpaResult -make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char *name) +make_node (SpaNode **node, const char *lib, const char *name) { + SpaHandle *handle; SpaResult res; void *hnd, *state = NULL; SpaEnumHandleFactoryFunc enum_func; @@ -95,7 +95,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char while (true) { const SpaHandleFactory *factory; - const void *iface; + void *iface; if ((res = enum_func (&factory, &state)) < 0) { if (res != SPA_RESULT_ENUM_END) @@ -105,12 +105,12 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char if (strcmp (factory->name, name)) continue; - *handle = calloc (1, factory->size); - if ((res = factory->init (factory, *handle)) < 0) { + handle = calloc (1, factory->size); + if ((res = factory->init (factory, handle)) < 0) { g_error ("can't make factory instance: %d", res); return res; } - if ((res = (*handle)->get_interface (*handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { + if ((res = handle->get_interface (handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { g_error ("can't get interface %d", res); return res; } @@ -121,7 +121,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char } static void -on_sink_event (SpaHandle *handle, SpaEvent *event, void *user_data) +on_sink_event (SpaNode *node, SpaEvent *event, void *user_data) { PinosSpaAlsaSink *this = user_data; PinosSpaAlsaSinkPrivate *priv = this->priv; @@ -129,25 +129,19 @@ on_sink_event (SpaHandle *handle, SpaEvent *event, void *user_data) switch (event->type) { case SPA_EVENT_TYPE_PULL_INPUT: { - SpaBuffer *buf; SpaInputInfo iinfo; - SpaOutputInfo oinfo; SpaResult res; PinosRingbufferArea areas[2]; uint8_t *data; size_t size, towrite, total; + SpaEventPullInput *pi; - buf = event->data; + pi = event->data; - oinfo.port_id = 0; - oinfo.flags = SPA_OUTPUT_FLAG_PULL; - oinfo.buffer = buf; - oinfo.event = NULL; + g_debug ("pull ringbuffer %zd", pi->size); - g_debug ("pull ringbuffer %p", buf); - - size = buf->size; - data = buf->datas[0].ptr; + size = pi->size; + data = NULL; pinos_ringbuffer_get_read_areas (priv->ringbuffer, areas); @@ -165,15 +159,14 @@ on_sink_event (SpaHandle *handle, SpaEvent *event, void *user_data) pinos_ringbuffer_read_advance (priv->ringbuffer, total); - buf->size = total; - iinfo.port_id = event->port_id; iinfo.flags = SPA_INPUT_FLAG_NONE; - iinfo.buffer = oinfo.buffer; - iinfo.event = oinfo.event; + iinfo.id = 0; + iinfo.offset = 0; + iinfo.size = total; - g_debug ("push sink %p", iinfo.buffer); - if ((res = priv->sink_node->port_push_input (priv->sink, 1, &iinfo)) < 0) + g_debug ("push sink %d", iinfo.id); + if ((res = spa_node_port_push_input (priv->sink, 1, &iinfo)) < 0) g_debug ("got error %d", res); break; } @@ -204,21 +197,21 @@ create_pipeline (PinosSpaAlsaSink *this) SpaProps *props; SpaPropValue value; - if ((res = make_node (&priv->sink, &priv->sink_node, "spa/build/plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) { + if ((res = make_node (&priv->sink, "spa/build/plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) { g_error ("can't create alsa-sink: %d", res); return; } - priv->sink_node->set_event_callback (priv->sink, on_sink_event, this); + spa_node_set_event_callback (priv->sink, on_sink_event, this); - if ((res = priv->sink_node->get_props (priv->sink, &props)) < 0) + if ((res = spa_node_get_props (priv->sink, &props)) < 0) g_debug ("got get_props error %d", res); value.type = SPA_PROP_TYPE_STRING; value.value = "hw:0"; value.size = strlen (value.value)+1; - props->set_prop (props, spa_props_index_for_name (props, "device"), &value); + spa_props_set_prop (props, spa_props_index_for_name (props, "device"), &value); - if ((res = priv->sink_node->set_props (priv->sink, props)) < 0) + if ((res = spa_node_set_props (priv->sink, props)) < 0) g_debug ("got set_props error %d", res); } @@ -266,7 +259,7 @@ start_pipeline (PinosSpaAlsaSink *sink) g_debug ("spa-alsa-sink %p: starting pipeline", sink); cmd.type = SPA_COMMAND_START; - if ((res = priv->sink_node->send_command (priv->sink, &cmd)) < 0) + if ((res = spa_node_send_command (priv->sink, &cmd)) < 0) g_debug ("got error %d", res); priv->running = true; @@ -291,7 +284,7 @@ stop_pipeline (PinosSpaAlsaSink *sink) } cmd.type = SPA_COMMAND_STOP; - if ((res = priv->sink_node->send_command (priv->sink, &cmd)) < 0) + if ((res = spa_node_send_command (priv->sink, &cmd)) < 0) g_debug ("got error %d", res); } @@ -395,7 +388,7 @@ negotiate_formats (PinosSpaAlsaSink *this) SpaPropValue value; void *state = NULL; - if ((res = priv->sink_node->port_enum_formats (priv->sink, 0, &format, NULL, &state)) < 0) + if ((res = spa_node_port_enum_formats (priv->sink, 0, &format, NULL, &state)) < 0) return res; props = &format->props; @@ -405,19 +398,19 @@ negotiate_formats (PinosSpaAlsaSink *this) value.value = &val; val = SPA_AUDIO_FORMAT_S16LE; - if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_FORMAT), &value)) < 0) + if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_FORMAT), &value)) < 0) return res; val = SPA_AUDIO_LAYOUT_INTERLEAVED; - if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_LAYOUT), &value)) < 0) + if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_LAYOUT), &value)) < 0) return res; val = 44100; - if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_RATE), &value)) < 0) + if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_RATE), &value)) < 0) return res; val = 2; - if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_CHANNELS), &value)) < 0) + if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_CHANNELS), &value)) < 0) return res; - if ((res = priv->sink_node->port_set_format (priv->sink, 0, 0, format)) < 0) + if ((res = spa_node_port_set_format (priv->sink, 0, 0, format)) < 0) return res; priv->ringbuffer = pinos_ringbuffer_new (PINOS_RINGBUFFER_MODE_READ, 64 * 1024); diff --git a/pinos/modules/spa/spa-v4l2-source.c b/pinos/modules/spa/spa-v4l2-source.c index 96f1161d..9c61b074 100644 --- a/pinos/modules/spa/spa-v4l2-source.c +++ b/pinos/modules/spa/spa-v4l2-source.c @@ -48,8 +48,7 @@ typedef struct { struct _PinosSpaV4l2SourcePrivate { - SpaHandle *source; - const SpaNode *source_node; + SpaNode *source; SpaPollFd fds[16]; unsigned int n_fds; @@ -70,8 +69,9 @@ enum { G_DEFINE_TYPE (PinosSpaV4l2Source, pinos_spa_v4l2_source, PINOS_TYPE_NODE); static SpaResult -make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char *name) +make_node (SpaNode **node, const char *lib, const char *name) { + SpaHandle *handle; SpaResult res; void *hnd, *state = NULL; SpaEnumHandleFactoryFunc enum_func; @@ -87,7 +87,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char while (true) { const SpaHandleFactory *factory; - const void *iface; + void *iface; if ((res = enum_func (&factory, &state)) < 0) { if (res != SPA_RESULT_ENUM_END) @@ -97,12 +97,12 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char if (strcmp (factory->name, name)) continue; - *handle = calloc (1, factory->size); - if ((res = factory->init (factory, *handle)) < 0) { + handle = calloc (1, factory->size); + if ((res = factory->init (factory, handle)) < 0) { g_error ("can't make factory instance: %d", res); return res; } - if ((res = (*handle)->get_interface (*handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { + if ((res = handle->get_interface (handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { g_error ("can't get interface %d", res); return res; } @@ -113,7 +113,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char } static void -on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) +on_source_event (SpaNode *node, SpaEvent *event, void *user_data) { PinosSpaV4l2Source *source = user_data; PinosSpaV4l2SourcePrivate *priv = source->priv; @@ -126,10 +126,10 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) SpaBuffer *b; GList *walk; - if ((res = priv->source_node->port_pull_output (priv->source, 1, info)) < 0) + if ((res = spa_node_port_pull_output (priv->source, 1, info)) < 0) g_debug ("spa-v4l2-source %p: got pull error %d", source, res); - b = info[0].buffer; + b = NULL; /* info[0].id; */ for (walk = priv->ports; walk; walk = g_list_next (walk)) { SourcePortData *data = walk->data; @@ -174,23 +174,22 @@ create_pipeline (PinosSpaV4l2Source *this) SpaPropValue value; if ((res = make_node (&priv->source, - &priv->source_node, "spa/build/plugins/v4l2/libspa-v4l2.so", "v4l2-source")) < 0) { g_error ("can't create v4l2-source: %d", res); return; } - priv->source_node->set_event_callback (priv->source, on_source_event, this); + spa_node_set_event_callback (priv->source, on_source_event, this); - if ((res = priv->source_node->get_props (priv->source, &props)) < 0) + if ((res = spa_node_get_props (priv->source, &props)) < 0) g_debug ("got get_props error %d", res); value.type = SPA_PROP_TYPE_STRING; value.value = "/dev/video1"; value.size = strlen (value.value)+1; - props->set_prop (props, spa_props_index_for_name (props, "device"), &value); + spa_props_set_prop (props, spa_props_index_for_name (props, "device"), &value); - if ((res = priv->source_node->set_props (priv->source, props)) < 0) + if ((res = spa_node_set_props (priv->source, props)) < 0) g_debug ("got set_props error %d", res); } @@ -208,7 +207,7 @@ negotiate_formats (PinosSpaV4l2Source *this) SpaRectangle rect; const gchar *str; - if ((res = priv->source_node->port_enum_formats (priv->source, 0, &format, NULL, &state)) < 0) + if ((res = spa_node_port_enum_formats (priv->source, 0, &format, NULL, &state)) < 0) return res; props = &format->props; @@ -218,7 +217,7 @@ negotiate_formats (PinosSpaV4l2Source *this) value.value = &val; val = SPA_VIDEO_FORMAT_YUY2; - if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_FORMAT), &value)) < 0) + if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_FORMAT), &value)) < 0) return res; value.type = SPA_PROP_TYPE_RECTANGLE; @@ -226,7 +225,7 @@ negotiate_formats (PinosSpaV4l2Source *this) value.value = ▭ rect.width = 320; rect.height = 240; - if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_SIZE), &value)) < 0) + if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_SIZE), &value)) < 0) return res; value.type = SPA_PROP_TYPE_FRACTION; @@ -234,10 +233,10 @@ negotiate_formats (PinosSpaV4l2Source *this) value.value = &frac; frac.num = 25; frac.denom = 1; - if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_FRAMERATE), &value)) < 0) + if ((res = spa_props_set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_VIDEO_FRAMERATE), &value)) < 0) return res; - if ((res = priv->source_node->port_set_format (priv->source, 0, 0, format)) < 0) + if ((res = spa_node_port_set_format (priv->source, 0, 0, format)) < 0) return res; str = "video/x-raw," @@ -294,7 +293,7 @@ start_pipeline (PinosSpaV4l2Source *source) negotiate_formats (source); cmd.type = SPA_COMMAND_START; - if ((res = priv->source_node->send_command (priv->source, &cmd)) < 0) + if ((res = spa_node_send_command (priv->source, &cmd)) < 0) g_debug ("got error %d", res); priv->running = true; @@ -319,7 +318,7 @@ stop_pipeline (PinosSpaV4l2Source *source) } cmd.type = SPA_COMMAND_STOP; - if ((res = priv->source_node->send_command (priv->source, &cmd)) < 0) + if ((res = spa_node_send_command (priv->source, &cmd)) < 0) g_debug ("got error %d", res); } diff --git a/spa/include/spa/buffer.h b/spa/include/spa/buffer.h index 12b7e609..e0b23136 100644 --- a/spa/include/spa/buffer.h +++ b/spa/include/spa/buffer.h @@ -131,7 +131,7 @@ typedef struct { SpaDataType type; const char *ptr_type; void *ptr; - unsigned int offset; + off_t offset; size_t size; size_t stride; } SpaData; @@ -140,6 +140,7 @@ typedef struct { * SpaBuffer: * @refcount: reference counter * @notify: called when the refcount reaches 0 + * @user_data: extra user data * @id: buffer id * @size: total size of the buffer data * @n_metas: number of metadata @@ -150,6 +151,7 @@ typedef struct { struct _SpaBuffer { volatile int refcount; SpaNotify notify; + void *user_data; uint32_t id; size_t size; unsigned int n_metas; diff --git a/spa/include/spa/defs.h b/spa/include/spa/defs.h index 963308d9..c1eecfef 100644 --- a/spa/include/spa/defs.h +++ b/spa/include/spa/defs.h @@ -66,6 +66,8 @@ typedef enum { typedef void (*SpaNotify) (void *data); #define SPA_N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) +#define SPA_MIN(a,b) ((a)<(b) ? (a) : (b)) +#define SPA_MAX(a,b) ((a)>(b) ? (a) : (b)) #ifdef __cplusplus } /* extern "C" */ diff --git a/spa/include/spa/event.h b/spa/include/spa/event.h index d5733e5b..80038e28 100644 --- a/spa/include/spa/event.h +++ b/spa/include/spa/event.h @@ -73,6 +73,11 @@ struct _SpaEvent { size_t size; }; +typedef struct { + off_t offset; + size_t size; +} SpaEventPullInput; + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/node.h b/spa/include/spa/node.h index 1e58d78e..b68f2560 100644 --- a/spa/include/spa/node.h +++ b/spa/include/spa/node.h @@ -62,15 +62,18 @@ typedef enum { * SpaInputInfo: * @port_id: the port id * @flags: extra flags - * @buffer: a buffer + * @offset: offset of data in @id + * @size: size of data in @id + * @id: a buffer id * * Input information for a node. */ typedef struct { uint32_t port_id; SpaInputFlags flags; - SpaBuffer *buffer; - SpaEvent *event; + off_t offset; + size_t size; + uint32_t id; SpaResult status; } SpaInputInfo; @@ -93,7 +96,9 @@ typedef enum { * SpaOutputInfo: * @port_id: the port id * @flags: extra flags - * @buffer: a buffer + * @offset: offset to get + * @size: size to get + * @id: a buffer id will be set * @event: an event * * Output information for a node. @@ -101,21 +106,36 @@ typedef enum { typedef struct { uint32_t port_id; SpaOutputFlags flags; - SpaBuffer *buffer; - SpaEvent *event; + off_t offset; + size_t size; + uint32_t id; SpaResult status; } SpaOutputInfo; /** + * SpaNodeState: + * @SPA_NODE_STATE_INIT: the node is initializing + * @SPA_NODE_STATE_CONFIGURE: the node needs at least one port format + * @SPA_NODE_STATE_READY: the node is ready for memory allocation + * @SPA_NODE_STREAMING: the node is streaming + */ +typedef enum { + SPA_NODE_STATE_INIT, + SPA_NODE_STATE_CONFIGURE, + SPA_NODE_STATE_READY, + SPA_NODE_STATE_STREAMING +} SpaNodeState; + +/** * SpaEventCallback: - * @node: a #SpaHandle emiting the event + * @node: a #SpaNode emiting the event * @event: the event that was emited * @user_data: user data provided when registering the callback * * This will be called when an out-of-bound event is notified * on @node. */ -typedef void (*SpaEventCallback) (SpaHandle *handle, +typedef void (*SpaEventCallback) (SpaNode *node, SpaEvent *event, void *user_data); @@ -129,12 +149,14 @@ typedef void (*SpaEventCallback) (SpaHandle *handle, * The main processing nodes. */ struct _SpaNode { + /* pointer to the handle owning this interface */ + SpaHandle *handle; /* the total size of this node. This can be used to expand this * structure in the future */ size_t size; /** * SpaNode::get_props: - * @handle: a #SpaHandle + * @node: a #SpaNode * @props: a location for a #SpaProps pointer * * Get the configurable properties of @node. @@ -148,11 +170,11 @@ struct _SpaNode { * #SPA_RESULT_NOT_IMPLEMENTED when there are no properties * implemented on @node */ - SpaResult (*get_props) (SpaHandle *handle, + SpaResult (*get_props) (SpaNode *node, SpaProps **props); /** * SpaNode::set_props: - * @handle: a #SpaHandle + * @node: a #SpaNode * @props: a #SpaProps * * Set the configurable properties in @node. @@ -172,11 +194,11 @@ struct _SpaNode { * #SPA_RESULT_WRONG_PROPERTY_TYPE when a property has the wrong * type. */ - SpaResult (*set_props) (SpaHandle *handle, + SpaResult (*set_props) (SpaNode *node, const SpaProps *props); /** * SpaNode::send_command: - * @handle: a #SpaHandle + * @node: a #SpaNode * @command: a #SpaCommand * * Send a command to @node. @@ -186,11 +208,11 @@ struct _SpaNode { * #SPA_RESULT_NOT_IMPLEMENTED when this node can't process commands * #SPA_RESULT_INVALID_COMMAND @command is an invalid command */ - SpaResult (*send_command) (SpaHandle *handle, + SpaResult (*send_command) (SpaNode *node, SpaCommand *command); /** * SpaNode::set_event_callback: - * @handle: a #SpaHandle + * @node: a #SpaNode * @callback: a callback * @user_data: user data passed in the callback * @@ -198,17 +220,17 @@ struct _SpaNode { * current callback is removed. * * The callback can be emited from any thread. The caller should take - * appropriate actions to handle the event in other threads when needed. + * appropriate actions to node the event in other threads when needed. * * Returns: #SPA_RESULT_OK on success * #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL */ - SpaResult (*set_event_callback) (SpaHandle *handle, + SpaResult (*set_event_callback) (SpaNode *node, SpaEventCallback callback, void *user_data); /** * SpaNode::get_n_ports: - * @handle: a #SpaHandle + * @node: a #SpaNode * @n_input_ports: location to hold the number of input ports or %NULL * @max_input_ports: location to hold the maximum number of input ports or %NULL * @n_output_ports: location to hold the number of output ports or %NULL @@ -220,14 +242,14 @@ struct _SpaNode { * Returns: #SPA_RESULT_OK on success * #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL */ - SpaResult (*get_n_ports) (SpaHandle *handle, + SpaResult (*get_n_ports) (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports); /** * SpaNode::get_port_ids: - * @handle: a #SpaHandle + * @node: a #SpaNode * @n_input_ports: size of the @input_ids array * @input_ids: array to store the input stream ids * @n_output_ports: size of the @output_ids array @@ -239,21 +261,21 @@ struct _SpaNode { * Returns: #SPA_RESULT_OK on success * #SPA_RESULT_INVALID_ARGUMENTS when node is %NULL */ - SpaResult (*get_port_ids) (SpaHandle *handle, + SpaResult (*get_port_ids) (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids); - SpaResult (*add_port) (SpaHandle *handle, + SpaResult (*add_port) (SpaNode *node, SpaDirection direction, - uint32_t *port_id); - SpaResult (*remove_port) (SpaHandle *handle, + uint32_t port_id); + SpaResult (*remove_port) (SpaNode *node, uint32_t port_id); /** * SpaNode::port_enum_formats: - * @handle: a #SpaHandle + * @node: a #SpaNode * @port_id: the port to query * @format: pointer to a format * @filter: a format filter @@ -273,14 +295,14 @@ struct _SpaNode { * #SPA_RESULT_INVALID_PORT when port_id is not valid * #SPA_RESULT_ENUM_END when no format exists */ - SpaResult (*port_enum_formats) (SpaHandle *handle, + SpaResult (*port_enum_formats) (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state); /** * SpaNode::port_set_format: - * @handle: a #SpaHandle + * @node: a #SpaNode * @port_id: the port to configure * @flags: flags * @format: a #SpaFormat with the format @@ -298,13 +320,13 @@ struct _SpaNode { * #SPA_RESULT_WRONG_PROPERTY_TYPE when the type or size of a property * is not correct. */ - SpaResult (*port_set_format) (SpaHandle *handle, + SpaResult (*port_set_format) (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format); /** * SpaNode::port_get_format: - * @handle: a #SpaHandle + * @node: a #SpaNode * @port_id: the port to query * @format: a pointer to a location to hold the #SpaFormat * @@ -316,43 +338,83 @@ struct _SpaNode { * #SPA_RESULT_INVALID_PORT when @port_id is not valid * #SPA_RESULT_INVALID_NO_FORMAT when no format was set */ - SpaResult (*port_get_format) (SpaHandle *handle, + SpaResult (*port_get_format) (SpaNode *node, uint32_t port_id, const SpaFormat **format); - SpaResult (*port_get_info) (SpaHandle *handle, + SpaResult (*port_get_info) (SpaNode *node, uint32_t port_id, const SpaPortInfo **info); - SpaResult (*port_get_props) (SpaHandle *handle, + SpaResult (*port_get_props) (SpaNode *node, uint32_t port_id, SpaProps **props); - SpaResult (*port_set_props) (SpaHandle *handle, + SpaResult (*port_set_props) (SpaNode *node, uint32_t port_id, const SpaProps *props); - SpaResult (*port_use_buffers) (SpaHandle *handle, + /** + * SpaNode::port_use_buffers: + * @node: a #SpaNode + * @port_id: a port id + * @buffers: an array of buffer pointers + * @n_buffers: number of elements in @buffers + * + * Tell the port to use the given buffers + * + * For an input port, all the buffers will remain dequeued. Once a buffer + * has been pushed on a port with port_push_input, it should not be reused + * until the buffer refcount reached 0 and the notify is called. + * + * For output ports, all buffers will be queued in the port. with + * port_pull_output, a buffer can be dequeued. The notify of the buffers + * will be set by @node so that buffers will be reused when the refcount + * reaches 0. + * + * Returns: #SPA_RESULT_OK on success + */ + SpaResult (*port_use_buffers) (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, - uint32_t n_buffers); - SpaResult (*port_alloc_buffers) (SpaHandle *handle, + unsigned int n_buffers); + /** + * SpaNode::port_alloc_buffers: + * @node: a #SpaNode + * @port_id: a port id + * @params: allocation parameters + * @n_params: number of elements in @params + * @buffers: an array of buffer pointers + * @n_buffers: number of elements in @buffers + * + * Tell the port to allocate buffers. + * + * For input ports, the buffers will be dequeued and ready to be filled + * and pushed into the port. A notify should be configured so that you can + * know when a buffer can be reused. + * + * For output ports, the buffers remain queued. The notify will be configured + * so that buffers can be reused when no longer in use. + * + * Returns: #SPA_RESULT_OK on success + */ + SpaResult (*port_alloc_buffers) (SpaNode *node, uint32_t port_id, SpaAllocParam **params, - uint32_t n_params, + unsigned int n_params, SpaBuffer **buffers, - uint32_t *n_buffers); + unsigned int *n_buffers); - SpaResult (*port_get_status) (SpaHandle *handle, + SpaResult (*port_get_status) (SpaNode *node, uint32_t port_id, const SpaPortStatus **status); + /** * SpaNode::port_push_input: - * @handle: a #SpaHandle + * @node: a #SpaNode * @n_info: number of #SpaInputInfo in @info * @info: array of #SpaInputInfo * - * Push a buffer and/or an event into one or more input ports of - * @node. + * Push a buffer id into one or more input ports of @node. * * Returns: #SPA_RESULT_OK on success * #SPA_RESULT_INVALID_ARGUMENTS when node or info is %NULL @@ -361,17 +423,16 @@ struct _SpaNode { * @info. * #SPA_RESULT_HAVE_ENOUGH_INPUT when output can be produced. */ - SpaResult (*port_push_input) (SpaHandle *handle, + SpaResult (*port_push_input) (SpaNode *node, unsigned int n_info, SpaInputInfo *info); /** * SpaNode::port_pull_output: - * @handle: a #SpaHandle + * @node: a #SpaNode * @n_info: number of #SpaOutputInfo in @info * @info: array of #SpaOutputInfo * - * Pull a buffer and/or an event from one or more output ports of - * @node. + * Pull a buffer id from one or more output ports of @node. * * Returns: #SPA_RESULT_OK on success * #SPA_RESULT_INVALID_ARGUMENTS when node or info is %NULL @@ -386,11 +447,37 @@ struct _SpaNode { * #SPA_RESULT_NEED_MORE_INPUT when no output can be produced * because more input is needed. */ - SpaResult (*port_pull_output) (SpaHandle *handle, + SpaResult (*port_pull_output) (SpaNode *node, unsigned int n_info, SpaOutputInfo *info); + + SpaResult (*port_push_event) (SpaNode *node, + uint32_t port_id, + SpaEvent *event); + }; +#define spa_node_get_props(n,...) (n)->get_props((n),__VA_ARGS__) +#define spa_node_set_props(n,...) (n)->set_props((n),__VA_ARGS__) +#define spa_node_send_command(n,...) (n)->send_command((n),__VA_ARGS__) +#define spa_node_set_event_callback(n,...) (n)->set_event_callback((n),__VA_ARGS__) +#define spa_node_get_n_ports(n,...) (n)->get_n_ports((n),__VA_ARGS__) +#define spa_node_get_port_ids(n,...) (n)->get_port_ids((n),__VA_ARGS__) +#define spa_node_add_port(n,...) (n)->add_port((n),__VA_ARGS__) +#define spa_node_remove_port(n,...) (n)->remove_port((n),__VA_ARGS__) +#define spa_node_port_enum_formats(n,...) (n)->port_enum_formats((n),__VA_ARGS__) +#define spa_node_port_set_format(n,...) (n)->port_set_format((n),__VA_ARGS__) +#define spa_node_port_get_format(n,...) (n)->port_get_format((n),__VA_ARGS__) +#define spa_node_port_get_info(n,...) (n)->port_get_info((n),__VA_ARGS__) +#define spa_node_port_get_props(n,...) (n)->port_get_props((n),__VA_ARGS__) +#define spa_node_port_set_props(n,...) (n)->port_set_props((n),__VA_ARGS__) +#define spa_node_port_use_buffers(n,...) (n)->port_use_buffers((n),__VA_ARGS__) +#define spa_node_port_alloc_buffers(n,...) (n)->port_alloc_buffers((n),__VA_ARGS__) +#define spa_node_port_get_status(n,...) (n)->port_get_status((n),__VA_ARGS__) +#define spa_node_port_push_input(n,...) (n)->port_push_input((n),__VA_ARGS__) +#define spa_node_port_pull_output(n,...) (n)->port_pull_output((n),__VA_ARGS__) +#define spa_node_port_push_event(n,...) (n)->port_push_event((n),__VA_ARGS__) + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/include/spa/plugin.h b/spa/include/spa/plugin.h index b22af698..836d4a06 100644 --- a/spa/include/spa/plugin.h +++ b/spa/include/spa/plugin.h @@ -47,7 +47,7 @@ struct _SpaHandle { */ SpaResult (*get_interface) (SpaHandle *handle, uint32_t interface_id, - const void **interface); + void **interface); }; /** diff --git a/spa/include/spa/poll.h b/spa/include/spa/poll.h index afa21947..ccc61bdc 100644 --- a/spa/include/spa/poll.h +++ b/spa/include/spa/poll.h @@ -62,12 +62,16 @@ typedef int (*SpaPollNotify) (SpaPollNotifyData *data); /** * SpaPollItem: + * @id: id of the poll item * @fds: array of file descriptors to watch * @n_fds: number of elements in @fds - * @callback: callback called when there was activity on any of @fds - * @user_data: user data + * @idle_cb: callback called when there is no other work + * @idle_cb: callback called before starting the poll + * @idle_cb: callback called after the poll loop + * @user_data: user data pass to callbacks */ typedef struct { + uint32_t id; SpaPollFd *fds; unsigned int n_fds; SpaPollNotify idle_cb; diff --git a/spa/include/spa/props.h b/spa/include/spa/props.h index 89269613..5c81aeb0 100644 --- a/spa/include/spa/props.h +++ b/spa/include/spa/props.h @@ -43,6 +43,8 @@ typedef enum { SPA_PROP_TYPE_UINT32, SPA_PROP_TYPE_INT64, SPA_PROP_TYPE_UINT64, + SPA_PROP_TYPE_INT, + SPA_PROP_TYPE_UINT, SPA_PROP_TYPE_FLOAT, SPA_PROP_TYPE_DOUBLE, SPA_PROP_TYPE_STRING, @@ -208,6 +210,10 @@ struct _SpaProps { void *priv; }; +#define spa_props_set_prop(p,...) (p)->set_prop((p),__VA_ARGS__) +#define spa_props_get_prop(p,...) (p)->get_prop((p),__VA_ARGS__) + + static inline unsigned int spa_props_index_for_id (const SpaProps *props, uint32_t id) { diff --git a/spa/lib/control.c b/spa/lib/control.c index f7ae7600..db31963b 100644 --- a/spa/lib/control.c +++ b/spa/lib/control.c @@ -344,7 +344,7 @@ typedef struct { SpaBuffer buffer; SpaMeta metas[16]; SpaData datas[16]; - int mem[16]; + int memid[16]; } MyBuffer; static SpaResult @@ -377,8 +377,8 @@ parse_add_buffer (struct stack_iter *si, SpaData *d = &b->datas[i]; d->type = SPA_DATA_TYPE_MEMID; d->ptr_type = NULL; - b->mem[i] = *p++; - d->ptr = &b->mem[i]; + b->memid[i] = *p++; + d->ptr = &b->memid[i]; d->offset = *p++; d->size = *p++; d->stride = *p++; diff --git a/spa/plugins/alsa/alsa-sink.c b/spa/plugins/alsa/alsa-sink.c index 849e36c4..ab2bbed4 100644 --- a/spa/plugins/alsa/alsa-sink.c +++ b/spa/plugins/alsa/alsa-sink.c @@ -73,6 +73,7 @@ struct _ALSABuffer { struct _SpaALSASink { SpaHandle handle; + SpaNode node; SpaALSASinkProps props[2]; @@ -172,14 +173,16 @@ static const SpaPropInfo prop_info[] = }; static SpaResult -spa_alsa_sink_node_get_props (SpaHandle *handle, +spa_alsa_sink_node_get_props (SpaNode *node, SpaProps **props) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -187,16 +190,19 @@ spa_alsa_sink_node_get_props (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_set_props (SpaHandle *handle, +spa_alsa_sink_node_set_props (SpaNode *node, const SpaProps *props) { - SpaALSASink *this = (SpaALSASink *) handle; - SpaALSASinkProps *p = &this->props[1]; + SpaALSASink *this; + SpaALSASinkProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_alsa_sink_props (p); return SPA_RESULT_OK; @@ -208,14 +214,16 @@ spa_alsa_sink_node_set_props (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_send_command (SpaHandle *handle, +spa_alsa_sink_node_send_command (SpaNode *node, SpaCommand *command) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -233,7 +241,7 @@ spa_alsa_sink_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; case SPA_COMMAND_STOP: @@ -249,7 +257,7 @@ spa_alsa_sink_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; case SPA_COMMAND_FLUSH: @@ -261,15 +269,17 @@ spa_alsa_sink_node_send_command (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_set_event_callback (SpaHandle *handle, - SpaEventCallback event, - void *user_data) +spa_alsa_sink_node_set_event_callback (SpaNode *node, + SpaEventCallback event, + void *user_data) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -277,13 +287,13 @@ spa_alsa_sink_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_get_n_ports (SpaHandle *handle, +spa_alsa_sink_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -299,13 +309,13 @@ spa_alsa_sink_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_get_port_ids (SpaHandle *handle, +spa_alsa_sink_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports > 0) @@ -316,33 +326,35 @@ spa_alsa_sink_node_get_port_ids (SpaHandle *handle, static SpaResult -spa_alsa_sink_node_add_port (SpaHandle *handle, +spa_alsa_sink_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_alsa_sink_node_remove_port (SpaHandle *handle, +spa_alsa_sink_node_remove_port (SpaNode *node, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_alsa_sink_node_port_enum_formats (SpaHandle *handle, +spa_alsa_sink_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; int index; - if (handle == NULL || format == NULL || state == NULL) + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -365,17 +377,19 @@ spa_alsa_sink_node_port_enum_formats (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_set_format (SpaHandle *handle, +spa_alsa_sink_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; SpaResult res; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -393,15 +407,17 @@ spa_alsa_sink_node_port_set_format (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_get_format (SpaHandle *handle, +spa_alsa_sink_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -414,15 +430,17 @@ spa_alsa_sink_node_port_get_format (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_get_info (SpaHandle *handle, +spa_alsa_sink_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -432,7 +450,7 @@ spa_alsa_sink_node_port_get_info (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_get_props (SpaHandle *handle, +spa_alsa_sink_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -440,7 +458,7 @@ spa_alsa_sink_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_set_props (SpaHandle *handle, +spa_alsa_sink_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -448,15 +466,17 @@ spa_alsa_sink_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_get_status (SpaHandle *handle, +spa_alsa_sink_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -466,7 +486,7 @@ spa_alsa_sink_node_port_get_status (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_use_buffers (SpaHandle *handle, +spa_alsa_sink_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) @@ -475,7 +495,7 @@ spa_alsa_sink_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_alloc_buffers (SpaHandle *handle, +spa_alsa_sink_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -485,26 +505,38 @@ spa_alsa_sink_node_port_alloc_buffers (SpaHandle *handle, return SPA_RESULT_NOT_IMPLEMENTED; } +static SpaBuffer * +find_buffer (SpaALSASink *this, uint32_t id) +{ + return NULL; +} + static SpaResult -spa_alsa_sink_node_port_push_input (SpaHandle *handle, +spa_alsa_sink_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { - SpaALSASink *this = (SpaALSASink *) handle; + SpaALSASink *this; unsigned int i; bool have_error = false, have_enough = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) node->handle; + for (i = 0; i < n_info; i++) { + SpaBuffer *buffer; + if (info[i].port_id != 0) { info[i].status = SPA_RESULT_INVALID_PORT; have_error = true; continue; } - if (info[i].buffer != NULL) { + buffer = find_buffer (this, info[i].id); + + if (buffer != NULL) { if (!this->have_format) { info[i].status = SPA_RESULT_NO_FORMAT; have_error = true; @@ -516,7 +548,7 @@ spa_alsa_sink_node_port_push_input (SpaHandle *handle, have_enough = true; continue; } - this->input_buffer = spa_buffer_ref (info[i].buffer); + this->input_buffer = spa_buffer_ref (buffer); } info[i].status = SPA_RESULT_OK; } @@ -529,7 +561,7 @@ spa_alsa_sink_node_port_push_input (SpaHandle *handle, } static SpaResult -spa_alsa_sink_node_port_pull_output (SpaHandle *handle, +spa_alsa_sink_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { @@ -537,6 +569,7 @@ spa_alsa_sink_node_port_pull_output (SpaHandle *handle, } static const SpaNode alsasink_node = { + NULL, sizeof (SpaNode), spa_alsa_sink_node_get_props, spa_alsa_sink_node_set_props, @@ -562,14 +595,18 @@ static const SpaNode alsasink_node = { static SpaResult spa_alsa_sink_get_interface (SpaHandle *handle, uint32_t interface_id, - const void **interface) + void **interface) { + SpaALSASink *this; + if (handle == NULL || interface == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaALSASink *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &alsasink_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -589,6 +626,8 @@ alsa_sink_init (const SpaHandleFactory *factory, handle->get_interface = spa_alsa_sink_get_interface; this = (SpaALSASink *) handle; + this->node = alsasink_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/plugins/alsa/alsa-utils.c b/spa/plugins/alsa/alsa-utils.c index b427060e..d6fef158 100644 --- a/spa/plugins/alsa/alsa-utils.c +++ b/spa/plugins/alsa/alsa-utils.c @@ -236,7 +236,7 @@ pull_input (SpaALSASink *this, void *data, snd_pcm_uframes_t frames) buffer->data[0].ptr_type = "sysmem"; buffer->data[0].size = frames * sizeof (uint16_t) * 2; - this->event_cb (&this->handle, &event,this->user_data); + this->event_cb (&this->node, &event,this->user_data); spa_buffer_unref ((SpaBuffer *)event.data); } @@ -378,7 +378,7 @@ spa_alsa_start (SpaALSASink *this) state->poll.before_cb = NULL; state->poll.after_cb = alsa_on_fd_events; state->poll.user_data = this; - this->event_cb (&this->handle, &event, this->user_data); + this->event_cb (&this->node, &event, this->user_data); mmap_write (this); err = snd_pcm_start (state->handle); @@ -400,7 +400,7 @@ spa_alsa_stop (SpaALSASink *this) event.port_id = 0; event.data = &state->poll; event.size = sizeof (state->poll); - this->event_cb (&this->handle, &event, this->user_data); + this->event_cb (&this->node, &event, this->user_data); spa_alsa_close (this); diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index 121b54de..e5d94627 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -47,28 +47,30 @@ struct _MixerBuffer { typedef struct { bool valid; + bool have_format; + SpaAudioRawFormat format[2]; SpaAudioMixerPortProps props[2]; SpaPortInfo info; SpaPortStatus status; - SpaBuffer *buffer; size_t buffer_index; size_t buffer_offset; size_t buffer_queued; MixerBuffer mix; + + SpaBuffer **buffers; + unsigned int n_buffers; + SpaBuffer *buffer; } SpaAudioMixerPort; struct _SpaAudioMixer { SpaHandle handle; + SpaNode node; SpaAudioMixerProps props[2]; SpaEventCallback event_cb; void *user_data; - bool have_format; - SpaAudioRawFormat query_format; - SpaAudioRawFormat current_format; - int port_count; int port_queued; SpaAudioMixerPort ports[MAX_PORTS]; @@ -89,14 +91,16 @@ reset_audiomixer_props (SpaAudioMixerProps *props) } static SpaResult -spa_audiomixer_node_get_props (SpaHandle *handle, +spa_audiomixer_node_get_props (SpaNode *node, SpaProps **props) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -104,16 +108,19 @@ spa_audiomixer_node_get_props (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_set_props (SpaHandle *handle, +spa_audiomixer_node_set_props (SpaNode *node, const SpaProps *props) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; - SpaAudioMixerProps *p = &this->props[1]; + SpaAudioMixer *this; + SpaAudioMixerProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_audiomixer_props (p); return SPA_RESULT_OK; @@ -124,14 +131,16 @@ spa_audiomixer_node_set_props (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_send_command (SpaHandle *handle, +spa_audiomixer_node_send_command (SpaNode *node, SpaCommand *command) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -147,7 +156,7 @@ spa_audiomixer_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -162,7 +171,7 @@ spa_audiomixer_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -175,15 +184,17 @@ spa_audiomixer_node_send_command (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_set_event_callback (SpaHandle *handle, +spa_audiomixer_node_set_event_callback (SpaNode *node, SpaEventCallback event, void *user_data) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -191,13 +202,13 @@ spa_audiomixer_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_get_n_ports (SpaHandle *handle, +spa_audiomixer_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -213,18 +224,20 @@ spa_audiomixer_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_get_port_ids (SpaHandle *handle, +spa_audiomixer_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; int i, idx; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (input_ids) { for (i = 1, idx = 0; i < MAX_PORTS && idx < n_input_ports; i++) { if (this->ports[i].valid) @@ -238,34 +251,34 @@ spa_audiomixer_node_get_port_ids (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_add_port (SpaHandle *handle, +spa_audiomixer_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; - int i; + SpaAudioMixer *this; - if (handle == NULL || port_id == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (direction != SPA_DIRECTION_INPUT) return SPA_RESULT_INVALID_DIRECTION; - for (i = 1; i < MAX_PORTS; i++) - if (!this->ports[i].valid) - break; - if (i == MAX_PORTS) - return SPA_RESULT_TOO_MANY_PORTS; + if (port_id >= MAX_PORTS) + return SPA_RESULT_INVALID_PORT; + + if (this->ports[port_id].valid) + return SPA_RESULT_INVALID_PORT; - this->ports[i].valid = true; - *port_id = i; + this->ports[port_id].valid = true; this->port_count++; - this->ports[i].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFER | - SPA_PORT_INFO_FLAG_REMOVABLE | - SPA_PORT_INFO_FLAG_OPTIONAL | - SPA_PORT_INFO_FLAG_IN_PLACE; - this->ports[i].status.flags = SPA_PORT_STATUS_FLAG_NEED_INPUT; + this->ports[port_id].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFER | + SPA_PORT_INFO_FLAG_REMOVABLE | + SPA_PORT_INFO_FLAG_OPTIONAL | + SPA_PORT_INFO_FLAG_IN_PLACE; + this->ports[port_id].status.flags = SPA_PORT_STATUS_FLAG_NEED_INPUT; this->ports[0].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT; @@ -273,14 +286,16 @@ spa_audiomixer_node_add_port (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_remove_port (SpaHandle *handle, +spa_audiomixer_node_remove_port (SpaNode *node, uint32_t port_id) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (port_id == 0 || port_id >= MAX_PORTS || !this->ports[port_id].valid) return SPA_RESULT_INVALID_PORT; @@ -299,105 +314,124 @@ spa_audiomixer_node_remove_port (SpaHandle *handle, static SpaResult -spa_audiomixer_node_port_enum_formats (SpaHandle *handle, +spa_audiomixer_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; + SpaAudioMixerPort *port; int index; - if (handle == NULL || format == NULL || state == NULL) + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - if (port_id > MAX_PORTS) + this = (SpaAudioMixer *) node->handle; + + if (port_id > MAX_PORTS || !this->ports[port_id].valid) return SPA_RESULT_INVALID_PORT; + port = &this->ports[port_id]; + index = (*state == NULL ? 0 : *(int*)state); switch (index) { case 0: - spa_audio_raw_format_init (&this->query_format); + spa_audio_raw_format_init (&port->format[0]); break; default: return SPA_RESULT_ENUM_END; } - *format = &this->query_format.format; + *format = &port->format[0].format; *(int*)state = ++index; return SPA_RESULT_OK; } static SpaResult -spa_audiomixer_node_port_set_format (SpaHandle *handle, +spa_audiomixer_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; + SpaAudioMixerPort *port; SpaResult res; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; - if (port_id > MAX_PORTS) + this = (SpaAudioMixer *) node->handle; + + if (port_id > MAX_PORTS || !this->ports[port_id].valid) return SPA_RESULT_INVALID_PORT; + port = &this->ports[port_id]; + if (format == NULL) { - this->have_format = false; + port->have_format = false; return SPA_RESULT_OK; } - if ((res = spa_audio_raw_format_parse (format, &this->current_format)) < 0) + if ((res = spa_audio_raw_format_parse (format, &port->format[1])) < 0) return res; - this->have_format = true; + port->have_format = true; return SPA_RESULT_OK; } static SpaResult -spa_audiomixer_node_port_get_format (SpaHandle *handle, +spa_audiomixer_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; + SpaAudioMixerPort *port; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (port_id >= MAX_PORTS || !this->ports[port_id].valid) return SPA_RESULT_INVALID_PORT; - if (!this->have_format) + port = &this->ports[port_id]; + + if (!port->have_format) return SPA_RESULT_NO_FORMAT; - *format = &this->current_format.format; + *format = &port->format[1].format; return SPA_RESULT_OK; } static SpaResult -spa_audiomixer_node_port_get_info (SpaHandle *handle, +spa_audiomixer_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; + SpaAudioMixerPort *port; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (port_id >= MAX_PORTS || !this->ports[port_id].valid) return SPA_RESULT_INVALID_PORT; - *info = &this->ports[port_id].info; + port = &this->ports[port_id]; + *info = &port->info; return SPA_RESULT_OK; } static SpaResult -spa_audiomixer_node_port_get_props (SpaHandle *handle, +spa_audiomixer_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -405,7 +439,7 @@ spa_audiomixer_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_port_set_props (SpaHandle *handle, +spa_audiomixer_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -413,28 +447,32 @@ spa_audiomixer_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_port_get_status (SpaHandle *handle, +spa_audiomixer_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; + SpaAudioMixerPort *port; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (port_id >= MAX_PORTS || !this->ports[port_id].valid) return SPA_RESULT_INVALID_PORT; - if (!this->have_format) + port = &this->ports[port_id]; + if (!port->have_format) return SPA_RESULT_NO_FORMAT; - *status = &this->ports[port_id].status; + *status = &port->status; return SPA_RESULT_OK; } static SpaResult -spa_audiomixer_node_port_use_buffers (SpaHandle *handle, +spa_audiomixer_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) @@ -443,7 +481,7 @@ spa_audiomixer_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_port_alloc_buffers (SpaHandle *handle, +spa_audiomixer_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -454,23 +492,25 @@ spa_audiomixer_node_port_alloc_buffers (SpaHandle *handle, } static SpaResult -spa_audiomixer_node_port_push_input (SpaHandle *handle, +spa_audiomixer_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; - SpaBuffer *buffer; - SpaEvent *event; + SpaAudioMixer *this; unsigned int i; bool have_error = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (this->ports[0].status.flags & SPA_PORT_STATUS_FLAG_HAVE_OUTPUT) return SPA_RESULT_HAVE_ENOUGH_INPUT; for (i = 0; i < n_info; i++) { + SpaBuffer *buffer; + SpaAudioMixerPort *port; int idx = info[i].port_id; if (idx >= MAX_PORTS || !this->ports[idx].valid) { @@ -478,18 +518,17 @@ spa_audiomixer_node_port_push_input (SpaHandle *handle, have_error = true; continue; } + port = &this->ports[idx]; + buffer = port->buffers[info[i].id]; - event = info[i].event; - buffer = info[i].buffer; - - if (buffer == NULL && event == NULL) { + if (buffer == NULL) { info[i].status = SPA_RESULT_INVALID_ARGUMENTS; have_error = true; continue; } if (buffer) { - if (!this->have_format) { + if (!port->have_format) { info[i].status = SPA_RESULT_NO_FORMAT; have_error = true; continue; @@ -509,11 +548,6 @@ spa_audiomixer_node_port_push_input (SpaHandle *handle, if (this->port_queued == this->port_count) this->ports[0].status.flags |= SPA_PORT_STATUS_FLAG_HAVE_OUTPUT; } - if (event) { - info[i].status = SPA_RESULT_NOT_IMPLEMENTED; - have_error = true; - continue; - } info[i].status = SPA_RESULT_OK; } if (have_error) @@ -557,7 +591,7 @@ pull_port (SpaAudioMixer *this, uint32_t port_id, SpaOutputInfo *info, size_t pu buffer->data[0].ptr_type = "sysmem"; buffer->data[0].size = pull_size; - this->event_cb (&this->handle, &event, this->user_data); + this->event_cb (&this->node, &event, this->user_data); } static void @@ -613,15 +647,12 @@ static SpaResult mix_data (SpaAudioMixer *this, SpaOutputInfo *info) { int i, min_size, min_port, pull_size; + SpaBuffer *buf; if (info->port_id != 0) return SPA_RESULT_INVALID_PORT; - if (info->buffer) { - pull_size = info->buffer->size; - } else { - pull_size = 0; - } + pull_size = info->size; min_size = 0; min_port = 0; @@ -645,43 +676,42 @@ mix_data (SpaAudioMixer *this, SpaOutputInfo *info) if (min_port == 0) return SPA_RESULT_NEED_MORE_INPUT; - if (info->buffer) { - if (info->buffer->size < min_size) - min_size = info->buffer->size; - else - info->buffer->size = min_size; - } else { - info->buffer = this->ports[min_port].buffer; - this->ports[min_port].buffer = NULL; - this->ports[min_port].status.flags = SPA_PORT_STATUS_FLAG_NEED_INPUT; - this->ports[0].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT; - } + buf = this->ports[min_port].buffer; + info->id = buf->id; + this->ports[min_port].buffer = NULL; + this->ports[min_port].status.flags = SPA_PORT_STATUS_FLAG_NEED_INPUT; + this->ports[0].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT; for (i = 1; i < MAX_PORTS; i++) { if (!this->ports[i].valid || this->ports[i].buffer == NULL) continue; - add_port_data (this, info->buffer, &this->ports[i]); + add_port_data (this, buf, &this->ports[i]); } return SPA_RESULT_OK; } static SpaResult -spa_audiomixer_node_port_pull_output (SpaHandle *handle, +spa_audiomixer_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { - SpaAudioMixer *this = (SpaAudioMixer *) handle; + SpaAudioMixer *this; + SpaAudioMixerPort *port; int i; bool have_error = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) node->handle; + if (info->port_id != 0) return SPA_RESULT_INVALID_PORT; - if (!this->have_format) + port = &this->ports[info->port_id]; + + if (!port->have_format) return SPA_RESULT_NO_FORMAT; // if (!(this->ports[0].status.flags & SPA_PORT_STATUS_FLAG_HAVE_OUTPUT)) @@ -700,7 +730,16 @@ spa_audiomixer_node_port_pull_output (SpaHandle *handle, return SPA_RESULT_OK; } +static SpaResult +spa_audiomixer_node_port_push_event (SpaNode *node, + uint32_t port_id, + SpaEvent *event) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + static const SpaNode audiomixer_node = { + NULL, sizeof (SpaNode), spa_audiomixer_node_get_props, spa_audiomixer_node_set_props, @@ -721,19 +760,24 @@ static const SpaNode audiomixer_node = { spa_audiomixer_node_port_get_status, spa_audiomixer_node_port_push_input, spa_audiomixer_node_port_pull_output, + spa_audiomixer_node_port_push_event, }; static SpaResult spa_audiomixer_get_interface (SpaHandle *handle, uint32_t interface_id, - const void **interface) + void **interface) { + SpaAudioMixer *this; + if (handle == NULL || interface == 0) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioMixer *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &audiomixer_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -753,6 +797,8 @@ spa_audiomixer_init (const SpaHandleFactory *factory, handle->get_interface = spa_audiomixer_get_interface; this = (SpaAudioMixer *) handle; + this->node = audiomixer_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index a8e655ae..50960800 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -34,6 +34,7 @@ typedef struct { struct _SpaAudioTestSrc { SpaHandle handle; + SpaNode node; SpaAudioTestSrcProps props[2]; @@ -121,14 +122,16 @@ reset_audiotestsrc_props (SpaAudioTestSrcProps *props) } static SpaResult -spa_audiotestsrc_node_get_props (SpaHandle *handle, +spa_audiotestsrc_node_get_props (SpaNode *node, SpaProps **props) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -136,16 +139,19 @@ spa_audiotestsrc_node_get_props (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_set_props (SpaHandle *handle, +spa_audiotestsrc_node_set_props (SpaNode *node, const SpaProps *props) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; - SpaAudioTestSrcProps *p = &this->props[1]; + SpaAudioTestSrc *this; + SpaAudioTestSrcProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_audiotestsrc_props (p); return SPA_RESULT_OK; @@ -156,14 +162,16 @@ spa_audiotestsrc_node_set_props (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_send_command (SpaHandle *handle, +spa_audiotestsrc_node_send_command (SpaNode *node, SpaCommand *command) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -179,7 +187,7 @@ spa_audiotestsrc_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -194,7 +202,7 @@ spa_audiotestsrc_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -207,15 +215,17 @@ spa_audiotestsrc_node_send_command (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_set_event_callback (SpaHandle *handle, +spa_audiotestsrc_node_set_event_callback (SpaNode *node, SpaEventCallback event, void *user_data) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -223,13 +233,13 @@ spa_audiotestsrc_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_get_n_ports (SpaHandle *handle, +spa_audiotestsrc_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -245,13 +255,13 @@ spa_audiotestsrc_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_get_port_ids (SpaHandle *handle, +spa_audiotestsrc_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - if (handle == NULL || input_ids == NULL || output_ids == NULL) + if (node == NULL || node->handle == NULL || input_ids == NULL || output_ids == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_output_ports > 0) @@ -261,33 +271,35 @@ spa_audiotestsrc_node_get_port_ids (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_add_port (SpaHandle *handle, +spa_audiotestsrc_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_audiotestsrc_node_remove_port (SpaHandle *handle, +spa_audiotestsrc_node_remove_port (SpaNode *node, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_audiotestsrc_node_port_enum_formats (SpaHandle *handle, +spa_audiotestsrc_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; int index; - if (handle == NULL || format == NULL || state == NULL) + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -307,17 +319,19 @@ spa_audiotestsrc_node_port_enum_formats (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_set_format (SpaHandle *handle, +spa_audiotestsrc_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -335,15 +349,17 @@ spa_audiotestsrc_node_port_set_format (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_get_format (SpaHandle *handle, +spa_audiotestsrc_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -356,15 +372,17 @@ spa_audiotestsrc_node_port_get_format (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_get_info (SpaHandle *handle, +spa_audiotestsrc_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -374,7 +392,7 @@ spa_audiotestsrc_node_port_get_info (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_get_props (SpaHandle *handle, +spa_audiotestsrc_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -382,7 +400,7 @@ spa_audiotestsrc_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_set_props (SpaHandle *handle, +spa_audiotestsrc_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -390,15 +408,17 @@ spa_audiotestsrc_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_get_status (SpaHandle *handle, +spa_audiotestsrc_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -411,7 +431,7 @@ spa_audiotestsrc_node_port_get_status (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_use_buffers (SpaHandle *handle, +spa_audiotestsrc_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) @@ -420,7 +440,7 @@ spa_audiotestsrc_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_alloc_buffers (SpaHandle *handle, +spa_audiotestsrc_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -432,7 +452,7 @@ spa_audiotestsrc_node_port_alloc_buffers (SpaHandle *handle, static SpaResult -spa_audiotestsrc_node_port_push_input (SpaHandle *handle, +spa_audiotestsrc_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { @@ -440,19 +460,21 @@ spa_audiotestsrc_node_port_push_input (SpaHandle *handle, } static SpaResult -spa_audiotestsrc_node_port_pull_output (SpaHandle *handle, +spa_audiotestsrc_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { - SpaAudioTestSrc *this = (SpaAudioTestSrc *) handle; + SpaAudioTestSrc *this; size_t j, size; uint8_t *ptr; unsigned int i; bool have_error = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) node->handle; + for (i = 0; i < n_info; i++) { if (info[i].port_id != 0) { info[i].status = SPA_RESULT_INVALID_PORT; @@ -466,14 +488,7 @@ spa_audiotestsrc_node_port_pull_output (SpaHandle *handle, continue; } - if (info[i].buffer == NULL || info[i].buffer->n_datas == 0) { - info[i].status = SPA_RESULT_INVALID_ARGUMENTS; - have_error = true; - continue; - } - - ptr = info[i].buffer->datas[0].ptr; - size = info[i].buffer->datas[0].size; + size = info[i].size; for (j = 0; j < size; j++) ptr[j] = rand(); @@ -486,7 +501,16 @@ spa_audiotestsrc_node_port_pull_output (SpaHandle *handle, return SPA_RESULT_OK; } +static SpaResult +spa_audiotestsrc_node_port_push_event (SpaNode *node, + uint32_t port_id, + SpaEvent *event) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + static const SpaNode audiotestsrc_node = { + NULL, sizeof (SpaNode), spa_audiotestsrc_node_get_props, spa_audiotestsrc_node_set_props, @@ -507,19 +531,24 @@ static const SpaNode audiotestsrc_node = { spa_audiotestsrc_node_port_get_status, spa_audiotestsrc_node_port_push_input, spa_audiotestsrc_node_port_pull_output, + spa_audiotestsrc_node_port_push_event, }; static SpaResult -spa_audiotestsrc_get_interface (SpaHandle *handle, - uint32_t interface_id, - const void **interface) +spa_audiotestsrc_get_interface (SpaHandle *handle, + uint32_t interface_id, + void **interface) { + SpaAudioTestSrc *this; + if (handle == NULL || interface == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaAudioTestSrc *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &audiotestsrc_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -539,6 +568,8 @@ audiotestsrc_init (const SpaHandleFactory *factory, handle->get_interface = spa_audiotestsrc_get_interface; this = (SpaAudioTestSrc *) handle; + this->node = audiotestsrc_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/plugins/ffmpeg/ffmpeg-dec.c b/spa/plugins/ffmpeg/ffmpeg-dec.c index 8afa77c1..682c0107 100644 --- a/spa/plugins/ffmpeg/ffmpeg-dec.c +++ b/spa/plugins/ffmpeg/ffmpeg-dec.c @@ -67,6 +67,7 @@ typedef struct { struct _SpaFFMpegDec { SpaHandle handle; + SpaNode node; SpaFFMpegDecProps props[2]; @@ -86,14 +87,16 @@ static const SpaPropInfo prop_info[] = }; static SpaResult -spa_ffmpeg_dec_node_get_props (SpaHandle *handle, +spa_ffmpeg_dec_node_get_props (SpaNode *node, SpaProps **props) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -101,16 +104,19 @@ spa_ffmpeg_dec_node_get_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_set_props (SpaHandle *handle, +spa_ffmpeg_dec_node_set_props (SpaNode *node, const SpaProps *props) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; - SpaFFMpegDecProps *p = &this->props[1]; + SpaFFMpegDec *this; + SpaFFMpegDecProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_ffmpeg_dec_props (p); return SPA_RESULT_OK; @@ -122,14 +128,16 @@ spa_ffmpeg_dec_node_set_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_send_command (SpaHandle *handle, +spa_ffmpeg_dec_node_send_command (SpaNode *node, SpaCommand *command) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -145,7 +153,7 @@ spa_ffmpeg_dec_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; case SPA_COMMAND_STOP: @@ -159,7 +167,7 @@ spa_ffmpeg_dec_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -172,15 +180,17 @@ spa_ffmpeg_dec_node_send_command (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_set_event_callback (SpaHandle *handle, +spa_ffmpeg_dec_node_set_event_callback (SpaNode *node, SpaEventCallback event, void *user_data) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -188,13 +198,13 @@ spa_ffmpeg_dec_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_get_n_ports (SpaHandle *handle, +spa_ffmpeg_dec_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -210,13 +220,13 @@ spa_ffmpeg_dec_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_get_port_ids (SpaHandle *handle, +spa_ffmpeg_dec_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports > 0) @@ -229,34 +239,36 @@ spa_ffmpeg_dec_node_get_port_ids (SpaHandle *handle, static SpaResult -spa_ffmpeg_dec_node_add_port (SpaHandle *handle, +spa_ffmpeg_dec_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_ffmpeg_dec_node_remove_port (SpaHandle *handle, +spa_ffmpeg_dec_node_remove_port (SpaNode *node, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_ffmpeg_dec_node_port_enum_formats (SpaHandle *handle, +spa_ffmpeg_dec_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; SpaFFMpegState *s; int index; - if (handle == NULL || format == NULL || state == NULL) + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -278,20 +290,22 @@ spa_ffmpeg_dec_node_port_enum_formats (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_set_format (SpaHandle *handle, +spa_ffmpeg_dec_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; SpaFFMpegState *state; SpaResult res; SpaFormat *f, *tf; size_t fs; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -324,16 +338,18 @@ spa_ffmpeg_dec_node_port_set_format (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_get_format (SpaHandle *handle, +spa_ffmpeg_dec_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; SpaFFMpegState *state; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -348,15 +364,17 @@ spa_ffmpeg_dec_node_port_get_format (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_get_info (SpaHandle *handle, +spa_ffmpeg_dec_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -366,7 +384,7 @@ spa_ffmpeg_dec_node_port_get_info (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_get_props (SpaHandle *handle, +spa_ffmpeg_dec_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -374,7 +392,7 @@ spa_ffmpeg_dec_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_set_props (SpaHandle *handle, +spa_ffmpeg_dec_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -382,15 +400,17 @@ spa_ffmpeg_dec_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_get_status (SpaHandle *handle, +spa_ffmpeg_dec_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -400,12 +420,12 @@ spa_ffmpeg_dec_node_port_get_status (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_use_buffers (SpaHandle *handle, +spa_ffmpeg_dec_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (!IS_VALID_PORT (port_id)) @@ -415,7 +435,7 @@ spa_ffmpeg_dec_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_alloc_buffers (SpaHandle *handle, +spa_ffmpeg_dec_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -427,7 +447,7 @@ spa_ffmpeg_dec_node_port_alloc_buffers (SpaHandle *handle, static SpaResult -spa_ffmpeg_dec_node_port_push_input (SpaHandle *handle, +spa_ffmpeg_dec_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { @@ -435,18 +455,19 @@ spa_ffmpeg_dec_node_port_push_input (SpaHandle *handle, } static SpaResult -spa_ffmpeg_dec_node_port_pull_output (SpaHandle *handle, +spa_ffmpeg_dec_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { - SpaFFMpegDec *this = (SpaFFMpegDec *) handle; + SpaFFMpegDec *this; SpaFFMpegState *state; unsigned int i; bool have_error = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) node->handle; for (i = 0; i < n_info; i++) { if (info[i].port_id != OUTPUT_PORT_ID) { @@ -469,7 +490,17 @@ spa_ffmpeg_dec_node_port_pull_output (SpaHandle *handle, return SPA_RESULT_OK; } +static SpaResult +spa_ffmpeg_dec_node_port_push_event (SpaNode *node, + uint32_t port_id, + SpaEvent *event) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + + static const SpaNode ffmpeg_dec_node = { + NULL, sizeof (SpaNode), spa_ffmpeg_dec_node_get_props, spa_ffmpeg_dec_node_set_props, @@ -490,19 +521,24 @@ static const SpaNode ffmpeg_dec_node = { spa_ffmpeg_dec_node_port_get_status, spa_ffmpeg_dec_node_port_push_input, spa_ffmpeg_dec_node_port_pull_output, + spa_ffmpeg_dec_node_port_push_event, }; static SpaResult -spa_ffmpeg_dec_get_interface (SpaHandle *handle, - uint32_t interface_id, - const void **interface) +spa_ffmpeg_dec_get_interface (SpaHandle *handle, + uint32_t interface_id, + void **interface) { + SpaFFMpegDec *this; + if (handle == NULL || interface == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegDec *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &ffmpeg_dec_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -518,6 +554,8 @@ spa_ffmpeg_dec_init (SpaHandle *handle) handle->get_interface = spa_ffmpeg_dec_get_interface; this = (SpaFFMpegDec *) handle; + this->node = ffmpeg_dec_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/plugins/ffmpeg/ffmpeg-enc.c b/spa/plugins/ffmpeg/ffmpeg-enc.c index d4a79f65..ea6b316a 100644 --- a/spa/plugins/ffmpeg/ffmpeg-enc.c +++ b/spa/plugins/ffmpeg/ffmpeg-enc.c @@ -67,6 +67,7 @@ typedef struct { struct _SpaFFMpegEnc { SpaHandle handle; + SpaNode node; SpaFFMpegEncProps props[2]; @@ -86,14 +87,16 @@ static const SpaPropInfo prop_info[] = }; static SpaResult -spa_ffmpeg_enc_node_get_props (SpaHandle *handle, +spa_ffmpeg_enc_node_get_props (SpaNode *node, SpaProps **props) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -101,16 +104,19 @@ spa_ffmpeg_enc_node_get_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_set_props (SpaHandle *handle, +spa_ffmpeg_enc_node_set_props (SpaNode *node, const SpaProps *props) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; - SpaFFMpegEncProps *p = &this->props[1]; + SpaFFMpegEnc *this; + SpaFFMpegEncProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_ffmpeg_enc_props (p); return SPA_RESULT_OK; @@ -122,14 +128,16 @@ spa_ffmpeg_enc_node_set_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_send_command (SpaHandle *handle, +spa_ffmpeg_enc_node_send_command (SpaNode *node, SpaCommand *command) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -145,7 +153,7 @@ spa_ffmpeg_enc_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; case SPA_COMMAND_STOP: @@ -159,7 +167,7 @@ spa_ffmpeg_enc_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -172,15 +180,17 @@ spa_ffmpeg_enc_node_send_command (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_set_event_callback (SpaHandle *handle, +spa_ffmpeg_enc_node_set_event_callback (SpaNode *node, SpaEventCallback event, void *user_data) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -188,13 +198,13 @@ spa_ffmpeg_enc_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_get_n_ports (SpaHandle *handle, +spa_ffmpeg_enc_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -210,13 +220,13 @@ spa_ffmpeg_enc_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_get_port_ids (SpaHandle *handle, +spa_ffmpeg_enc_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports > 0) @@ -229,34 +239,36 @@ spa_ffmpeg_enc_node_get_port_ids (SpaHandle *handle, static SpaResult -spa_ffmpeg_enc_node_add_port (SpaHandle *handle, +spa_ffmpeg_enc_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_ffmpeg_enc_node_remove_port (SpaHandle *handle, +spa_ffmpeg_enc_node_remove_port (SpaNode *node, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_ffmpeg_enc_node_port_enum_formats (SpaHandle *handle, +spa_ffmpeg_enc_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; SpaFFMpegState *s; int index; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -278,20 +290,22 @@ spa_ffmpeg_enc_node_port_enum_formats (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_set_format (SpaHandle *handle, +spa_ffmpeg_enc_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; SpaFFMpegState *state; SpaResult res; SpaFormat *f, *tf; size_t fs; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -324,16 +338,18 @@ spa_ffmpeg_enc_node_port_set_format (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_get_format (SpaHandle *handle, +spa_ffmpeg_enc_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; SpaFFMpegState *state; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -348,15 +364,17 @@ spa_ffmpeg_enc_node_port_get_format (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_get_info (SpaHandle *handle, +spa_ffmpeg_enc_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -366,7 +384,7 @@ spa_ffmpeg_enc_node_port_get_info (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_get_props (SpaHandle *handle, +spa_ffmpeg_enc_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -374,7 +392,7 @@ spa_ffmpeg_enc_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_set_props (SpaHandle *handle, +spa_ffmpeg_enc_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -382,15 +400,17 @@ spa_ffmpeg_enc_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_get_status (SpaHandle *handle, +spa_ffmpeg_enc_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + if (!IS_VALID_PORT (port_id)) return SPA_RESULT_INVALID_PORT; @@ -400,12 +420,12 @@ spa_ffmpeg_enc_node_port_get_status (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_use_buffers (SpaHandle *handle, +spa_ffmpeg_enc_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (!IS_VALID_PORT (port_id)) @@ -415,7 +435,7 @@ spa_ffmpeg_enc_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_alloc_buffers (SpaHandle *handle, +spa_ffmpeg_enc_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -427,7 +447,7 @@ spa_ffmpeg_enc_node_port_alloc_buffers (SpaHandle *handle, static SpaResult -spa_ffmpeg_enc_node_port_push_input (SpaHandle *handle, +spa_ffmpeg_enc_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { @@ -435,18 +455,20 @@ spa_ffmpeg_enc_node_port_push_input (SpaHandle *handle, } static SpaResult -spa_ffmpeg_enc_node_port_pull_output (SpaHandle *handle, +spa_ffmpeg_enc_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { - SpaFFMpegEnc *this = (SpaFFMpegEnc *) handle; + SpaFFMpegEnc *this; SpaFFMpegState *state; unsigned int i; bool have_error = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) node->handle; + for (i = 0; i < n_info; i++) { if (info[i].port_id != OUTPUT_PORT_ID) { @@ -469,7 +491,16 @@ spa_ffmpeg_enc_node_port_pull_output (SpaHandle *handle, return SPA_RESULT_OK; } +static SpaResult +spa_ffmpeg_enc_node_port_push_event (SpaNode *node, + uint32_t port_id, + SpaEvent *event) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + static const SpaNode ffmpeg_enc_node = { + NULL, sizeof (SpaNode), spa_ffmpeg_enc_node_get_props, spa_ffmpeg_enc_node_set_props, @@ -490,19 +521,24 @@ static const SpaNode ffmpeg_enc_node = { spa_ffmpeg_enc_node_port_get_status, spa_ffmpeg_enc_node_port_push_input, spa_ffmpeg_enc_node_port_pull_output, + spa_ffmpeg_enc_node_port_push_event, }; static SpaResult -spa_ffmpeg_enc_get_interface (SpaHandle *handle, - uint32_t interface_id, - const void **interface) +spa_ffmpeg_enc_get_interface (SpaHandle *handle, + uint32_t interface_id, + void **interface) { + SpaFFMpegEnc *this; + if (handle == NULL || interface == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaFFMpegEnc *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &ffmpeg_enc_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -518,6 +554,8 @@ spa_ffmpeg_enc_init (SpaHandle *handle) handle->get_interface = spa_ffmpeg_enc_get_interface; this = (SpaFFMpegEnc *) handle; + this->node = ffmpeg_enc_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/plugins/meson.build b/spa/plugins/meson.build index e8a9e231..2d43f779 100644 --- a/spa/plugins/meson.build +++ b/spa/plugins/meson.build @@ -2,6 +2,7 @@ subdir('alsa') subdir('audiomixer') subdir('audiotestsrc') subdir('ffmpeg') +subdir('remote') #subdir('libva') subdir('volume') subdir('v4l2') diff --git a/spa/plugins/remote/meson.build b/spa/plugins/remote/meson.build new file mode 100644 index 00000000..880b8e3b --- /dev/null +++ b/spa/plugins/remote/meson.build @@ -0,0 +1,7 @@ +remote_sources = ['proxy.c', 'plugin.c'] + +remotelib = shared_library('spa-remote', + remote_sources, + include_directories : inc, + link_with : spalib, + install : true) diff --git a/spa/plugins/remote/plugin.c b/spa/plugins/remote/plugin.c new file mode 100644 index 00000000..05539cd0 --- /dev/null +++ b/spa/plugins/remote/plugin.c @@ -0,0 +1,46 @@ +/* Spa Volume plugin + * Copyright (C) 2016 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 <spa/plugin.h> +#include <spa/node.h> + +extern const SpaHandleFactory spa_proxy_factory; + +SpaResult +spa_enum_handle_factory (const SpaHandleFactory **factory, + void **state) +{ + int index; + + if (factory == NULL || state == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + index = (*state == NULL ? 0 : *(int*)state); + + switch (index) { + case 0: + *factory = &spa_proxy_factory; + break; + default: + return SPA_RESULT_ENUM_END; + } + *(int*)state = ++index; + + return SPA_RESULT_OK; +} diff --git a/spa/plugins/remote/proxy.c b/spa/plugins/remote/proxy.c new file mode 100644 index 00000000..af988c56 --- /dev/null +++ b/spa/plugins/remote/proxy.c @@ -0,0 +1,975 @@ +/* Spa + * Copyright (C) 2016 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. + */ + +#define _GNU_SOURCE + +#include <string.h> +#include <stddef.h> +#include <stdio.h> +#include <poll.h> +#include <sys/socket.h> +#include <errno.h> +#include <sys/mman.h> +#include <unistd.h> +#include <fcntl.h> + + +#include <spa/node.h> +#include <spa/control.h> + +#define MAX_INPUTS 64 +#define MAX_OUTPUTS 64 +#define MAX_PORTS (MAX_INPUTS + MAX_OUTPUTS) + +#define CHECK_PORT_ID(this,id) ((id) < MAX_PORTS && (this)->ports[id].valid) +#define CHECK_PORT_ID_DIR(this,id,dir) (CHECK_PORT_ID(this,id) && (this)->ports[i].direction == (dir)) + +typedef struct _SpaProxy SpaProxy; + +typedef struct { + SpaProps props; + int socketfd; +} SpaProxyProps; + +typedef struct { + SpaDirection direction; + bool valid; + bool have_format; + SpaPortInfo info; + SpaPortStatus status; + SpaFormat formats[2]; + SpaBuffer **buffers; + unsigned int n_buffers; +} SpaProxyPort; + +struct _SpaProxy { + SpaHandle handle; + SpaNode node; + + SpaProxyProps props[2]; + + SpaEventCallback event_cb; + void *user_data; + + SpaPollFd fds[1]; + SpaPollItem poll; + + unsigned int n_inputs; + unsigned int n_outputs; + SpaProxyPort ports[MAX_PORTS]; +}; + +enum { + PROP_ID_SOCKET, + PROP_ID_LAST, +}; + +static const SpaPropInfo prop_info[PROP_ID_LAST] = +{ + { PROP_ID_SOCKET, "socket", "The Socket factor", + SPA_PROP_FLAG_READWRITE, + SPA_PROP_TYPE_INT, sizeof (int), + sizeof (int), NULL, + SPA_PROP_RANGE_TYPE_NONE, 0, NULL, + NULL, + offsetof (SpaProxyProps, socketfd), + 0, 0, + NULL }, +}; + +static void +reset_proxy_props (SpaProxyProps *props) +{ + props->socketfd = -1; +} + +static void +update_poll (SpaProxy *this, int socketfd) +{ + SpaEvent event; + SpaProxyProps *p; + + p = &this->props[1]; + + if (p->socketfd != -1) { + event.refcount = 1; + event.notify = NULL; + event.type = SPA_EVENT_TYPE_REMOVE_POLL; + event.port_id = 0; + event.data = &this->poll; + event.size = sizeof (this->poll); + this->event_cb (&this->node, &event, this->user_data); + } + p->socketfd = socketfd; + + if (p->socketfd != -1) { + this->fds[0].fd = p->socketfd; + event.refcount = 1; + event.notify = NULL; + event.type = SPA_EVENT_TYPE_ADD_POLL; + event.port_id = 0; + event.data = &this->poll; + event.size = sizeof (this->poll); + this->event_cb (&this->node, &event, this->user_data); + } +} + +static SpaResult +spa_proxy_node_get_props (SpaNode *node, + SpaProps **props) +{ + SpaProxy *this; + + if (node == NULL || node->handle == NULL || props == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); + *props = &this->props[0].props; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_set_props (SpaNode *node, + const SpaProps *props) +{ + SpaProxy *this; + SpaProxyProps *op, *np; + SpaResult res; + + if (node == NULL || node->handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + op = &this->props[1]; + np = &this->props[0]; + + if (props == NULL) { + reset_proxy_props (np); + props = &np->props; + } + + /* copy new properties */ + res = spa_props_copy (props, &np->props); + + /* compare changes */ + if (op->socketfd != np->socketfd) + update_poll (this, np->socketfd); + + /* commit changes */ + memcpy (op, np, sizeof (*np)); + + return res; +} + +static SpaResult +spa_proxy_node_send_command (SpaNode *node, + SpaCommand *command) +{ + SpaProxy *this; + + if (node == NULL || node->handle == NULL || command == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + switch (command->type) { + case SPA_COMMAND_INVALID: + return SPA_RESULT_INVALID_COMMAND; + + case SPA_COMMAND_START: + if (this->event_cb) { + SpaEvent event; + + event.refcount = 1; + event.notify = NULL; + event.type = SPA_EVENT_TYPE_STARTED; + event.port_id = -1; + event.data = NULL; + event.size = 0; + + this->event_cb (&this->node, &event, this->user_data); + } + break; + + case SPA_COMMAND_STOP: + if (this->event_cb) { + SpaEvent event; + + event.refcount = 1; + event.notify = NULL; + event.type = SPA_EVENT_TYPE_STOPPED; + event.port_id = -1; + event.data = NULL; + event.size = 0; + + this->event_cb (&this->node, &event, this->user_data); + } + break; + + case SPA_COMMAND_FLUSH: + case SPA_COMMAND_DRAIN: + case SPA_COMMAND_MARKER: + return SPA_RESULT_NOT_IMPLEMENTED; + } + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_set_event_callback (SpaNode *node, + SpaEventCallback event, + void *user_data) +{ + SpaProxy *this; + + if (node == NULL || node->handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + this->event_cb = event; + this->user_data = user_data; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_get_n_ports (SpaNode *node, + unsigned int *n_input_ports, + unsigned int *max_input_ports, + unsigned int *n_output_ports, + unsigned int *max_output_ports) +{ + SpaProxy *this; + + if (node == NULL || node->handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (n_input_ports) + *n_input_ports = this->n_inputs; + if (n_output_ports) + *n_output_ports = this->n_outputs; + if (max_input_ports) + *max_input_ports = MAX_INPUTS; + if (max_output_ports) + *max_output_ports = MAX_OUTPUTS; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_get_port_ids (SpaNode *node, + unsigned int n_input_ports, + uint32_t *input_ids, + unsigned int n_output_ports, + uint32_t *output_ids) +{ + SpaProxy *this; + int c, i; + + if (node == NULL || node->handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (input_ids) { + n_input_ports = SPA_MIN (n_input_ports, MAX_PORTS); + for (c = 0, i = 0; i < n_input_ports; i++) { + if (this->ports[i].valid && this->ports[i].direction == SPA_DIRECTION_INPUT) + input_ids[c++] = i; + } + } + if (output_ids) { + n_output_ports = SPA_MIN (n_output_ports, MAX_PORTS); + for (c = 0, i = 0; i < n_output_ports; i++) { + if (this->ports[i].valid && this->ports[i].direction == SPA_DIRECTION_OUTPUT) + output_ids[c++] = i; + } + } + return SPA_RESULT_OK; +} + + +static SpaResult +spa_proxy_node_add_port (SpaNode *node, + SpaDirection direction, + uint32_t port_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_proxy_node_remove_port (SpaNode *node, + uint32_t port_id) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_proxy_node_port_enum_formats (SpaNode *node, + uint32_t port_id, + SpaFormat **format, + const SpaFormat *filter, + void **state) +{ + SpaProxy *this; + SpaProxyPort *port; + int index; + + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (!CHECK_PORT_ID (this, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = &this->ports[port_id]; + + index = (*state == NULL ? 0 : *(int*)state); + + switch (index) { + case 0: + break; + default: + return SPA_RESULT_ENUM_END; + } + *format = &port->formats[0]; + *(int*)state = ++index; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_set_format (SpaNode *node, + uint32_t port_id, + SpaPortFormatFlags flags, + const SpaFormat *format) +{ + SpaProxy *this; + SpaProxyPort *port; + SpaControl control; + SpaControlBuilder builder; + SpaControlCmdSetFormat sf; + uint8_t buf[128]; + SpaResult res; + + if (node == NULL || node->handle == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (!CHECK_PORT_ID (this, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = &this->ports[port_id]; + + spa_control_builder_init_into (&builder, buf, sizeof (buf), NULL, 0); + sf.port = port_id; + sf.format = format; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_SET_FORMAT, &sf); + spa_control_builder_end (&builder, &control); + + if ((res = spa_control_write (&control, this->fds[0].fd)) < 0) + fprintf (stderr, "proxy %p: error writing control", this); + + port->have_format = format != NULL; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_get_format (SpaNode *node, + uint32_t port_id, + const SpaFormat **format) +{ + SpaProxy *this; + SpaProxyPort *port; + + if (node == NULL || node->handle == NULL || format == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (!CHECK_PORT_ID (this, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = &this->ports[port_id]; + + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; + + *format = &port->formats[1]; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_get_info (SpaNode *node, + uint32_t port_id, + const SpaPortInfo **info) +{ + SpaProxy *this; + SpaProxyPort *port; + + if (node == NULL || node->handle == NULL || info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (!CHECK_PORT_ID (this, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = &this->ports[port_id]; + + *info = &port->info; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_get_props (SpaNode *node, + uint32_t port_id, + SpaProps **props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_proxy_node_port_set_props (SpaNode *node, + uint32_t port_id, + const SpaProps *props) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + +static SpaResult +spa_proxy_node_port_get_status (SpaNode *node, + uint32_t port_id, + const SpaPortStatus **status) +{ + SpaProxy *this; + SpaProxyPort *port; + + if (node == NULL || node->handle == NULL || status == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (!CHECK_PORT_ID (this, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = &this->ports[port_id]; + + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; + + *status = &port->status; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_use_buffers (SpaNode *node, + uint32_t port_id, + SpaBuffer **buffers, + uint32_t n_buffers) +{ + SpaProxy *this; + SpaProxyPort *port; + + if (node == NULL || node->handle == NULL || buffers == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (!CHECK_PORT_ID (this, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = &this->ports[port_id]; + + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; + + port->buffers = buffers; + port->n_buffers = n_buffers; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_alloc_buffers (SpaNode *node, + uint32_t port_id, + SpaAllocParam **params, + uint32_t n_params, + SpaBuffer **buffers, + uint32_t *n_buffers) +{ + SpaProxy *this; + SpaProxyPort *port; + + if (node == NULL || node->handle == NULL || buffers == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + if (!CHECK_PORT_ID (this, port_id)) + return SPA_RESULT_INVALID_PORT; + + port = &this->ports[port_id]; + + if (!port->have_format) + return SPA_RESULT_NO_FORMAT; + + return SPA_RESULT_OK; +} + +static int +tmpfile_create (void *data, size_t size) +{ + char filename[] = "/dev/shm/tmpfilepay.XXXXXX"; + int fd; + + fd = mkostemp (filename, O_CLOEXEC); + if (fd == -1) { + fprintf (stderr, "Failed to create temporary file: %s", strerror (errno)); + return -1; + } + unlink (filename); + + if (write (fd, data, size) != (ssize_t) size) + fprintf (stderr, "Failed to write data: %s", strerror (errno)); + + return fd; +} + +typedef struct { + SpaBuffer buffer; + SpaData datas[16]; + int idx[16]; + SpaBuffer *orig; +} MyBuffer; + +static SpaResult +send_buffer (SpaProxy *this, SpaBuffer *buffer) +{ + SpaControl control; + SpaControlBuilder builder; + uint8_t buf[1024]; + int fds[16]; + SpaControlCmdAddBuffer ab; + SpaControlCmdProcessBuffer pb; + SpaControlCmdRemoveBuffer rb; + bool tmpfile = false; + unsigned int i; + MyBuffer b; + SpaResult res; + + spa_control_builder_init_into (&builder, buf, 1024, fds, 16); + + b.buffer.refcount = 1; + b.buffer.notify = NULL; + b.buffer.id = buffer->id; + b.buffer.size = buffer->size; + b.buffer.n_metas = buffer->n_metas; + b.buffer.metas = buffer->metas; + b.buffer.n_datas = buffer->n_datas; + b.buffer.datas = b.datas; + + for (i = 0; i < buffer->n_datas; i++) { + SpaData *d = &buffer->datas[i]; + int fd; + SpaControlCmdAddMem am; + + if (d->type == SPA_DATA_TYPE_FD) { + fd = *((int *)d->ptr); + } else { + fd = tmpfile_create (d->ptr, d->size + d->offset); + tmpfile = true; + } + am.port = 0; + am.id = i; + am.type = 0; + am.fd_index = spa_control_builder_add_fd (&builder, fd, tmpfile ? true : false); + am.offset = 0; + am.size = d->offset + d->size; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_MEM, &am); + + b.idx[i] = i; + b.datas[i].type = SPA_DATA_TYPE_MEMID; + b.datas[i].ptr_type = NULL; + b.datas[i].ptr = &b.idx[i]; + b.datas[i].offset = d->offset; + b.datas[i].size = d->size; + b.datas[i].stride = d->stride; + } + ab.port = 0; + ab.buffer = &b.buffer; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_ADD_BUFFER, &ab); + pb.port = 0; + pb.id = b.buffer.id; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_PROCESS_BUFFER, &pb); + rb.port = 0; + rb.id = b.buffer.id; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_REMOVE_BUFFER, &rb); + + for (i = 0; i < buffer->n_datas; i++) { + SpaControlCmdRemoveMem rm; + rm.port = 0; + rm.id = i; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_REMOVE_MEM, &rm); + } + spa_control_builder_end (&builder, &control); + + if ((res = spa_control_write (&control, this->fds[0].fd)) < 0) + fprintf (stderr, "proxy %p: error writing control", this); + + spa_control_clear (&control); + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_push_input (SpaNode *node, + unsigned int n_info, + SpaInputInfo *info) +{ + SpaProxy *this; + SpaProxyPort *port; + unsigned int i; + bool have_error = false; + bool have_enough = false; + + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + for (i = 0; i < n_info; i++) { + if (!CHECK_PORT_ID_DIR (this, info[i].port_id, SPA_DIRECTION_INPUT)) { + info[i].status = SPA_RESULT_INVALID_PORT; + have_error = true; + continue; + } + port = &this->ports[info[i].port_id]; + + if (!port->have_format) { + info[i].status = SPA_RESULT_NO_FORMAT; + have_error = true; + continue; + } + + info[i].status = SPA_RESULT_OK; + } + if (have_error) + return SPA_RESULT_ERROR; + if (have_enough) + return SPA_RESULT_HAVE_ENOUGH_INPUT; + + return SPA_RESULT_OK; +} + +static SpaResult +spa_proxy_node_port_pull_output (SpaNode *node, + unsigned int n_info, + SpaOutputInfo *info) +{ + SpaProxy *this; + SpaProxyPort *port; + unsigned int i; + bool have_error = false; + bool need_more = false; + + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaProxy *) node->handle; + + for (i = 0; i < n_info; i++) { + if (!CHECK_PORT_ID_DIR (this, info[i].port_id, SPA_DIRECTION_OUTPUT)) { + info[i].status = SPA_RESULT_INVALID_PORT; + have_error = true; + continue; + } + + port = &this->ports[info[i].port_id]; + + if (!port->have_format) { + info[i].status = SPA_RESULT_NO_FORMAT; + have_error = true; + continue; + } + } + if (have_error) + return SPA_RESULT_ERROR; + if (need_more) + return SPA_RESULT_NEED_MORE_INPUT; + + return SPA_RESULT_OK; +} + +static SpaResult +parse_control (SpaProxy *this, + SpaControl *ctrl) +{ + SpaControlIter it; + SpaResult res; + + spa_control_iter_init (&it, ctrl); + while (spa_control_iter_next (&it) == SPA_RESULT_OK) { + SpaControlCmd cmd = spa_control_iter_get_cmd (&it); + + switch (cmd) { + case SPA_CONTROL_CMD_ADD_PORT: + case SPA_CONTROL_CMD_REMOVE_PORT: + case SPA_CONTROL_CMD_SET_FORMAT: + case SPA_CONTROL_CMD_SET_PROPERTY: + case SPA_CONTROL_CMD_END_CONFIGURE: + case SPA_CONTROL_CMD_PAUSE: + case SPA_CONTROL_CMD_START: + case SPA_CONTROL_CMD_STOP: + fprintf (stderr, "proxy %p: got unexpected control %d", this, cmd); + break; + + case SPA_CONTROL_CMD_NODE_UPDATE: + case SPA_CONTROL_CMD_PORT_UPDATE: + case SPA_CONTROL_CMD_PORT_REMOVED: + fprintf (stderr, "proxy %p: command not implemented %d", this, cmd); + break; + + case SPA_CONTROL_CMD_START_CONFIGURE: + { + SpaControlBuilder builder; + SpaControl control; + uint8_t buf[128]; + + /* set port format */ + + /* send end-configure */ + spa_control_builder_init_into (&builder, buf, sizeof (buf), NULL, 0); + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_END_CONFIGURE, NULL); + spa_control_builder_end (&builder, &control); + + if ((res = spa_control_write (&control, this->fds[0].fd)) < 0) + fprintf (stderr, "proxy %p: error writing control: %d", this, res); + break; + } + case SPA_CONTROL_CMD_PORT_STATUS_CHANGE: + { + fprintf (stderr, "proxy %p: command not implemented %d", this, cmd); + break; + } + case SPA_CONTROL_CMD_START_ALLOC: + { + SpaControlBuilder builder; + SpaControl control; + uint8_t buf[128]; + + /* FIXME read port memory requirements */ + /* FIXME add_mem */ + + /* send start */ + spa_control_builder_init_into (&builder, buf, sizeof (buf), NULL, 0); + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_START, NULL); + spa_control_builder_end (&builder, &control); + + if ((res = spa_control_write (&control, this->fds[0].fd)) < 0) + fprintf (stderr, "proxy %p: error writing control %d", this, res); + break; + } + case SPA_CONTROL_CMD_NEED_INPUT: + { + break; + } + case SPA_CONTROL_CMD_HAVE_OUTPUT: + { + break; + } + + case SPA_CONTROL_CMD_ADD_MEM: + break; + case SPA_CONTROL_CMD_REMOVE_MEM: + break; + case SPA_CONTROL_CMD_ADD_BUFFER: + break; + case SPA_CONTROL_CMD_REMOVE_BUFFER: + break; + + case SPA_CONTROL_CMD_PROCESS_BUFFER: + { + break; + } + case SPA_CONTROL_CMD_REUSE_BUFFER: + { + break; + } + default: + fprintf (stderr, "proxy %p: command unhandled %d", this, cmd); + break; + } + } + spa_control_iter_end (&it); + + return SPA_RESULT_OK; +} + +static int +proxy_on_fd_events (SpaPollNotifyData *data) +{ + SpaProxy *this = data->user_data; + SpaResult res; + + if (data->fds[0].revents & POLLIN) { + SpaControl control; + uint8_t buf[1024]; + int fds[16]; + + if ((res = spa_control_read (&control, data->fds[0].fd, buf, 1024, fds, 16)) < 0) { + fprintf (stderr, "proxy %p: failed to read control: %d", this, res); + return 0; + } + parse_control (this, &control); + spa_control_clear (&control); + } + return 0; +} + +static const SpaNode proxy_node = { + NULL, + sizeof (SpaNode), + spa_proxy_node_get_props, + spa_proxy_node_set_props, + spa_proxy_node_send_command, + spa_proxy_node_set_event_callback, + spa_proxy_node_get_n_ports, + spa_proxy_node_get_port_ids, + spa_proxy_node_add_port, + spa_proxy_node_remove_port, + spa_proxy_node_port_enum_formats, + spa_proxy_node_port_set_format, + spa_proxy_node_port_get_format, + spa_proxy_node_port_get_info, + spa_proxy_node_port_get_props, + spa_proxy_node_port_set_props, + spa_proxy_node_port_use_buffers, + spa_proxy_node_port_alloc_buffers, + spa_proxy_node_port_get_status, + spa_proxy_node_port_push_input, + spa_proxy_node_port_pull_output, +}; + +static SpaResult +spa_proxy_get_interface (SpaHandle *handle, + uint32_t interface_id, + void **interface) +{ + SpaProxy *this = (SpaProxy *) handle; + + if (handle == NULL || interface == 0) + return SPA_RESULT_INVALID_ARGUMENTS; + + switch (interface_id) { + case SPA_INTERFACE_ID_NODE: + *interface = &this->node; + break; + default: + return SPA_RESULT_UNKNOWN_INTERFACE; + + } + return SPA_RESULT_OK; +} + +static SpaResult +proxy_instantiate (const SpaHandleFactory *factory, + SpaHandle *handle) +{ + SpaProxy *this; + + if (factory == NULL || handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + handle->get_interface = spa_proxy_get_interface; + + this = (SpaProxy *) handle; + this->node = proxy_node; + this->node.handle = handle; + this->props[1].props.n_prop_info = PROP_ID_LAST; + this->props[1].props.prop_info = prop_info; + this->props[1].props.set_prop = spa_props_generic_set_prop; + this->props[1].props.get_prop = spa_props_generic_get_prop; + reset_proxy_props (&this->props[1]); + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); + + this->fds[0].fd = -1; + this->fds[0].events = POLLIN | POLLPRI | POLLERR; + this->fds[0].revents = 0; + this->poll.id = 0; + this->poll.fds = this->fds; + this->poll.n_fds = 1; + this->poll.idle_cb = NULL; + this->poll.before_cb = NULL; + this->poll.after_cb = proxy_on_fd_events; + this->poll.user_data = this; + + return SPA_RESULT_OK; +} + +static const SpaInterfaceInfo proxy_interfaces[] = +{ + { SPA_INTERFACE_ID_NODE, + SPA_INTERFACE_ID_NODE_NAME, + SPA_INTERFACE_ID_NODE_DESCRIPTION, + }, +}; + +static SpaResult +proxy_enum_interface_info (const SpaHandleFactory *factory, + const SpaInterfaceInfo **info, + void **state) +{ + int index; + + if (factory == NULL || info == NULL || state == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + index = (*state == NULL ? 0 : *(int*)state); + + switch (index) { + case 0: + *info = &proxy_interfaces[index]; + break; + default: + return SPA_RESULT_ENUM_END; + } + *(int*)state = ++index; + + return SPA_RESULT_OK; +} + +const SpaHandleFactory spa_proxy_factory = +{ "proxy", + NULL, + sizeof (SpaProxy), + proxy_instantiate, + proxy_enum_interface_info, +}; diff --git a/spa/plugins/v4l2/v4l2-source.c b/spa/plugins/v4l2/v4l2-source.c index 312f9e31..1b5293f6 100644 --- a/spa/plugins/v4l2/v4l2-source.c +++ b/spa/plugins/v4l2/v4l2-source.c @@ -117,6 +117,7 @@ typedef struct { struct _SpaV4l2Source { SpaHandle handle; + SpaNode node; SpaV4l2SourceProps props[2]; @@ -167,14 +168,16 @@ static const SpaPropInfo prop_info[] = }; static SpaResult -spa_v4l2_source_node_get_props (SpaHandle *handle, +spa_v4l2_source_node_get_props (SpaNode *node, SpaProps **props) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -182,16 +185,19 @@ spa_v4l2_source_node_get_props (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_set_props (SpaHandle *handle, +spa_v4l2_source_node_set_props (SpaNode *node, const SpaProps *props) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; - SpaV4l2SourceProps *p = &this->props[1]; + SpaV4l2Source *this; + SpaV4l2SourceProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_v4l2_source_props (p); return SPA_RESULT_OK; @@ -203,14 +209,16 @@ spa_v4l2_source_node_set_props (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_send_command (SpaHandle *handle, +spa_v4l2_source_node_send_command (SpaNode *node, SpaCommand *command) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -228,7 +236,7 @@ spa_v4l2_source_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; case SPA_COMMAND_STOP: @@ -244,7 +252,7 @@ spa_v4l2_source_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -257,15 +265,17 @@ spa_v4l2_source_node_send_command (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_set_event_callback (SpaHandle *handle, +spa_v4l2_source_node_set_event_callback (SpaNode *node, SpaEventCallback event, void *user_data) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -273,13 +283,13 @@ spa_v4l2_source_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_get_n_ports (SpaHandle *handle, +spa_v4l2_source_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -295,13 +305,13 @@ spa_v4l2_source_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_get_port_ids (SpaHandle *handle, +spa_v4l2_source_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_output_ports > 0) @@ -312,15 +322,15 @@ spa_v4l2_source_node_get_port_ids (SpaHandle *handle, static SpaResult -spa_v4l2_source_node_add_port (SpaHandle *handle, +spa_v4l2_source_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_v4l2_source_node_remove_port (SpaHandle *handle, +spa_v4l2_source_node_remove_port (SpaNode *node, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; @@ -354,18 +364,20 @@ spa_v4l2_format_init (V4l2Format *f) } static SpaResult -spa_v4l2_source_node_port_enum_formats (SpaHandle *handle, +spa_v4l2_source_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; SpaResult res; - if (handle == NULL || format == NULL || state == NULL) + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -375,20 +387,22 @@ spa_v4l2_source_node_port_enum_formats (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_set_format (SpaHandle *handle, +spa_v4l2_source_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; SpaV4l2State *state; SpaResult res; V4l2Format *f, *tf; size_t fs; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -421,16 +435,18 @@ spa_v4l2_source_node_port_set_format (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_get_format (SpaHandle *handle, +spa_v4l2_source_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; SpaV4l2State *state; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -445,15 +461,17 @@ spa_v4l2_source_node_port_get_format (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_get_info (SpaHandle *handle, +spa_v4l2_source_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -463,7 +481,7 @@ spa_v4l2_source_node_port_get_info (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_get_props (SpaHandle *handle, +spa_v4l2_source_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -471,7 +489,7 @@ spa_v4l2_source_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_set_props (SpaHandle *handle, +spa_v4l2_source_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -479,15 +497,17 @@ spa_v4l2_source_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_get_status (SpaHandle *handle, +spa_v4l2_source_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -497,16 +517,18 @@ spa_v4l2_source_node_port_get_status (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_use_buffers (SpaHandle *handle, +spa_v4l2_source_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -516,19 +538,31 @@ spa_v4l2_source_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_alloc_buffers (SpaHandle *handle, +spa_v4l2_source_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, - uint32_t n_params, + unsigned int n_params, SpaBuffer **buffers, - uint32_t *n_buffers) + unsigned int *n_buffers) { - return SPA_RESULT_NOT_IMPLEMENTED; + SpaV4l2Source *this; + + if (node == NULL || node->handle == NULL) + return SPA_RESULT_INVALID_ARGUMENTS; + + this = (SpaV4l2Source *) node->handle; + + if (port_id != 0) + return SPA_RESULT_INVALID_PORT; + + spa_v4l2_alloc_buffers (this, params, n_params, buffers, n_buffers); + + return SPA_RESULT_OK; } static SpaResult -spa_v4l2_source_node_port_push_input (SpaHandle *handle, +spa_v4l2_source_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { @@ -536,18 +570,20 @@ spa_v4l2_source_node_port_push_input (SpaHandle *handle, } static SpaResult -spa_v4l2_source_node_port_pull_output (SpaHandle *handle, +spa_v4l2_source_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { - SpaV4l2Source *this = (SpaV4l2Source *) handle; + SpaV4l2Source *this; SpaV4l2State *state; unsigned int i; bool have_error = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) node->handle; + for (i = 0; i < n_info; i++) { V4l2Buffer *b; @@ -576,7 +612,7 @@ spa_v4l2_source_node_port_pull_output (SpaHandle *handle, b->outstanding = true; - info[i].buffer = &b->buffer; + info[i].id = b->buffer.id; info[i].status = SPA_RESULT_OK; } if (have_error) @@ -585,7 +621,17 @@ spa_v4l2_source_node_port_pull_output (SpaHandle *handle, return SPA_RESULT_OK; } +static SpaResult +spa_v4l2_source_node_port_push_event (SpaNode *node, + uint32_t port_id, + SpaEvent *event) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + + static const SpaNode v4l2source_node = { + NULL, sizeof (SpaNode), spa_v4l2_source_node_get_props, spa_v4l2_source_node_set_props, @@ -606,19 +652,24 @@ static const SpaNode v4l2source_node = { spa_v4l2_source_node_port_get_status, spa_v4l2_source_node_port_push_input, spa_v4l2_source_node_port_pull_output, + spa_v4l2_source_node_port_push_event, }; static SpaResult spa_v4l2_source_get_interface (SpaHandle *handle, uint32_t interface_id, - const void **interface) + void **interface) { + SpaV4l2Source *this; + if (handle == NULL || interface == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaV4l2Source *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &v4l2source_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -638,6 +689,8 @@ v4l2_source_init (const SpaHandleFactory *factory, handle->get_interface = spa_v4l2_source_get_interface; this = (SpaV4l2Source *) handle; + this->node = v4l2source_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index 5eb7ede4..290170f5 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -481,19 +481,20 @@ v4l2_on_fd_events (SpaPollNotifyData *data) event.port_id = 0; event.size = 0; event.data = NULL; - this->event_cb (&this->handle, &event, this->user_data); + this->event_cb (&this->node, &event, this->user_data); return 0; } static void -v4l2_buffer_free (void *data) +v4l2_buffer_recycle (void *data) { - V4l2Buffer *b = (V4l2Buffer *) data; - SpaV4l2Source *this = b->source; + SpaBuffer *buf = data; + SpaV4l2Source *this = buf->user_data; SpaV4l2State *state = &this->state[0]; + V4l2Buffer *b = &state->buffers[buf->id]; - b->buffer.refcount = 1; + b->imported->refcount = 1; b->outstanding = false; if (xioctl (state->fd, VIDIOC_QBUF, &b->v4l2_buffer) < 0) { @@ -531,10 +532,15 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu b = &state->buffers[i]; + buffers[i]->notify = v4l2_buffer_recycle; + buffers[i]->user_data = this; + + fprintf (stderr, "import buffer %p\n", buffers[i]); + b->source = this; b->buffer.refcount = 0; - b->buffer.notify = v4l2_buffer_free; - b->buffer.id = i; + b->buffer.notify = v4l2_buffer_recycle; + b->buffer.id = buffers[i]->id; b->buffer.size = buffers[i]->size; b->buffer.n_metas = buffers[i]->n_metas; b->buffer.metas = buffers[i]->metas; @@ -550,7 +556,7 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu b->v4l2_buffer.m.userptr = (unsigned long) b->buffer.datas[0].ptr; b->v4l2_buffer.length = b->buffer.datas[0].size; - v4l2_buffer_free (b); + v4l2_buffer_recycle (buffers[i]); } state->have_buffers = true; @@ -558,7 +564,11 @@ spa_v4l2_import_buffers (SpaV4l2Source *this, SpaBuffer **buffers, uint32_t n_bu } static int -mmap_init (SpaV4l2Source *this) +mmap_init (SpaV4l2Source *this, + SpaAllocParam **params, + unsigned int n_params, + SpaBuffer **buffers, + unsigned int *n_buffers) { SpaV4l2State *state = &this->state[0]; struct v4l2_requestbuffers reqbuf; @@ -569,7 +579,7 @@ mmap_init (SpaV4l2Source *this) CLEAR(reqbuf); reqbuf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; reqbuf.memory = state->memtype; - reqbuf.count = MAX_BUFFERS; + reqbuf.count = *n_buffers; if (xioctl (state->fd, VIDIOC_REQBUFS, &reqbuf) < 0) { perror ("VIDIOC_REQBUFS"); @@ -577,6 +587,8 @@ mmap_init (SpaV4l2Source *this) } fprintf (stderr, "got %d buffers\n", reqbuf.count); + *n_buffers = reqbuf.count; + if (reqbuf.count < 2) { fprintf (stderr, "can't allocate enough buffers\n"); return -1; @@ -601,9 +613,13 @@ mmap_init (SpaV4l2Source *this) } b = &state->buffers[i]; + + buffers[i] = &b->buffer; + b->source = this; b->buffer.refcount = 0; - b->buffer.notify = v4l2_buffer_free; + b->buffer.notify = v4l2_buffer_recycle; + b->buffer.user_data = this; b->buffer.id = i; b->buffer.size = buf.length; b->buffer.n_metas = 1; @@ -655,6 +671,7 @@ mmap_init (SpaV4l2Source *this) continue; } } + b->imported = &b->buffer; b->outstanding = true; CLEAR (b->v4l2_buffer); @@ -662,7 +679,7 @@ mmap_init (SpaV4l2Source *this) b->v4l2_buffer.memory = state->memtype; b->v4l2_buffer.index = i; - v4l2_buffer_free (b); + v4l2_buffer_recycle (b); } state->have_buffers = true; @@ -682,6 +699,27 @@ read_init (SpaV4l2Source *this) } static int +spa_v4l2_alloc_buffers (SpaV4l2Source *this, + SpaAllocParam **params, + unsigned int n_params, + SpaBuffer **buffers, + unsigned int *n_buffers) +{ + SpaV4l2State *state = &this->state[0]; + + if (state->cap.capabilities & V4L2_CAP_STREAMING) { + if (mmap_init (this, params, n_params, buffers, n_buffers) < 0) + if (userptr_init (this) < 0) + return -1; + } else if (state->cap.capabilities & V4L2_CAP_READWRITE) { + if (read_init (this) < 0) + return -1; + } else + return -1; + return 0; +} + +static int spa_v4l2_start (SpaV4l2Source *this) { SpaV4l2State *state = &this->state[0]; @@ -691,17 +729,9 @@ spa_v4l2_start (SpaV4l2Source *this) if (spa_v4l2_open (this) < 0) return -1; - if (!state->have_buffers) { - if (state->cap.capabilities & V4L2_CAP_STREAMING) { - if (mmap_init (this) < 0) - if (userptr_init (this) < 0) - return -1; - } else if (state->cap.capabilities & V4L2_CAP_READWRITE) { - if (read_init (this) < 0) - return -1; - } else - return -1; - } + if (!state->have_buffers) + return -1; + event.refcount = 1; event.notify = NULL; @@ -714,13 +744,14 @@ spa_v4l2_start (SpaV4l2Source *this) state->fds[0].events = POLLIN | POLLPRI | POLLERR; state->fds[0].revents = 0; + state->poll.id = 0; state->poll.fds = state->fds; state->poll.n_fds = 1; state->poll.idle_cb = NULL; state->poll.before_cb = NULL; state->poll.after_cb = v4l2_on_fd_events; state->poll.user_data = this; - this->event_cb (&this->handle, &event, this->user_data); + this->event_cb (&this->node, &event, this->user_data); type = V4L2_BUF_TYPE_VIDEO_CAPTURE; if (xioctl (state->fd, VIDIOC_STREAMON, &type) < 0) { @@ -750,7 +781,7 @@ spa_v4l2_stop (SpaV4l2Source *this) b = &state->buffers[i]; if (b->outstanding) { fprintf (stderr, "queueing outstanding buffer %p\n", b); - v4l2_buffer_free (b); + v4l2_buffer_recycle (b); } if (state->export_buf) { close (b->dmafd); @@ -766,7 +797,7 @@ spa_v4l2_stop (SpaV4l2Source *this) event.port_id = 0; event.data = &state->poll; event.size = sizeof (state->poll); - this->event_cb (&this->handle, &event, this->user_data); + this->event_cb (&this->node, &event, this->user_data); spa_v4l2_close (this); diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 9c501c09..e5afc217 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -35,10 +35,14 @@ typedef struct { bool have_format; SpaPortInfo info; SpaPortStatus status; + SpaBuffer **buffers; + unsigned int n_buffers; + SpaBuffer *buffer; } SpaVolumePort; struct _SpaVolume { SpaHandle handle; + SpaNode node; SpaVolumeProps props[2]; @@ -50,7 +54,6 @@ struct _SpaVolume { SpaAudioRawFormat current_format; SpaVolumePort ports[2]; - SpaBuffer *input_buffer; }; static const double default_volume = 1.0; @@ -99,14 +102,16 @@ reset_volume_props (SpaVolumeProps *props) } static SpaResult -spa_volume_node_get_props (SpaHandle *handle, +spa_volume_node_get_props (SpaNode *node, SpaProps **props) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -114,16 +119,19 @@ spa_volume_node_get_props (SpaHandle *handle, } static SpaResult -spa_volume_node_set_props (SpaHandle *handle, +spa_volume_node_set_props (SpaNode *node, const SpaProps *props) { - SpaVolume *this = (SpaVolume *) handle; - SpaVolumeProps *p = &this->props[1]; + SpaVolume *this; + SpaVolumeProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_volume_props (p); return SPA_RESULT_OK; @@ -134,14 +142,16 @@ spa_volume_node_set_props (SpaHandle *handle, } static SpaResult -spa_volume_node_send_command (SpaHandle *handle, +spa_volume_node_send_command (SpaNode *node, SpaCommand *command) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -157,7 +167,7 @@ spa_volume_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -172,7 +182,7 @@ spa_volume_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -185,15 +195,17 @@ spa_volume_node_send_command (SpaHandle *handle, } static SpaResult -spa_volume_node_set_event_callback (SpaHandle *handle, +spa_volume_node_set_event_callback (SpaNode *node, SpaEventCallback event, void *user_data) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -201,13 +213,13 @@ spa_volume_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_volume_node_get_n_ports (SpaHandle *handle, +spa_volume_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -223,13 +235,13 @@ spa_volume_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_volume_node_get_port_ids (SpaHandle *handle, +spa_volume_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports > 0 && input_ids) @@ -242,33 +254,35 @@ spa_volume_node_get_port_ids (SpaHandle *handle, static SpaResult -spa_volume_node_add_port (SpaHandle *handle, +spa_volume_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_volume_node_remove_port (SpaHandle *handle, +spa_volume_node_remove_port (SpaNode *node, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_volume_node_port_enum_formats (SpaHandle *handle, +spa_volume_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; int index; - if (handle == NULL || format == NULL || state == NULL) + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -288,47 +302,57 @@ spa_volume_node_port_enum_formats (SpaHandle *handle, } static SpaResult -spa_volume_node_port_set_format (SpaHandle *handle, +spa_volume_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; + SpaVolumePort *port; SpaResult res; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + if (port_id >= 2) return SPA_RESULT_INVALID_PORT; + port = &this->ports[port_id]; + if (format == NULL) { - this->ports[port_id].have_format = false; + port->have_format = false; return SPA_RESULT_OK; } if ((res = spa_audio_raw_format_parse (format, &this->current_format)) < 0) return res; - this->ports[port_id].have_format = true; + port->have_format = true; return SPA_RESULT_OK; } static SpaResult -spa_volume_node_port_get_format (SpaHandle *handle, +spa_volume_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; + SpaVolumePort *port; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + if (port_id >= 2) return SPA_RESULT_INVALID_PORT; - if (!this->ports[port_id].have_format) + port = &this->ports[port_id]; + + if (!port->have_format) return SPA_RESULT_NO_FORMAT; *format = &this->current_format.format; @@ -337,25 +361,29 @@ spa_volume_node_port_get_format (SpaHandle *handle, } static SpaResult -spa_volume_node_port_get_info (SpaHandle *handle, +spa_volume_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; + SpaVolumePort *port; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + if (port_id >= 2) return SPA_RESULT_INVALID_PORT; - *info = &this->ports[port_id].info; + port = &this->ports[port_id]; + *info = &port->info; return SPA_RESULT_OK; } static SpaResult -spa_volume_node_port_get_props (SpaHandle *handle, +spa_volume_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -363,7 +391,7 @@ spa_volume_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_volume_node_port_set_props (SpaHandle *handle, +spa_volume_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -371,28 +399,33 @@ spa_volume_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_volume_node_port_get_status (SpaHandle *handle, +spa_volume_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; + SpaVolumePort *port; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + if (port_id >= 2) return SPA_RESULT_INVALID_PORT; - if (!this->ports[port_id].have_format) + port = &this->ports[port_id]; + + if (!port->have_format) return SPA_RESULT_NO_FORMAT; - *status = &this->ports[port_id].status; + *status = &port->status; return SPA_RESULT_OK; } static SpaResult -spa_volume_node_port_use_buffers (SpaHandle *handle, +spa_volume_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) @@ -401,7 +434,7 @@ spa_volume_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_volume_node_port_alloc_buffers (SpaHandle *handle, +spa_volume_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -413,59 +446,56 @@ spa_volume_node_port_alloc_buffers (SpaHandle *handle, static SpaResult -spa_volume_node_port_push_input (SpaHandle *handle, +spa_volume_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { - SpaVolume *this = (SpaVolume *) handle; - SpaBuffer *buffer; - SpaEvent *event; + SpaVolume *this; unsigned int i; bool have_error = false; bool have_enough = false; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + for (i = 0; i < n_info; i++) { + SpaVolumePort *port; + SpaBuffer *buffer; + if (info[i].port_id != 0) { info[i].status = SPA_RESULT_INVALID_PORT; have_error = true; continue; } - event = info[i].event; - buffer = info[i].buffer; + port = &this->ports[info[i].port_id]; + buffer = port->buffers[info[i].id]; - if (buffer == NULL && event == NULL) { + if (buffer == NULL) { info[i].status = SPA_RESULT_INVALID_ARGUMENTS; have_error = true; continue; } if (buffer) { - if (!this->ports[0].have_format) { + if (!port->have_format) { info[i].status = SPA_RESULT_NO_FORMAT; have_error = true; continue; } - if (this->input_buffer != NULL) { + if (port->buffer != NULL) { info[i].status = SPA_RESULT_HAVE_ENOUGH_INPUT; have_enough = true; continue; } - this->input_buffer = spa_buffer_ref (buffer); + port->buffer = spa_buffer_ref (buffer); this->ports[0].status.flags &= ~SPA_PORT_STATUS_FLAG_NEED_INPUT; this->ports[1].status.flags |= SPA_PORT_STATUS_FLAG_HAVE_OUTPUT; } - if (event) { - switch (event->type) { - default: - break; - } - } info[i].status = SPA_RESULT_OK; } if (have_error) @@ -476,36 +506,44 @@ spa_volume_node_port_push_input (SpaHandle *handle, return SPA_RESULT_OK; } -#define MIN(a,b) ((a) < (b) ? (a) : (b)) +static SpaBuffer * +find_free_buffer (SpaVolume *this, SpaVolumePort *port) +{ + return NULL; +} static SpaResult -spa_volume_node_port_pull_output (SpaHandle *handle, +spa_volume_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { - SpaVolume *this = (SpaVolume *) handle; + SpaVolume *this; + SpaVolumePort *port; unsigned int si, di, i, n_samples, n_bytes, soff, doff ; SpaBuffer *sbuf, *dbuf; SpaData *sd, *dd; uint16_t *src, *dst; double volume; - if (handle == NULL || n_info == 0 || info == NULL) + if (node == NULL || node->handle == NULL || n_info == 0 || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) node->handle; + if (info->port_id != 1) return SPA_RESULT_INVALID_PORT; - if (!this->ports[1].have_format) + port = &this->ports[info[0].port_id]; + if (!port->have_format) return SPA_RESULT_NO_FORMAT; - if (this->input_buffer == NULL) + if (this->ports[0].buffer == NULL) return SPA_RESULT_NEED_MORE_INPUT; volume = this->props[1].volume; - sbuf = this->input_buffer; - dbuf = info->buffer ? info->buffer : this->input_buffer; + sbuf = this->ports[0].buffer; + dbuf = find_free_buffer (this, port); si = di = 0; soff = doff = 0; @@ -528,7 +566,7 @@ spa_volume_node_port_pull_output (SpaHandle *handle, src = (uint16_t*) ((uint8_t*)sd->ptr + soff); dst = (uint16_t*) ((uint8_t*)dd->ptr + doff); - n_bytes = MIN (sd->size - soff, dd->size - doff); + n_bytes = SPA_MIN (sd->size - soff, dd->size - doff); n_samples = n_bytes / sizeof (uint16_t); for (i = 0; i < n_samples; i++) @@ -550,8 +588,8 @@ spa_volume_node_port_pull_output (SpaHandle *handle, if (sbuf != dbuf) spa_buffer_unref (sbuf); - this->input_buffer = NULL; - info->buffer = dbuf; + this->ports[0].buffer = NULL; + info->id = dbuf->id; this->ports[0].status.flags |= SPA_PORT_STATUS_FLAG_NEED_INPUT; this->ports[1].status.flags &= ~SPA_PORT_STATUS_FLAG_HAVE_OUTPUT; @@ -559,7 +597,16 @@ spa_volume_node_port_pull_output (SpaHandle *handle, return SPA_RESULT_OK; } +static SpaResult +spa_volume_node_port_push_event (SpaNode *node, + uint32_t port_id, + SpaEvent *event) +{ + return SPA_RESULT_NOT_IMPLEMENTED; +} + static const SpaNode volume_node = { + NULL, sizeof (SpaNode), spa_volume_node_get_props, spa_volume_node_set_props, @@ -580,19 +627,24 @@ static const SpaNode volume_node = { spa_volume_node_port_get_status, spa_volume_node_port_push_input, spa_volume_node_port_pull_output, + spa_volume_node_port_push_event, }; static SpaResult spa_volume_get_interface (SpaHandle *handle, uint32_t interface_id, - const void **interface) + void **interface) { + SpaVolume *this; + if (handle == NULL || interface == 0) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaVolume *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &volume_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -613,6 +665,8 @@ volume_instantiate (const SpaHandleFactory *factory, handle->get_interface = spa_volume_get_interface; this = (SpaVolume *) handle; + this->node = volume_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/plugins/xv/xv-sink.c b/spa/plugins/xv/xv-sink.c index b8a5dd55..75350a0c 100644 --- a/spa/plugins/xv/xv-sink.c +++ b/spa/plugins/xv/xv-sink.c @@ -69,6 +69,7 @@ typedef struct { struct _SpaXvSink { SpaHandle handle; + SpaNode node; SpaXvSinkProps props[2]; @@ -126,14 +127,16 @@ static const SpaPropInfo prop_info[] = }; static SpaResult -spa_xv_sink_node_get_props (SpaHandle *handle, +spa_xv_sink_node_get_props (SpaNode *node, SpaProps **props) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; - if (handle == NULL || props == NULL) + if (node == NULL || node->handle == NULL || props == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + memcpy (&this->props[0], &this->props[1], sizeof (this->props[1])); *props = &this->props[0].props; @@ -141,16 +144,19 @@ spa_xv_sink_node_get_props (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_set_props (SpaHandle *handle, +spa_xv_sink_node_set_props (SpaNode *node, const SpaProps *props) { - SpaXvSink *this = (SpaXvSink *) handle; - SpaXvSinkProps *p = &this->props[1]; + SpaXvSink *this; + SpaXvSinkProps *p; SpaResult res; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + p = &this->props[1]; + if (props == NULL) { reset_xv_sink_props (p); return SPA_RESULT_OK; @@ -162,14 +168,16 @@ spa_xv_sink_node_set_props (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_send_command (SpaHandle *handle, - SpaCommand *command) +spa_xv_sink_node_send_command (SpaNode *node, + SpaCommand *command) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; - if (handle == NULL || command == NULL) + if (node == NULL || node->handle == NULL || command == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + switch (command->type) { case SPA_COMMAND_INVALID: return SPA_RESULT_INVALID_COMMAND; @@ -187,7 +195,7 @@ spa_xv_sink_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; case SPA_COMMAND_STOP: @@ -203,7 +211,7 @@ spa_xv_sink_node_send_command (SpaHandle *handle, event.data = NULL; event.size = 0; - this->event_cb (handle, &event, this->user_data); + this->event_cb (node, &event, this->user_data); } break; @@ -216,15 +224,17 @@ spa_xv_sink_node_send_command (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_set_event_callback (SpaHandle *handle, +spa_xv_sink_node_set_event_callback (SpaNode *node, SpaEventCallback event, void *user_data) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + this->event_cb = event; this->user_data = user_data; @@ -232,13 +242,13 @@ spa_xv_sink_node_set_event_callback (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_get_n_ports (SpaHandle *handle, +spa_xv_sink_node_get_n_ports (SpaNode *node, unsigned int *n_input_ports, unsigned int *max_input_ports, unsigned int *n_output_ports, unsigned int *max_output_ports) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_input_ports) @@ -254,13 +264,13 @@ spa_xv_sink_node_get_n_ports (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_get_port_ids (SpaHandle *handle, +spa_xv_sink_node_get_port_ids (SpaNode *node, unsigned int n_input_ports, uint32_t *input_ids, unsigned int n_output_ports, uint32_t *output_ids) { - if (handle == NULL) + if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; if (n_output_ports > 0) @@ -271,33 +281,35 @@ spa_xv_sink_node_get_port_ids (SpaHandle *handle, static SpaResult -spa_xv_sink_node_add_port (SpaHandle *handle, +spa_xv_sink_node_add_port (SpaNode *node, SpaDirection direction, - uint32_t *port_id) + uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_xv_sink_node_remove_port (SpaHandle *handle, +spa_xv_sink_node_remove_port (SpaNode *node, uint32_t port_id) { return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_xv_sink_node_port_enum_formats (SpaHandle *handle, +spa_xv_sink_node_port_enum_formats (SpaNode *node, uint32_t port_id, SpaFormat **format, const SpaFormat *filter, void **state) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; int index; - if (handle == NULL || format == NULL || state == NULL) + if (node == NULL || node->handle == NULL || format == NULL || state == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -317,19 +329,21 @@ spa_xv_sink_node_port_enum_formats (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_set_format (SpaHandle *handle, +spa_xv_sink_node_port_set_format (SpaNode *node, uint32_t port_id, SpaPortFormatFlags flags, const SpaFormat *format) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; SpaResult res; SpaFormat *f, *tf; size_t fs; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -363,15 +377,17 @@ spa_xv_sink_node_port_set_format (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_get_format (SpaHandle *handle, +spa_xv_sink_node_port_get_format (SpaNode *node, uint32_t port_id, const SpaFormat **format) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; - if (handle == NULL || format == NULL) + if (node == NULL || node->handle == NULL || format == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -384,15 +400,17 @@ spa_xv_sink_node_port_get_format (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_get_info (SpaHandle *handle, +spa_xv_sink_node_port_get_info (SpaNode *node, uint32_t port_id, const SpaPortInfo **info) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; - if (handle == NULL || info == NULL) + if (node == NULL || node->handle == NULL || info == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -402,7 +420,7 @@ spa_xv_sink_node_port_get_info (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_get_props (SpaHandle *handle, +spa_xv_sink_node_port_get_props (SpaNode *node, uint32_t port_id, SpaProps **props) { @@ -410,7 +428,7 @@ spa_xv_sink_node_port_get_props (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_set_props (SpaHandle *handle, +spa_xv_sink_node_port_set_props (SpaNode *node, uint32_t port_id, const SpaProps *props) { @@ -418,15 +436,17 @@ spa_xv_sink_node_port_set_props (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_get_status (SpaHandle *handle, +spa_xv_sink_node_port_get_status (SpaNode *node, uint32_t port_id, const SpaPortStatus **status) { - SpaXvSink *this = (SpaXvSink *) handle; + SpaXvSink *this; - if (handle == NULL || status == NULL) + if (node == NULL || node->handle == NULL || status == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) node->handle; + if (port_id != 0) return SPA_RESULT_INVALID_PORT; @@ -436,7 +456,7 @@ spa_xv_sink_node_port_get_status (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_use_buffers (SpaHandle *handle, +spa_xv_sink_node_port_use_buffers (SpaNode *node, uint32_t port_id, SpaBuffer **buffers, uint32_t n_buffers) @@ -445,7 +465,7 @@ spa_xv_sink_node_port_use_buffers (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_alloc_buffers (SpaHandle *handle, +spa_xv_sink_node_port_alloc_buffers (SpaNode *node, uint32_t port_id, SpaAllocParam **params, uint32_t n_params, @@ -456,63 +476,31 @@ spa_xv_sink_node_port_alloc_buffers (SpaHandle *handle, } static SpaResult -spa_xv_sink_node_port_push_input (SpaHandle *handle, +spa_xv_sink_node_port_push_input (SpaNode *node, unsigned int n_info, SpaInputInfo *info) { - return SPA_RESULT_INVALID_PORT; + return SPA_RESULT_NOT_IMPLEMENTED; } static SpaResult -spa_xv_sink_node_port_pull_output (SpaHandle *handle, +spa_xv_sink_node_port_pull_output (SpaNode *node, unsigned int n_info, SpaOutputInfo *info) { - SpaXvSink *this = (SpaXvSink *) handle; - SpaXvState *state; - unsigned int i; - bool have_error = false; - - if (handle == NULL || n_info == 0 || info == NULL) - return SPA_RESULT_INVALID_ARGUMENTS; - - state = &this->state; - - for (i = 0; i < n_info; i++) { - XvBuffer *b; - - if (info[i].port_id != 0) { - info[i].status = SPA_RESULT_INVALID_PORT; - have_error = true; - continue; - } - if (this->current_format == NULL) { - info[i].status = SPA_RESULT_NO_FORMAT; - have_error = true; - continue; - } - if (state->ready_count == 0) { - info[i].status = SPA_RESULT_UNEXPECTED; - have_error = true; - continue; - } - - b = state->ready; - state->ready = b->next; - state->ready_count--; - - b->outstanding = true; - - info[i].buffer = &b->buffer; - info[i].status = SPA_RESULT_OK; - } - if (have_error) - return SPA_RESULT_ERROR; + return SPA_RESULT_INVALID_PORT; +} - return SPA_RESULT_OK; +static SpaResult +spa_xv_sink_node_port_push_event (SpaNode *node, + uint32_t port_id, + SpaEvent *event) +{ + return SPA_RESULT_NOT_IMPLEMENTED; } static const SpaNode xvsink_node = { + NULL, sizeof (SpaNode), spa_xv_sink_node_get_props, spa_xv_sink_node_set_props, @@ -533,19 +521,24 @@ static const SpaNode xvsink_node = { spa_xv_sink_node_port_get_status, spa_xv_sink_node_port_push_input, spa_xv_sink_node_port_pull_output, + spa_xv_sink_node_port_push_event, }; static SpaResult spa_xv_sink_get_interface (SpaHandle *handle, uint32_t interface_id, - const void **interface) + void **interface) { + SpaXvSink *this; + if (handle == NULL || interface == NULL) return SPA_RESULT_INVALID_ARGUMENTS; + this = (SpaXvSink *) handle; + switch (interface_id) { case SPA_INTERFACE_ID_NODE: - *interface = &xvsink_node; + *interface = &this->node; break; default: return SPA_RESULT_UNKNOWN_INTERFACE; @@ -565,6 +558,8 @@ xv_sink_init (const SpaHandleFactory *factory, handle->get_interface = spa_xv_sink_get_interface; this = (SpaXvSink *) handle; + this->node = xvsink_node; + this->node.handle = handle; this->props[1].props.n_prop_info = PROP_ID_LAST; this->props[1].props.prop_info = prop_info; this->props[1].props.set_prop = spa_props_generic_set_prop; diff --git a/spa/tests/test-mixer.c b/spa/tests/test-mixer.c index db1ab611..2bf34b3d 100644 --- a/spa/tests/test-mixer.c +++ b/spa/tests/test-mixer.c @@ -30,15 +30,11 @@ #include <spa/audio/format.h> typedef struct { - SpaHandle *sink; - const SpaNode *sink_node; - SpaHandle *mix; - const SpaNode *mix_node; + SpaNode *sink; + SpaNode *mix; uint32_t mix_ports[2]; - SpaHandle *source1; - const SpaNode *source1_node; - SpaHandle *source2; - const SpaNode *source2_node; + SpaNode *source1; + SpaNode *source2; bool running; pthread_t thread; SpaPollFd fds[16]; @@ -47,8 +43,9 @@ typedef struct { } AppData; static SpaResult -make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char *name) +make_node (SpaNode **node, const char *lib, const char *name) { + SpaHandle *handle; SpaResult res; void *hnd; SpaEnumHandleFactoryFunc enum_func; @@ -66,7 +63,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char for (i = 0; ;i++) { const SpaHandleFactory *factory; - const void *iface; + void *iface; if ((res = enum_func (&factory, &state)) < 0) { if (res != SPA_RESULT_ENUM_END) @@ -76,12 +73,12 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char if (strcmp (factory->name, name)) continue; - *handle = calloc (1, factory->size); - if ((res = factory->init (factory, *handle)) < 0) { + handle = calloc (1, factory->size); + if ((res = factory->init (factory, handle)) < 0) { printf ("can't make factory instance: %d\n", res); return res; } - if ((res = (*handle)->get_interface (*handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { + if ((res = handle->get_interface (handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { printf ("can't get interface %d\n", res); return res; } @@ -92,39 +89,38 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char } static void -on_mix_event (SpaHandle *handle, SpaEvent *event, void *user_data) +on_mix_event (SpaNode *node, SpaEvent *event, void *user_data) { AppData *data = user_data; switch (event->type) { case SPA_EVENT_TYPE_PULL_INPUT: { - SpaBuffer *buf; SpaInputInfo iinfo; SpaOutputInfo oinfo; SpaResult res; + SpaEventPullInput *pi; - buf = event->data; + pi = event->data; oinfo.port_id = 0; oinfo.flags = SPA_OUTPUT_FLAG_NONE; - oinfo.buffer = buf; - oinfo.event = NULL; + oinfo.size = pi->size; + oinfo.offset = pi->offset; if (event->port_id == data->mix_ports[0]) { - if ((res = data->source1_node->port_pull_output (data->source1, 1, &oinfo)) < 0) + if ((res = spa_node_port_pull_output (data->source1, 1, &oinfo)) < 0) printf ("got error %d\n", res); } else { - if ((res = data->source2_node->port_pull_output (data->source2, 1, &oinfo)) < 0) + if ((res = spa_node_port_pull_output (data->source2, 1, &oinfo)) < 0) printf ("got error %d\n", res); } iinfo.port_id = event->port_id; iinfo.flags = SPA_INPUT_FLAG_NONE; - iinfo.buffer = oinfo.buffer; - iinfo.event = oinfo.event; + iinfo.id = oinfo.id; - if ((res = data->mix_node->port_push_input (data->mix, 1, &iinfo)) < 0) + if ((res = spa_node_port_push_input (data->mix, 1, &iinfo)) < 0) printf ("got error from mixer %d\n", res); break; } @@ -135,34 +131,33 @@ on_mix_event (SpaHandle *handle, SpaEvent *event, void *user_data) } static void -on_sink_event (SpaHandle *handle, SpaEvent *event, void *user_data) +on_sink_event (SpaNode *node, SpaEvent *event, void *user_data) { AppData *data = user_data; switch (event->type) { case SPA_EVENT_TYPE_PULL_INPUT: { - SpaBuffer *buf; SpaInputInfo iinfo; SpaOutputInfo oinfo; SpaResult res; + SpaEventPullInput *pi; - buf = event->data; + pi = event->data; oinfo.port_id = 0; oinfo.flags = SPA_OUTPUT_FLAG_PULL; - oinfo.buffer = buf; - oinfo.event = NULL; + oinfo.offset = pi->offset; + oinfo.size = pi->size; - if ((res = data->mix_node->port_pull_output (data->mix, 1, &oinfo)) < 0) + if ((res = spa_node_port_pull_output (data->mix, 1, &oinfo)) < 0) printf ("got error %d\n", res); iinfo.port_id = event->port_id; iinfo.flags = SPA_INPUT_FLAG_NONE; - iinfo.buffer = oinfo.buffer; - iinfo.event = oinfo.event; + iinfo.id = oinfo.id; - if ((res = data->sink_node->port_push_input (data->sink, 1, &iinfo)) < 0) + if ((res = spa_node_port_push_input (data->sink, 1, &iinfo)) < 0) printf ("got error %d\n", res); break; } @@ -192,13 +187,13 @@ make_nodes (AppData *data) SpaProps *props; SpaPropValue value; - if ((res = make_node (&data->sink, &data->sink_node, "plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) { + if ((res = make_node (&data->sink, "plugins/alsa/libspa-alsa.so", "alsa-sink")) < 0) { printf ("can't create alsa-sink: %d\n", res); return res; } - data->sink_node->set_event_callback (data->sink, on_sink_event, data); + spa_node_set_event_callback (data->sink, on_sink_event, data); - if ((res = data->sink_node->get_props (data->sink, &props)) < 0) + if ((res = spa_node_get_props (data->sink, &props)) < 0) printf ("got get_props error %d\n", res); value.type = SPA_PROP_TYPE_STRING; @@ -206,21 +201,21 @@ make_nodes (AppData *data) value.size = strlen (value.value)+1; props->set_prop (props, spa_props_index_for_name (props, "device"), &value); - if ((res = data->sink_node->set_props (data->sink, props)) < 0) + if ((res = spa_node_set_props (data->sink, props)) < 0) printf ("got set_props error %d\n", res); - if ((res = make_node (&data->mix, &data->mix_node, "plugins/audiomixer/libspa-audiomixer.so", "audiomixer")) < 0) { + if ((res = make_node (&data->mix, "plugins/audiomixer/libspa-audiomixer.so", "audiomixer")) < 0) { printf ("can't create audiomixer: %d\n", res); return res; } - data->mix_node->set_event_callback (data->mix, on_mix_event, data); + spa_node_set_event_callback (data->mix, on_mix_event, data); - if ((res = make_node (&data->source1, &data->source1_node, "plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) { + if ((res = make_node (&data->source1, "plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) { printf ("can't create audiotestsrc: %d\n", res); return res; } - if ((res = make_node (&data->source2, &data->source2_node, "plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) { + if ((res = make_node (&data->source2, "plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc")) < 0) { printf ("can't create audiotestsrc: %d\n", res); return res; } @@ -237,7 +232,7 @@ negotiate_formats (AppData *data) SpaPropValue value; void *state = NULL; - if ((res = data->sink_node->port_enum_formats (data->sink, 0, &format, NULL, &state)) < 0) + if ((res = spa_node_port_enum_formats (data->sink, 0, &format, NULL, &state)) < 0) return res; props = &format->props; @@ -259,28 +254,30 @@ negotiate_formats (AppData *data) if ((res = props->set_prop (props, spa_props_index_for_id (props, SPA_PROP_ID_AUDIO_CHANNELS), &value)) < 0) return res; - if ((res = data->sink_node->port_set_format (data->sink, 0, false, format)) < 0) + if ((res = spa_node_port_set_format (data->sink, 0, false, format)) < 0) return res; - if ((res = data->mix_node->port_set_format (data->mix, 0, false, format)) < 0) + if ((res = spa_node_port_set_format (data->mix, 0, false, format)) < 0) return res; - if ((res = data->mix_node->add_port (data->mix, SPA_DIRECTION_INPUT, &data->mix_ports[0])) < 0) + data->mix_ports[0] = 0; + if ((res = spa_node_add_port (data->mix, SPA_DIRECTION_INPUT, 0)) < 0) return res; - if ((res = data->mix_node->port_set_format (data->mix, data->mix_ports[0], false, format)) < 0) + if ((res = spa_node_port_set_format (data->mix, data->mix_ports[0], false, format)) < 0) return res; - if ((res = data->source1_node->port_set_format (data->source1, 0, false, format)) < 0) + if ((res = spa_node_port_set_format (data->source1, 0, false, format)) < 0) return res; - if ((res = data->mix_node->add_port (data->mix, SPA_DIRECTION_INPUT, &data->mix_ports[1])) < 0) + data->mix_ports[1] = 0; + if ((res = spa_node_add_port (data->mix, SPA_DIRECTION_INPUT, 1)) < 0) return res; - if ((res = data->mix_node->port_set_format (data->mix, data->mix_ports[1], false, format)) < 0) + if ((res = spa_node_port_set_format (data->mix, data->mix_ports[1], false, format)) < 0) return res; - if ((res = data->source2_node->port_set_format (data->source2, 0, false, format)) < 0) + if ((res = spa_node_port_set_format (data->source2, 0, false, format)) < 0) return res; @@ -327,7 +324,7 @@ run_async_sink (AppData *data) int err; cmd.type = SPA_COMMAND_START; - if ((res = data->sink_node->send_command (data->sink, &cmd)) < 0) + if ((res = spa_node_send_command (data->sink, &cmd)) < 0) printf ("got error %d\n", res); data->running = true; @@ -345,7 +342,7 @@ run_async_sink (AppData *data) } cmd.type = SPA_COMMAND_STOP; - if ((res = data->sink_node->send_command (data->sink, &cmd)) < 0) + if ((res = spa_node_send_command (data->sink, &cmd)) < 0) printf ("got error %d\n", res); } diff --git a/spa/tests/test-v4l2.c b/spa/tests/test-v4l2.c index 66989dee..e8a5695a 100644 --- a/spa/tests/test-v4l2.c +++ b/spa/tests/test-v4l2.c @@ -32,7 +32,7 @@ #include <spa/debug.h> #include <spa/video/format.h> -#define USE_BUFFER +#undef USE_BUFFER #define MAX_BUFFERS 8 @@ -45,8 +45,7 @@ typedef struct { } SDLBuffer; typedef struct { - SpaHandle *source; - const SpaNode *source_node; + SpaNode *source; SDL_Renderer *renderer; SDL_Window *window; SDL_Texture *texture; @@ -55,13 +54,16 @@ typedef struct { SpaPollFd fds[16]; unsigned int n_fds; SpaPollItem poll; + SpaBuffer *bp[MAX_BUFFERS]; SDLBuffer buffers[MAX_BUFFERS]; + unsigned int n_buffers; } AppData; static SpaResult -make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char *name) +make_node (SpaNode **node, const char *lib, const char *name) { + SpaHandle *handle; SpaResult res; void *hnd; SpaEnumHandleFactoryFunc enum_func; @@ -79,7 +81,7 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char for (i = 0; ;i++) { const SpaHandleFactory *factory; - const void *iface; + void *iface; if ((res = enum_func (&factory, &state)) < 0) { if (res != SPA_RESULT_ENUM_END) @@ -89,12 +91,12 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char if (strcmp (factory->name, name)) continue; - *handle = calloc (1, factory->size); - if ((res = factory->init (factory, *handle)) < 0) { + handle = calloc (1, factory->size); + if ((res = factory->init (factory, handle)) < 0) { printf ("can't make factory instance: %d\n", res); return res; } - if ((res = (*handle)->get_interface (*handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { + if ((res = handle->get_interface (handle, SPA_INTERFACE_ID_NODE, &iface)) < 0) { printf ("can't get interface %d\n", res); return res; } @@ -103,10 +105,9 @@ make_node (SpaHandle **handle, const SpaNode **node, const char *lib, const char } return SPA_RESULT_ERROR; } -#define MIN(a,b) (a < b ? a : b) static void -on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) +on_source_event (SpaNode *node, SpaEvent *event, void *user_data) { AppData *data = user_data; @@ -121,10 +122,10 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) int i; uint8_t *src, *dst; - if ((res = data->source_node->port_pull_output (data->source, 1, info)) < 0) + if ((res = spa_node_port_pull_output (data->source, 1, info)) < 0) printf ("got pull error %d\n", res); - b = info[0].buffer; + b = data->bp[info->id]; if (b->metas[1].type == SPA_META_TYPE_POINTER && strcmp (((SpaMetaPointer*)b->metas[1].data)->ptr_type, "SDL_Texture") == 0) { @@ -156,7 +157,7 @@ on_source_event (SpaHandle *handle, SpaEvent *event, void *user_data) for (i = 0; i < 240; i++) { src = ((uint8_t*)sdata + i * sstride); dst = ((uint8_t*)ddata + i * dstride); - memcpy (dst, src, MIN (sstride, dstride)); + memcpy (dst, src, SPA_MIN (sstride, dstride)); } SDL_UnlockTexture(data->texture); @@ -190,13 +191,13 @@ make_nodes (AppData *data, const char *device) SpaProps *props; SpaPropValue value; - if ((res = make_node (&data->source, &data->source_node, "plugins/v4l2/libspa-v4l2.so", "v4l2-source")) < 0) { + if ((res = make_node (&data->source, "plugins/v4l2/libspa-v4l2.so", "v4l2-source")) < 0) { printf ("can't create v4l2-source: %d\n", res); return res; } - data->source_node->set_event_callback (data->source, on_source_event, data); + spa_node_set_event_callback (data->source, on_source_event, data); - if ((res = data->source_node->get_props (data->source, &props)) < 0) + if ((res = spa_node_get_props (data->source, &props)) < 0) printf ("got get_props error %d\n", res); value.type = SPA_PROP_TYPE_STRING; @@ -204,7 +205,7 @@ make_nodes (AppData *data, const char *device) value.size = strlen (value.value)+1; props->set_prop (props, spa_props_index_for_name (props, "device"), &value); - if ((res = data->source_node->set_props (data->source, props)) < 0) + if ((res = spa_node_set_props (data->source, props)) < 0) printf ("got set_props error %d\n", res); return res; } @@ -238,6 +239,7 @@ alloc_buffers (AppData *data) b->buffer.refcount = 1; b->buffer.notify = NULL; + b->buffer.id = i; b->buffer.size = stride * 240; b->buffer.n_metas = 2; b->buffer.metas = b->metas; @@ -265,7 +267,9 @@ alloc_buffers (AppData *data) b->datas[0].size = stride * 240; b->datas[0].stride = stride; } - data->source_node->port_use_buffers (data->source, 0, data->bp, MAX_BUFFERS); + data->n_buffers = MAX_BUFFERS; + + spa_node_port_use_buffers (data->source, 0, data->bp, MAX_BUFFERS); } #endif @@ -287,7 +291,7 @@ negotiate_formats (AppData *data) #if 0 void *state = NULL; - if ((res = data->source_node->port_enum_formats (data->source, 0, &format, NULL, &state)) < 0) + if ((res = spa_node_port_enum_formats (data->source, 0, &format, NULL, &state)) < 0) return res; #else f.fmt.media_type = SPA_MEDIA_TYPE_VIDEO; @@ -315,10 +319,10 @@ negotiate_formats (AppData *data) f.framerate.denom = 1; #endif - if ((res = data->source_node->port_set_format (data->source, 0, false, &f.fmt)) < 0) + if ((res = spa_node_port_set_format (data->source, 0, false, &f.fmt)) < 0) return res; - if ((res = data->source_node->port_get_info (data->source, 0, &info)) < 0) + if ((res = spa_node_port_get_info (data->source, 0, &info)) < 0) return res; spa_debug_port_info (info); @@ -326,13 +330,23 @@ negotiate_formats (AppData *data) #ifdef USE_BUFFER alloc_buffers (data); #else - data->texture = SDL_CreateTexture (data->renderer, - SDL_PIXELFORMAT_YUY2, - SDL_TEXTUREACCESS_STREAMING, - 320, 240); - if (!data->texture) { - printf ("can't create texture: %s\n", SDL_GetError ()); - return -1; + { + unsigned int n_buffers; + + data->texture = SDL_CreateTexture (data->renderer, + SDL_PIXELFORMAT_YUY2, + SDL_TEXTUREACCESS_STREAMING, + 320, 240); + if (!data->texture) { + printf ("can't create texture: %s\n", SDL_GetError ()); + return -1; + } + n_buffers = MAX_BUFFERS; + if ((res = spa_node_port_alloc_buffers (data->source, 0, NULL, 0, data->bp, &n_buffers)) < 0) { + printf ("can't allocate buffers: %s\n", SDL_GetError ()); + return -1; + } + data->n_buffers = n_buffers; } #endif @@ -379,7 +393,7 @@ run_async_source (AppData *data) int err; cmd.type = SPA_COMMAND_START; - if ((res = data->source_node->send_command (data->source, &cmd)) < 0) + if ((res = spa_node_send_command (data->source, &cmd)) < 0) printf ("got error %d\n", res); data->running = true; @@ -412,7 +426,7 @@ run_async_source (AppData *data) } cmd.type = SPA_COMMAND_STOP; - if ((res = data->source_node->send_command (data->source, &cmd)) < 0) + if ((res = spa_node_send_command (data->source, &cmd)) < 0) printf ("got error %d\n", res); } diff --git a/spa/tools/spa-inspect.c b/spa/tools/spa-inspect.c index c8387992..f0290f2b 100644 --- a/spa/tools/spa-inspect.c +++ b/spa/tools/spa-inspect.c @@ -56,7 +56,8 @@ struct prop_type_name { { "uint32", "UInt32" }, { "int64", "Int64" }, { "uint64", "UInt64" }, - { "float", "Float" }, + { "int", "Int" }, + { "uint", "UInt" }, { "double", "Double" }, { "string", "String" }, { "rectangle", "Rectangle" }, @@ -116,6 +117,12 @@ print_value (const SpaPropInfo *info, int size, const void *value) case SPA_PROP_TYPE_UINT64: printf ("%" PRIu64 "\n", *(uint64_t *)value); break; + case SPA_PROP_TYPE_INT: + printf ("%d", *(int *)value); + break; + case SPA_PROP_TYPE_UINT: + printf ("%u", *(unsigned int *)value); + break; case SPA_PROP_TYPE_FLOAT: printf ("%f", *(float *)value); break; @@ -292,7 +299,7 @@ print_format (const SpaFormat *format) } static void -inspect_node (const SpaNode *node, SpaHandle *handle) +inspect_node (SpaNode *node) { SpaResult res; SpaProps *props; @@ -300,18 +307,18 @@ inspect_node (const SpaNode *node, SpaHandle *handle) SpaFormat *format; void *state = NULL; - if ((res = node->get_props (handle, &props)) < 0) + if ((res = node->get_props (node, &props)) < 0) printf ("can't get properties: %d\n", res); else print_props (props, 1); - if ((res = node->get_n_ports (handle, &n_input, &max_input, &n_output, &max_output)) < 0) + if ((res = node->get_n_ports (node, &n_input, &max_input, &n_output, &max_output)) < 0) printf ("can't get n_ports: %d\n", res); else printf ("supported ports %d %d %d %d\n", n_input, max_input, n_output, max_output); while (true) { - if ((res = node->port_enum_formats (handle, 0, &format, NULL, &state)) < 0) { + if ((res = node->port_enum_formats (node, 0, &format, NULL, &state)) < 0) { if (res != SPA_RESULT_ENUM_END) printf ("got error %d\n", res); break; @@ -319,7 +326,7 @@ inspect_node (const SpaNode *node, SpaHandle *handle) if (format) print_format (format); } - if ((res = node->port_get_props (handle, 0, &props)) < 0) + if ((res = node->port_get_props (node, 0, &props)) < 0) printf ("port_get_props error: %d\n", res); else print_props (props, 1); @@ -330,7 +337,7 @@ inspect_factory (const SpaHandleFactory *factory) { SpaResult res; SpaHandle *handle; - const void *interface; + void *interface; void *state = NULL; printf ("factory name:\t\t'%s'\n", factory->name); @@ -366,7 +373,7 @@ inspect_factory (const SpaHandleFactory *factory) switch (info->interface_id) { case SPA_INTERFACE_ID_NODE: - inspect_node (interface, handle); + inspect_node (interface); break; default: printf ("skipping unknown interface\n"); |