From 41399b0b25de6969f86684cd29f729836659cdb5 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 6 Mar 2017 15:48:04 +0100 Subject: [PATCH] Rework serialization Move serialization to the protocol, we now just send blocks of bytes over the connection and let the protocol deserialize them. --- pinos/client/connection.c | 1289 +----------------------- pinos/client/connection.h | 297 +----- pinos/client/context.c | 35 +- pinos/client/interfaces.h | 30 +- pinos/client/introspect.c | 9 +- pinos/client/introspect.h | 1 + pinos/client/protocol-native.c | 1055 +++++++++++++------ pinos/client/protocol-native.h | 17 +- pinos/client/proxy.h | 2 +- pinos/client/serialize.c | 166 --- pinos/client/serialize.h | 15 - pinos/client/stream.c | 49 +- pinos/client/utils.h | 10 + pinos/modules/module-access.c | 10 +- pinos/modules/module-protocol-native.c | 37 +- pinos/server/client-node.c | 18 +- pinos/server/client-node.h | 4 - pinos/server/node.c | 11 +- pinos/server/protocol-native.c | 951 +++++++++++------ pinos/server/protocol-native.h | 8 +- pinos/server/resource.h | 2 +- spa/include/spa/node.h | 4 +- spa/include/spa/pod-builder.h | 21 +- spa/include/spa/pod.h | 68 ++ spa/lib/debug.c | 7 + spa/tests/test-props2.c | 2 +- 26 files changed, 1617 insertions(+), 2501 deletions(-) diff --git a/pinos/client/connection.c b/pinos/client/connection.c index 35a89ce08..3c1f2da0e 100644 --- a/pinos/client/connection.c +++ b/pinos/client/connection.c @@ -26,7 +26,6 @@ #include #include "connection.h" -#include "serialize.h" #include "log.h" #define MAX_BUFFER_SIZE 1024 @@ -39,8 +38,6 @@ typedef struct { int fds[MAX_FDS]; unsigned int n_fds; - uint32_t dest_id; - PinosMessageType type; off_t offset; void *data; size_t size; @@ -53,9 +50,9 @@ struct _PinosConnection { int fd; }; -static int -connection_get_fd (PinosConnection *conn, - int index) +int +pinos_connection_get_fd (PinosConnection *conn, + int index) { if (index < 0 || index >= conn->in.n_fds) return -1; @@ -63,9 +60,9 @@ connection_get_fd (PinosConnection *conn, return conn->in.fds[index]; } -static int -connection_add_fd (PinosConnection *conn, - int fd) +int +pinos_connection_add_fd (PinosConnection *conn, + int fd) { int index, i; @@ -83,271 +80,6 @@ connection_add_fd (PinosConnection *conn, #define PINOS_DEBUG_MESSAGE(format,args...) pinos_log_trace(format,##args) -static void -connection_parse_client_update (PinosConnection *conn, PinosMessageClientUpdate *m) -{ - void *p; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageClientUpdate)); - if (m->props) - m->props = pinos_serialize_dict_deserialize (p, SPA_PTR_TO_INT (m->props)); -} - -static void -connection_parse_error (PinosConnection *conn, PinosMessageError *m) -{ - void *p; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageError)); - if (m->error) - m->error = SPA_MEMBER (p, SPA_PTR_TO_INT (m->error), const char); -} - -static void -connection_parse_notify_global (PinosConnection *conn, PinosMessageNotifyGlobal *ng) -{ - void *p; - - p = conn->in.data; - memcpy (ng, p, sizeof (PinosMessageNotifyGlobal)); - if (ng->type) - ng->type = SPA_MEMBER (p, SPA_PTR_TO_INT (ng->type), const char); -} - -static void -connection_parse_create_node (PinosConnection *conn, PinosMessageCreateNode *m) -{ - void *p; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageCreateNode)); - if (m->factory_name) - m->factory_name = SPA_MEMBER (p, SPA_PTR_TO_INT (m->factory_name), const char); - if (m->name) - m->name = SPA_MEMBER (p, SPA_PTR_TO_INT (m->name), const char); - if (m->props) - m->props = pinos_serialize_dict_deserialize (p, SPA_PTR_TO_INT (m->props)); -} - -static void -connection_parse_create_client_node (PinosConnection *conn, PinosMessageCreateClientNode *m) -{ - void *p; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageCreateClientNode)); - if (m->name) - m->name = SPA_MEMBER (p, SPA_PTR_TO_INT (m->name), const char); - if (m->props) - m->props = pinos_serialize_dict_deserialize (p, SPA_PTR_TO_INT (m->props)); -} - -static void -connection_parse_core_info (PinosConnection *conn, PinosMessageCoreInfo *m) -{ - void *p; - PinosCoreInfo *di; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageCoreInfo)); - if (m->info) { - m->info = SPA_MEMBER (p, SPA_PTR_TO_INT (m->info), PinosCoreInfo); - di = m->info; - - if (m->info->user_name) - m->info->user_name = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->user_name), const char); - if (m->info->host_name) - m->info->host_name = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->host_name), const char); - if (m->info->version) - m->info->version = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->version), const char); - if (m->info->name) - m->info->name = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->name), const char); - if (m->info->props) - m->info->props = pinos_serialize_dict_deserialize (di, SPA_PTR_TO_INT (m->info->props)); - } -} - -static void -connection_parse_module_info (PinosConnection *conn, PinosMessageModuleInfo *m) -{ - void *p; - PinosModuleInfo *di; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageModuleInfo)); - if (m->info) { - m->info = SPA_MEMBER (p, SPA_PTR_TO_INT (m->info), PinosModuleInfo); - di = m->info; - if (m->info->name) - m->info->name = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->name), const char); - if (m->info->filename) - m->info->filename = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->filename), const char); - if (m->info->args) - m->info->args = SPA_MEMBER (di, SPA_PTR_TO_INT (m->info->args), const char); - if (m->info->props) - m->info->props = pinos_serialize_dict_deserialize (di, SPA_PTR_TO_INT (m->info->props)); - } -} - -static void -connection_parse_node_info (PinosConnection *conn, PinosMessageNodeInfo *m) -{ - void *p; - PinosNodeInfo *di; - int i; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageNodeInfo)); - if (m->info) { - m->info = SPA_MEMBER (p, SPA_PTR_TO_INT (m->info), PinosNodeInfo); - di = m->info; - - if (di->name) - di->name = SPA_MEMBER (di, SPA_PTR_TO_INT (di->name), const char); - - if (di->input_formats) - di->input_formats = SPA_MEMBER (di, - SPA_PTR_TO_INT (di->input_formats), SpaFormat *); - for (i = 0; i < di->n_input_formats; i++) { - if (di->input_formats[i]) { - di->input_formats[i] = pinos_serialize_format_deserialize (di, - SPA_PTR_TO_INT (di->input_formats[i])); - } - } - - if (di->output_formats) - di->output_formats = SPA_MEMBER (di, - SPA_PTR_TO_INT (di->output_formats), SpaFormat *); - for (i = 0; i < di->n_output_formats; i++) { - if (di->output_formats[i]) { - di->output_formats[i] = pinos_serialize_format_deserialize (di, - SPA_PTR_TO_INT (di->output_formats[i])); - } - } - if (di->error) - di->error = SPA_MEMBER (di, SPA_PTR_TO_INT (di->error), const char); - if (di->props) - di->props = pinos_serialize_dict_deserialize (di, SPA_PTR_TO_INT (di->props)); - } -} - -static void -connection_parse_client_info (PinosConnection *conn, PinosMessageClientInfo *m) -{ - void *p; - PinosClientInfo *di; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageClientInfo)); - if (m->info) { - m->info = SPA_MEMBER (p, SPA_PTR_TO_INT (m->info), PinosClientInfo); - di = m->info; - if (m->info->props) - m->info->props = pinos_serialize_dict_deserialize (di, SPA_PTR_TO_INT (m->info->props)); - } -} - -static void -connection_parse_link_info (PinosConnection *conn, PinosMessageLinkInfo *m) -{ - void *p; - - p = conn->in.data; - memcpy (m, p, sizeof (PinosMessageLinkInfo)); - if (m->info) - m->info = SPA_MEMBER (p, SPA_PTR_TO_INT (m->info), PinosLinkInfo); -} - -static void -connection_parse_node_update (PinosConnection *conn, PinosMessageNodeUpdate *nu) -{ - memcpy (nu, conn->in.data, sizeof (PinosMessageNodeUpdate)); - if (nu->props) - nu->props = pinos_serialize_props_deserialize (conn->in.data, SPA_PTR_TO_INT (nu->props)); -} - -static void -connection_parse_port_update (PinosConnection *conn, PinosMessagePortUpdate *pu) -{ - void *p; - unsigned int i; - - memcpy (pu, conn->in.data, sizeof (PinosMessagePortUpdate)); - - p = conn->in.data; - - if (pu->possible_formats) - pu->possible_formats = SPA_MEMBER (p, - SPA_PTR_TO_INT (pu->possible_formats), SpaFormat *); - for (i = 0; i < pu->n_possible_formats; i++) { - if (pu->possible_formats[i]) { - pu->possible_formats[i] = pinos_serialize_format_deserialize (p, - SPA_PTR_TO_INT (pu->possible_formats[i])); - } - } - if (pu->format) - pu->format = pinos_serialize_format_deserialize (p, SPA_PTR_TO_INT (pu->format)); - if (pu->props) - pu->props = pinos_serialize_props_deserialize (p, SPA_PTR_TO_INT (pu->props)); - if (pu->info) - pu->info = pinos_serialize_port_info_deserialize (p, SPA_PTR_TO_INT (pu->info)); -} - -static void -connection_parse_set_format (PinosConnection *conn, PinosMessageSetFormat *cmd) -{ - memcpy (cmd, conn->in.data, sizeof (PinosMessageSetFormat)); - if (cmd->format) - cmd->format = pinos_serialize_format_deserialize (conn->in.data, SPA_PTR_TO_INT (cmd->format)); -} - -static void -connection_parse_use_buffers (PinosConnection *conn, PinosMessageUseBuffers *cmd) -{ - void *p; - unsigned int i; - - p = conn->in.data; - memcpy (cmd, p, sizeof (PinosMessageUseBuffers)); - if (cmd->buffers) - cmd->buffers = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->buffers), PinosClientNodeBuffer); - - for (i = 0; i < cmd->n_buffers; i++) { - if (cmd->buffers[i].buffer) - cmd->buffers[i].buffer = pinos_serialize_buffer_deserialize (conn->in.data, - SPA_PTR_TO_INT (cmd->buffers[i].buffer)); - } -} - -static void -connection_parse_node_event (PinosConnection *conn, PinosMessageNodeEvent *cmd) -{ - void *p = conn->in.data; - memcpy (cmd, p, sizeof (PinosMessageNodeEvent)); - if (cmd->event) - cmd->event = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->event), SpaNodeEvent); -} - -static void -connection_parse_node_command (PinosConnection *conn, PinosMessageNodeCommand *cmd) -{ - void *p = conn->in.data; - memcpy (cmd, p, sizeof (PinosMessageNodeCommand)); - if (cmd->command) - cmd->command = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->command), SpaNodeCommand); -} - -static void -connection_parse_port_command (PinosConnection *conn, PinosMessagePortCommand *cmd) -{ - void *p = conn->in.data; - memcpy (cmd, p, sizeof (PinosMessagePortCommand)); - if (cmd->command) - cmd->command = SPA_MEMBER (p, SPA_PTR_TO_INT (cmd->command), SpaNodeCommand); -} - static void * connection_ensure_size (PinosConnection *conn, ConnectionBuffer *buf, size_t size) { @@ -359,624 +91,6 @@ connection_ensure_size (PinosConnection *conn, ConnectionBuffer *buf, size_t siz return (uint8_t *) buf->buffer_data + buf->buffer_size; } -static void * -connection_add_message (PinosConnection *conn, - uint32_t dest_id, - PinosMessageType type, - size_t size) -{ - uint32_t *p; - ConnectionBuffer *buf = &conn->out; - - /* 4 for dest_id, 2 for cmd, 2 for size and size for payload */ - p = connection_ensure_size (conn, buf, 8 + size); - - buf->type = type; - buf->offset = buf->buffer_size; - buf->buffer_size += 8 + size; - - *p++ = dest_id; - *p++ = (type << 24) | (size & 0xffffff); - - return p; -} - -static void -connection_add_client_update (PinosConnection *conn, - uint32_t dest_id, - PinosMessageClientUpdate *m) -{ - size_t len; - void *p; - PinosMessageClientUpdate *d; - - len = sizeof (PinosMessageClientUpdate); - len += pinos_serialize_dict_get_size (m->props); - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_CLIENT_UPDATE, len); - memcpy (p, m, sizeof (PinosMessageClientUpdate)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageClientUpdate), void); - if (m->props) { - len = pinos_serialize_dict_serialize (p, m->props); - d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } -} - -static void -connection_add_error (PinosConnection *conn, - uint32_t dest_id, - PinosMessageError *m) -{ - size_t len; - void *p; - PinosMessageError *d; - - /* calc len */ - len = sizeof (PinosMessageError); - len += m->error ? strlen (m->error) + 1 : 0; - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_ERROR, len); - memcpy (p, m, sizeof (PinosMessageError)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageError), void); - if (m->error) { - strcpy (p, m->error); - d->error = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } -} - -static void -connection_add_notify_global (PinosConnection *conn, - uint32_t dest_id, - PinosMessageNotifyGlobal *m) -{ - size_t len; - void *p; - PinosMessageNotifyGlobal *d; - - /* calc len */ - len = sizeof (PinosMessageNotifyGlobal); - len += m->type ? strlen (m->type) + 1 : 0; - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_NOTIFY_GLOBAL, len); - memcpy (p, m, sizeof (PinosMessageNotifyGlobal)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageNotifyGlobal), void); - if (m->type) { - strcpy (p, m->type); - d->type = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } -} - -static void -connection_add_create_node (PinosConnection *conn, uint32_t dest_id, PinosMessageCreateNode *m) -{ - size_t len, slen; - void *p; - PinosMessageCreateNode *d; - - /* calc len */ - len = sizeof (PinosMessageCreateNode); - len += m->factory_name ? strlen (m->factory_name) + 1 : 0; - len += m->name ? strlen (m->name) + 1 : 0; - len += pinos_serialize_dict_get_size (m->props); - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_CREATE_NODE, len); - memcpy (p, m, sizeof (PinosMessageCreateNode)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageCreateNode), void); - if (m->factory_name) { - slen = strlen (m->factory_name) + 1; - memcpy (p, m->factory_name, slen); - d->factory_name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p += slen; - } - if (m->name) { - slen = strlen (m->name) + 1; - memcpy (p, m->name, slen); - d->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p += slen; - } - if (m->props) { - len = pinos_serialize_dict_serialize (p, m->props); - d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } -} - -static void -connection_add_create_client_node (PinosConnection *conn, uint32_t dest_id, PinosMessageCreateClientNode *m) -{ - size_t len, slen; - void *p; - PinosMessageCreateClientNode *d; - - /* calc len */ - len = sizeof (PinosMessageCreateClientNode); - len += m->name ? strlen (m->name) + 1 : 0; - len += pinos_serialize_dict_get_size (m->props); - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_CREATE_CLIENT_NODE, len); - memcpy (p, m, sizeof (PinosMessageCreateClientNode)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageCreateClientNode), void); - if (m->name) { - slen = strlen (m->name) + 1; - memcpy (p, m->name, slen); - d->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p += slen; - } - if (m->props) { - len = pinos_serialize_dict_serialize (p, m->props); - d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } -} - -static void -connection_add_core_info (PinosConnection *conn, uint32_t dest_id, PinosMessageCoreInfo *m) -{ - size_t len, slen; - void *p; - PinosMessageCoreInfo *d; - - /* calc len */ - len = sizeof (PinosMessageCoreInfo); - if (m->info) { - len += sizeof (PinosCoreInfo); - len += m->info->user_name ? strlen (m->info->user_name) + 1 : 0; - len += m->info->host_name ? strlen (m->info->host_name) + 1 : 0; - len += m->info->version ? strlen (m->info->version) + 1 : 0; - len += m->info->name ? strlen (m->info->name) + 1 : 0; - len += pinos_serialize_dict_get_size (m->info->props); - } - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_CORE_INFO, len); - memcpy (p, m, sizeof (PinosMessageCoreInfo)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageCoreInfo), void); - if (m->info) { - PinosCoreInfo *di; - - memcpy (p, m->info, sizeof (PinosCoreInfo)); - di = p; - - d->info = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - - p = SPA_MEMBER (p, sizeof (PinosCoreInfo), void); - if (m->info->user_name) { - slen = strlen (m->info->user_name) + 1; - memcpy (p, m->info->user_name, slen); - di->user_name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->host_name) { - slen = strlen (m->info->host_name) + 1; - memcpy (p, m->info->host_name, slen); - di->host_name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->version) { - slen = strlen (m->info->version) + 1; - memcpy (p, m->info->version, slen); - di->version = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->name) { - slen = strlen (m->info->name) + 1; - memcpy (p, m->info->name, slen); - di->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->props) { - len = pinos_serialize_dict_serialize (p, m->info->props); - di->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - } - } -} - -static void -connection_add_module_info (PinosConnection *conn, uint32_t dest_id, PinosMessageModuleInfo *m) -{ - size_t len, slen; - void *p; - PinosMessageModuleInfo *d; - - /* calc len */ - len = sizeof (PinosMessageModuleInfo); - if (m->info) { - len += sizeof (PinosModuleInfo); - len += m->info->name ? strlen (m->info->name) + 1 : 0; - len += m->info->filename ? strlen (m->info->filename) + 1 : 0; - len += m->info->args ? strlen (m->info->args) + 1 : 0; - len += pinos_serialize_dict_get_size (m->info->props); - } - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_MODULE_INFO, len); - memcpy (p, m, sizeof (PinosMessageModuleInfo)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageModuleInfo), void); - if (m->info) { - PinosModuleInfo *di; - - memcpy (p, m->info, sizeof (PinosModuleInfo)); - d->info = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - di = p; - - p = SPA_MEMBER (p, sizeof (PinosModuleInfo), void); - if (m->info->name) { - slen = strlen (m->info->name) + 1; - memcpy (p, m->info->name, slen); - di->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->filename) { - slen = strlen (m->info->filename) + 1; - memcpy (p, m->info->filename, slen); - di->filename = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->args) { - slen = strlen (m->info->args) + 1; - memcpy (p, m->info->args, slen); - di->args = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->props) { - len = pinos_serialize_dict_serialize (p, m->info->props); - di->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - } - } -} - -static void -connection_add_node_info (PinosConnection *conn, uint32_t dest_id, PinosMessageNodeInfo *m) -{ - size_t len, slen; - void *p; - PinosMessageNodeInfo *d; - int i; - - /* calc len */ - len = sizeof (PinosMessageNodeInfo); - if (m->info) { - len += sizeof (PinosNodeInfo); - len += m->info->name ? strlen (m->info->name) + 1 : 0; - len += m->info->n_input_formats * sizeof (SpaFormat *); - for (i = 0; i < m->info->n_input_formats; i++) - len += pinos_serialize_format_get_size (m->info->input_formats[i]); - len += m->info->n_output_formats * sizeof (SpaFormat *); - for (i = 0; i < m->info->n_output_formats; i++) - len += pinos_serialize_format_get_size (m->info->output_formats[i]); - len += m->info->error ? strlen (m->info->error) + 1 : 0; - len += pinos_serialize_dict_get_size (m->info->props); - } - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_NODE_INFO, len); - memcpy (p, m, sizeof (PinosMessageNodeInfo)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageNodeInfo), void); - if (m->info) { - PinosNodeInfo *di; - SpaFormat **ifa, **ofa; - - memcpy (p, m->info, sizeof (PinosNodeInfo)); - d->info = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - di = p; - - p = SPA_MEMBER (p, sizeof (PinosNodeInfo), void); - ifa = p; - if (m->info->n_input_formats) - di->input_formats = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - else - di->input_formats = 0; - p = SPA_MEMBER (p, sizeof (SpaFormat*) * m->info->n_input_formats, void); - - ofa = p; - if (m->info->n_output_formats) - di->output_formats = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - else - di->output_formats = 0; - p = SPA_MEMBER (p, sizeof (SpaFormat*) * m->info->n_output_formats, void); - - if (m->info->name) { - slen = strlen (m->info->name) + 1; - memcpy (p, m->info->name, slen); - di->name = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - for (i = 0; i < m->info->n_input_formats; i++) { - len = pinos_serialize_format_serialize (p, m->info->input_formats[i]); - ifa[i] = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p = SPA_MEMBER (p, len, void); - } - for (i = 0; i < m->info->n_output_formats; i++) { - len = pinos_serialize_format_serialize (p, m->info->output_formats[i]); - ofa[i] = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p = SPA_MEMBER (p, len, void); - } - if (m->info->error) { - slen = strlen (m->info->error) + 1; - memcpy (p, m->info->error, slen); - di->error = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += slen; - } - if (m->info->props) { - len = pinos_serialize_dict_serialize (p, m->info->props); - di->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - p += len; - } - } -} - -static void -connection_add_client_info (PinosConnection *conn, uint32_t dest_id, PinosMessageClientInfo *m) -{ - size_t len; - void *p; - PinosMessageClientInfo *d; - - /* calc len */ - len = sizeof (PinosMessageClientInfo); - if (m->info) { - len += sizeof (PinosClientInfo); - len += pinos_serialize_dict_get_size (m->info->props); - } - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_CLIENT_INFO, len); - memcpy (p, m, sizeof (PinosMessageClientInfo)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageClientInfo), void); - if (m->info) { - PinosClientInfo *di; - - memcpy (p, m->info, sizeof (PinosClientInfo)); - d->info = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - di = p; - - p = SPA_MEMBER (p, sizeof (PinosClientInfo), void); - if (m->info->props) { - len = pinos_serialize_dict_serialize (p, m->info->props); - di->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, di)); - } - } -} - -static void -connection_add_link_info (PinosConnection *conn, uint32_t dest_id, PinosMessageLinkInfo *m) -{ - size_t len; - void *p; - PinosMessageLinkInfo *d; - - /* calc len */ - len = sizeof (PinosMessageLinkInfo); - if (m->info) { - len += sizeof (PinosLinkInfo); - } - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_LINK_INFO, len); - memcpy (p, m, sizeof (PinosMessageLinkInfo)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageLinkInfo), void); - if (m->info) { - memcpy (p, m->info, sizeof (PinosLinkInfo)); - d->info = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } -} - -static void -connection_add_node_update (PinosConnection *conn, uint32_t dest_id, PinosMessageNodeUpdate *nu) -{ - size_t len; - void *p; - PinosMessageNodeUpdate *d; - - /* calc len */ - len = sizeof (PinosMessageNodeUpdate); - len += pinos_serialize_props_get_size (nu->props); - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_NODE_UPDATE, len); - memcpy (p, nu, sizeof (PinosMessageNodeUpdate)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageNodeUpdate), void); - if (nu->props) { - len = pinos_serialize_props_serialize (p, nu->props); - d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } else { - d->props = 0; - } -} - -static void -connection_add_port_update (PinosConnection *conn, uint32_t dest_id, PinosMessagePortUpdate *pu) -{ - size_t len; - void *p; - int i; - SpaFormat **bfa; - PinosMessagePortUpdate *d; - - /* calc len */ - len = sizeof (PinosMessagePortUpdate); - len += pu->n_possible_formats * sizeof (SpaFormat *); - for (i = 0; i < pu->n_possible_formats; i++) { - len += pinos_serialize_format_get_size (pu->possible_formats[i]); - } - len += pinos_serialize_format_get_size (pu->format); - len += pinos_serialize_props_get_size (pu->props); - if (pu->info) - len += pinos_serialize_port_info_get_size (pu->info); - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_PORT_UPDATE, len); - memcpy (p, pu, sizeof (PinosMessagePortUpdate)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessagePortUpdate), void); - bfa = p; - if (pu->n_possible_formats) - d->possible_formats = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - else - d->possible_formats = 0; - - p = SPA_MEMBER (p, sizeof (SpaFormat*) * pu->n_possible_formats, void); - - for (i = 0; i < pu->n_possible_formats; i++) { - len = pinos_serialize_format_serialize (p, pu->possible_formats[i]); - bfa[i] = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p = SPA_MEMBER (p, len, void); - } - if (pu->format) { - len = pinos_serialize_format_serialize (p, pu->format); - d->format = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p = SPA_MEMBER (p, len, void); - } else { - d->format = 0; - } - if (pu->props) { - len = pinos_serialize_props_serialize (p, pu->props); - d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p = SPA_MEMBER (p, len, void); - } else { - d->props = 0; - } - if (pu->info) { - len = pinos_serialize_port_info_serialize (p, pu->info); - d->info = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p = SPA_MEMBER (p, len, void); - } else { - d->info = 0; - } -} - -static void -connection_add_set_format (PinosConnection *conn, uint32_t dest_id, PinosMessageSetFormat *sf) -{ - size_t len; - void *p; - - /* calculate length */ - /* port_id + format + mask */ - len = sizeof (PinosMessageSetFormat) + pinos_serialize_format_get_size (sf->format); - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_SET_FORMAT, len); - memcpy (p, sf, sizeof (PinosMessageSetFormat)); - sf = p; - - p = SPA_MEMBER (sf, sizeof (PinosMessageSetFormat), void); - if (sf->format) { - len = pinos_serialize_format_serialize (p, sf->format); - sf->format = SPA_INT_TO_PTR (SPA_PTRDIFF (p, sf)); - } else - sf->format = 0; -} - -static void -connection_add_use_buffers (PinosConnection *conn, uint32_t dest_id, PinosMessageUseBuffers *ub) -{ - size_t len; - int i; - PinosMessageUseBuffers *d; - PinosClientNodeBuffer *b; - void *p; - - /* calculate length */ - len = sizeof (PinosMessageUseBuffers); - len += ub->n_buffers * sizeof (PinosClientNodeBuffer); - for (i = 0; i < ub->n_buffers; i++) - len += pinos_serialize_buffer_get_size (ub->buffers[i].buffer); - - d = connection_add_message (conn, dest_id, PINOS_MESSAGE_USE_BUFFERS, len); - memcpy (d, ub, sizeof (PinosMessageUseBuffers)); - - b = SPA_MEMBER (d, sizeof (PinosMessageUseBuffers), void); - p = SPA_MEMBER (b, ub->n_buffers * sizeof (PinosClientNodeBuffer), void); - - if (d->n_buffers) - d->buffers = SPA_INT_TO_PTR (SPA_PTRDIFF (b, d)); - else - d->buffers = 0; - - for (i = 0; i < ub->n_buffers; i++) { - memcpy (&b[i], &ub->buffers[i], sizeof (PinosClientNodeBuffer)); - len = pinos_serialize_buffer_serialize (p, b[i].buffer); - b[i].buffer = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - p += len; - } -} - -static void -connection_add_node_event (PinosConnection *conn, uint32_t dest_id, PinosMessageNodeEvent *ev) -{ - size_t len; - void *p; - PinosMessageNodeEvent *d; - - /* calculate length */ - len = sizeof (PinosMessageNodeEvent); - len += ev->event->size; - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_NODE_EVENT, len); - memcpy (p, ev, sizeof (PinosMessageNodeEvent)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageNodeEvent), void); - d->event = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - - memcpy (p, ev->event, ev->event->size); -} - -static void -connection_add_node_command (PinosConnection *conn, uint32_t dest_id, PinosMessageNodeCommand *cm) -{ - size_t len; - void *p; - PinosMessageNodeCommand *d; - - /* calculate length */ - len = sizeof (PinosMessageNodeCommand); - len += cm->command->size; - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_NODE_COMMAND, len); - memcpy (p, cm, sizeof (PinosMessageNodeCommand)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessageNodeCommand), void); - d->command = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - - memcpy (p, cm->command, cm->command->size); -} - -static void -connection_add_port_command (PinosConnection *conn, uint32_t dest_id, PinosMessagePortCommand *cm) -{ - size_t len; - void *p; - PinosMessagePortCommand *d; - - /* calculate length */ - len = sizeof (PinosMessagePortCommand); - len += cm->command->size; - - p = connection_add_message (conn, dest_id, PINOS_MESSAGE_PORT_COMMAND, len); - memcpy (p, cm, sizeof (PinosMessagePortCommand)); - d = p; - - p = SPA_MEMBER (d, sizeof (PinosMessagePortCommand), void); - d->command = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - - memcpy (p, cm->command, cm->command->size); -} - static bool refill_buffer (PinosConnection *conn, ConnectionBuffer *buf) { @@ -1031,7 +145,6 @@ static void clear_buffer (ConnectionBuffer *buf) { buf->n_fds = 0; - buf->type = PINOS_MESSAGE_INVALID; buf->offset = 0; buf->size = 0; buf->buffer_size = 0; @@ -1086,8 +199,9 @@ pinos_connection_destroy (PinosConnection *conn) */ bool pinos_connection_get_next (PinosConnection *conn, - PinosMessageType *type, + uint8_t *opcode, uint32_t *dest_id, + void **dt, size_t *sz) { size_t len, size; @@ -1130,8 +244,8 @@ again: data += 8; size -= 8; - buf->dest_id = p[0]; - buf->type = p[1] >> 24; + *dest_id = p[0]; + *opcode = p[1] >> 24; len = p[1] & 0xffffff; if (len > size) { @@ -1143,379 +257,38 @@ again: buf->data = data; buf->offset += 8; - *type = buf->type; - *dest_id = buf->dest_id; + *dt = buf->data; *sz = buf->size; return true; } -bool -pinos_connection_parse_message (PinosConnection *conn, - void *message) +void * +pinos_connection_begin_write (PinosConnection *conn, + size_t size) { - spa_return_val_if_fail (conn != NULL, false); - - switch (conn->in.type) { - case PINOS_MESSAGE_CLIENT_UPDATE: - connection_parse_client_update (conn, message); - break; - - case PINOS_MESSAGE_SYNC: - if (conn->in.size < sizeof (PinosMessageSync)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageSync)); - break; - - case PINOS_MESSAGE_NOTIFY_DONE: - if (conn->in.size < sizeof (PinosMessageNotifyDone)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageNotifyDone)); - break; - - case PINOS_MESSAGE_ERROR: - connection_parse_error (conn, message); - break; - - case PINOS_MESSAGE_GET_REGISTRY: - if (conn->in.size < sizeof (PinosMessageGetRegistry)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageGetRegistry)); - break; - - case PINOS_MESSAGE_BIND: - if (conn->in.size < sizeof (PinosMessageBind)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageBind)); - break; - - case PINOS_MESSAGE_NOTIFY_GLOBAL: - connection_parse_notify_global (conn, message); - break; - - case PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE: - if (conn->in.size < sizeof (PinosMessageNotifyGlobalRemove)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageNotifyGlobalRemove)); - break; - - case PINOS_MESSAGE_CREATE_NODE: - connection_parse_create_node (conn, message); - break; - - case PINOS_MESSAGE_CREATE_NODE_DONE: - if (conn->in.size < sizeof (PinosMessageCreateNodeDone)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageCreateNodeDone)); - break; - - case PINOS_MESSAGE_CREATE_CLIENT_NODE: - connection_parse_create_client_node (conn, message); - break; - - case PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE: - { - PinosMessageCreateClientNodeDone *d = message; - if (conn->in.size < sizeof (PinosMessageCreateClientNodeDone)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageCreateClientNodeDone)); - d->datafd = connection_get_fd (conn, d->datafd); - break; - } - case PINOS_MESSAGE_DESTROY: - if (conn->in.size < sizeof (PinosMessageDestroy)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageDestroy)); - break; - - case PINOS_MESSAGE_REMOVE_ID: - if (conn->in.size < sizeof (PinosMessageRemoveId)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageRemoveId)); - break; - - case PINOS_MESSAGE_CORE_INFO: - connection_parse_core_info (conn, message); - break; - - case PINOS_MESSAGE_MODULE_INFO: - connection_parse_module_info (conn, message); - break; - - case PINOS_MESSAGE_NODE_INFO: - connection_parse_node_info (conn, message); - break; - - case PINOS_MESSAGE_CLIENT_INFO: - connection_parse_client_info (conn, message); - break; - - case PINOS_MESSAGE_LINK_INFO: - connection_parse_link_info (conn, message); - break; - - /* C -> S */ - case PINOS_MESSAGE_NODE_UPDATE: - connection_parse_node_update (conn, message); - break; - - case PINOS_MESSAGE_PORT_UPDATE: - connection_parse_port_update (conn, message); - break; - - case PINOS_MESSAGE_NODE_STATE_CHANGE: - if (conn->in.size < sizeof (PinosMessageNodeStateChange)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageNodeStateChange)); - break; - - /* S -> C */ - case PINOS_MESSAGE_ADD_PORT: - if (conn->in.size < sizeof (PinosMessageAddPort)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageAddPort)); - break; - - case PINOS_MESSAGE_REMOVE_PORT: - if (conn->in.size < sizeof (PinosMessageRemovePort)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageRemovePort)); - break; - - case PINOS_MESSAGE_SET_FORMAT: - connection_parse_set_format (conn, message); - break; - - case PINOS_MESSAGE_SET_PROPERTY: - pinos_log_warn ("implement iter of %d", conn->in.type); - break; - - /* bidirectional */ - case PINOS_MESSAGE_ADD_MEM: - { - PinosMessageAddMem *d = message; - if (conn->in.size < sizeof (PinosMessageAddMem)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageAddMem)); - d->memfd = connection_get_fd (conn, d->memfd); - break; - } - - case PINOS_MESSAGE_USE_BUFFERS: - connection_parse_use_buffers (conn, message); - break; - - case PINOS_MESSAGE_NODE_EVENT: - connection_parse_node_event (conn, message); - break; - - case PINOS_MESSAGE_NODE_COMMAND: - connection_parse_node_command (conn, message); - break; - - case PINOS_MESSAGE_PORT_COMMAND: - connection_parse_port_command (conn, message); - break; - - case PINOS_MESSAGE_TRANSPORT_UPDATE: - { - PinosMessageTransportUpdate *d = message; - if (conn->in.size < sizeof (PinosMessageTransportUpdate)) - return false; - memcpy (message, conn->in.data, sizeof (PinosMessageTransportUpdate)); - d->memfd = connection_get_fd (conn, d->memfd); - break; - } - - case PINOS_MESSAGE_INVALID: - pinos_log_error ("invalid message %d received", conn->in.type); - return false; - } - return true; + uint32_t *p; + ConnectionBuffer *buf = &conn->out; + /* 4 for dest_id, 1 for opcode, 3 for size and size for payload */ + p = connection_ensure_size (conn, buf, 8 + size); + return p + 2; } -/** - * pinos_connection_add_message: - * @conn: a #PinosConnection - * @type: a #PinosMessageType - * @message: a message - * - * Add a @cmd to @conn with data from @message. - * - * Returns: %true on success. - */ -bool -pinos_connection_add_message (PinosConnection *conn, - uint32_t dest_id, - PinosMessageType type, - void *message) +void +pinos_connection_end_write (PinosConnection *conn, + uint32_t dest_id, + uint8_t opcode, + size_t size) { - void *p; + uint32_t *p; + ConnectionBuffer *buf = &conn->out; - spa_return_val_if_fail (conn != NULL, false); - spa_return_val_if_fail (message != NULL, false); + p = connection_ensure_size (conn, buf, 8 + size); + *p++ = dest_id; + *p++ = (opcode << 24) | (size & 0xffffff); - switch (type) { - case PINOS_MESSAGE_CLIENT_UPDATE: - connection_add_client_update (conn, dest_id, message); - break; - - case PINOS_MESSAGE_SYNC: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageSync)); - memcpy (p, message, sizeof (PinosMessageSync)); - break; - - case PINOS_MESSAGE_NOTIFY_DONE: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageNotifyDone)); - memcpy (p, message, sizeof (PinosMessageNotifyDone)); - break; - - case PINOS_MESSAGE_ERROR: - connection_add_error (conn, dest_id, message); - break; - - case PINOS_MESSAGE_GET_REGISTRY: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageGetRegistry)); - memcpy (p, message, sizeof (PinosMessageGetRegistry)); - break; - - case PINOS_MESSAGE_BIND: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageBind)); - memcpy (p, message, sizeof (PinosMessageBind)); - break; - - case PINOS_MESSAGE_NOTIFY_GLOBAL: - connection_add_notify_global (conn, dest_id, message); - break; - - case PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageNotifyGlobalRemove)); - memcpy (p, message, sizeof (PinosMessageNotifyGlobalRemove)); - break; - - case PINOS_MESSAGE_CREATE_NODE: - connection_add_create_node (conn, dest_id, message); - break; - - case PINOS_MESSAGE_CREATE_NODE_DONE: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageCreateNodeDone)); - memcpy (p, message, sizeof (PinosMessageCreateNodeDone)); - break; - - case PINOS_MESSAGE_CREATE_CLIENT_NODE: - connection_add_create_client_node (conn, dest_id, message); - break; - - case PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE: - { - PinosMessageCreateClientNodeDone *d; - d = connection_add_message (conn, dest_id, type, sizeof (PinosMessageCreateClientNodeDone)); - memcpy (d, message, sizeof (PinosMessageCreateClientNodeDone)); - d->datafd = connection_add_fd (conn, d->datafd); - break; - } - case PINOS_MESSAGE_DESTROY: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageDestroy)); - memcpy (p, message, sizeof (PinosMessageDestroy)); - break; - - case PINOS_MESSAGE_REMOVE_ID: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageRemoveId)); - memcpy (p, message, sizeof (PinosMessageRemoveId)); - break; - - case PINOS_MESSAGE_CORE_INFO: - connection_add_core_info (conn, dest_id, message); - break; - - case PINOS_MESSAGE_MODULE_INFO: - connection_add_module_info (conn, dest_id, message); - break; - - case PINOS_MESSAGE_NODE_INFO: - connection_add_node_info (conn, dest_id, message); - break; - - case PINOS_MESSAGE_CLIENT_INFO: - connection_add_client_info (conn, dest_id, message); - break; - - case PINOS_MESSAGE_LINK_INFO: - connection_add_link_info (conn, dest_id, message); - break; - - /* C -> S */ - case PINOS_MESSAGE_NODE_UPDATE: - connection_add_node_update (conn, dest_id, message); - break; - - case PINOS_MESSAGE_PORT_UPDATE: - connection_add_port_update (conn, dest_id, message); - break; - - case PINOS_MESSAGE_NODE_STATE_CHANGE: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageNodeStateChange)); - memcpy (p, message, sizeof (PinosMessageNodeStateChange)); - break; - - /* S -> C */ - case PINOS_MESSAGE_ADD_PORT: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageAddPort)); - memcpy (p, message, sizeof (PinosMessageAddPort)); - break; - - case PINOS_MESSAGE_REMOVE_PORT: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageRemovePort)); - memcpy (p, message, sizeof (PinosMessageRemovePort)); - break; - - case PINOS_MESSAGE_SET_FORMAT: - connection_add_set_format (conn, dest_id, message); - break; - - case PINOS_MESSAGE_SET_PROPERTY: - pinos_log_warn ("implement builder of %d", type); - break; - - /* bidirectional */ - case PINOS_MESSAGE_ADD_MEM: - { - PinosMessageAddMem *d; - d = connection_add_message (conn, dest_id, type, sizeof (PinosMessageAddMem)); - memcpy (d, message, sizeof (PinosMessageAddMem)); - d->memfd = connection_add_fd (conn, d->memfd); - break; - } - - case PINOS_MESSAGE_USE_BUFFERS: - connection_add_use_buffers (conn, dest_id, message); - break; - - case PINOS_MESSAGE_NODE_EVENT: - connection_add_node_event (conn, dest_id, message); - break; - - case PINOS_MESSAGE_NODE_COMMAND: - connection_add_node_command (conn, dest_id, message); - break; - - case PINOS_MESSAGE_PORT_COMMAND: - connection_add_port_command (conn, dest_id, message); - break; - - case PINOS_MESSAGE_TRANSPORT_UPDATE: - { - PinosMessageTransportUpdate *d; - d = connection_add_message (conn, dest_id, type, sizeof (PinosMessageTransportUpdate)); - memcpy (d, message, sizeof (PinosMessageTransportUpdate)); - d->memfd = connection_add_fd (conn, d->memfd); - break; - } - - case PINOS_MESSAGE_INVALID: - return false; - } - return true; + buf->buffer_size += 8 + size; + pinos_connection_flush (conn); } bool diff --git a/pinos/client/connection.h b/pinos/client/connection.h index 7e9890ee3..7cbf94632 100644 --- a/pinos/client/connection.h +++ b/pinos/client/connection.h @@ -25,300 +25,29 @@ extern "C" { #endif #include -#include -#include -#include -#include - -#include typedef struct _PinosConnection PinosConnection; -typedef enum { - PINOS_MESSAGE_INVALID = 0, - - PINOS_MESSAGE_CLIENT_UPDATE, - - PINOS_MESSAGE_SYNC, - PINOS_MESSAGE_NOTIFY_DONE, - PINOS_MESSAGE_ERROR, - PINOS_MESSAGE_GET_REGISTRY, - PINOS_MESSAGE_REMOVE_ID, - PINOS_MESSAGE_CORE_INFO, - - PINOS_MESSAGE_BIND, - PINOS_MESSAGE_NOTIFY_GLOBAL, - PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE, - - PINOS_MESSAGE_CREATE_NODE, - PINOS_MESSAGE_CREATE_NODE_DONE, - - PINOS_MESSAGE_CREATE_CLIENT_NODE, - PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE, - - PINOS_MESSAGE_DESTROY, - - PINOS_MESSAGE_MODULE_INFO, - PINOS_MESSAGE_NODE_INFO, - PINOS_MESSAGE_CLIENT_INFO, - PINOS_MESSAGE_LINK_INFO, - - /* client to server */ - PINOS_MESSAGE_NODE_UPDATE, - PINOS_MESSAGE_PORT_UPDATE, - PINOS_MESSAGE_NODE_STATE_CHANGE, - PINOS_MESSAGE_NODE_EVENT, - - /* server to client */ - PINOS_MESSAGE_TRANSPORT_UPDATE, - - PINOS_MESSAGE_ADD_PORT, - PINOS_MESSAGE_REMOVE_PORT, - - PINOS_MESSAGE_SET_FORMAT, - PINOS_MESSAGE_SET_PROPERTY, - - PINOS_MESSAGE_NODE_COMMAND, - PINOS_MESSAGE_PORT_COMMAND, - - /* both */ - PINOS_MESSAGE_ADD_MEM, - PINOS_MESSAGE_USE_BUFFERS, - -} PinosMessageType; - -#include - -/* PINOS_MESSAGE_CLIENT_UPDATE */ -typedef struct { - const SpaDict *props; -} PinosMessageClientUpdate; - -/* PINOS_MESSAGE_SYNC */ -typedef struct { - uint32_t seq; -} PinosMessageSync; - -/* PINOS_MESSAGE_NOTIFY_DONE */ -typedef struct { - uint32_t seq; -} PinosMessageNotifyDone; - -/* PINOS_MESSAGE_ERROR */ -typedef struct { - uint32_t id; - SpaResult res; - const char *error; -} PinosMessageError; - -/* PINOS_MESSAGE_GET_REGISTRY */ -typedef struct { - uint32_t seq; - uint32_t new_id; -} PinosMessageGetRegistry; - -/* PINOS_MESSAGE_REMOVE_ID */ -typedef struct { - uint32_t id; -} PinosMessageRemoveId; - -/* PINOS_MESSAGE_CORE_INFO */ -typedef struct { - PinosCoreInfo *info; -} PinosMessageCoreInfo; - -/* PINOS_MESSAGE_MODULE_INFO */ -typedef struct { - PinosModuleInfo *info; -} PinosMessageModuleInfo; - -/* PINOS_MESSAGE_NODE_INFO */ -typedef struct { - PinosNodeInfo *info; -} PinosMessageNodeInfo; - -/* PINOS_MESSAGE_CLIENT_INFO */ -typedef struct { - PinosClientInfo *info; -} PinosMessageClientInfo; - -/* PINOS_MESSAGE_LINK_INFO */ -typedef struct { - PinosLinkInfo *info; -} PinosMessageLinkInfo; - -/* PINOS_MESSAGE_BIND */ -typedef struct { - uint32_t id; - uint32_t new_id; -} PinosMessageBind; - -/* PINOS_MESSAGE_NOTIFY_GLOBAL */ -typedef struct { - uint32_t id; - const char *type; -} PinosMessageNotifyGlobal; - -/* PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE */ -typedef struct { - uint32_t id; -} PinosMessageNotifyGlobalRemove; - -/* PINOS_MESSAGE_CREATE_NODE */ -typedef struct { - uint32_t seq; - const char *factory_name; - const char *name; - const SpaDict *props; - uint32_t new_id; -} PinosMessageCreateNode; - -/* PINOS_MESSAGE_CREATE_NODE_DONE */ -typedef struct { - uint32_t seq; -} PinosMessageCreateNodeDone; - -/* PINOS_MESSAGE_CREATE_CLIENT_NODE */ -typedef struct { - uint32_t seq; - const char *name; - const SpaDict *props; - uint32_t new_id; -} PinosMessageCreateClientNode; - -/* PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE */ -typedef struct { - uint32_t seq; - int datafd; -} PinosMessageCreateClientNodeDone; - -/* PINOS_MESSAGE_DESTROY */ -typedef struct { - uint32_t seq; -} PinosMessageDestroy; - -/* PINOS_MESSAGE_NODE_UPDATE */ -typedef struct { -#define PINOS_MESSAGE_NODE_UPDATE_MAX_INPUTS (1 << 0) -#define PINOS_MESSAGE_NODE_UPDATE_MAX_OUTPUTS (1 << 1) -#define PINOS_MESSAGE_NODE_UPDATE_PROPS (1 << 2) - uint32_t change_mask; - unsigned int max_input_ports; - unsigned int max_output_ports; - const SpaProps *props; -} PinosMessageNodeUpdate; - -/* PINOS_MESSAGE_PORT_UPDATE */ -typedef struct { - SpaDirection direction; - uint32_t port_id; -#define PINOS_MESSAGE_PORT_UPDATE_POSSIBLE_FORMATS (1 << 0) -#define PINOS_MESSAGE_PORT_UPDATE_FORMAT (1 << 1) -#define PINOS_MESSAGE_PORT_UPDATE_PROPS (1 << 2) -#define PINOS_MESSAGE_PORT_UPDATE_INFO (1 << 3) - uint32_t change_mask; - unsigned int n_possible_formats; - SpaFormat **possible_formats; - SpaFormat *format; - const SpaProps *props; - const SpaPortInfo *info; -} PinosMessagePortUpdate; - -/* PINOS_MESSAGE_NODE_STATE_CHANGE */ -typedef struct { - SpaNodeState state; -} PinosMessageNodeStateChange; - -/* PINOS_MESSAGE_NODE_EVENT */ -typedef struct { - SpaNodeEvent *event; -} PinosMessageNodeEvent; - -/* PINOS_MESSAGE_ADD_PORT */ -typedef struct { - uint32_t seq; - SpaDirection direction; - uint32_t port_id; -} PinosMessageAddPort; - -/* PINOS_MESSAGE_REMOVE_PORT */ -typedef struct { - uint32_t seq; - SpaDirection direction; - uint32_t port_id; -} PinosMessageRemovePort; - - -/* PINOS_MESSAGE_SET_FORMAT */ -typedef struct { - uint32_t seq; - SpaDirection direction; - uint32_t port_id; - SpaPortFormatFlags flags; - const SpaFormat *format; -} PinosMessageSetFormat; - -/* PINOS_MESSAGE_SET_PROPERTY */ -typedef struct { - uint32_t seq; - uint32_t id; - size_t size; - void *value; -} PinosMessageSetProperty; - -/* PINOS_MESSAGE_NODE_COMMAND */ -typedef struct { - uint32_t seq; - SpaNodeCommand *command; -} PinosMessageNodeCommand; - -/* PINOS_MESSAGE_PORT_COMMAND */ -typedef struct { - uint32_t port_id; - SpaNodeCommand *command; -} PinosMessagePortCommand; - -/* PINOS_MESSAGE_TRANSPORT_UPDATE */ -typedef struct { - int memfd; - off_t offset; - size_t size; -} PinosMessageTransportUpdate; - -/* PINOS_MESSAGE_ADD_MEM */ -typedef struct { - SpaDirection direction; - uint32_t port_id; - uint32_t mem_id; - SpaDataType type; - int memfd; - uint32_t flags; - off_t offset; - size_t size; -} PinosMessageAddMem; - -/* PINOS_MESSAGE_USE_BUFFERS */ -typedef struct { - uint32_t seq; - SpaDirection direction; - uint32_t port_id; - unsigned int n_buffers; - PinosClientNodeBuffer *buffers; -} PinosMessageUseBuffers; - PinosConnection * pinos_connection_new (int fd); void pinos_connection_destroy (PinosConnection *conn); +int pinos_connection_add_fd (PinosConnection *conn, + int fd); +int pinos_connection_get_fd (PinosConnection *conn, + int index); + bool pinos_connection_get_next (PinosConnection *conn, - PinosMessageType *type, + uint8_t *opcode, uint32_t *dest_id, + void **data, size_t *size); -bool pinos_connection_parse_message (PinosConnection *conn, - void *msg); -bool pinos_connection_add_message (PinosConnection *conn, + +void * pinos_connection_begin_write (PinosConnection *conn, + size_t size); +void pinos_connection_end_write (PinosConnection *conn, uint32_t dest_id, - PinosMessageType type, - void *msg); + uint8_t opcode, + size_t size); bool pinos_connection_flush (PinosConnection *conn); bool pinos_connection_clear (PinosConnection *conn); diff --git a/pinos/client/context.c b/pinos/client/context.c index 380fcaea5..d76443909 100644 --- a/pinos/client/context.c +++ b/pinos/client/context.c @@ -303,7 +303,7 @@ registry_event_global (void *object, goto no_mem; proxy->event = &node_events; - proxy->marshall = &pinos_protocol_native_client_node_marshall; + proxy->demarshal = &pinos_protocol_native_client_node_demarshal; proxy->interface = NULL; } else if (!strcmp (type, PINOS_MODULE_URI)) { proxy = pinos_proxy_new (this, @@ -313,7 +313,7 @@ registry_event_global (void *object, goto no_mem; proxy->event = &module_events; - proxy->marshall = &pinos_protocol_native_client_module_marshall; + proxy->demarshal = &pinos_protocol_native_client_module_demarshal; proxy->interface = NULL; } else if (!strcmp (type, PINOS_CLIENT_URI)) { proxy = pinos_proxy_new (this, @@ -323,7 +323,7 @@ registry_event_global (void *object, goto no_mem; proxy->event = &client_events; - proxy->marshall = &pinos_protocol_native_client_client_marshall; + proxy->demarshal = &pinos_protocol_native_client_client_demarshal; proxy->interface = NULL; } else if (!strcmp (type, PINOS_LINK_URI)) { proxy = pinos_proxy_new (this, @@ -333,7 +333,7 @@ registry_event_global (void *object, goto no_mem; proxy->event = &link_events; - proxy->marshall = &pinos_protocol_native_client_link_marshall; + proxy->demarshal = &pinos_protocol_native_client_link_demarshal; proxy->interface = NULL; } if (proxy) @@ -385,32 +385,27 @@ on_context_data (SpaSource *source, if (mask & SPA_IO_IN) { PinosConnection *conn = impl->connection; - PinosMessageType type; + uint8_t opcode; uint32_t id; size_t size; + void *message; - while (pinos_connection_get_next (conn, &type, &id, &size)) { - void *p = alloca (size); + while (pinos_connection_get_next (conn, &opcode, &id, &message, &size)) { PinosProxy *proxy; - const PinosMarshallFunc *marshall; - - if (!pinos_connection_parse_message (conn, p)) { - pinos_log_error ("context %p: failed to parse message", this); - continue; - } + const PinosDemarshalFunc *demarshal; proxy = pinos_map_lookup (&this->objects, id); if (proxy == NULL) { pinos_log_error ("context %p: could not find proxy %u", this, id); continue; } - pinos_log_debug ("context %p: object marshall %u, %u", this, id, type); + pinos_log_debug ("context %p: object demarshal %u, %u", this, id, opcode); - marshall = proxy->marshall; - if (marshall[type]) - marshall[type] (proxy, p, size); + demarshal = proxy->demarshal; + if (demarshal[opcode]) + demarshal[opcode] (proxy, message, size); else - pinos_log_error ("context %p: function %d not implemented", this, type); + pinos_log_error ("context %p: function %d not implemented", this, opcode); } } @@ -602,7 +597,7 @@ pinos_context_connect_fd (PinosContext *context, context->core_proxy->event = &core_events; context->core_proxy->interface = &pinos_protocol_native_client_core_interface; - context->core_proxy->marshall = &pinos_protocol_native_client_core_marshall; + context->core_proxy->demarshal = &pinos_protocol_native_client_core_demarshal; pinos_core_do_client_update (context->core_proxy, &context->properties->dict); @@ -615,7 +610,7 @@ pinos_context_connect_fd (PinosContext *context, context->registry_proxy->event = ®istry_events; context->registry_proxy->interface = &pinos_protocol_native_client_registry_interface; - context->registry_proxy->marshall = &pinos_protocol_native_client_registry_marshall; + context->registry_proxy->demarshal = &pinos_protocol_native_client_registry_demarshal; pinos_core_do_get_registry (context->core_proxy, 0, diff --git a/pinos/client/interfaces.h b/pinos/client/interfaces.h index 73cd783e2..f30cda02c 100644 --- a/pinos/client/interfaces.h +++ b/pinos/client/interfaces.h @@ -34,12 +34,6 @@ typedef struct _PinosClientNodeBuffer PinosClientNodeBuffer; #include -#define PINOS_CORE_CLIENT_UPDATE 0 -#define PINOS_CORE_SYNC 1 -#define PINOS_CORE_GET_REGISTRY 2 -#define PINOS_CORE_CREATE_NODE 3 -#define PINOS_CORE_CREATE_CLIENT_NODE 4 - typedef struct { void (*client_update) (void *object, const SpaDict *props); @@ -85,8 +79,6 @@ typedef struct { #define pinos_core_notify_error(r,...) ((PinosCoreEvent*)r->event)->error(r,__VA_ARGS__) #define pinos_core_notify_remove_id(r,...) ((PinosCoreEvent*)r->event)->remove_id(r,__VA_ARGS__) -#define PINOS_REGISTRY_BIND 0 - typedef struct { void (*bind) (void *object, uint32_t id, @@ -123,17 +115,11 @@ typedef struct { #define pinos_node_notify_done(r,...) ((PinosNodeEvent*)r->event)->done(r,__VA_ARGS__) #define pinos_node_notify_info(r,...) ((PinosNodeEvent*)r->event)->info(r,__VA_ARGS__) -#define PINOS_CLIENT_NODE_UPDATE 0 -#define PINOS_CLIENT_NODE_PORT_UPDATE 1 -#define PINOS_CLIENT_NODE_STATE_CHANGE 2 -#define PINOS_CLIENT_NODE_EVENT 3 -#define PINOS_CLIENT_NODE_DESTROY 4 - struct _PinosClientNodeBuffer { - SpaBuffer *buffer; uint32_t mem_id; off_t offset; size_t size; + SpaBuffer *buffer; }; typedef struct { @@ -155,8 +141,8 @@ typedef struct { #define PINOS_MESSAGE_PORT_UPDATE_INFO (1 << 3) uint32_t change_mask, unsigned int n_possible_formats, - SpaFormat **possible_formats, - SpaFormat *format, + const SpaFormat **possible_formats, + const SpaFormat *format, const SpaProps *props, const SpaPortInfo *info); void (*state_change) (void *object, @@ -177,8 +163,8 @@ typedef struct { void (*done) (void *object, uint32_t seq, int datafd); - void (*event) (void *object, - SpaNodeEvent *event); + void (*event) (void *object, + const SpaNodeEvent *event); void (*add_port) (void *object, uint32_t seq, SpaDirection direction, @@ -197,7 +183,7 @@ typedef struct { uint32_t seq, uint32_t id, size_t size, - void *value); + const void *value); void (*add_mem) (void *object, SpaDirection direction, uint32_t port_id, @@ -215,10 +201,10 @@ typedef struct { PinosClientNodeBuffer *buffers); void (*node_command) (void *object, uint32_t seq, - SpaNodeCommand *command); + const SpaNodeCommand *command); void (*port_command) (void *object, uint32_t port_id, - SpaNodeCommand *command); + const SpaNodeCommand *command); void (*transport) (void *object, int memfd, off_t offset, diff --git a/pinos/client/introspect.c b/pinos/client/introspect.c index a8ef11c78..1fe3b64a0 100644 --- a/pinos/client/introspect.c +++ b/pinos/client/introspect.c @@ -20,7 +20,6 @@ #include #include "pinos/client/pinos.h" -#include "pinos/client/serialize.h" #include "pinos/client/context.h" #include "pinos/client/subscribe.h" @@ -254,8 +253,8 @@ pinos_node_info_update (PinosNodeInfo *info, info->input_formats = NULL; } for (i = 0; i < info->n_input_formats; i++) { - size = pinos_serialize_format_get_size (update->input_formats[i]); - info->input_formats[i] = size ? pinos_serialize_format_copy_into (malloc (size), update->input_formats[i]) : NULL; + size = SPA_POD_SIZE (update->input_formats[i]); + info->input_formats[i] = memcpy (malloc (size), update->input_formats[i], size); } } if (update->change_mask & (1 << 3)) @@ -271,8 +270,8 @@ pinos_node_info_update (PinosNodeInfo *info, info->output_formats = NULL; } for (i = 0; i < info->n_output_formats; i++) { - size = pinos_serialize_format_get_size (update->output_formats[i]); - info->output_formats[i] = size ? pinos_serialize_format_copy_into (malloc (size), update->output_formats[i]) : NULL; + size = SPA_POD_SIZE (update->output_formats[i]); + info->output_formats[i] = memcpy (malloc (size), update->output_formats[i], size); } } diff --git a/pinos/client/introspect.h b/pinos/client/introspect.h index 73e623ccc..a69a09f01 100644 --- a/pinos/client/introspect.h +++ b/pinos/client/introspect.h @@ -21,6 +21,7 @@ #define __PINOS_INTROSPECT_H__ #include +#include #ifdef __cplusplus extern "C" { diff --git a/pinos/client/protocol-native.c b/pinos/client/protocol-native.c index 256ce2c84..22c56b491 100644 --- a/pinos/client/protocol-native.c +++ b/pinos/client/protocol-native.c @@ -25,54 +25,83 @@ #include "pinos/client/interfaces.h" #include "pinos/client/connection.h" +typedef struct { + SpaPODBuilder b; + PinosConnection *connection; +} Builder; + +static off_t +write_pod (SpaPODBuilder *b, off_t ref, const void *data, size_t size) +{ + if (ref == -1) + ref = b->offset; + + if (b->size <= b->offset) { + b->size = SPA_ROUND_UP_N (b->offset + size, 512); + b->data = pinos_connection_begin_write (((Builder*)b)->connection, b->size); + } + memcpy (b->data + ref, data, size); + return ref; +} + static void -core_interface_client_update (void *object, +core_marshal_client_update (void *object, const SpaDict *props) { PinosProxy *proxy = object; PinosConnection *connection = proxy->context->protocol_private; - PinosMessageClientUpdate m = { props }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_CLIENT_UPDATE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + n_items = props ? props->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, props->items[i].key); + spa_pod_builder_string (&b.b, props->items[i].value); + } + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 0, b.b.offset); } static void -core_interface_sync (void *object, +core_marshal_sync (void *object, uint32_t seq) { PinosProxy *proxy = object; PinosConnection *connection = proxy->context->protocol_private; - PinosMessageSync m = { seq }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_SYNC, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 1, b.b.offset); } static void -core_interface_get_registry (void *object, +core_marshal_get_registry (void *object, uint32_t seq, uint32_t new_id) { PinosProxy *proxy = object; PinosConnection *connection = proxy->context->protocol_private; - PinosMessageGetRegistry m = { seq, new_id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_GET_REGISTRY, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_int (&b.b, new_id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 2, b.b.offset); } static void -core_interface_create_node (void *object, +core_marshal_create_node (void *object, uint32_t seq, const char *factory_name, const char *name, @@ -81,428 +110,816 @@ core_interface_create_node (void *object, { PinosProxy *proxy = object; PinosConnection *connection = proxy->context->protocol_private; - PinosMessageCreateNode m = { seq, factory_name, name, props, new_id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_CREATE_NODE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_string (&b.b, factory_name); + spa_pod_builder_string (&b.b, name); + n_items = props ? props->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, props->items[i].key); + spa_pod_builder_string (&b.b, props->items[i].value); + } + spa_pod_builder_int (&b.b, new_id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 3, b.b.offset); } static void -core_interface_create_client_node (void *object, - uint32_t seq, - const char *name, - const SpaDict *props, - uint32_t new_id) +core_marshal_create_client_node (void *object, + uint32_t seq, + const char *name, + const SpaDict *props, + uint32_t new_id) { PinosProxy *proxy = object; PinosConnection *connection = proxy->context->protocol_private; - PinosMessageCreateClientNode m = { seq, name, props, new_id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_CREATE_CLIENT_NODE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_string (&b.b, name); + n_items = props ? props->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, props->items[i].key); + spa_pod_builder_string (&b.b, props->items[i].value); + } + spa_pod_builder_int (&b.b, new_id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 4, b.b.offset); } static void -core_marshall_info (void *object, - void *data, - size_t size) -{ - PinosProxy *proxy = object; - PinosMessageCoreInfo *m = data; - pinos_core_notify_info (proxy, m->info); -} - -static void -core_marshall_done (void *object, - void *data, - size_t size) -{ - PinosProxy *proxy = object; - PinosMessageNotifyDone *m = data; - pinos_core_notify_done (proxy, m->seq); -} - -static void -core_marshall_error (void *object, +core_demarshal_info (void *object, void *data, size_t size) { PinosProxy *proxy = object; - PinosMessageError *m = data; - pinos_core_notify_error (proxy, m->id, m->res, m->error); + SpaDict props; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosCoreInfo info; + int32_t i1, i2, i3; + int64_t l1; + int i; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_long (&p, &l1) || + !spa_pod_get_string (&p, &info.user_name) || + !spa_pod_get_string (&p, &info.host_name) || + !spa_pod_get_string (&p, &info.version) || + !spa_pod_get_string (&p, &info.name) || + !spa_pod_get_int (&p, &i3) || + !spa_pod_get_int (&p, &i2)) + return; + + info.id = i1; + info.change_mask = l1; + info.cookie = i3; + info.props = &props; + props.n_items = i2; + props.items = alloca (props.n_items * sizeof (SpaDictItem)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_get_string (&p, &props.items[i].key) || + !spa_pod_get_string (&p, &props.items[i].value)) + return; + } + pinos_core_notify_info (proxy, &info); } static void -core_marshall_remove_id (void *object, - void *data, - size_t size) +core_demarshal_done (void *object, + void *data, + size_t size) { PinosProxy *proxy = object; - PinosMessageRemoveId *m = data; - pinos_core_notify_remove_id (proxy, m->id); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i32; + + if (!spa_pod_get_int (&p, &i32)) + return; + + pinos_core_notify_done (proxy, i32); } static void -module_marshall_info (void *object, +core_demarshal_error (void *object, void *data, size_t size) { PinosProxy *proxy = object; - PinosMessageModuleInfo *m = data; - pinos_module_notify_info (proxy, m->info); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1, i2; + const char *error; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_string (&p, &error)) + return; + + pinos_core_notify_error (proxy, i1, i2, error); } static void -node_marshall_done (void *object, - void *data, - size_t size) -{ - PinosProxy *proxy = object; - PinosMessageCreateNodeDone *m = data; - pinos_node_notify_done (proxy, m->seq); -} - -static void -node_marshall_info (void *object, - void *data, - size_t size) -{ - PinosProxy *proxy = object; - PinosMessageNodeInfo *m = data; - pinos_node_notify_info (proxy, m->info); -} - -static void -client_node_interface_update (void *object, - uint32_t change_mask, - unsigned int max_input_ports, - unsigned int max_output_ports, - const SpaProps *props) -{ - PinosProxy *proxy = object; - PinosConnection *connection = proxy->context->protocol_private; - PinosMessageNodeUpdate m = { change_mask, max_input_ports, max_output_ports, props }; - - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_NODE_UPDATE, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_interface_port_update (void *object, - SpaDirection direction, - uint32_t port_id, - uint32_t change_mask, - unsigned int n_possible_formats, - SpaFormat **possible_formats, - SpaFormat *format, - const SpaProps *props, - const SpaPortInfo *info) -{ - PinosProxy *proxy = object; - PinosConnection *connection = proxy->context->protocol_private; - PinosMessagePortUpdate m = { direction, port_id, change_mask, n_possible_formats, - possible_formats, format, props, info }; - - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_PORT_UPDATE, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_interface_state_change (void *object, - SpaNodeState state) -{ - PinosProxy *proxy = object; - PinosConnection *connection = proxy->context->protocol_private; - PinosMessageNodeStateChange m = { state }; - - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_NODE_STATE_CHANGE, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_interface_event (void *object, - SpaNodeEvent *event) -{ - PinosProxy *proxy = object; - PinosConnection *connection = proxy->context->protocol_private; - PinosMessageNodeEvent m = { event }; - - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_NODE_EVENT, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_interface_destroy (void *object, - uint32_t seq) -{ - PinosProxy *proxy = object; - PinosConnection *connection = proxy->context->protocol_private; - PinosMessageDestroy m = { seq }; - - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_DESTROY, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_mashall_done (void *object, +core_demarshal_remove_id (void *object, void *data, size_t size) { PinosProxy *proxy = object; - PinosMessageCreateClientNodeDone *m = data; - pinos_client_node_notify_done (proxy, m->seq, m->datafd); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1; + + if (!spa_pod_get_int (&p, &i1)) + return; + + pinos_core_notify_remove_id (proxy, i1); } static void -client_node_mashall_event (void *object, - void *data, - size_t size) +module_demarshal_info (void *object, + void *data, + size_t size) { PinosProxy *proxy = object; - PinosMessageNodeEvent *m = data; - pinos_client_node_notify_event (proxy, m->event); + SpaDict props; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosModuleInfo info; + int32_t i1, i2; + int64_t l1; + int i; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_long (&p, &l1) || + !spa_pod_get_string (&p, &info.name) || + !spa_pod_get_string (&p, &info.filename) || + !spa_pod_get_string (&p, &info.args) || + !spa_pod_get_int (&p, &i2)) + return; + + info.id = i1; + info.change_mask = l1; + info.props = &props; + props.n_items = i2; + props.items = alloca (props.n_items * sizeof (SpaDictItem)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_get_string (&p, &props.items[i].key) || + !spa_pod_get_string (&p, &props.items[i].value)) + return; + } + pinos_module_notify_info (proxy, &info); } static void -client_node_mashall_add_port (void *object, - void *data, - size_t size) +node_demarshal_done (void *object, + void *data, + size_t size) { PinosProxy *proxy = object; - PinosMessageAddPort *m = data; - pinos_client_node_notify_add_port (proxy, m->seq, m->direction, m->port_id); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1; + + if (!spa_pod_get_int (&p, &i1)) + return; + + pinos_node_notify_done (proxy, i1); } static void -client_node_mashall_remove_port (void *object, - void *data, - size_t size) +node_demarshal_info (void *object, + void *data, + size_t size) { PinosProxy *proxy = object; - PinosMessageRemovePort *m = data; - pinos_client_node_notify_remove_port (proxy, m->seq, m->direction, m->port_id); + SpaDict props; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosNodeInfo info; + int32_t i1, i2, i3, i4; + int64_t l1; + int i; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_long (&p, &l1) || + !spa_pod_get_string (&p, &info.name) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3) || + !spa_pod_get_int (&p, &i4)) + return; + + info.id = i1; + info.change_mask = l1; + info.max_inputs = i2; + info.n_inputs = i3; + info.n_input_formats = i4; + info.input_formats = alloca (info.n_input_formats * sizeof (SpaFormat*)); + for (i = 0; i < info.n_input_formats; i++) + spa_pod_get_object (&p, (const SpaPOD**)&info.input_formats[i]); + + if (!spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3) || + !spa_pod_get_int (&p, &i4)) + return; + + info.max_outputs = i2; + info.n_outputs = i3; + info.n_output_formats = i4; + info.output_formats = alloca (info.n_output_formats * sizeof (SpaFormat*)); + for (i = 0; i < info.n_output_formats; i++) + spa_pod_get_object (&p, (const SpaPOD**)&info.output_formats[i]); + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_string (&p, &info.error) || + !spa_pod_get_int (&p, &i2)) + return; + + info.state = i1; + info.props = &props; + props.n_items = i2; + props.items = alloca (props.n_items * sizeof (SpaDictItem)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_get_string (&p, &props.items[i].key) || + !spa_pod_get_string (&p, &props.items[i].value)) + return; + } + pinos_node_notify_info (proxy, &info); } static void -client_node_mashall_set_format (void *object, - void *data, - size_t size) +client_node_marshal_update (void *object, + uint32_t change_mask, + unsigned int max_input_ports, + unsigned int max_output_ports, + const SpaProps *props) { PinosProxy *proxy = object; - PinosMessageSetFormat *m = data; - pinos_client_node_notify_set_format (proxy, m->seq, m->direction, m->port_id, - m->flags, m->format); + PinosConnection *connection = proxy->context->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, change_mask); + spa_pod_builder_int (&b.b, max_input_ports); + spa_pod_builder_int (&b.b, max_output_ports); + spa_pod_builder_int (&b.b, props ? 1 : 0); + if (props) + spa_pod_builder_raw (&b.b, props, SPA_POD_SIZE (props), true); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 0, b.b.offset); } static void -client_node_mashall_set_property (void *object, - void *data, - size_t size) +client_node_marshal_port_update (void *object, + SpaDirection direction, + uint32_t port_id, + uint32_t change_mask, + unsigned int n_possible_formats, + const SpaFormat **possible_formats, + const SpaFormat *format, + const SpaProps *props, + const SpaPortInfo *info) { PinosProxy *proxy = object; - PinosMessageSetProperty *m = data; - pinos_client_node_notify_set_property (proxy, m->seq, m->id, m->size, m->value); + PinosConnection *connection = proxy->context->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, direction); + spa_pod_builder_int (&b.b, port_id); + spa_pod_builder_int (&b.b, change_mask); + spa_pod_builder_int (&b.b, n_possible_formats); + for (i = 0; i < n_possible_formats; i++) + spa_pod_builder_raw (&b.b, possible_formats[i], SPA_POD_SIZE (possible_formats[i]), true); + spa_pod_builder_int (&b.b, format ? 1 : 0); + if (format) + spa_pod_builder_raw (&b.b, format, SPA_POD_SIZE (format), true); + spa_pod_builder_int (&b.b, props ? 1 : 0); + if (props) + spa_pod_builder_raw (&b.b, props, SPA_POD_SIZE (props), true); + spa_pod_builder_int (&b.b, info ? 1 : 0); + if (info) { + spa_pod_builder_int (&b.b, info->flags); + spa_pod_builder_long (&b.b, info->maxbuffering); + spa_pod_builder_long (&b.b, info->latency); + spa_pod_builder_int (&b.b, info->n_params); + for (i = 0; i < info->n_params; i++) { + SpaAllocParam *p = info->params[i]; + spa_pod_builder_bytes (&b.b, p, p->size); + } + n_items = info->extra ? info->extra->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, info->extra->items[i].key); + spa_pod_builder_string (&b.b, info->extra->items[i].value); + } + } + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 1, b.b.offset); } static void -client_node_mashall_add_mem (void *object, +client_node_marshal_state_change (void *object, + SpaNodeState state) +{ + PinosProxy *proxy = object; + PinosConnection *connection = proxy->context->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, state); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 2, b.b.offset); +} + +static void +client_node_marshal_event (void *object, + SpaNodeEvent *event) +{ + PinosProxy *proxy = object; + PinosConnection *connection = proxy->context->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_bytes (&b.b, event, event->size); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 3, b.b.offset); +} + +static void +client_node_marshal_destroy (void *object, + uint32_t seq) +{ + PinosProxy *proxy = object; + PinosConnection *connection = proxy->context->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 4, b.b.offset); +} + +static void +client_node_demarshal_done (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosConnection *connection = proxy->context->protocol_private; + int32_t i1, i2; + int fd; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2)) + return; + + fd = pinos_connection_get_fd (connection, i2); + pinos_client_node_notify_done (proxy, i1, fd); +} + +static void +client_node_demarshal_event (void *object, void *data, size_t size) { PinosProxy *proxy = object; - PinosMessageAddMem *m = data; - pinos_client_node_notify_add_mem (proxy, - m->direction, - m->port_id, - m->mem_id, - m->type, - m->memfd, - m->flags, - m->offset, - m->size); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + const SpaNodeEvent *event; + uint32_t s; + + if (!spa_pod_get_bytes (&p, (const void**)&event, &s)) + return; + + pinos_client_node_notify_event (proxy, event); } static void -client_node_mashall_use_buffers (void *object, +client_node_demarshal_add_port (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1, i2, i3; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3)) + return; + + pinos_client_node_notify_add_port (proxy, i1, i2, i3); +} + +static void +client_node_demarshal_remove_port (void *object, void *data, size_t size) { PinosProxy *proxy = object; - PinosMessageUseBuffers *m = data; - pinos_client_node_notify_use_buffers (proxy, - m->seq, - m->direction, - m->port_id, - m->n_buffers, - m->buffers); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1, i2, i3; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3)) + return; + + pinos_client_node_notify_remove_port (proxy, i1, i2, i3); } static void -client_node_mashall_node_command (void *object, - void *data, - size_t size) +client_node_demarshal_set_format (void *object, + void *data, + size_t size) { PinosProxy *proxy = object; - PinosMessageNodeCommand *m = data; - pinos_client_node_notify_node_command (proxy, m->seq, m->command); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq, direction, port_id, flags, have_format; + const SpaFormat *format = NULL; + + if (!spa_pod_get_int (&p, &seq) || + !spa_pod_get_int (&p, &direction) || + !spa_pod_get_int (&p, &port_id) || + !spa_pod_get_int (&p, &flags) || + !spa_pod_get_int (&p, &have_format)) + return; + + if (have_format && !spa_pod_get_object (&p, (const SpaPOD**)&format)) + return; + + pinos_client_node_notify_set_format (proxy, seq, direction, port_id, + flags, format); } static void -client_node_mashall_port_command (void *object, - void *data, - size_t size) +client_node_demarshal_set_property (void *object, + void *data, + size_t size) { PinosProxy *proxy = object; - PinosMessagePortCommand *m = data; - pinos_client_node_notify_port_command (proxy, m->port_id, m->command); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq, id; + const void *value; + uint32_t s; + + if (!spa_pod_get_int (&p, &seq) || + !spa_pod_get_int (&p, &id) || + !spa_pod_get_bytes (&p, &value, &s)) + return; + + pinos_client_node_notify_set_property (proxy, seq, id, s, value); } static void -client_node_mashall_transport (void *object, +client_node_demarshal_add_mem (void *object, void *data, size_t size) { PinosProxy *proxy = object; - PinosMessageTransportUpdate *m = data; - pinos_client_node_notify_transport (proxy, m->memfd, m->offset, m->size); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosConnection *connection = proxy->context->protocol_private; + int32_t direction, port_id, mem_id, type, memfd, flags, offset, sz; + + if (!spa_pod_get_int (&p, &direction) || + !spa_pod_get_int (&p, &port_id) || + !spa_pod_get_int (&p, &mem_id) || + !spa_pod_get_int (&p, &type) || + !spa_pod_get_int (&p, &memfd) || + !spa_pod_get_int (&p, &flags) || + !spa_pod_get_int (&p, &offset) || + !spa_pod_get_int (&p, &sz)) + return; + + memfd = pinos_connection_get_fd (connection, memfd); + + pinos_client_node_notify_add_mem (proxy, + direction, + port_id, + mem_id, + type, + memfd, + flags, + offset, + sz); } static void -client_marshall_info (void *object, - void *data, - size_t size) -{ - PinosProxy *proxy = object; - PinosMessageClientInfo *m = data; - pinos_client_notify_info (proxy, m->info); -} - -static void -link_marshall_info (void *object, - void *data, - size_t size) -{ - PinosProxy *proxy = object; - PinosMessageLinkInfo *m = data; - pinos_link_notify_info (proxy, m->info); -} - -static void -registry_marshall_global (void *object, - void *data, - size_t size) -{ - PinosProxy *proxy = object; - PinosMessageNotifyGlobal *m = data; - pinos_registry_notify_global (proxy, m->id, m->type); -} - -static void -registry_marshall_global_remove (void *object, +client_node_demarshal_use_buffers (void *object, void *data, size_t size) { PinosProxy *proxy = object; - PinosMessageNotifyGlobalRemove *m = data; - pinos_registry_notify_global_remove (proxy, m->id); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq, direction, port_id, n_buffers; + PinosClientNodeBuffer *buffers; + int i, j; + + if (!spa_pod_get_int (&p, &seq) || + !spa_pod_get_int (&p, &direction) || + !spa_pod_get_int (&p, &port_id) || + !spa_pod_get_int (&p, &n_buffers)) + return; + + buffers = alloca (sizeof (PinosClientNodeBuffer) * n_buffers); + for (i = 0; i < n_buffers; i++) { + SpaBuffer *buf = buffers[i].buffer = alloca (sizeof (SpaBuffer)); + int32_t i1, i2, i3, i4, i5; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3) || + !spa_pod_get_int (&p, &i4) || + !spa_pod_get_int (&p, &i5)) + return; + + buffers[i].mem_id = i1; + buffers[i].offset = i2; + buffers[i].size = i3; + buf->id = i4; + buf->n_metas = i5; + + buf->metas = alloca (sizeof (SpaMeta) * buf->n_metas); + for (j = 0; j < buf->n_metas; j++) { + SpaMeta *m = &buf->metas[j]; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2)) + return; + + m->type = i1; + m->size = i2; + } + if (!spa_pod_get_int (&p, &i1)) + return; + + buf->n_datas = i1; + buf->datas = alloca (sizeof (SpaData) * buf->n_datas); + for (j = 0; j < buf->n_datas; j++) { + SpaData *d = &buf->datas[j]; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3) || + !spa_pod_get_int (&p, &i4) || + !spa_pod_get_int (&p, &i5)) + return; + + d->type = i1; + d->data = SPA_UINT32_TO_PTR (i2); + d->flags = i3; + d->mapoffset = i4; + d->maxsize = i5; + } + } + pinos_client_node_notify_use_buffers (proxy, + seq, + direction, + port_id, + n_buffers, + buffers); } static void -registry_bind (void *object, - uint32_t id, - uint32_t new_id) +client_node_demarshal_node_command (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + const SpaNodeCommand *command; + int32_t i1; + uint32_t s; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_bytes (&p, (const void**)&command, &s)) + return; + + pinos_client_node_notify_node_command (proxy, i1, command); +} + +static void +client_node_demarshal_port_command (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + const SpaNodeCommand *command; + int32_t i1; + uint32_t s; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_bytes (&p, (const void**)&command, &s)) + return; + + pinos_client_node_notify_port_command (proxy, i1, command); +} + +static void +client_node_demarshal_transport (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosConnection *connection = proxy->context->protocol_private; + int32_t memfd, offset, sz; + + if (!spa_pod_get_int (&p, &memfd) || + !spa_pod_get_int (&p, &offset) || + !spa_pod_get_int (&p, &sz)) + return; + + memfd = pinos_connection_get_fd (connection, memfd); + pinos_client_node_notify_transport (proxy, memfd, offset, sz); +} + +static void +client_demarshal_info (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaDict props; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosClientInfo info; + int32_t i1, i2; + int64_t l1; + int i; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_long (&p, &l1) || + !spa_pod_get_int (&p, &i2)) + return; + + info.id = i1; + info.change_mask = l1; + info.props = &props; + props.n_items = i2; + props.items = alloca (props.n_items * sizeof (SpaDictItem)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_get_string (&p, &props.items[i].key) || + !spa_pod_get_string (&p, &props.items[i].value)) + return; + } + pinos_client_notify_info (proxy, &info); +} + +static void +link_demarshal_info (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + PinosLinkInfo info; + int32_t i1, i2, i3, i4, i5; + int64_t l1; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_long (&p, &l1) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3) || + !spa_pod_get_int (&p, &i4) || + !spa_pod_get_int (&p, &i5)) + return; + + info.id = i1; + info.change_mask = l1; + info.output_node_id = i2; + info.output_port_id = i3; + info.input_node_id = i4; + info.input_port_id = i5; + + pinos_link_notify_info (proxy, &info); +} + +static void +registry_demarshal_global (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1; + const char *type; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_string (&p, &type)) + return; + + pinos_registry_notify_global (proxy, i1, type); +} + +static void +registry_demarshal_global_remove (void *object, + void *data, + size_t size) +{ + PinosProxy *proxy = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1; + + if (!spa_pod_get_int (&p, &i1)) + return; + + pinos_registry_notify_global_remove (proxy, i1); +} + +static void +registry_marshal_bind (void *object, + uint32_t id, + uint32_t new_id) { PinosProxy *proxy = object; PinosConnection *connection = proxy->context->protocol_private; - PinosMessageBind m = { id, new_id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - proxy->id, - PINOS_MESSAGE_BIND, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, id); + spa_pod_builder_int (&b.b, new_id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, proxy->id, 0, b.b.offset); } const PinosCoreInterface pinos_protocol_native_client_core_interface = { - &core_interface_client_update, - &core_interface_sync, - &core_interface_get_registry, - &core_interface_create_node, - &core_interface_create_client_node + &core_marshal_client_update, + &core_marshal_sync, + &core_marshal_get_registry, + &core_marshal_create_node, + &core_marshal_create_client_node }; const PinosRegistryInterface pinos_protocol_native_client_registry_interface = { - ®istry_bind + ®istry_marshal_bind }; const PinosClientNodeInterface pinos_protocol_native_client_client_node_interface = { - &client_node_interface_update, - &client_node_interface_port_update, - &client_node_interface_state_change, - &client_node_interface_event, - &client_node_interface_destroy + &client_node_marshal_update, + &client_node_marshal_port_update, + &client_node_marshal_state_change, + &client_node_marshal_event, + &client_node_marshal_destroy }; -const PinosMarshallFunc pinos_protocol_native_client_core_marshall[] = { - [PINOS_MESSAGE_CORE_INFO] = &core_marshall_info, - [PINOS_MESSAGE_NOTIFY_DONE] = &core_marshall_done, - [PINOS_MESSAGE_ERROR] = &core_marshall_error, - [PINOS_MESSAGE_REMOVE_ID] = &core_marshall_remove_id, +const PinosDemarshalFunc pinos_protocol_native_client_core_demarshal[] = { + &core_demarshal_info, + &core_demarshal_done, + &core_demarshal_error, + &core_demarshal_remove_id, }; -const PinosMarshallFunc pinos_protocol_native_client_module_marshall[] = { - [PINOS_MESSAGE_MODULE_INFO] = &module_marshall_info, +const PinosDemarshalFunc pinos_protocol_native_client_module_demarshal[] = { + &module_demarshal_info, }; -const PinosMarshallFunc pinos_protocol_native_client_node_marshall[] = { - [PINOS_MESSAGE_CREATE_NODE_DONE] = &node_marshall_done, - [PINOS_MESSAGE_NODE_INFO] = &node_marshall_info, +const PinosDemarshalFunc pinos_protocol_native_client_node_demarshal[] = { + &node_demarshal_done, + &node_demarshal_info, }; -const PinosMarshallFunc pinos_protocol_native_client_client_node_marshall[] = { - [PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE] = &client_node_mashall_done, - [PINOS_MESSAGE_NODE_EVENT] = &client_node_mashall_event, - [PINOS_MESSAGE_ADD_PORT] = &client_node_mashall_add_port, - [PINOS_MESSAGE_REMOVE_PORT] = &client_node_mashall_remove_port, - [PINOS_MESSAGE_SET_FORMAT] = &client_node_mashall_set_format, - [PINOS_MESSAGE_SET_PROPERTY] = &client_node_mashall_set_property, - [PINOS_MESSAGE_ADD_MEM] = &client_node_mashall_add_mem, - [PINOS_MESSAGE_USE_BUFFERS] = &client_node_mashall_use_buffers, - [PINOS_MESSAGE_NODE_COMMAND] = &client_node_mashall_node_command, - [PINOS_MESSAGE_PORT_COMMAND] = &client_node_mashall_port_command, - [PINOS_MESSAGE_TRANSPORT_UPDATE] = &client_node_mashall_transport +const PinosDemarshalFunc pinos_protocol_native_client_client_node_demarshal[] = { + &client_node_demarshal_done, + &client_node_demarshal_event, + &client_node_demarshal_add_port, + &client_node_demarshal_remove_port, + &client_node_demarshal_set_format, + &client_node_demarshal_set_property, + &client_node_demarshal_add_mem, + &client_node_demarshal_use_buffers, + &client_node_demarshal_node_command, + &client_node_demarshal_port_command, + &client_node_demarshal_transport }; -const PinosMarshallFunc pinos_protocol_native_client_client_marshall[] = { - [PINOS_MESSAGE_CLIENT_INFO] = &client_marshall_info, +const PinosDemarshalFunc pinos_protocol_native_client_client_demarshal[] = { + &client_demarshal_info, }; -const PinosMarshallFunc pinos_protocol_native_client_link_marshall[] = { - [PINOS_MESSAGE_LINK_INFO] = &link_marshall_info, +const PinosDemarshalFunc pinos_protocol_native_client_link_demarshal[] = { + &link_demarshal_info, }; -const PinosMarshallFunc pinos_protocol_native_client_registry_marshall[] = { - [PINOS_MESSAGE_NOTIFY_GLOBAL] = ®istry_marshall_global, - [PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE] = ®istry_marshall_global_remove, +const PinosDemarshalFunc pinos_protocol_native_client_registry_demarshal[] = { + ®istry_demarshal_global, + ®istry_demarshal_global_remove, }; diff --git a/pinos/client/protocol-native.h b/pinos/client/protocol-native.h index ad94f1a4d..a5120593c 100644 --- a/pinos/client/protocol-native.h +++ b/pinos/client/protocol-native.h @@ -18,17 +18,18 @@ */ #include "pinos/client/pinos.h" +#include "pinos/client/interfaces.h" -typedef void (*PinosMarshallFunc) (void *object, void *data, size_t size); +typedef void (*PinosDemarshalFunc) (void *object, void *data, size_t size); extern const PinosCoreInterface pinos_protocol_native_client_core_interface; extern const PinosRegistryInterface pinos_protocol_native_client_registry_interface; extern const PinosClientNodeInterface pinos_protocol_native_client_client_node_interface; -extern const PinosMarshallFunc pinos_protocol_native_client_core_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_client_module_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_client_node_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_client_client_node_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_client_client_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_client_link_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_client_registry_marshall[]; +extern const PinosDemarshalFunc pinos_protocol_native_client_core_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_client_module_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_client_node_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_client_client_node_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_client_client_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_client_link_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_client_registry_demarshal[]; diff --git a/pinos/client/proxy.h b/pinos/client/proxy.h index 9c8990f53..aad472802 100644 --- a/pinos/client/proxy.h +++ b/pinos/client/proxy.h @@ -40,7 +40,7 @@ struct _PinosProxy { const void *interface; const void *event; - const void *marshall; + const void *demarshal; PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosProxy *proxy)); diff --git a/pinos/client/serialize.c b/pinos/client/serialize.c index 35719f91b..12745c1e5 100644 --- a/pinos/client/serialize.c +++ b/pinos/client/serialize.c @@ -89,45 +89,6 @@ pinos_serialize_buffer_copy_into (void *dest, const SpaBuffer *buffer) return pinos_serialize_buffer_deserialize (dest, 0); } -size_t -pinos_serialize_format_get_size (const SpaFormat *format) -{ - if (format == NULL) - return 0; - - return SPA_POD_SIZE (format); -} - -size_t -pinos_serialize_format_serialize (void *dest, const SpaFormat *format) -{ - size_t size; - - if (format == NULL) - return 0; - - size = SPA_POD_SIZE (format); - memcpy (dest, format, size); - - return size; -} - -SpaFormat * -pinos_serialize_format_deserialize (void *src, off_t offset) -{ - return SPA_MEMBER (src, offset, SpaFormat); -} - -SpaFormat * -pinos_serialize_format_copy_into (void *dest, const SpaFormat *format) -{ - if (format == NULL) - return NULL; - - pinos_serialize_format_serialize (dest, format); - return pinos_serialize_format_deserialize (dest, 0); -} - size_t pinos_serialize_port_info_get_size (const SpaPortInfo *info) { @@ -201,130 +162,3 @@ pinos_serialize_port_info_copy_into (void *dest, const SpaPortInfo *info) pinos_serialize_port_info_serialize (dest, info); return pinos_serialize_port_info_deserialize (dest, 0); } - -size_t -pinos_serialize_props_get_size (const SpaProps *props) -{ - if (props == NULL) - return 0; - - return SPA_POD_SIZE (props); -} - -size_t -pinos_serialize_props_serialize (void *p, const SpaProps *props) -{ - size_t size; - - if (props == NULL) - return 0; - - size = SPA_POD_SIZE (props); - memcpy (p, props, size); - - return size; -} - -SpaProps * -pinos_serialize_props_deserialize (void *p, off_t offset) -{ - return SPA_MEMBER (p, offset, SpaProps); -} - -SpaProps * -pinos_serialize_props_copy_into (void *dest, const SpaProps *props) -{ - if (props == NULL) - return NULL; - - pinos_serialize_props_serialize (dest, props); - return pinos_serialize_props_deserialize (dest, 0); -} - -size_t -pinos_serialize_dict_get_size (const SpaDict *dict) -{ - size_t len; - unsigned int i; - - if (dict == NULL) - return 0; - - len = sizeof (SpaDict); - len += dict->n_items * sizeof (SpaDictItem); - for (i = 0; i < dict->n_items; i++) { - SpaDictItem *di = &dict->items[i]; - len += di->key ? strlen (di->key) + 1 : 0; - len += di->value ? strlen (di->value) + 1 : 0; - } - return len; -} - -size_t -pinos_serialize_dict_serialize (void *p, const SpaDict *dict) -{ - SpaDict *pi; - SpaDictItem *di; - int i; - size_t len; - - if (dict == NULL) - return 0; - - pi = p; - memcpy (pi, dict, sizeof (SpaDict)); - - di = SPA_MEMBER (pi, sizeof (SpaDict), SpaDictItem); - if (dict->n_items) - pi->items = SPA_INT_TO_PTR (SPA_PTRDIFF (di, pi)); - else - pi->items = 0; - - p = SPA_MEMBER (di, sizeof (SpaDictItem) * dict->n_items, void); - - for (i = 0; i < dict->n_items; i++) { - if (dict->items[i].key) { - len = strlen (dict->items[i].key) + 1; - memcpy (p, dict->items[i].key, len); - di[i].key = SPA_INT_TO_PTR (SPA_PTRDIFF (p, pi)); - p += len; - } else { - di[i].key = NULL; - } - if (dict->items[i].value) { - len = strlen (dict->items[i].value) + 1; - memcpy (p, dict->items[i].value, len); - di[i].value = SPA_INT_TO_PTR (SPA_PTRDIFF (p, pi)); - p += len; - } else { - di[i].value = NULL; - } - } - return SPA_PTRDIFF (p, pi); -} - -SpaDict * -pinos_serialize_dict_deserialize (void *p, off_t offset) -{ - SpaDict *pi; - unsigned int i; - - pi = SPA_MEMBER (p, offset, SpaDict); - if (pi->items) - pi->items = SPA_MEMBER (pi, SPA_PTR_TO_INT (pi->items), SpaDictItem); - for (i = 0; i < pi->n_items; i++) { - pi->items[i].key = SPA_MEMBER (pi, SPA_PTR_TO_INT (pi->items[i].key), char); - pi->items[i].value = SPA_MEMBER (pi, SPA_PTR_TO_INT (pi->items[i].value), char); - } - return pi; -} - -SpaDict * -pinos_serialize_dict_copy_into (void *dest, const SpaDict *dict) -{ - if (dict == NULL) - return NULL; - - pinos_serialize_dict_serialize (dest, dict); - return pinos_serialize_dict_deserialize (dest, 0); -} diff --git a/pinos/client/serialize.h b/pinos/client/serialize.h index 568ce879d..405d960ed 100644 --- a/pinos/client/serialize.h +++ b/pinos/client/serialize.h @@ -34,26 +34,11 @@ size_t pinos_serialize_buffer_serialize (void *dest, const SpaBuff SpaBuffer * pinos_serialize_buffer_deserialize (void *src, off_t offset); SpaBuffer * pinos_serialize_buffer_copy_into (void *dest, const SpaBuffer *buffer); -size_t pinos_serialize_format_get_size (const SpaFormat *format); -size_t pinos_serialize_format_serialize (void *dest, const SpaFormat *format); -SpaFormat * pinos_serialize_format_deserialize (void *src, off_t offset); -SpaFormat * pinos_serialize_format_copy_into (void *dest, const SpaFormat *format); - size_t pinos_serialize_port_info_get_size (const SpaPortInfo *info); size_t pinos_serialize_port_info_serialize (void *dest, const SpaPortInfo *info); SpaPortInfo * pinos_serialize_port_info_deserialize (void *src, off_t offset); SpaPortInfo * pinos_serialize_port_info_copy_into (void *dest, const SpaPortInfo *info); -size_t pinos_serialize_props_get_size (const SpaProps *props); -size_t pinos_serialize_props_serialize (void *dest, const SpaProps *props); -SpaProps * pinos_serialize_props_deserialize (void *src, off_t offset); -SpaProps * pinos_serialize_props_copy_into (void *dest, const SpaProps *props); - -size_t pinos_serialize_dict_get_size (const SpaDict *dict); -size_t pinos_serialize_dict_serialize (void *dest, const SpaDict *dict); -SpaDict * pinos_serialize_dict_deserialize (void *src, off_t offset); -SpaDict * pinos_serialize_dict_copy_into (void *dest, const SpaDict *dict); - #ifdef __cplusplus } #endif diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 834f06ea2..dbf20a6af 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -27,6 +27,7 @@ #include "spa/lib/debug.h" #include "pinos/client/pinos.h" +#include "pinos/client/interfaces.h" #include "pinos/client/protocol-native.h" #include "pinos/client/array.h" #include "pinos/client/connection.h" @@ -34,6 +35,7 @@ #include "pinos/client/stream.h" #include "pinos/client/serialize.h" #include "pinos/client/transport.h" +#include "pinos/client/utils.h" #define MAX_BUFFER_SIZE 4096 #define MAX_FDS 32 @@ -344,8 +346,8 @@ add_port_update (PinosStream *stream, uint32_t change_mask, bool flush) impl->port_id, change_mask, impl->n_possible_formats, - impl->possible_formats, - impl->format, + (const SpaFormat **) impl->possible_formats, + (const SpaFormat *) impl->format, NULL, &impl->port_info); } @@ -582,8 +584,8 @@ handle_socket (PinosStream *stream, int rtfd) } static void -handle_node_event (PinosStream *stream, - SpaNodeEvent *event) +handle_node_event (PinosStream *stream, + const SpaNodeEvent *event) { switch (event->type) { case SPA_NODE_EVENT_TYPE_INVALID: @@ -601,9 +603,9 @@ handle_node_event (PinosStream *stream, } static bool -handle_node_command (PinosStream *stream, - uint32_t seq, - SpaNodeCommand *command) +handle_node_command (PinosStream *stream, + uint32_t seq, + const SpaNodeCommand *command) { PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this); @@ -671,8 +673,8 @@ client_node_done (void *object, } static void -client_node_event (void *object, - SpaNodeEvent *event) +client_node_event (void *object, + const SpaNodeEvent *event) { PinosProxy *proxy = object; PinosStream *stream = proxy->user_data; @@ -708,13 +710,10 @@ client_node_set_format (void *object, PinosProxy *proxy = object; PinosStream *stream = proxy->user_data; PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this); - void *mem; if (impl->format) free (impl->format); - mem = malloc (pinos_serialize_format_get_size (format)); - impl->format = pinos_serialize_format_copy_into (mem, format); - + impl->format = spa_format_copy (format); impl->pending_seq = seq; pinos_signal_emit (&stream->format_changed, stream, impl->format); @@ -722,11 +721,11 @@ client_node_set_format (void *object, } static void -client_node_set_property (void *object, - uint32_t seq, - uint32_t id, - size_t size, - void *value) +client_node_set_property (void *object, + uint32_t seq, + uint32_t id, + size_t size, + const void *value) { pinos_log_warn ("set property not implemented"); } @@ -874,9 +873,9 @@ client_node_use_buffers (void *object, } static void -client_node_node_command (void *object, - uint32_t seq, - SpaNodeCommand *command) +client_node_node_command (void *object, + uint32_t seq, + const SpaNodeCommand *command) { PinosProxy *proxy = object; PinosStream *stream = proxy->user_data; @@ -884,9 +883,9 @@ client_node_node_command (void *object, } static void -client_node_port_command (void *object, - uint32_t port_id, - SpaNodeCommand *command) +client_node_port_command (void *object, + uint32_t port_id, + const SpaNodeCommand *command) { pinos_log_warn ("port command not supported"); } @@ -1000,7 +999,7 @@ pinos_stream_connect (PinosStream *stream, impl->node_proxy->user_data = stream; impl->node_proxy->event = &client_node_events; impl->node_proxy->interface = &pinos_protocol_native_client_client_node_interface; - impl->node_proxy->marshall = &pinos_protocol_native_client_client_node_marshall; + impl->node_proxy->demarshal = &pinos_protocol_native_client_client_node_demarshal; pinos_core_do_create_client_node (stream->context->core_proxy, ++impl->seq, diff --git a/pinos/client/utils.h b/pinos/client/utils.h index ab5d75ec0..0539f5875 100644 --- a/pinos/client/utils.h +++ b/pinos/client/utils.h @@ -25,6 +25,7 @@ extern "C" { #endif #include +#include const char * pinos_split_walk (const char *str, const char *delimiter, @@ -39,6 +40,15 @@ void pinos_free_strv (char **str); char * pinos_strip (char *str, const char *whitespace); +static inline SpaPOD * +pinos_spa_pod_copy (const SpaPOD *pod) +{ + return pod ? memcpy (malloc (SPA_POD_SIZE (pod)), pod, SPA_POD_SIZE (pod)) : NULL; +} + +#define spa_format_copy(f) ((SpaFormat*)pinos_spa_pod_copy(&(f)->pod)) +#define spa_props_copy(p) ((SpaProps*)pinos_spa_pod_copy(&(p)->pod)) + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/pinos/modules/module-access.c b/pinos/modules/module-access.c index b90eee304..d6d1eb97f 100644 --- a/pinos/modules/module-access.c +++ b/pinos/modules/module-access.c @@ -63,8 +63,9 @@ do_check_send (PinosListener *listener, PinosCore *core = client->core; if (data->resource->type == core->uri.registry) { +#if 0 switch (data->opcode) { - case PINOS_MESSAGE_NOTIFY_GLOBAL: + case 0: { PinosMessageNotifyGlobal *m = data->message; @@ -74,7 +75,7 @@ do_check_send (PinosListener *listener, data->res = SPA_RESULT_SKIPPED; break; } - case PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE: + case 1: { PinosMessageNotifyGlobalRemove *m = data->message; @@ -89,6 +90,7 @@ do_check_send (PinosListener *listener, data->res = SPA_RESULT_NO_PERMISSION; break; } +#endif } else { data->res = SPA_RESULT_OK; @@ -104,7 +106,8 @@ do_check_dispatch (PinosListener *listener, PinosCore *core = client->core; if (data->resource->type == core->uri.registry) { - if (data->opcode == PINOS_MESSAGE_BIND) { +#if 0 + if (data->opcode == 0) { PinosMessageBind *m = data->message; if (check_global_owner (core, client, m->id)) @@ -114,6 +117,7 @@ do_check_dispatch (PinosListener *listener, } else { data->res = SPA_RESULT_NO_PERMISSION; } +#endif } else { data->res = SPA_RESULT_OK; diff --git a/pinos/modules/module-protocol-native.c b/pinos/modules/module-protocol-native.c index 65a805319..e30312135 100644 --- a/pinos/modules/module-protocol-native.c +++ b/pinos/modules/module-protocol-native.c @@ -103,31 +103,31 @@ on_resource_added (PinosListener *listener, { if (resource->type == resource->core->uri.core) { resource->event = &pinos_protocol_native_server_core_event; - resource->marshall = &pinos_protocol_native_server_core_marshall; + resource->demarshal = &pinos_protocol_native_server_core_demarshal; } else if (resource->type == resource->core->uri.registry) { resource->event = &pinos_protocol_native_server_registry_event; - resource->marshall = &pinos_protocol_native_server_registry_marshall; + resource->demarshal = &pinos_protocol_native_server_registry_demarshal; } else if (resource->type == resource->core->uri.module) { resource->event = &pinos_protocol_native_server_module_event; - resource->marshall = NULL; + resource->demarshal = NULL; } else if (resource->type == resource->core->uri.node) { resource->event = &pinos_protocol_native_server_node_event; - resource->marshall = NULL; + resource->demarshal = NULL; } else if (resource->type == resource->core->uri.client) { resource->event = &pinos_protocol_native_server_client_event; - resource->marshall = NULL; + resource->demarshal = NULL; } else if (resource->type == resource->core->uri.client_node) { resource->event = &pinos_protocol_native_server_client_node_events; - resource->marshall = &pinos_protocol_native_server_client_node_marshall; + resource->demarshal = &pinos_protocol_native_server_client_node_demarshal; } else if (resource->type == resource->core->uri.link) { resource->event = &pinos_protocol_native_server_link_event; - resource->marshall = NULL; + resource->demarshal = NULL; } } @@ -139,10 +139,11 @@ connection_data (SpaSource *source, { PinosProtocolNativeClient *client = data; PinosConnection *conn = client->connection; - PinosMessageType type; + uint8_t opcode; uint32_t id; size_t size; PinosClient *c = client->client; + void *message; if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { pinos_log_debug ("protocol-native %p: got connection error", client->impl); @@ -150,28 +151,22 @@ connection_data (SpaSource *source, return; } - while (pinos_connection_get_next (conn, &type, &id, &size)) { + while (pinos_connection_get_next (conn, &opcode, &id, &message, &size)) { PinosResource *resource; - void *message = alloca (size); - const PinosMarshallFunc *marshall; + const PinosDemarshalFunc *demarshal; - pinos_log_debug ("protocol-native %p: got message %d from %u", client->impl, type, id); - - if (!pinos_connection_parse_message (conn, message)) { - pinos_log_error ("protocol-native %p: failed to parse message", client->impl); - continue; - } + pinos_log_debug ("protocol-native %p: got message %d from %u", client->impl, opcode, id); resource = pinos_map_lookup (&c->objects, id); if (resource == NULL) { pinos_log_error ("protocol-native %p: unknown resource %u", client->impl, id); continue; } - marshall = resource->marshall; - if (marshall[type]) - marshall[type] (resource, message, size); + demarshal = resource->demarshal; + if (demarshal[opcode]) + demarshal[opcode] (resource, message, size); else - pinos_log_error ("protocol-native %p: function %d not implemented", client->impl, type); + pinos_log_error ("protocol-native %p: function %d not implemented", client->impl, opcode); } } diff --git a/pinos/server/client-node.c b/pinos/server/client-node.c index 9264857fe..603196196 100644 --- a/pinos/server/client-node.c +++ b/pinos/server/client-node.c @@ -314,8 +314,8 @@ do_update_port (SpaProxy *this, uint32_t port_id, uint32_t change_mask, unsigned int n_possible_formats, - SpaFormat **possible_formats, - SpaFormat *format, + const SpaFormat **possible_formats, + const SpaFormat *format, const SpaProps *props, const SpaPortInfo *info) { @@ -340,15 +340,13 @@ do_update_port (SpaProxy *this, port->formats = NULL; } for (i = 0; i < port->n_formats; i++) { - size = pinos_serialize_format_get_size (possible_formats[i]); - port->formats[i] = size ? pinos_serialize_format_copy_into (malloc (size), possible_formats[i]) : NULL; + port->formats[i] = spa_format_copy (possible_formats[i]); } } if (change_mask & PINOS_MESSAGE_PORT_UPDATE_FORMAT) { if (port->format) free (port->format); - size = pinos_serialize_format_get_size (format); - port->format = size ? pinos_serialize_format_copy_into (malloc (size), format) : NULL; + port->format = spa_format_copy (format); } if (change_mask & PINOS_MESSAGE_PORT_UPDATE_PROPS) { @@ -912,8 +910,8 @@ client_node_port_update (void *object, uint32_t port_id, uint32_t change_mask, unsigned int n_possible_formats, - SpaFormat **possible_formats, - SpaFormat *format, + const SpaFormat **possible_formats, + const SpaFormat *format, const SpaProps *props, const SpaPortInfo *info) { @@ -961,8 +959,8 @@ client_node_state_change (void *object, } static void -client_node_event (void *object, - SpaNodeEvent *event) +client_node_event (void *object, + SpaNodeEvent *event) { PinosResource *resource = object; PinosClientNode *node = resource->object; diff --git a/pinos/server/client-node.h b/pinos/server/client-node.h index 4798188fb..3549e447c 100644 --- a/pinos/server/client-node.h +++ b/pinos/server/client-node.h @@ -54,10 +54,6 @@ void pinos_client_node_destroy (PinosClientNode *node); SpaResult pinos_client_node_get_data_socket (PinosClientNode *node, int *fd); -SpaResult pinos_client_node_dispatch_message (PinosClientNode *node, - PinosMessageType type, - void *message); - #ifdef __cplusplus } #endif diff --git a/pinos/server/node.c b/pinos/server/node.c index 90810ae21..ccb8689e7 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -23,7 +23,6 @@ #include "pinos/client/pinos.h" #include "pinos/client/interfaces.h" -#include "pinos/client/serialize.h" #include "pinos/server/node.h" #include "pinos/server/data-loop.h" @@ -404,7 +403,6 @@ node_bind_func (PinosGlobal *global, info.input_formats = NULL; for (info.n_input_formats = 0; ; info.n_input_formats++) { SpaFormat *fmt; - void *p; if (spa_node_port_enum_formats (this->node, SPA_DIRECTION_INPUT, @@ -415,16 +413,13 @@ node_bind_func (PinosGlobal *global, break; info.input_formats = realloc (info.input_formats, sizeof (SpaFormat*) * (info.n_input_formats + 1)); - - p = malloc (pinos_serialize_format_get_size (fmt)); - info.input_formats[info.n_input_formats] = pinos_serialize_format_copy_into (p, fmt); + info.input_formats[info.n_input_formats] = spa_format_copy (fmt); } info.max_outputs = this->transport->area->max_outputs; info.n_outputs = this->transport->area->n_outputs; info.output_formats = NULL; for (info.n_output_formats = 0; ; info.n_output_formats++) { SpaFormat *fmt; - void *p; if (spa_node_port_enum_formats (this->node, SPA_DIRECTION_OUTPUT, @@ -435,9 +430,7 @@ node_bind_func (PinosGlobal *global, break; info.output_formats = realloc (info.output_formats, sizeof (SpaFormat*) * (info.n_output_formats + 1)); - - p = malloc (pinos_serialize_format_get_size (fmt)); - info.output_formats[info.n_output_formats] = pinos_serialize_format_copy_into (p, fmt); + info.output_formats[info.n_output_formats] = spa_format_copy (fmt); } info.state = this->state; info.error = this->error; diff --git a/pinos/server/protocol-native.c b/pinos/server/protocol-native.c index 8556d9262..2f7e69016 100644 --- a/pinos/server/protocol-native.c +++ b/pinos/server/protocol-native.c @@ -21,38 +21,73 @@ #include "pinos/server/resource.h" #include "pinos/server/protocol-native.h" + +typedef struct { + SpaPODBuilder b; + PinosConnection *connection; +} Builder; + +static off_t +write_pod (SpaPODBuilder *b, off_t ref, const void *data, size_t size) +{ + if (ref == -1) + ref = b->offset; + + if (b->size <= b->offset) { + b->size = SPA_ROUND_UP_N (b->offset + size, 512); + b->data = pinos_connection_begin_write (((Builder*)b)->connection, b->size); + } + memcpy (b->data + ref, data, size); + return ref; +} + static void -core_event_info (void *object, +core_marshal_info (void *object, PinosCoreInfo *info) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageCoreInfo m = { info }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_CORE_INFO, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, info->id); + spa_pod_builder_long (&b.b, info->change_mask); + spa_pod_builder_string (&b.b, info->user_name); + spa_pod_builder_string (&b.b, info->host_name); + spa_pod_builder_string (&b.b, info->version); + spa_pod_builder_string (&b.b, info->name); + spa_pod_builder_int (&b.b, info->cookie); + n_items = info->props ? info->props->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, info->props->items[i].key); + spa_pod_builder_string (&b.b, info->props->items[i].value); + } + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 0, b.b.offset); } static void -core_event_done (void *object, +core_marshal_done (void *object, uint32_t seq) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageNotifyDone m = { seq }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_NOTIFY_DONE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 1, b.b.offset); } static void -core_event_error (void *object, +core_marshal_error (void *object, uint32_t id, SpaResult res, const char *error, ...) @@ -60,526 +95,800 @@ core_event_error (void *object, PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; char buffer[128]; - PinosMessageError m = { id, res, buffer }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + va_list ap; va_start (ap, error); vsnprintf (buffer, sizeof (buffer), error, ap); va_end (ap); - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_ERROR, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, id); + spa_pod_builder_int (&b.b, res); + spa_pod_builder_string (&b.b, buffer); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 2, b.b.offset); } static void -core_event_remove_id (void *object, +core_marshal_remove_id (void *object, uint32_t id) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageRemoveId m = { id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_REMOVE_ID, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 3, b.b.offset); } static void -core_marshall_client_update (void *object, +core_demarshal_client_update (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageClientUpdate *m = data; - pinos_core_do_client_update (resource, m->props); + SpaDict props; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i32; + int i; + + if (!spa_pod_get_int (&p, &i32)) + return; + props.n_items = i32; + props.items = alloca (props.n_items * sizeof (SpaDictItem)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_get_string (&p, &props.items[i].key) || + !spa_pod_get_string (&p, &props.items[i].value)) + return; + } + + pinos_core_do_client_update (resource, &props); } static void -core_marshall_sync (void *object, +core_demarshal_sync (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageSync *m = data; - pinos_core_do_sync (resource, m->seq); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq; + + if (!spa_pod_get_int (&p, &seq)) + return; + + pinos_core_do_sync (resource, seq); } static void -core_marshall_get_registry (void *object, +core_demarshal_get_registry (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageGetRegistry *m = data; - pinos_core_do_get_registry (resource, m->seq, m->new_id); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq, new_id; + + if (!spa_pod_get_int (&p, &seq) || + !spa_pod_get_int (&p, &new_id)) + return; + + pinos_core_do_get_registry (resource, seq, new_id); } static void -core_marshall_create_node (void *object, +core_demarshal_create_node (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageCreateNode *m = data; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq, new_id, i32; + const char *factory_name, *name; + int i; + SpaDict props; + + if (!spa_pod_get_int (&p, &seq) || + !spa_pod_get_string (&p, &factory_name) || + !spa_pod_get_string (&p, &name) || + !spa_pod_get_int (&p, &i32)) + return; + + props.n_items = i32; + props.items = alloca (props.n_items * sizeof (SpaDictItem)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_get_string (&p, &props.items[i].key) || + !spa_pod_get_string (&p, &props.items[i].value)) + return; + } + if (!spa_pod_get_int (&p, &new_id)) + return; + pinos_core_do_create_node (resource, - m->seq, - m->factory_name, - m->name, - m->props, - m->new_id); + seq, + factory_name, + name, + &props, + new_id); } static void -core_marshall_create_client_node (void *object, +core_demarshal_create_client_node (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageCreateClientNode *m = data; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq, new_id, i32; + const char *name; + int i; + SpaDict props; + + if (!spa_pod_get_int (&p, &seq) || + !spa_pod_get_string (&p, &name) || + !spa_pod_get_int (&p, &i32)) + return; + + props.n_items = i32; + props.items = alloca (props.n_items * sizeof (SpaDictItem)); + for (i = 0; i < props.n_items; i++) { + if (!spa_pod_get_string (&p, &props.items[i].key) || + !spa_pod_get_string (&p, &props.items[i].value)) + return; + } + if (!spa_pod_get_int (&p, &new_id)) + return; + pinos_core_do_create_client_node (resource, - m->seq, - m->name, - m->props, - m->new_id); + seq, + name, + &props, + new_id); } static void -registry_event_global (void *object, +registry_marshal_global (void *object, uint32_t id, const char *type) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageNotifyGlobal m = { id, type }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_NOTIFY_GLOBAL, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, id); + spa_pod_builder_string (&b.b, type); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 0, b.b.offset); } static void -registry_event_global_remove (void *object, +registry_marshal_global_remove (void *object, uint32_t id) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageNotifyGlobalRemove m = { id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 1, b.b.offset); } static void -registry_marshall_bind (void *object, +registry_demarshal_bind (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageBind *m = data; - pinos_registry_do_bind (resource, - m->id, - m->new_id); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1, i2; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2)) + return; + + pinos_registry_do_bind (resource, i1, i2); } static void -module_event_info (void *object, - PinosModuleInfo *info) +module_marshal_info (void *object, + PinosModuleInfo *info) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageModuleInfo m = { info }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_MODULE_INFO, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, info->id); + spa_pod_builder_long (&b.b, info->change_mask); + spa_pod_builder_string (&b.b, info->name); + spa_pod_builder_string (&b.b, info->filename); + spa_pod_builder_string (&b.b, info->args); + n_items = info->props ? info->props->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, info->props->items[i].key); + spa_pod_builder_string (&b.b, info->props->items[i].value); + } + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 0, b.b.offset); } static void -node_event_done (void *object, - uint32_t seq) +node_marshal_done (void *object, + uint32_t seq) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageCreateNodeDone m = { seq }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_CREATE_NODE_DONE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 0, b.b.offset); } static void -node_event_info (void *object, - PinosNodeInfo *info) +node_marshal_info (void *object, + PinosNodeInfo *info) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageNodeInfo m = { info }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_NODE_INFO, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, info->id); + spa_pod_builder_long (&b.b, info->change_mask); + spa_pod_builder_string (&b.b, info->name); + spa_pod_builder_int (&b.b, info->max_inputs); + spa_pod_builder_int (&b.b, info->n_inputs); + spa_pod_builder_int (&b.b, info->n_input_formats); + for (i = 0; i < info->n_input_formats; i++) + spa_pod_builder_raw (&b.b, info->input_formats[i], SPA_POD_SIZE (info->input_formats[i]), true); + spa_pod_builder_int (&b.b, info->max_outputs); + spa_pod_builder_int (&b.b, info->n_outputs); + spa_pod_builder_int (&b.b, info->n_output_formats); + for (i = 0; i < info->n_output_formats; i++) + spa_pod_builder_raw (&b.b, info->output_formats[i], SPA_POD_SIZE (info->output_formats[i]), true); + spa_pod_builder_int (&b.b, info->state); + spa_pod_builder_string (&b.b, info->error); + n_items = info->props ? info->props->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, info->props->items[i].key); + spa_pod_builder_string (&b.b, info->props->items[i].value); + } + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 1, b.b.offset); } static void -client_event_info (void *object, - PinosClientInfo *info) +client_marshal_info (void *object, + PinosClientInfo *info) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageClientInfo m = { info }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, n_items; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_CLIENT_INFO, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, info->id); + spa_pod_builder_long (&b.b, info->change_mask); + n_items = info->props ? info->props->n_items : 0; + spa_pod_builder_int (&b.b, n_items); + for (i = 0; i < n_items; i++) { + spa_pod_builder_string (&b.b, info->props->items[i].key); + spa_pod_builder_string (&b.b, info->props->items[i].value); + } + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 0, b.b.offset); } static void -client_node_event_done (void *object, - uint32_t seq, - int datafd) +client_node_marshal_done (void *object, + uint32_t seq, + int datafd) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageCreateClientNodeDone m = { seq, datafd }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_int (&b.b, pinos_connection_add_fd (connection, datafd)); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 0, b.b.offset); } static void -client_node_event_event (void *object, - SpaNodeEvent *event) +client_node_marshal_event (void *object, + const SpaNodeEvent *event) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageNodeEvent m = { event }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_NODE_EVENT, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_bytes (&b.b, event, event->size); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 1, b.b.offset); } static void -client_node_event_add_port (void *object, - uint32_t seq, - SpaDirection direction, - uint32_t port_id) +client_node_marshal_add_port (void *object, + uint32_t seq, + SpaDirection direction, + uint32_t port_id) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageAddPort m = { seq, direction, port_id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_ADD_PORT, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_int (&b.b, direction); + spa_pod_builder_int (&b.b, port_id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 2, b.b.offset); } static void -client_node_event_remove_port (void *object, - uint32_t seq, - SpaDirection direction, - uint32_t port_id) +client_node_marshal_remove_port (void *object, + uint32_t seq, + SpaDirection direction, + uint32_t port_id) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageRemovePort m = { seq, direction, port_id }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_REMOVE_PORT, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_int (&b.b, direction); + spa_pod_builder_int (&b.b, port_id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 3, b.b.offset); } static void -client_node_event_set_format (void *object, - uint32_t seq, - SpaDirection direction, - uint32_t port_id, - SpaPortFormatFlags flags, - const SpaFormat *format) -{ - PinosResource *resource = object; - PinosConnection *connection = resource->client->protocol_private; - PinosMessageSetFormat m = { seq, direction, port_id, flags, format }; - - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_SET_FORMAT, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_event_set_property (void *object, +client_node_marshal_set_format (void *object, uint32_t seq, - uint32_t id, - size_t size, - void *value) -{ - PinosResource *resource = object; - PinosConnection *connection = resource->client->protocol_private; - PinosMessageSetProperty m = { seq, id, size, value }; - - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_SET_PROPERTY, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_event_add_mem (void *object, - SpaDirection direction, - uint32_t port_id, - uint32_t mem_id, - SpaDataType type, - int memfd, - uint32_t flags, - off_t offset, - size_t size) -{ - PinosResource *resource = object; - PinosConnection *connection = resource->client->protocol_private; - PinosMessageAddMem m = { direction, port_id, mem_id, type, memfd, flags, offset, size }; - - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_ADD_MEM, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_event_use_buffers (void *object, - uint32_t seq, - SpaDirection direction, - uint32_t port_id, - unsigned int n_buffers, - PinosClientNodeBuffer *buffers) -{ - PinosResource *resource = object; - PinosConnection *connection = resource->client->protocol_private; - PinosMessageUseBuffers m = { seq, direction, port_id, n_buffers, buffers }; - - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_USE_BUFFERS, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_event_node_command (void *object, - uint32_t seq, - SpaNodeCommand *command) -{ - PinosResource *resource = object; - PinosConnection *connection = resource->client->protocol_private; - PinosMessageNodeCommand m = { seq, command }; - - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_NODE_COMMAND, - &m); - pinos_connection_flush (connection); -} - -static void -client_node_event_port_command (void *object, + SpaDirection direction, uint32_t port_id, - SpaNodeCommand *command) + SpaPortFormatFlags flags, + const SpaFormat *format) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessagePortCommand m = { port_id, command }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_PORT_COMMAND, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_int (&b.b, direction); + spa_pod_builder_int (&b.b, port_id); + spa_pod_builder_int (&b.b, flags); + spa_pod_builder_int (&b.b, format ? 1 : 0); + if (format) + spa_pod_builder_raw (&b.b, format, SPA_POD_SIZE (format), true); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 4, b.b.offset); } static void -client_node_event_transport (void *object, +client_node_marshal_set_property (void *object, + uint32_t seq, + uint32_t id, + size_t size, + const void *value) +{ + PinosResource *resource = object; + PinosConnection *connection = resource->client->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_int (&b.b, id); + spa_pod_builder_bytes (&b.b, value, size); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 5, b.b.offset); +} + +static void +client_node_marshal_add_mem (void *object, + SpaDirection direction, + uint32_t port_id, + uint32_t mem_id, + SpaDataType type, int memfd, + uint32_t flags, off_t offset, size_t size) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageTransportUpdate m = { memfd, offset, size }; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_TRANSPORT_UPDATE, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, direction); + spa_pod_builder_int (&b.b, port_id); + spa_pod_builder_int (&b.b, mem_id); + spa_pod_builder_int (&b.b, type); + spa_pod_builder_int (&b.b, pinos_connection_add_fd (connection, memfd)); + spa_pod_builder_int (&b.b, flags); + spa_pod_builder_int (&b.b, offset); + spa_pod_builder_int (&b.b, size); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 6, b.b.offset); } static void -client_node_marshall_update (void *object, - void *data, - size_t size) +client_node_marshal_use_buffers (void *object, + uint32_t seq, + SpaDirection direction, + uint32_t port_id, + unsigned int n_buffers, + PinosClientNodeBuffer *buffers) { PinosResource *resource = object; - PinosMessageNodeUpdate *m = data; - pinos_client_node_do_update (resource, - m->change_mask, - m->max_input_ports, - m->max_output_ports, - m->props); + PinosConnection *connection = resource->client->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + int i, j; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_int (&b.b, direction); + spa_pod_builder_int (&b.b, port_id); + spa_pod_builder_int (&b.b, n_buffers); + for (i = 0; i < n_buffers; i++) { + SpaBuffer *buf = buffers[i].buffer; + + spa_pod_builder_int (&b.b, buffers[i].mem_id); + spa_pod_builder_int (&b.b, buffers[i].offset); + spa_pod_builder_int (&b.b, buffers[i].size); + spa_pod_builder_int (&b.b, buf->id); + spa_pod_builder_int (&b.b, buf->n_metas); + for (j = 0; j < buf->n_metas; j++) { + SpaMeta *m = &buf->metas[j]; + spa_pod_builder_int (&b.b, m->type); + spa_pod_builder_int (&b.b, m->size); + } + spa_pod_builder_int (&b.b, buf->n_datas); + for (j = 0; j < buf->n_datas; j++) { + SpaData *d = &buf->datas[j]; + spa_pod_builder_int (&b.b, d->type); + spa_pod_builder_int (&b.b, SPA_PTR_TO_UINT32 (d->data)); + spa_pod_builder_int (&b.b, d->flags); + spa_pod_builder_int (&b.b, d->mapoffset); + spa_pod_builder_int (&b.b, d->maxsize); + } + } + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 7, b.b.offset); } static void -client_node_marshall_port_update (void *object, - void *data, - size_t size) +client_node_marshal_node_command (void *object, + uint32_t seq, + const SpaNodeCommand *command) { PinosResource *resource = object; - PinosMessagePortUpdate *m = data; - pinos_client_node_do_port_update (resource, - m->direction, - m->port_id, - m->change_mask, - m->n_possible_formats, - m->possible_formats, - m->format, - m->props, - m->info); + PinosConnection *connection = resource->client->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, seq); + spa_pod_builder_bytes (&b.b, command, command->size); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 8, b.b.offset); } static void -client_node_marshall_state_change (void *object, +client_node_marshal_port_command (void *object, + uint32_t port_id, + const SpaNodeCommand *command) +{ + PinosResource *resource = object; + PinosConnection *connection = resource->client->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, port_id); + spa_pod_builder_bytes (&b.b, command, command->size); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 9, b.b.offset); +} + +static void +client_node_marshal_transport (void *object, + int memfd, + off_t offset, + size_t size) +{ + PinosResource *resource = object; + PinosConnection *connection = resource->client->protocol_private; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; + + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, pinos_connection_add_fd (connection, memfd)); + spa_pod_builder_int (&b.b, offset); + spa_pod_builder_int (&b.b, size); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 10, b.b.offset); +} + +static void +client_node_demarshal_update (void *object, + void *data, + size_t size) +{ + PinosResource *resource = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1, i2, i3, i4; + const SpaPOD *props = NULL; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_int (&p, &i2) || + !spa_pod_get_int (&p, &i3) || + !spa_pod_get_int (&p, &i4)) + return; + + if (i4 && !spa_pod_get_object (&p, &props)) + return; + + pinos_client_node_do_update (resource, i1, i2, i3, (SpaProps *)props); +} + +static void +client_node_demarshal_port_update (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageNodeStateChange *m = data; - pinos_client_node_do_state_change (resource, m->state); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t i1, i2, direction, port_id, change_mask, n_possible_formats; + int64_t l1, l2; + const SpaProps *props = NULL; + const SpaFormat **possible_formats = NULL, *format = NULL; + SpaPortInfo info, *infop = NULL; + int i; + uint32_t sz; + + if (!spa_pod_get_int (&p, &direction) || + !spa_pod_get_int (&p, &port_id) || + !spa_pod_get_int (&p, &change_mask) || + !spa_pod_get_int (&p, &n_possible_formats)) + return; + + possible_formats = alloca (n_possible_formats * sizeof (SpaFormat*)); + for (i = 0; i < n_possible_formats; i++) + spa_pod_get_object (&p, (const SpaPOD**)&possible_formats[i]); + + if (!spa_pod_get_int (&p, &i1) || + (i1 && !spa_pod_get_object (&p, (const SpaPOD**)&format))) + return; + + if (!spa_pod_get_int (&p, &i1) || + (i1 && !spa_pod_get_object (&p, (const SpaPOD**)&props))) + return; + + if (!spa_pod_get_int (&p, &i1)) + return; + + if (i1) { + SpaDict dict; + infop = &info; + + if (!spa_pod_get_int (&p, &i1) || + !spa_pod_get_long (&p, &l1) || + !spa_pod_get_long (&p, &l2) || + !spa_pod_get_int (&p, &i2)) + return; + + info.flags = i1; + info.maxbuffering = l1; + info.latency = l2; + info.n_params = i2; + info.params = alloca (info.n_params * sizeof (SpaAllocParam *)); + + for (i = 0; i < info.n_params; i++) + spa_pod_get_bytes (&p, (const void **)&info.params[i], &sz); + + if (!spa_pod_get_int (&p, &i1)) + return; + + info.extra = &dict; + dict.n_items = i1; + dict.items = alloca (dict.n_items * sizeof (SpaDictItem)); + for (i = 0; i < dict.n_items; i++) { + if (!spa_pod_get_string (&p, &dict.items[i].key) || + !spa_pod_get_string (&p, &dict.items[i].value)) + return; + } + } + + pinos_client_node_do_port_update (resource, + direction, + port_id, + change_mask, + n_possible_formats, + possible_formats, + format, + props, + infop); } static void -client_node_marshall_event (void *object, +client_node_demarshal_state_change (void *object, + void *data, + size_t size) +{ + PinosResource *resource = object; + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t state; + + if (!spa_pod_get_int (&p, &state)) + return; + + pinos_client_node_do_state_change (resource, state); +} + +static void +client_node_demarshal_event (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageNodeEvent *m = data; - pinos_client_node_do_event (resource, m->event); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + SpaNodeEvent *event; + uint32_t sz; + + if (!spa_pod_get_bytes (&p, (const void **)&event, &sz)) + return; + + pinos_client_node_do_event (resource, event); } static void -client_node_marshall_destroy (void *object, +client_node_demarshal_destroy (void *object, void *data, size_t size) { PinosResource *resource = object; - PinosMessageDestroy *m = data; - pinos_client_node_do_destroy (resource, m->seq); + SpaPOD *p = SPA_POD_CONTENTS (SpaPODStruct, data); + int32_t seq; + + if (!spa_pod_get_int (&p, &seq)) + return; + + pinos_client_node_do_destroy (resource, seq); } static void -link_event_info (void *object, +link_marshal_info (void *object, PinosLinkInfo *info) { PinosResource *resource = object; PinosConnection *connection = resource->client->protocol_private; - PinosMessageLinkInfo m; + Builder b = { { NULL, 0, 0, NULL, write_pod }, connection }; + SpaPODFrame f; - m.info = info; - pinos_connection_add_message (connection, - resource->id, - PINOS_MESSAGE_LINK_INFO, - &m); - pinos_connection_flush (connection); + spa_pod_builder_push_struct (&b.b, &f); + spa_pod_builder_int (&b.b, info->id); + spa_pod_builder_long (&b.b, info->change_mask); + spa_pod_builder_int (&b.b, info->output_node_id); + spa_pod_builder_int (&b.b, info->output_port_id); + spa_pod_builder_int (&b.b, info->input_node_id); + spa_pod_builder_int (&b.b, info->input_port_id); + spa_pod_builder_pop (&b.b, &f); + + pinos_connection_end_write (connection, resource->id, 0, b.b.offset); } const PinosCoreEvent pinos_protocol_native_server_core_event = { - &core_event_info, - &core_event_done, - &core_event_error, - &core_event_remove_id + &core_marshal_info, + &core_marshal_done, + &core_marshal_error, + &core_marshal_remove_id }; -const PinosMarshallFunc pinos_protocol_native_server_core_marshall[] = { - [PINOS_MESSAGE_CLIENT_UPDATE] = &core_marshall_client_update, - [PINOS_MESSAGE_SYNC] = &core_marshall_sync, - [PINOS_MESSAGE_GET_REGISTRY] = &core_marshall_get_registry, - [PINOS_MESSAGE_CREATE_NODE] = &core_marshall_create_node, - [PINOS_MESSAGE_CREATE_CLIENT_NODE] = &core_marshall_create_client_node +const PinosDemarshalFunc pinos_protocol_native_server_core_demarshal[] = { + &core_demarshal_client_update, + &core_demarshal_sync, + &core_demarshal_get_registry, + &core_demarshal_create_node, + &core_demarshal_create_client_node }; const PinosRegistryEvent pinos_protocol_native_server_registry_event = { - ®istry_event_global, - ®istry_event_global_remove, + ®istry_marshal_global, + ®istry_marshal_global_remove, }; -const PinosMarshallFunc pinos_protocol_native_server_registry_marshall[] = { - [PINOS_MESSAGE_BIND] = ®istry_marshall_bind, +const PinosDemarshalFunc pinos_protocol_native_server_registry_demarshal[] = { + ®istry_demarshal_bind, }; const PinosModuleEvent pinos_protocol_native_server_module_event = { - &module_event_info, + &module_marshal_info, }; const PinosNodeEvent pinos_protocol_native_server_node_event = { - &node_event_done, - &node_event_info, + &node_marshal_done, + &node_marshal_info, }; const PinosClientEvent pinos_protocol_native_server_client_event = { - &client_event_info, + &client_marshal_info, }; const PinosClientNodeEvent pinos_protocol_native_server_client_node_events = { - &client_node_event_done, - &client_node_event_event, - &client_node_event_add_port, - &client_node_event_remove_port, - &client_node_event_set_format, - &client_node_event_set_property, - &client_node_event_add_mem, - &client_node_event_use_buffers, - &client_node_event_node_command, - &client_node_event_port_command, - &client_node_event_transport, + &client_node_marshal_done, + &client_node_marshal_event, + &client_node_marshal_add_port, + &client_node_marshal_remove_port, + &client_node_marshal_set_format, + &client_node_marshal_set_property, + &client_node_marshal_add_mem, + &client_node_marshal_use_buffers, + &client_node_marshal_node_command, + &client_node_marshal_port_command, + &client_node_marshal_transport, }; -const PinosMarshallFunc pinos_protocol_native_server_client_node_marshall[] = { - [PINOS_MESSAGE_NODE_UPDATE] = &client_node_marshall_update, - [PINOS_MESSAGE_PORT_UPDATE] = &client_node_marshall_port_update, - [PINOS_MESSAGE_NODE_STATE_CHANGE] = &client_node_marshall_state_change, - [PINOS_MESSAGE_NODE_EVENT] = &client_node_marshall_event, - [PINOS_MESSAGE_DESTROY] = &client_node_marshall_destroy, +const PinosDemarshalFunc pinos_protocol_native_server_client_node_demarshal[] = { + &client_node_demarshal_update, + &client_node_demarshal_port_update, + &client_node_demarshal_state_change, + &client_node_demarshal_event, + &client_node_demarshal_destroy, }; const PinosLinkEvent pinos_protocol_native_server_link_event = { - &link_event_info, + &link_marshal_info, }; diff --git a/pinos/server/protocol-native.h b/pinos/server/protocol-native.h index 4c30ba2ad..77160741d 100644 --- a/pinos/server/protocol-native.h +++ b/pinos/server/protocol-native.h @@ -19,7 +19,7 @@ #include "pinos/client/pinos.h" -typedef void (*PinosMarshallFunc) (void *object, void *data, size_t size); +typedef void (*PinosDemarshalFunc) (void *object, void *data, size_t size); extern const PinosCoreEvent pinos_protocol_native_server_core_event; extern const PinosRegistryEvent pinos_protocol_native_server_registry_event; @@ -29,6 +29,6 @@ extern const PinosClientEvent pinos_protocol_native_server_client_event; extern const PinosClientNodeEvent pinos_protocol_native_server_client_node_events; extern const PinosLinkEvent pinos_protocol_native_server_link_event; -extern const PinosMarshallFunc pinos_protocol_native_server_core_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_server_registry_marshall[]; -extern const PinosMarshallFunc pinos_protocol_native_server_client_node_marshall[]; +extern const PinosDemarshalFunc pinos_protocol_native_server_core_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_server_registry_demarshal[]; +extern const PinosDemarshalFunc pinos_protocol_native_server_client_node_demarshal[]; diff --git a/pinos/server/resource.h b/pinos/server/resource.h index 582dd7ef9..798be19ba 100644 --- a/pinos/server/resource.h +++ b/pinos/server/resource.h @@ -50,7 +50,7 @@ struct _PinosResource { const void *interface; const void *event; - const void *marshall; + const void *demarshal; PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosResource *resource)); diff --git a/spa/include/spa/node.h b/spa/include/spa/node.h index 4f3410cc3..dcd3edffc 100644 --- a/spa/include/spa/node.h +++ b/spa/include/spa/node.h @@ -231,8 +231,8 @@ struct _SpaNode { * #SPA_RESULT_INVALID_COMMAND @command is an invalid command * #SPA_RESULT_ASYNC @command is executed asynchronously */ - SpaResult (*send_command) (SpaNode *node, - SpaNodeCommand *command); + SpaResult (*send_command) (SpaNode *node, + SpaNodeCommand *command); /** * SpaNode::set_event_callback: * @node: a #SpaNode diff --git a/spa/include/spa/pod-builder.h b/spa/include/spa/pod-builder.h index 865cb510d..79c2cfa6f 100644 --- a/spa/include/spa/pod-builder.h +++ b/spa/include/spa/pod-builder.h @@ -211,7 +211,7 @@ spa_pod_builder_double (SpaPODBuilder *builder, double val) } static inline off_t -spa_pod_builder_string (SpaPODBuilder *builder, const char *str, uint32_t len) +spa_pod_builder_string_len (SpaPODBuilder *builder, const char *str, uint32_t len) { const SpaPODString p = { { len + 1, SPA_POD_TYPE_STRING } }; off_t out = spa_pod_builder_raw (builder, &p, sizeof (p) , false); @@ -220,6 +220,23 @@ spa_pod_builder_string (SpaPODBuilder *builder, const char *str, uint32_t len) return out; } +static inline off_t +spa_pod_builder_string (SpaPODBuilder *builder, const char *str) +{ + uint32_t len = str ? strlen (str) : 0; + return spa_pod_builder_string_len (builder, str ? str : "", len); +} + +static inline off_t +spa_pod_builder_bytes (SpaPODBuilder *builder, const void *bytes, uint32_t len) +{ + const SpaPODBytes p = { { len, SPA_POD_TYPE_BYTES } }; + off_t out = spa_pod_builder_raw (builder, &p, sizeof (p) , false); + if (spa_pod_builder_raw (builder, bytes, len, true) == -1) + out = -1; + return out; +} + static inline off_t spa_pod_builder_rectangle (SpaPODBuilder *builder, uint32_t width, uint32_t height) { @@ -334,7 +351,7 @@ spa_pod_builder_propv (SpaPODBuilder *builder, { const char *str = va_arg (args, char *); uint32_t len = va_arg (args, uint32_t); - spa_pod_builder_string (builder, str, len); + spa_pod_builder_string_len (builder, str, len); break; } case SPA_POD_TYPE_RECTANGLE: diff --git a/spa/include/spa/pod.h b/spa/include/spa/pod.h index c5aa02774..12b4d85c8 100644 --- a/spa/include/spa/pod.h +++ b/spa/include/spa/pod.h @@ -70,6 +70,16 @@ typedef struct { int32_t value; } SpaPODInt; +static inline bool +spa_pod_get_int (SpaPOD **pod, int32_t *val) +{ + if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_INT) + return false; + *val = ((SpaPODInt *)(*pod))->value; + *pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD); + return true; +} + typedef SpaPODInt SpaPODBool; typedef SpaPODInt SpaPODURI; @@ -78,6 +88,16 @@ typedef struct { int64_t value; } SpaPODLong; +static inline bool +spa_pod_get_long (SpaPOD **pod, int64_t *val) +{ + if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_LONG) + return false; + *val = ((SpaPODLong *)*pod)->value; + *pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD); + return true; +} + typedef struct { SpaPOD pod; float value; @@ -93,6 +113,21 @@ typedef struct { /* value here */ } SpaPODString; +static inline bool +spa_pod_get_string (SpaPOD **pod, const char **val) +{ + if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_STRING) + return false; + *val = SPA_POD_CONTENTS (SpaPODString, *pod); + *pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD); + return true; +} + +typedef struct { + SpaPOD pod; + /* value here */ +} SpaPODBytes; + typedef struct { SpaPOD pod; SpaRectangle value; @@ -123,6 +158,16 @@ typedef struct { /* one or more SpaPOD follow */ } SpaPODStruct; +static inline bool +spa_pod_get_struct (SpaPOD **pod, SpaPOD **val) +{ + if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_STRUCT) + return false; + *val = *pod; + *pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD); + return true; +} + typedef struct { uint32_t key; #define SPA_POD_PROP_RANGE_NONE 0 @@ -161,6 +206,28 @@ typedef struct { SpaPODObjectBody body; } SpaPODObject; +static inline bool +spa_pod_get_object (SpaPOD **pod, const SpaPOD **val) +{ + if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_OBJECT) + return false; + *val = *pod; + *pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD); + return true; +} + +static inline bool +spa_pod_get_bytes (SpaPOD **pod, const void **val, uint32_t *size) +{ + if (*pod == NULL || (*pod)->type != SPA_POD_TYPE_BYTES) + return false; + *val = SPA_POD_CONTENTS (SpaPODBytes, *pod); + *size = SPA_POD_SIZE (*pod); + *pod = SPA_MEMBER (*pod, SPA_ROUND_UP_N (SPA_POD_SIZE (*pod), 8), SpaPOD); + return true; +} + + #define SPA_POD_ARRAY_BODY_FOREACH(body, size, iter) \ for ((iter) = SPA_MEMBER (body, sizeof(SpaPODArrayBody), __typeof__(*iter)); \ (iter) < SPA_MEMBER (body, (size), __typeof__(*iter)); \ @@ -204,6 +271,7 @@ spa_pod_object_find_prop (const SpaPODObject *obj, uint32_t key) return spa_pod_contents_find_prop (&obj->pod, sizeof (SpaPODObject), key); } + #ifdef __cplusplus } /* extern "C" */ #endif diff --git a/spa/lib/debug.c b/spa/lib/debug.c index dcbeef3cd..5959688cd 100644 --- a/spa/lib/debug.c +++ b/spa/lib/debug.c @@ -424,6 +424,10 @@ print_pod_value (uint32_t size, uint32_t type, void *body, int prefix) } break; } + case SPA_POD_TYPE_BYTES: + printf ("%-*sBytes\n", prefix, ""); + spa_debug_dump_mem (body, size); + break; default: printf ("unhandled prop type %d\n", type); break; @@ -477,6 +481,9 @@ print_format_value (uint32_t size, uint32_t type, void *body) case SPA_POD_TYPE_BITMASK: fprintf (stderr, "Bitmask"); break; + case SPA_POD_TYPE_BYTES: + fprintf (stderr, "Bytes"); + break; default: break; } diff --git a/spa/tests/test-props2.c b/spa/tests/test-props2.c index eef7a5eae..39ba3558a 100644 --- a/spa/tests/test-props2.c +++ b/spa/tests/test-props2.c @@ -72,7 +72,7 @@ main (int argc, char *argv[]) spa_pod_builder_long (&b, 6000); spa_pod_builder_float (&b, 4.0); spa_pod_builder_double (&b, 3.14); - spa_pod_builder_string (&b, "test123", strlen ("test123")); + spa_pod_builder_string (&b, "test123"); spa_pod_builder_rectangle (&b, 320, 240); spa_pod_builder_fraction (&b, 25, 1); spa_pod_builder_push_array (&b, &frame[3]);