diff --git a/doc/design.txt b/doc/design.txt index 26ed958e9..5c0a2698f 100644 --- a/doc/design.txt +++ b/doc/design.txt @@ -391,6 +391,59 @@ communication channel +----+ + Client Proxy + | INIT + node-update | + -------------------------------------->| + port-update | + -------------------------------------->| + state-change CONFIGURE | CONFIGURE + -------------------------------------->| + |<--- enum-ports + |<--- enum-formats + |<--- add-port + |<--- remove-port + set-property |<--- set-property + <--------------------------------------| + set-format |<--- set-format + <--------------------------------------| + | + port-update | + -------------------------------------->| + state-change READY | READY + -------------------------------------->| + |<--- port memory requirements + add-mem |<--- use-buffers + <--------------------------------------| + remove-mem | + <--------------------------------------| + add-buffer | + <--------------------------------------| + remove-buffer | + <--------------------------------------| + | + pause |<--- stop + <--------------------------------------| + state-change PAUSED | PAUSED + -------------------------------------->| + | + play |<--- start + <--------------------------------------| + state-change STREAMING | STREAMING + -------------------------------------->| + | + need-input | + <------------------------------------->| + have-output | + <------------------------------------->| + process-buffer | + <------------------------------------->| + reuse-buffer | + <------------------------------------->| + + + + 1) Update config C->S INIT node-update diff --git a/pinos/client/stream.c b/pinos/client/stream.c index d2fb70b1b..c05cb6fc4 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -74,6 +74,7 @@ struct _PinosStreamPrivate GPtrArray *possible_formats; SpaFormat *format; + SpaPortInfo port_info; PinosStreamFlags flags; @@ -512,17 +513,28 @@ pinos_stream_get_error (PinosStream *stream) return stream->priv->error; } +static void +control_builder_init (PinosStream *stream, SpaControlBuilder *builder) +{ + PinosStreamPrivate *priv = stream->priv; + + spa_control_builder_init_into (builder, + priv->send_data, + MAX_BUFFER_SIZE, + priv->send_fds, + MAX_FDS); +} + static void send_need_input (PinosStream *stream, uint32_t port_id, uint32_t buffer_id) { PinosStreamPrivate *priv = stream->priv; SpaControlBuilder builder; SpaControl control; - guint8 buffer[64]; SpaControlCmdNeedInput ni; SpaControlCmdReuseBuffer rb; - spa_control_builder_init_into (&builder, buffer, 64, NULL, 0); + control_builder_init (stream, &builder); if (buffer_id != SPA_ID_INVALID) { rb.port_id = port_id; rb.buffer_id = buffer_id; @@ -586,7 +598,6 @@ parse_control (PinosStream *stream, SpaControlBuilder builder; SpaControl control; SpaControlCmdStateChange sc; - guint8 buffer[64]; if (spa_control_iter_parse_cmd (&it, &p) < 0) break; @@ -598,10 +609,11 @@ parse_control (PinosStream *stream, spa_debug_format (p.format); g_object_notify (G_OBJECT (stream), "format"); + control_builder_init (stream, &builder); + /* FIXME send update port status */ /* send state-change */ - spa_control_builder_init_into (&builder, buffer, sizeof(buffer), NULL, 0); sc.state = SPA_NODE_STATE_READY; spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_STATE_CHANGE, &sc); spa_control_builder_end (&builder, &control); @@ -852,6 +864,44 @@ unhandle_socket (PinosStream *stream) } } +static void +do_node_init (PinosStream *stream) +{ + PinosStreamPrivate *priv = stream->priv; + SpaControlCmdNodeUpdate nu; + SpaControlCmdPortUpdate pu; + SpaControlBuilder builder; + SpaControl control; + + control_builder_init (stream, &builder); + nu.change_mask = SPA_CONTROL_CMD_NODE_UPDATE_MAX_INPUTS | + SPA_CONTROL_CMD_NODE_UPDATE_MAX_OUTPUTS; + nu.max_input_ports = 1; + nu.max_output_ports = 0; + nu.props = NULL; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_NODE_UPDATE, &nu); + + pu.port_id = 0; + pu.change_mask = SPA_CONTROL_CMD_PORT_UPDATE_DIRECTION | + SPA_CONTROL_CMD_PORT_UPDATE_POSSIBLE_FORMATS | + SPA_CONTROL_CMD_PORT_UPDATE_INFO; + + pu.direction = priv->direction; + pu.n_possible_formats = priv->possible_formats->len; + pu.possible_formats = (const SpaFormat **)priv->possible_formats->pdata; + pu.props = NULL; + pu.info = &priv->port_info; + priv->port_info.flags = SPA_PORT_INFO_FLAG_NONE | + SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS; + spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_PORT_UPDATE, &pu); + spa_control_builder_end (&builder, &control); + + if (spa_control_write (&control, priv->fd) < 0) + g_warning ("stream %p: error writing control", stream); + + spa_control_clear (&control); +} + static void on_node_proxy (GObject *source_object, @@ -869,6 +919,8 @@ on_node_proxy (GObject *source_object, if (priv->node == NULL) goto node_failed; + do_node_init (stream); + stream_set_state (stream, PINOS_STREAM_STATE_READY, NULL); g_object_unref (stream); @@ -951,25 +1003,12 @@ do_connect (PinosStream *stream) { PinosStreamPrivate *priv = stream->priv; PinosContext *context = priv->context; - GVariantBuilder b; - GVariant *ports; - - g_variant_builder_init (&b, G_VARIANT_TYPE ("a(uusa{sv}s)")); - g_variant_builder_open (&b, G_VARIANT_TYPE ("(uusa{sv}s)")); - g_variant_builder_add (&b, "u", priv->direction); - g_variant_builder_add (&b, "u", 0); - g_variant_builder_add (&b, "s", ""); - g_variant_builder_add_value (&b, pinos_properties_to_variant (priv->properties)); - g_variant_builder_add (&b, "s", priv->path == NULL ? "" : priv->path); - g_variant_builder_close (&b); - ports = g_variant_builder_end (&b); g_dbus_proxy_call (context->priv->daemon, "CreateClientNode", - g_variant_new ("(s@a{sv}@a(uusa{sv}s))", + g_variant_new ("(s@a{sv})", "client-node", - pinos_properties_to_variant (priv->properties), - ports), + pinos_properties_to_variant (priv->properties)), G_DBUS_CALL_FLAGS_NONE, -1, NULL, /* GCancellable *cancellable */ @@ -1025,34 +1064,17 @@ pinos_stream_connect (PinosStream *stream, return TRUE; } -static void -control_builder_init (PinosStream *stream, SpaControlBuilder *builder) -{ - PinosStreamPrivate *priv = stream->priv; - - spa_control_builder_init_into (builder, - priv->send_data, - MAX_BUFFER_SIZE, - priv->send_fds, - MAX_FDS); -} - static gboolean do_start (PinosStream *stream) { PinosStreamPrivate *priv = stream->priv; SpaControlBuilder builder; - SpaControlCmdPortUpdate pu; SpaControlCmdStateChange sc; SpaControl control; handle_socket (stream, priv->fd); control_builder_init (stream, &builder); - pu.port_id = 0; - pu.change_mask = 0; - - spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_PORT_UPDATE, &pu); sc.state = SPA_NODE_STATE_CONFIGURE; spa_control_builder_add_cmd (&builder, SPA_CONTROL_CMD_STATE_CHANGE, &sc); spa_control_builder_end (&builder, &control); @@ -1060,6 +1082,8 @@ do_start (PinosStream *stream) if (spa_control_write (&control, priv->fd) < 0) g_warning ("stream %p: failed to write control", stream); + spa_control_clear (&control); + g_object_unref (stream); return FALSE; diff --git a/pinos/dbus/org.pinos.xml b/pinos/dbus/org.pinos.xml index 633e99a7d..a82651dd8 100644 --- a/pinos/dbus/org.pinos.xml +++ b/pinos/dbus/org.pinos.xml @@ -41,15 +41,13 @@ - diff --git a/pinos/modules/spa/spa-v4l2-source.c b/pinos/modules/spa/spa-v4l2-source.c index bc8a01866..1d248f657 100644 --- a/pinos/modules/spa/spa-v4l2-source.c +++ b/pinos/modules/spa/spa-v4l2-source.c @@ -38,14 +38,6 @@ #define PINOS_SPA_V4L2_SOURCE_GET_PRIVATE(obj) \ (G_TYPE_INSTANCE_GET_PRIVATE ((obj), PINOS_TYPE_SPA_V4L2_SOURCE, PinosSpaV4l2SourcePrivate)) -typedef struct { - PinosSpaV4l2Source *source; - - guint id; - gboolean have_format; - PinosPort *port; -} SourcePortData; - struct _PinosSpaV4l2SourcePrivate { SpaPollFd fds[16]; @@ -56,8 +48,6 @@ struct _PinosSpaV4l2SourcePrivate pthread_t thread; GBytes *format; - - GList *ports; }; enum { @@ -158,11 +148,12 @@ on_source_event (SpaNode *node, SpaEvent *event, void *user_data) if ((res = spa_node_port_pull_output (node, 1, info)) < 0) g_debug ("spa-v4l2-source %p: got pull error %d, %d", this, res, info[0].status); - for (walk = priv->ports; walk; walk = g_list_next (walk)) { - SourcePortData *data = walk->data; + walk = pinos_node_get_ports (PINOS_NODE (this)); + for (; walk; walk = g_list_next (walk)) { + PinosPort *port = walk->data; GError *error = NULL; - if (!pinos_port_send_buffer (data->port, info[0].buffer_id, &error)) { + if (!pinos_port_send_buffer (port, info[0].buffer_id, &error)) { g_debug ("send failed: %s", error->message); g_clear_error (&error); } @@ -309,8 +300,7 @@ set_property (GObject *object, static gboolean on_activate (PinosPort *port, gpointer user_data) { - SourcePortData *data = user_data; - PinosSpaV4l2Source *source = data->source; + PinosSpaV4l2Source *source = user_data; pinos_node_report_busy (PINOS_NODE (source)); @@ -320,39 +310,17 @@ on_activate (PinosPort *port, gpointer user_data) static void on_deactivate (PinosPort *port, gpointer user_data) { - SourcePortData *data = user_data; - PinosSpaV4l2Source *source = data->source; + PinosSpaV4l2Source *source = user_data; pinos_node_report_idle (PINOS_NODE (source)); } -static void -free_source_port_data (SourcePortData *data) -{ - g_slice_free (SourcePortData, data); -} - static gboolean remove_port (PinosNode *node, guint id) { - PinosSpaV4l2Source *source = PINOS_SPA_V4L2_SOURCE (node); - PinosSpaV4l2SourcePrivate *priv = source->priv; - GList *walk; - - for (walk = priv->ports; walk; walk = g_list_next (walk)) { - SourcePortData *data = walk->data; - - if (data->id == id) { - free_source_port_data (data); - priv->ports = g_list_delete_link (priv->ports, walk); - break; - } - } - if (priv->ports == NULL) - pinos_node_report_idle (node); - - return TRUE; + return PINOS_NODE_CLASS (pinos_spa_v4l2_source_parent_class) + ->remove_port (node, id); } static void @@ -417,26 +385,18 @@ add_port (PinosNode *node, GError **error) { PinosSpaV4l2Source *source = PINOS_SPA_V4L2_SOURCE (node); - PinosSpaV4l2SourcePrivate *priv = source->priv; - SourcePortData *data; + PinosPort *port; - data = g_slice_new0 (SourcePortData); - data->source = source; - data->id = id; - data->have_format = FALSE; - - data->port = PINOS_NODE_CLASS (pinos_spa_v4l2_source_parent_class) + port = PINOS_NODE_CLASS (pinos_spa_v4l2_source_parent_class) ->add_port (node, direction, id, error); - pinos_port_set_received_cb (data->port, on_received_buffer, on_received_event, node, NULL); + pinos_port_set_received_cb (port, on_received_buffer, on_received_event, node, NULL); g_debug ("connecting signals"); - g_signal_connect (data->port, "activate", (GCallback) on_activate, data); - g_signal_connect (data->port, "deactivate", (GCallback) on_deactivate, data); + g_signal_connect (port, "activate", (GCallback) on_activate, source); + g_signal_connect (port, "deactivate", (GCallback) on_deactivate, source); - priv->ports = g_list_append (priv->ports, data); - - return data->port; + return port; } static void diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index 79c726fc1..f60b2d446 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -38,6 +38,7 @@ #include "pinos/server/daemon.h" #include "pinos/server/client-node.h" #include "pinos/server/utils.h" +#include "pinos/server/link.h" #include "pinos/dbus/org-pinos.h" @@ -174,8 +175,6 @@ static gboolean on_received_buffer (PinosPort *port, uint32_t buffer_id, GError **error, gpointer user_data) { PinosNode *node = user_data; - PinosClientNode *this = PINOS_CLIENT_NODE (node); - PinosClientNodePrivate *priv = this->priv; SpaResult res; SpaInputInfo info[1]; @@ -195,8 +194,6 @@ static gboolean on_received_event (PinosPort *port, SpaEvent *event, GError **error, gpointer user_data) { PinosNode *node = user_data; - PinosClientNode *this = PINOS_CLIENT_NODE (node); - PinosClientNodePrivate *priv = this->priv; SpaResult res; if ((res = spa_node_port_push_event (node->node, port->id, event)) < 0) @@ -271,6 +268,45 @@ on_node_event (SpaNode *node, SpaEvent *event, void *user_data) PinosClientNodePrivate *priv = this->priv; switch (event->type) { + case SPA_EVENT_TYPE_PORT_ADDED: + { + SpaEventPortAdded *pa = event->data; + PinosPort *port, *target; + PinosLink *link; + PinosNode *pnode = PINOS_NODE (this); + GError *error = NULL; + + port = PINOS_NODE_CLASS (pinos_client_node_parent_class)->add_port (pnode, + pa->direction, + event->port_id, + &error); + + if (port == NULL) { + g_warning ("proxy %p: can't create port: %s", this, error->message); + g_clear_error (&error); + break; + } + pinos_port_set_received_cb (port, on_received_buffer, on_received_event, this, NULL); + + target = pinos_daemon_find_port (pinos_node_get_daemon (pnode), + pinos_direction_reverse (pa->direction), + "/org/pinos/node_8", + NULL, + NULL, + &error); + if (target == NULL) { + g_warning ("proxy %p: can't find port target: %s", this, error->message); + g_clear_error (&error); + break; + } + link = pinos_link_new (pinos_node_get_daemon (pnode), port, target, NULL); + + break; + } + case SPA_EVENT_TYPE_PORT_REMOVED: + { + break; + } case SPA_EVENT_TYPE_STATE_CHANGE: { SpaEventStateChange *sc = event->data; diff --git a/pinos/server/daemon.c b/pinos/server/daemon.c index 367b581a6..177208ab5 100644 --- a/pinos/server/daemon.c +++ b/pinos/server/daemon.c @@ -187,7 +187,6 @@ handle_create_client_node (PinosDaemon1 *interface, GDBusMethodInvocation *invocation, const gchar *arg_name, GVariant *arg_properties, - GVariant *arg_ports, gpointer user_data) { PinosDaemon *daemon = user_data; @@ -210,56 +209,11 @@ handle_create_client_node (PinosDaemon1 *interface, arg_name, props); - client = sender_get_client (daemon, sender); - - { - GVariantIter it; - guint direction; - guint id; - const gchar *format_str, *target_node; - GVariant *port_props; - - g_variant_iter_init (&it, arg_ports); - while (g_variant_iter_loop (&it, "(uu&s@a{sv}&s)", &direction, &id, &format_str, &port_props, &target_node)) { - PinosPort *port, *target; - PinosProperties *pprops; - GBytes *formats; - PinosLink *link; - - port = pinos_node_add_port (node, direction, id, &error); - if (port == NULL) - goto add_failed; - - pprops = pinos_properties_from_variant (port_props); - formats = g_bytes_new (format_str, strlen (format_str) + 1); - - g_object_set (port, "possible-formats", formats, - "properties", port_props, - NULL); - - target = pinos_daemon_find_port (daemon, - pinos_direction_reverse (direction), - target_node, - pprops, - formats, - &error); - if (target == NULL) { - g_warning ("daemon %p: can't find port target: %s", daemon, error->message); - g_clear_error (&error); - continue; - } - -// pinos_client_add_object (client, G_OBJECT (target)); - - link = pinos_link_new (daemon, port, target, NULL); - pinos_client_add_object (client, G_OBJECT (link)); - } - } - socket = pinos_client_node_get_socket_pair (PINOS_CLIENT_NODE (node), &error); if (socket == NULL) goto no_socket; + client = sender_get_client (daemon, sender); pinos_client_add_object (client, G_OBJECT (node)); object_path = pinos_node_get_object_path (PINOS_NODE (node)); @@ -279,11 +233,6 @@ no_socket: g_debug ("daemon %p: could not create node %s", daemon, error->message); goto exit_error; } -add_failed: - { - g_debug ("daemon %p: failed to add port %s", daemon, error->message); - goto exit_error; - } exit_error: { g_dbus_method_invocation_return_gerror (invocation, error); diff --git a/pinos/server/node.c b/pinos/server/node.c index 61086919d..ff70d8f70 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -81,6 +81,12 @@ node_set_state (PinosNode *node, return FALSE; } +static void +do_remove_port (PinosPort *port, PinosNode *node) +{ + pinos_node_remove_port (node, port->id); +} + static PinosPort * node_add_port (PinosNode *node, PinosDirection direction, @@ -96,6 +102,10 @@ node_add_port (PinosNode *node, "direction", direction, "id", id, NULL); + if (port) { + g_hash_table_insert (priv->ports, GUINT_TO_POINTER (id), port); + g_signal_connect (port, "remove", (GCallback) do_remove_port, node); + } return port; } @@ -103,6 +113,9 @@ static gboolean node_remove_port (PinosNode *node, guint id) { + PinosNodePrivate *priv = node->priv; + g_debug ("node %p: removed port %u", node, id); + g_hash_table_remove (priv->ports, GUINT_TO_POINTER (id)); return TRUE; } @@ -670,12 +683,6 @@ pinos_node_remove (PinosNode *node) g_signal_emit (node, signals[SIGNAL_REMOVE], 0, NULL); } -static void -do_remove_port (PinosPort *port, PinosNode *node) -{ - pinos_node_remove_port (node, port->id); -} - /** * pinos_node_add_port: * @node: a #PinosNode @@ -693,11 +700,9 @@ pinos_node_add_port (PinosNode *node, GError **error) { PinosNodeClass *klass; - PinosNodePrivate *priv; PinosPort *port; g_return_val_if_fail (PINOS_IS_NODE (node), NULL); - priv = node->priv; klass = PINOS_NODE_GET_CLASS (node); if (!klass->add_port) { @@ -708,10 +713,6 @@ pinos_node_add_port (PinosNode *node, g_debug ("node %p: add port", node); port = klass->add_port (node, direction, id, error); - if (port) { - g_hash_table_insert (priv->ports, GUINT_TO_POINTER (id), port); - g_signal_connect (port, "remove", (GCallback) do_remove_port, node); - } return port; } @@ -727,12 +728,10 @@ pinos_node_add_port (PinosNode *node, gboolean pinos_node_remove_port (PinosNode *node, guint id) { - PinosNodePrivate *priv; PinosNodeClass *klass; gboolean res = FALSE; g_return_val_if_fail (PINOS_IS_NODE (node), FALSE); - priv = node->priv; klass = PINOS_NODE_GET_CLASS (node); @@ -740,10 +739,6 @@ pinos_node_remove_port (PinosNode *node, guint id) return FALSE; res = klass->remove_port (node, id); - if (res) { - g_debug ("node %p: removed port %u", node, id); - g_hash_table_remove (priv->ports, GUINT_TO_POINTER (id)); - } return res; } diff --git a/spa/include/spa/control.h b/spa/include/spa/control.h index b4c52264c..0807e83ff 100644 --- a/spa/include/spa/control.h +++ b/spa/include/spa/control.h @@ -96,6 +96,10 @@ typedef struct { const SpaProps *props; } SpaControlCmdNodeUpdate; +#define SPA_CONTROL_CMD_NODE_UPDATE_MAX_INPUTS (1 << 0) +#define SPA_CONTROL_CMD_NODE_UPDATE_MAX_OUTPUTS (1 << 1) +#define SPA_CONTROL_CMD_NODE_UPDATE_PROPS (1 << 2) + /* SPA_CONTROL_CMD_PORT_UPDATE */ typedef struct { uint32_t port_id; @@ -107,6 +111,11 @@ typedef struct { const SpaPortInfo *info; } SpaControlCmdPortUpdate; +#define SPA_CONTROL_CMD_PORT_UPDATE_DIRECTION (1 << 0) +#define SPA_CONTROL_CMD_PORT_UPDATE_POSSIBLE_FORMATS (1 << 1) +#define SPA_CONTROL_CMD_PORT_UPDATE_PROPS (1 << 2) +#define SPA_CONTROL_CMD_PORT_UPDATE_INFO (1 << 3) + /* SPA_CONTROL_CMD_PORT_REMOVED */ typedef struct { uint32_t port_id; diff --git a/spa/include/spa/event.h b/spa/include/spa/event.h index 985b9143a..bc3083073 100644 --- a/spa/include/spa/event.h +++ b/spa/include/spa/event.h @@ -49,6 +49,8 @@ typedef struct _SpaEvent SpaEvent; */ typedef enum { SPA_EVENT_TYPE_INVALID = 0, + SPA_EVENT_TYPE_PORT_ADDED, + SPA_EVENT_TYPE_PORT_REMOVED, SPA_EVENT_TYPE_STATE_CHANGE, SPA_EVENT_TYPE_CAN_PULL_OUTPUT, SPA_EVENT_TYPE_CAN_PUSH_INPUT, @@ -70,6 +72,10 @@ struct _SpaEvent { size_t size; }; +typedef struct { + SpaDirection direction; +} SpaEventPortAdded; + typedef struct { uint32_t buffer_id; off_t offset; diff --git a/spa/include/spa/port.h b/spa/include/spa/port.h index 997318e7c..9bc04c7d3 100644 --- a/spa/include/spa/port.h +++ b/spa/include/spa/port.h @@ -74,18 +74,18 @@ typedef struct { * @SPA_PORT_INFO_FLAG_NONE: no flags * @SPA_PORT_INFO_FLAG_REMOVABLE: port can be removed * @SPA_PORT_INFO_FLAG_OPTIONAL: processing on port is optional - * @SPA_PORT_INFO_FLAG_CAN_GIVE_BUFFER: the port can give a buffer - * @SPA_PORT_INFO_FLAG_CAN_USE_BUFFER: the port can use a provided buffer + * @SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS: the port can give a buffer + * @SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS: the port can use a provided buffer * @SPA_PORT_INFO_FLAG_IN_PLACE: the port can process data in-place and will need - * a writable input buffer when no output buffer is specified. + * a writable input buffer * @SPA_PORT_INFO_FLAG_NO_REF: the port does not keep a ref on the buffer */ typedef enum { SPA_PORT_INFO_FLAG_NONE = 0, SPA_PORT_INFO_FLAG_REMOVABLE = 1 << 0, SPA_PORT_INFO_FLAG_OPTIONAL = 1 << 1, - SPA_PORT_INFO_FLAG_CAN_GIVE_BUFFER = 1 << 2, - SPA_PORT_INFO_FLAG_CAN_USE_BUFFER = 1 << 3, + SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS = 1 << 2, + SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS = 1 << 3, SPA_PORT_INFO_FLAG_IN_PLACE = 1 << 4, SPA_PORT_INFO_FLAG_NO_REF = 1 << 5, } SpaPortInfoFlags; @@ -103,10 +103,10 @@ typedef enum { */ typedef struct { SpaPortInfoFlags flags; - unsigned int maxbuffering; + uint64_t maxbuffering; uint64_t latency; SpaAllocParam **params; - uint32_t n_params; + unsigned int n_params; const char **features; } SpaPortInfo; diff --git a/spa/lib/control.c b/spa/lib/control.c index 3eb77d8c7..7351e40f5 100644 --- a/spa/lib/control.c +++ b/spa/lib/control.c @@ -398,10 +398,15 @@ spa_control_iter_parse_cmd (SpaControlIter *iter, switch (si->cmd) { /* C -> S */ case SPA_CONTROL_CMD_NODE_UPDATE: - case SPA_CONTROL_CMD_PORT_UPDATE: fprintf (stderr, "implement iter of %d\n", si->cmd); break; + case SPA_CONTROL_CMD_PORT_UPDATE: + if (si->size < sizeof (SpaControlCmdPortUpdate)) + return SPA_RESULT_ERROR; + memcpy (command, si->data, sizeof (SpaControlCmdPortUpdate)); + break; + case SPA_CONTROL_CMD_PORT_REMOVED: if (si->size < sizeof (SpaControlCmdPortRemoved)) return SPA_RESULT_ERROR; @@ -722,6 +727,55 @@ builder_add_cmd (struct stack_builder *sb, SpaControlCmd cmd, size_t size) return p; } +static size_t +calc_props_len (const SpaProps *props) +{ + size_t len; + unsigned int i, j; + SpaPropInfo *pi; + SpaPropRangeInfo *ri; + + /* props and unset mask */ + len = sizeof (SpaProps) + sizeof (uint32_t); + for (i = 0; i < props->n_prop_info; i++) { + pi = (SpaPropInfo *) &props->prop_info[i]; + len += sizeof (SpaPropInfo); + len += pi->name ? strlen (pi->name) + 1 : 0; + len += pi->description ? strlen (pi->description) + 1 : 0; + /* for the value and the default value */ + len += pi->maxsize + pi->default_size; + for (j = 0; j < pi->n_range_values; j++) { + ri = (SpaPropRangeInfo *)&pi->range_values[j]; + len += sizeof (SpaPropRangeInfo); + len += ri->name ? strlen (ri->name) + 1 : 0; + len += ri->description ? strlen (ri->description) + 1 : 0; + /* the size of the range value */ + len += ri->size; + } + } + return len; +} + +static size_t +calc_format_len (const SpaFormat *format) +{ + return calc_props_len (&format->props) - sizeof (SpaProps) + sizeof (SpaFormat); +} + +static void +builder_add_port_update (struct stack_builder *sb, SpaControlCmdPortUpdate *pu) +{ + size_t len; + void *base; + + /* calc len */ + len = sizeof (SpaControlCmdPortUpdate); + base = builder_add_cmd (sb, SPA_CONTROL_CMD_PORT_UPDATE, len); + memcpy (base, pu, sizeof (SpaControlCmdPortUpdate)); + + /* FIXME add more things */ +} + static void builder_add_set_format (struct stack_builder *sb, SpaControlCmdSetFormat *sf) { @@ -738,24 +792,7 @@ builder_add_set_format (struct stack_builder *sb, SpaControlCmdSetFormat *sf) /* calculate length */ /* port_id + format + mask */ - len = sizeof (uint32_t) + sizeof (SpaFormat) + sizeof (uint32_t); - for (i = 0; i < sp->n_prop_info; i++) { - pi = (SpaPropInfo *) &sp->prop_info[i]; - len += sizeof (SpaPropInfo); - len += pi->name ? strlen (pi->name) + 1 : 0; - len += pi->description ? strlen (pi->description) + 1 : 0; - /* for the value and the default value */ - len += pi->maxsize + pi->default_size; - for (j = 0; j < pi->n_range_values; j++) { - ri = (SpaPropRangeInfo *)&pi->range_values[j]; - len += sizeof (SpaPropRangeInfo); - len += ri->name ? strlen (ri->name) + 1 : 0; - len += ri->description ? strlen (ri->description) + 1 : 0; - /* the size of the range value */ - len += ri->size; - } - } - + len = sizeof (uint32_t) + calc_format_len (sf->format); base = builder_add_cmd (sb, SPA_CONTROL_CMD_SET_FORMAT, len); memcpy (base, &sf->port_id, sizeof (uint32_t)); @@ -881,10 +918,13 @@ spa_control_builder_add_cmd (SpaControlBuilder *builder, switch (cmd) { /* C -> S */ case SPA_CONTROL_CMD_NODE_UPDATE: - case SPA_CONTROL_CMD_PORT_UPDATE: fprintf (stderr, "implement builder of %d\n", cmd); break; + case SPA_CONTROL_CMD_PORT_UPDATE: + builder_add_port_update (sb, command); + break; + case SPA_CONTROL_CMD_PORT_REMOVED: p = builder_add_cmd (sb, cmd, sizeof (SpaControlCmdPortRemoved)); memcpy (p, command, sizeof (SpaControlCmdPortRemoved)); diff --git a/spa/lib/debug.c b/spa/lib/debug.c index 704c16b0d..7362becec 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -34,7 +34,7 @@ spa_debug_port_info (const SpaPortInfo *info) fprintf (stderr, "SpaPortInfo %p:\n", info); fprintf (stderr, " flags: \t%08x\n", info->flags); - fprintf (stderr, " maxbuffering: \t%u\n", info->maxbuffering); + fprintf (stderr, " maxbuffering: \t%"PRIu64"\n", info->maxbuffering); fprintf (stderr, " latency: \t%" PRIu64 "\n", info->latency); fprintf (stderr, " n_params: \t%d\n", info->n_params); for (i = 0; i < info->n_params; i++) { diff --git a/spa/plugins/audiomixer/audiomixer.c b/spa/plugins/audiomixer/audiomixer.c index d0c92bcbc..e8e2f0811 100644 --- a/spa/plugins/audiomixer/audiomixer.c +++ b/spa/plugins/audiomixer/audiomixer.c @@ -275,7 +275,7 @@ spa_audiomixer_node_add_port (SpaNode *node, this->ports[port_id].valid = true; this->port_count++; - this->ports[port_id].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFER | + this->ports[port_id].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_REMOVABLE | SPA_PORT_INFO_FLAG_OPTIONAL | SPA_PORT_INFO_FLAG_IN_PLACE; @@ -798,8 +798,8 @@ spa_audiomixer_init (const SpaHandleFactory *factory, reset_audiomixer_props (&this->props[1]); this->ports[0].valid = true; - this->ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_GIVE_BUFFER | - SPA_PORT_INFO_FLAG_CAN_USE_BUFFER | + this->ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS | + SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_NO_REF; return SPA_RESULT_OK; } diff --git a/spa/plugins/audiotestsrc/audiotestsrc.c b/spa/plugins/audiotestsrc/audiotestsrc.c index 1dd2f747f..9b5518128 100644 --- a/spa/plugins/audiotestsrc/audiotestsrc.c +++ b/spa/plugins/audiotestsrc/audiotestsrc.c @@ -585,7 +585,7 @@ audiotestsrc_init (const SpaHandleFactory *factory, this->props[1].props.prop_info = prop_info; reset_audiotestsrc_props (&this->props[1]); - this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFER | + this->info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_NO_REF; this->status.flags = SPA_PORT_STATUS_FLAG_HAVE_OUTPUT; diff --git a/spa/plugins/remote/proxy.c b/spa/plugins/remote/proxy.c index 39e13d674..7b06937c8 100644 --- a/spa/plugins/remote/proxy.c +++ b/spa/plugins/remote/proxy.c @@ -57,7 +57,6 @@ typedef struct { SpaFormat formats[2]; unsigned int n_buffers; SpaBuffer **buffers; - SpaBuffer *remote_buffers[128]; } SpaProxyPort; struct _SpaProxy { @@ -334,6 +333,59 @@ spa_proxy_node_get_port_ids (SpaNode *node, return SPA_RESULT_OK; } +static void +do_init_port (SpaProxy *this, + uint32_t port_id, + SpaDirection direction) +{ + SpaEvent event; + SpaProxyPort *port; + SpaEventPortAdded pa; + + fprintf (stderr, "%p: adding port %d, %d\n", this, port_id, direction); + port = &this->ports[port_id]; + port->direction = direction; + port->valid = true; + port->have_format = false; + + if (direction == SPA_DIRECTION_INPUT) + this->n_inputs++; + else + this->n_outputs++; + + event.type = SPA_EVENT_TYPE_PORT_ADDED; + event.port_id = port_id; + event.data = &pa; + event.size = sizeof (pa); + pa.direction = direction; + this->event_cb (&this->node, &event, this->user_data); +} + +static void +do_uninit_port (SpaProxy *this, + uint32_t port_id) +{ + SpaEvent event; + SpaProxyPort *port; + + fprintf (stderr, "%p: removing port %d\n", this, port_id); + port = &this->ports[port_id]; + + if (port->direction == SPA_DIRECTION_INPUT) + this->n_inputs--; + else + this->n_outputs--; + + port->direction = SPA_DIRECTION_INVALID; + port->valid = false; + port->have_format = false; + + event.type = SPA_EVENT_TYPE_PORT_REMOVED; + event.port_id = port_id; + event.data = NULL; + event.size = 0; + this->event_cb (&this->node, &event, this->user_data); +} static SpaResult spa_proxy_node_add_port (SpaNode *node, @@ -341,7 +393,6 @@ spa_proxy_node_add_port (SpaNode *node, uint32_t port_id) { SpaProxy *this; - SpaProxyPort *port; if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -351,12 +402,7 @@ spa_proxy_node_add_port (SpaNode *node, if (!CHECK_FREE_PORT_ID (this, port_id)) return SPA_RESULT_INVALID_PORT; - fprintf (stderr, "%p: adding port %d, %d\n", node, port_id, direction); - port = &this->ports[port_id]; - - port->direction = direction; - port->valid = true; - port->have_format = false; + do_init_port (this, port_id, direction); return SPA_RESULT_OK; } @@ -366,7 +412,6 @@ spa_proxy_node_remove_port (SpaNode *node, uint32_t port_id) { SpaProxy *this; - SpaProxyPort *port; if (node == NULL || node->handle == NULL) return SPA_RESULT_INVALID_ARGUMENTS; @@ -376,8 +421,7 @@ spa_proxy_node_remove_port (SpaNode *node, if (!CHECK_PORT_ID (this, port_id)) return SPA_RESULT_INVALID_PORT; - port = &this->ports[port_id]; - port->valid = false; + do_uninit_port (this, port_id); return SPA_RESULT_OK; } @@ -868,11 +912,31 @@ parse_control (SpaProxy *this, 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\n", this, cmd); break; + case SPA_CONTROL_CMD_PORT_UPDATE: + { + SpaControlCmdPortUpdate pu; + SpaProxyPort *port; + + fprintf (stderr, "proxy %p: got port update %d\n", this, cmd); + if (spa_control_iter_parse_cmd (&it, &pu) < 0) + break; + + if (pu.port_id >= MAX_PORTS) + break; + + port = &this->ports[pu.port_id]; + if (!port->valid && pu.direction != SPA_DIRECTION_INVALID) { + do_init_port (this, pu.port_id, pu.direction); + } else { + do_uninit_port (this, pu.port_id); + } + break; + } + case SPA_CONTROL_CMD_STATE_CHANGE: { SpaControlCmdStateChange sc; diff --git a/spa/plugins/v4l2/v4l2-utils.c b/spa/plugins/v4l2/v4l2-utils.c index d49c858db..408ce9597 100644 --- a/spa/plugins/v4l2/v4l2-utils.c +++ b/spa/plugins/v4l2/v4l2-utils.c @@ -398,7 +398,8 @@ spa_v4l2_set_format (SpaV4l2Source *this, V4l2Format *f, bool try_only) return 0; state->fmt = fmt; - state->info.flags = SPA_PORT_INFO_FLAG_CAN_GIVE_BUFFER; + state->info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS | + SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS; state->info.maxbuffering = -1; state->info.latency = -1; diff --git a/spa/plugins/volume/volume.c b/spa/plugins/volume/volume.c index 26e4779df..5399485e7 100644 --- a/spa/plugins/volume/volume.c +++ b/spa/plugins/volume/volume.c @@ -695,10 +695,10 @@ volume_instantiate (const SpaHandleFactory *factory, this->props[1].props.prop_info = prop_info; reset_volume_props (&this->props[1]); - this->ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFER | + this->ports[0].info.flags = SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_IN_PLACE; - this->ports[1].info.flags = SPA_PORT_INFO_FLAG_CAN_GIVE_BUFFER | - SPA_PORT_INFO_FLAG_CAN_USE_BUFFER | + this->ports[1].info.flags = SPA_PORT_INFO_FLAG_CAN_ALLOC_BUFFERS | + SPA_PORT_INFO_FLAG_CAN_USE_BUFFERS | SPA_PORT_INFO_FLAG_NO_REF; this->ports[0].status.flags = SPA_PORT_STATUS_FLAG_NEED_INPUT;