diff --git a/pinos/client/connection.c b/pinos/client/connection.c index 09c25babb..877591ff3 100644 --- a/pinos/client/connection.c +++ b/pinos/client/connection.c @@ -126,6 +126,99 @@ connection_parse_create_client_node (PinosConnection *conn, PinosMessageCreateCl 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; + + 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 (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_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) { @@ -297,8 +390,6 @@ connection_add_create_node (PinosConnection *conn, uint32_t dest_id, PinosMessag if (m->props) { len = pinos_serialize_dict_serialize (p, m->props); d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } else { - d->props = 0; } } @@ -328,8 +419,223 @@ connection_add_create_client_node (PinosConnection *conn, uint32_t dest_id, Pino if (m->props) { len = pinos_serialize_dict_serialize (p, m->props); d->props = SPA_INT_TO_PTR (SPA_PTRDIFF (p, d)); - } else { - d->props = 0; + } +} + +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; + + /* calc len */ + len = sizeof (PinosMessageNodeInfo); + if (m->info) { + len += sizeof (PinosNodeInfo); + 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_NODE_INFO, len); + memcpy (p, m, sizeof (PinosMessageNodeInfo)); + d = p; + + p = SPA_MEMBER (d, sizeof (PinosMessageNodeInfo), void); + if (m->info) { + PinosNodeInfo *di; + + 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); + 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_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)); } } @@ -761,10 +1067,30 @@ pinos_connection_parse_message (PinosConnection *conn, memcpy (message, conn->in.data, sizeof (PinosMessageDestroy)); break; - case PINOS_MESSAGE_DESTROY_DONE: - if (conn->in.size < sizeof (PinosMessageDestroyDone)) + case PINOS_MESSAGE_REMOVE_ID: + if (conn->in.size < sizeof (PinosMessageRemoveId)) return false; - memcpy (message, conn->in.data, sizeof (PinosMessageDestroyDone)); + 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 */ @@ -927,11 +1253,30 @@ pinos_connection_add_message (PinosConnection *conn, memcpy (p, message, sizeof (PinosMessageDestroy)); break; - case PINOS_MESSAGE_DESTROY_DONE: - p = connection_add_message (conn, dest_id, type, sizeof (PinosMessageDestroyDone)); - memcpy (p, message, sizeof (PinosMessageDestroyDone)); + 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: diff --git a/pinos/client/connection.h b/pinos/client/connection.h index 0ff90e55f..96d34b7df 100644 --- a/pinos/client/connection.h +++ b/pinos/client/connection.h @@ -38,6 +38,8 @@ typedef enum { PINOS_MESSAGE_SYNC, PINOS_MESSAGE_NOTIFY_DONE, PINOS_MESSAGE_GET_REGISTRY, + PINOS_MESSAGE_REMOVE_ID, + PINOS_MESSAGE_CORE_INFO, PINOS_MESSAGE_BIND, PINOS_MESSAGE_NOTIFY_GLOBAL, @@ -50,7 +52,11 @@ typedef enum { PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE, PINOS_MESSAGE_DESTROY, - PINOS_MESSAGE_DESTROY_DONE, + + PINOS_MESSAGE_MODULE_INFO, + PINOS_MESSAGE_NODE_INFO, + PINOS_MESSAGE_CLIENT_INFO, + PINOS_MESSAGE_LINK_INFO, /* client to server */ PINOS_MESSAGE_NODE_UPDATE, @@ -78,6 +84,8 @@ typedef enum { } PinosMessageType; +#include + /* PINOS_MESSAGE_SYNC */ typedef struct { uint32_t seq; @@ -94,6 +102,36 @@ typedef struct { 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; @@ -145,12 +183,6 @@ typedef struct { uint32_t id; } PinosMessageDestroy; -/* PINOS_MESSAGE_DESTROY_DONE */ -typedef struct { - uint32_t seq; - uint32_t id; -} PinosMessageDestroyDone; - /* PINOS_MESSAGE_NODE_UPDATE */ typedef struct { #define PINOS_MESSAGE_NODE_UPDATE_MAX_INPUTS (1 << 0) diff --git a/pinos/client/context.c b/pinos/client/context.c index d15aa5bdb..b61f45086 100644 --- a/pinos/client/context.c +++ b/pinos/client/context.c @@ -38,7 +38,6 @@ typedef struct { bool disconnecting; - PinosSubscriptionFlags subscribe_mask; PinosSubscriptionFunc subscribe_func; void *subscribe_data; } PinosContextImpl; @@ -102,7 +101,8 @@ core_dispatch_func (void *object, void *message, void *data) { - PinosContext *context = data; + PinosContextImpl *impl = data; + PinosContext *this = &impl->this; switch (type) { case PINOS_MESSAGE_NOTIFY_DONE: @@ -110,7 +110,142 @@ core_dispatch_func (void *object, PinosMessageNotifyDone *nd = message; if (nd->seq == 0) - context_set_state (context, PINOS_CONTEXT_STATE_CONNECTED, NULL); + context_set_state (this, PINOS_CONTEXT_STATE_CONNECTED, NULL); + break; + } + case PINOS_MESSAGE_REMOVE_ID: + { + PinosMessageRemoveId *m = message; + PinosProxy *proxy; + + proxy = pinos_map_lookup (&this->objects, m->id); + if (proxy) { + pinos_log_debug ("context %p: object remove %u", this, m->id); + pinos_map_remove (&this->objects, m->id); + pinos_proxy_destroy (proxy); + } + break; + } + + default: + pinos_log_warn ("unhandled message %d", type); + break; + } + return SPA_RESULT_OK; +} + +static SpaResult +module_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosContextImpl *impl = data; + PinosContext *this = &impl->this; + PinosProxy *proxy = object; + + switch (type) { + case PINOS_MESSAGE_MODULE_INFO: + { + PinosMessageModuleInfo *m = message; + PinosSubscriptionEvent event; + + pinos_log_debug ("got module info %d", type); + if (proxy->user_data == NULL) + event = PINOS_SUBSCRIPTION_EVENT_NEW; + else + event = PINOS_SUBSCRIPTION_EVENT_CHANGE; + + proxy->user_data = pinos_module_info_update (proxy->user_data, m->info); + + if (impl->subscribe_func) { + impl->subscribe_func (this, + event, + proxy->type, + proxy->id, + impl->subscribe_data); + } + break; + } + + default: + pinos_log_warn ("unhandled message %d", type); + break; + } + return SPA_RESULT_OK; +} + +static SpaResult +node_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosContextImpl *impl = data; + PinosContext *this = &impl->this; + PinosProxy *proxy = object; + + switch (type) { + case PINOS_MESSAGE_NODE_INFO: + { + PinosMessageNodeInfo *m = message; + PinosSubscriptionEvent event; + + pinos_log_debug ("got node info %d", type); + if (proxy->user_data == NULL) + event = PINOS_SUBSCRIPTION_EVENT_NEW; + else + event = PINOS_SUBSCRIPTION_EVENT_CHANGE; + + proxy->user_data = pinos_node_info_update (proxy->user_data, m->info); + + if (impl->subscribe_func) { + impl->subscribe_func (this, + event, + proxy->type, + proxy->id, + impl->subscribe_data); + } + break; + } + default: + pinos_log_warn ("unhandled message %d", type); + break; + } + return SPA_RESULT_OK; +} + +static SpaResult +client_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosContextImpl *impl = data; + PinosContext *this = &impl->this; + PinosProxy *proxy = object; + + switch (type) { + case PINOS_MESSAGE_CLIENT_INFO: + { + PinosMessageClientInfo *m = message; + PinosSubscriptionEvent event; + + pinos_log_debug ("got client info %d", type); + if (proxy->user_data == NULL) + event = PINOS_SUBSCRIPTION_EVENT_NEW; + else + event = PINOS_SUBSCRIPTION_EVENT_CHANGE; + + proxy->user_data = pinos_client_info_update (proxy->user_data, m->info); + + if (impl->subscribe_func) { + impl->subscribe_func (this, + event, + proxy->type, + proxy->id, + impl->subscribe_data); + } break; } default: @@ -126,17 +261,61 @@ registry_dispatch_func (void *object, void *message, void *data) { + PinosContextImpl *impl = data; + PinosContext *this = &impl->this; + switch (type) { case PINOS_MESSAGE_NOTIFY_GLOBAL: { PinosMessageNotifyGlobal *ng = message; + PinosProxy *proxy = NULL; + pinos_log_debug ("got global %u %s", ng->id, ng->type); + + if (!strcmp (ng->type, PINOS_NODE_URI)) { + proxy = pinos_proxy_new (this, + SPA_ID_INVALID, + this->uri.node); + proxy->dispatch_func = node_dispatch_func; + proxy->dispatch_data = impl; + } else if (!strcmp (ng->type, PINOS_MODULE_URI)) { + proxy = pinos_proxy_new (this, + SPA_ID_INVALID, + this->uri.module); + proxy->dispatch_func = module_dispatch_func; + proxy->dispatch_data = impl; + } else if (!strcmp (ng->type, PINOS_CLIENT_URI)) { + proxy = pinos_proxy_new (this, + SPA_ID_INVALID, + this->uri.client); + proxy->dispatch_func = client_dispatch_func; + proxy->dispatch_data = impl; + } else if (!strcmp (ng->type, PINOS_LINK_URI)) { + } + if (proxy) { + PinosMessageBind m; + + m.id = ng->id; + m.new_id = proxy->id; + pinos_proxy_send_message (this->registry_proxy, + PINOS_MESSAGE_BIND, + &m, + true); + } break; } case PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE: { PinosMessageNotifyGlobalRemove *ng = message; pinos_log_debug ("got global remove %u", ng->id); + + if (impl->subscribe_func) { + impl->subscribe_func (this, + PINOS_SUBSCRIPTION_EVENT_REMOVE, + SPA_ID_INVALID, + ng->id, + impl->subscribe_data); + } break; } default: @@ -146,19 +325,6 @@ registry_dispatch_func (void *object, return SPA_RESULT_OK; } -static PinosProxy * -find_proxy (PinosContext *context, - uint32_t id) -{ - PinosProxy *p; - - spa_list_for_each (p, &context->proxy_list, link) { - if (p->id == id) - return p; - } - return NULL; -} - static void on_context_data (SpaSource *source, int fd, @@ -190,11 +356,15 @@ on_context_data (SpaSource *source, continue; } - proxy = find_proxy (this, id); + proxy = pinos_map_lookup (&this->objects, id); if (proxy == NULL) { pinos_log_error ("context %p: could not find proxy %u", this, id); continue; } + if (proxy->dispatch_func == NULL) { + pinos_log_error ("context %p: no dispatch function for proxy %u", this, id); + continue; + } proxy->dispatch_func (proxy, type, p, proxy->dispatch_data); } @@ -250,6 +420,8 @@ pinos_context_new (PinosLoop *loop, pinos_fill_context_properties (properties); this->properties = properties; + pinos_uri_init (&this->uri); + this->loop = loop; this->state = PINOS_CONTEXT_STATE_UNCONNECTED; @@ -365,15 +537,15 @@ pinos_context_connect (PinosContext *context) context->core_proxy = pinos_proxy_new (context, SPA_ID_INVALID, - 0); + context->uri.core); context->core_proxy->dispatch_func = core_dispatch_func; - context->core_proxy->dispatch_data = context; + context->core_proxy->dispatch_data = impl; context->registry_proxy = pinos_proxy_new (context, SPA_ID_INVALID, - 0); + context->uri.registry); context->registry_proxy->dispatch_func = registry_dispatch_func; - context->registry_proxy->dispatch_data = context; + context->registry_proxy->dispatch_data = impl; grm.seq = 0; grm.new_id = context->registry_proxy->id; @@ -409,23 +581,84 @@ pinos_context_disconnect (PinosContext *context) void pinos_context_subscribe (PinosContext *context, - PinosSubscriptionFlags mask, PinosSubscriptionFunc func, void *data) { PinosContextImpl *impl = SPA_CONTAINER_OF (context, PinosContextImpl, this); - impl->subscribe_mask = mask; impl->subscribe_func = func; impl->subscribe_data = data; } void -pinos_context_get_daemon_info (PinosContext *context, - PinosDaemonInfoCallback cb, - void *user_data) +pinos_context_get_core_info (PinosContext *context, + PinosCoreInfoCallback cb, + void *user_data) { - cb (context, SPA_RESULT_OK, NULL, user_data); + PinosProxy *proxy; + + proxy = pinos_map_lookup (&context->objects, 0); + if (proxy == NULL) { + cb (context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data); + } else if (proxy->type == context->uri.core && proxy->user_data) { + PinosCoreInfo *info = proxy->user_data; + cb (context, SPA_RESULT_OK, info, user_data); + info->change_mask = 0; + } + cb (context, SPA_RESULT_ENUM_END, NULL, user_data); +} + +typedef void (*ListFunc) (PinosContext *, SpaResult, void *, void *); + +static void +do_list (PinosContext *context, + uint32_t type, + ListFunc cb, + void *user_data) +{ + PinosMapItem *item; + + pinos_array_for_each (item, &context->objects.items) { + PinosProxy *proxy; + + if (pinos_map_item_is_free (item)) + continue; + + proxy = item->data; + if (proxy->type != type) + continue; + + cb (context, SPA_RESULT_OK, proxy->user_data, user_data); + } + cb (context, SPA_RESULT_ENUM_END, NULL, user_data); +} + + +void +pinos_context_list_module_info (PinosContext *context, + PinosModuleInfoCallback cb, + void *user_data) +{ + do_list (context, context->uri.module, (ListFunc) cb, user_data); +} + +void +pinos_context_get_module_info_by_id (PinosContext *context, + uint32_t id, + PinosModuleInfoCallback cb, + void *user_data) +{ + PinosProxy *proxy; + + proxy = pinos_map_lookup (&context->objects, id); + if (proxy == NULL) { + cb (context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data); + } else if (proxy->type == context->uri.module && proxy->user_data) { + PinosModuleInfo *info = proxy->user_data; + cb (context, SPA_RESULT_OK, info, user_data); + info->change_mask = 0; + } + cb (context, SPA_RESULT_ENUM_END, NULL, user_data); } void @@ -433,7 +666,7 @@ pinos_context_list_client_info (PinosContext *context, PinosClientInfoCallback cb, void *user_data) { - cb (context, SPA_RESULT_OK, NULL, user_data); + do_list (context, context->uri.client, (ListFunc) cb, user_data); } void @@ -442,7 +675,17 @@ pinos_context_get_client_info_by_id (PinosContext *context, PinosClientInfoCallback cb, void *user_data) { - cb (context, SPA_RESULT_OK, NULL, user_data); + PinosProxy *proxy; + + proxy = pinos_map_lookup (&context->objects, id); + if (proxy == NULL) { + cb (context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data); + } else if (proxy->type == context->uri.client && proxy->user_data) { + PinosClientInfo *info = proxy->user_data; + cb (context, SPA_RESULT_OK, info, user_data); + info->change_mask = 0; + } + cb (context, SPA_RESULT_ENUM_END, NULL, user_data); } void @@ -450,7 +693,7 @@ pinos_context_list_node_info (PinosContext *context, PinosNodeInfoCallback cb, void *user_data) { - cb (context, SPA_RESULT_OK, NULL, user_data); + do_list (context, context->uri.node, (ListFunc) cb, user_data); } void @@ -459,7 +702,17 @@ pinos_context_get_node_info_by_id (PinosContext *context, PinosNodeInfoCallback cb, void *user_data) { - cb (context, SPA_RESULT_OK, NULL, user_data); + PinosProxy *proxy; + + proxy = pinos_map_lookup (&context->objects, id); + if (proxy == NULL) { + cb (context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data); + } else if (proxy->type == context->uri.node && proxy->user_data) { + PinosNodeInfo *info = proxy->user_data; + cb (context, SPA_RESULT_OK, info, user_data); + info->change_mask = 0; + } + cb (context, SPA_RESULT_ENUM_END, NULL, user_data); } void @@ -467,7 +720,7 @@ pinos_context_list_link_info (PinosContext *context, PinosLinkInfoCallback cb, void *user_data) { - cb (context, SPA_RESULT_OK, NULL, user_data); + do_list (context, context->uri.link, (ListFunc) cb, user_data); } void @@ -476,5 +729,15 @@ pinos_context_get_link_info_by_id (PinosContext *context, PinosLinkInfoCallback cb, void *user_data) { - cb (context, SPA_RESULT_OK, NULL, user_data); + PinosProxy *proxy; + + proxy = pinos_map_lookup (&context->objects, id); + if (proxy == NULL) { + cb (context, SPA_RESULT_INVALID_OBJECT_ID, NULL, user_data); + } else if (proxy->type == context->uri.link && proxy->user_data) { + PinosLinkInfo *info = proxy->user_data; + cb (context, SPA_RESULT_OK, info, user_data); + info->change_mask = 0; + } + cb (context, SPA_RESULT_ENUM_END, NULL, user_data); } diff --git a/pinos/client/context.h b/pinos/client/context.h index cc461ec5d..da4077114 100644 --- a/pinos/client/context.h +++ b/pinos/client/context.h @@ -28,10 +28,9 @@ typedef struct _PinosContext PinosContext; #include #include -#include #include -#include #include +#include /** * PinosContextState: @@ -60,6 +59,8 @@ struct _PinosContext { char *name; PinosProperties *properties; + PinosURI uri; + PinosLoop *loop; PinosProxy *core_proxy; diff --git a/pinos/client/introspect.c b/pinos/client/introspect.c index 4eb5143f8..81727650f 100644 --- a/pinos/client/introspect.c +++ b/pinos/client/introspect.c @@ -103,3 +103,177 @@ pinos_link_state_as_string (PinosLinkState state) } return "invalid-state"; } + +static void +pinos_spa_dict_destroy (SpaDict *dict) +{ + SpaDictItem *item; + + spa_dict_for_each (item, dict) { + free ((void *)item->key); + free ((void *)item->value); + } + free (dict->items); + free (dict); +} + +static SpaDict * +pinos_spa_dict_copy (SpaDict *dict) +{ + SpaDict *copy; + unsigned int i; + + if (dict == NULL) + return NULL; + + copy = calloc (1, sizeof (SpaDict)); + copy->items = calloc (dict->n_items, sizeof (SpaDictItem)); + copy->n_items = dict->n_items; + + for (i = 0; i < dict->n_items; i++) { + copy->items[i].key = strdup (dict->items[i].key); + copy->items[i].value = strdup (dict->items[i].value); + } + return copy; +} + +PinosNodeInfo * +pinos_node_info_update (PinosNodeInfo *info, + const PinosNodeInfo *update) +{ + uint64_t change_mask; + + if (update == NULL) + return info; + + if (info == NULL) { + info = calloc (1, sizeof (PinosNodeInfo)); + change_mask = ~0; + } else { + change_mask = info->change_mask | update->change_mask; + } + info->id = update->id; + info->change_mask = change_mask; + + if (update->change_mask & (1 << 0)) { + if (info->name) + free ((void*)info->name); + info->name = update->name ? strdup (update->name) : NULL; + } + if (update->change_mask & (1 << 1)) { + info->state = update->state; + } + if (update->change_mask & (1 << 2)) { + if (info->props) + pinos_spa_dict_destroy (info->props); + info->props = pinos_spa_dict_copy (update->props); + } + return info; +} + +void +pinos_node_info_free (PinosNodeInfo *info) +{ + if (info == NULL) + return; + if (info->name) + free ((void*)info->name); + if (info->props) + pinos_spa_dict_destroy (info->props); + free (info); +} + +PinosModuleInfo * +pinos_module_info_update (PinosModuleInfo *info, + const PinosModuleInfo *update) +{ + uint64_t change_mask; + + if (update == NULL) + return info; + + if (info == NULL) { + info = calloc (1, sizeof (PinosModuleInfo)); + change_mask = ~0; + } else { + change_mask = info->change_mask | update->change_mask; + } + info->id = update->id; + info->change_mask = change_mask; + + if (update->change_mask & (1 << 0)) { + if (info->name) + free ((void*)info->name); + info->name = update->name ? strdup (update->name) : NULL; + } + if (update->change_mask & (1 << 1)) { + if (info->filename) + free ((void*)info->filename); + info->filename = update->filename ? strdup (update->filename) : NULL; + } + if (update->change_mask & (1 << 2)) { + if (info->args) + free ((void*)info->args); + info->args = update->args ? strdup (update->args) : NULL; + } + if (update->change_mask & (1 << 3)) { + if (info->props) + pinos_spa_dict_destroy (info->props); + info->props = pinos_spa_dict_copy (update->props); + } + return info; +} + +void +pinos_module_info_free (PinosModuleInfo *info) +{ + if (info == NULL) + return; + + if (info->name) + free ((void*)info->name); + if (info->filename) + free ((void*)info->filename); + if (info->args) + free ((void*)info->args); + if (info->props) + pinos_spa_dict_destroy (info->props); + free (info); +} + + +PinosClientInfo * +pinos_client_info_update (PinosClientInfo *info, + const PinosClientInfo *update) +{ + uint64_t change_mask; + + if (update == NULL) + return info; + + if (info == NULL) { + info = calloc (1, sizeof (PinosClientInfo)); + change_mask = ~0; + } else { + change_mask = info->change_mask | update->change_mask; + } + info->id = update->id; + info->change_mask = change_mask; + + if (update->change_mask & (1 << 0)) { + if (info->props) + pinos_spa_dict_destroy (info->props); + info->props = pinos_spa_dict_copy (update->props); + } + return info; +} + +void +pinos_client_info_free (PinosClientInfo *info) +{ + if (info == NULL) + return; + if (info->props) + pinos_spa_dict_destroy (info->props); + free (info); +} diff --git a/pinos/client/introspect.h b/pinos/client/introspect.h index a810171be..fe714159a 100644 --- a/pinos/client/introspect.h +++ b/pinos/client/introspect.h @@ -26,6 +26,19 @@ extern "C" { #endif +typedef enum _PinosNodeState PinosNodeState; +typedef enum _PinosDirection PinosDirection; +typedef enum _PinosLinkState PinosLinkState; + +typedef struct _PinosCoreInfo PinosCoreInfo; +typedef struct _PinosModuleInfo PinosModuleInfo; +typedef struct _PinosClientInfo PinosClientInfo; +typedef struct _PinosNodeInfo PinosNodeInfo; +typedef struct _PinosLinkInfo PinosLinkInfo; + +#include +#include + /** * PinosNodeState: * @PINOS_NODE_STATE_ERROR: the node is in error @@ -40,14 +53,14 @@ extern "C" { * * The different node states */ -typedef enum { +enum _PinosNodeState { PINOS_NODE_STATE_ERROR = -1, PINOS_NODE_STATE_CREATING = 0, PINOS_NODE_STATE_SUSPENDED = 1, PINOS_NODE_STATE_INITIALIZING = 2, PINOS_NODE_STATE_IDLE = 3, PINOS_NODE_STATE_RUNNING = 4, -} PinosNodeState; +}; const char * pinos_node_state_as_string (PinosNodeState state); @@ -59,11 +72,11 @@ const char * pinos_node_state_as_string (PinosNodeState state); * * The direction of a port */ -typedef enum { +enum _PinosDirection { PINOS_DIRECTION_INVALID = SPA_DIRECTION_INVALID, PINOS_DIRECTION_INPUT = SPA_DIRECTION_INPUT, PINOS_DIRECTION_OUTPUT = SPA_DIRECTION_OUTPUT -} PinosDirection; +}; const char * pinos_direction_as_string (PinosDirection direction); @@ -79,7 +92,7 @@ const char * pinos_direction_as_string (PinosDirection direction); * * The different link states */ -typedef enum { +enum _PinosLinkState { PINOS_LINK_STATE_ERROR = -2, PINOS_LINK_STATE_UNLINKED = -1, PINOS_LINK_STATE_INIT = 0, @@ -87,28 +100,25 @@ typedef enum { PINOS_LINK_STATE_ALLOCATING = 2, PINOS_LINK_STATE_PAUSED = 3, PINOS_LINK_STATE_RUNNING = 4, -} PinosLinkState; +}; const char * pinos_link_state_as_string (PinosLinkState state); -#include -#include - /** - * PinosDaemonInfo: - * @id: generic id of the daemon + * PinosCoreInfo: + * @id: generic id of the core * @change_mask: bitfield of changed fields since last call - * @user_name: name of the user that started the daemon - * @host_name: name of the machine the daemon is running on - * @version: version of the daemon - * @name: name of the daemon + * @user_name: name of the user that started the core + * @host_name: name of the machine the core is running on + * @version: version of the core + * @name: name of the core * @cookie: a random cookie for identifying this instance of Pinos - * @properties: extra properties + * @props: extra properties * - * The daemon information. Extra information can be added in later + * The core information. Extra information can be added in later * versions. */ -typedef struct { +struct _PinosCoreInfo { uint32_t id; uint64_t change_mask; const char *user_name; @@ -116,41 +126,93 @@ typedef struct { const char *version; const char *name; uint32_t cookie; - PinosProperties *properties; -} PinosDaemonInfo; + SpaDict *props; +}; + +PinosCoreInfo * pinos_core_info_update (PinosCoreInfo *info, + const PinosCoreInfo *update); +void pinos_core_info_free (PinosCoreInfo *info); + +/** + * PinosCoreInfoCallback: + * @c: a #PinosContext + * @info: a #PinosCoreInfo + * @user_data: user data + * + * Callback with information about the Pinos core in @info. + */ +typedef void (*PinosCoreInfoCallback) (PinosContext *c, + SpaResult res, + const PinosCoreInfo *info, + void *user_data); + +void pinos_context_get_core_info (PinosContext *context, + PinosCoreInfoCallback cb, + void *user_data); + +/** + * PinosModuleInfo: + * @id: generic id of the module + * @change_mask: bitfield of changed fields since last call + * @props: extra properties + * + * The module information. Extra information can be added in later + * versions. + */ +struct _PinosModuleInfo { + uint32_t id; + uint64_t change_mask; + const char *name; + const char *filename; + const char *args; + SpaDict *props; +}; + +PinosModuleInfo * pinos_module_info_update (PinosModuleInfo *info, + const PinosModuleInfo *update); +void pinos_module_info_free (PinosModuleInfo *info); /** - * PinosDaemonInfoCallback: + * PinosModuleInfoCallback: * @c: a #PinosContext - * @info: a #PinosDaemonInfo + * @info: a #PinosModuleInfo * @user_data: user data * - * Callback with information about the Pinos daemon in @info. + * Callback with information about the Pinos module in @info. */ -typedef void (*PinosDaemonInfoCallback) (PinosContext *c, - SpaResult res, - const PinosDaemonInfo *info, +typedef void (*PinosModuleInfoCallback) (PinosContext *c, + SpaResult res, + const PinosModuleInfo *info, void *user_data); -void pinos_context_get_daemon_info (PinosContext *context, - PinosDaemonInfoCallback cb, - void *user_data); +void pinos_context_list_module_info (PinosContext *context, + PinosModuleInfoCallback cb, + void *user_data); +void pinos_context_get_module_info_by_id (PinosContext *context, + uint32_t id, + PinosModuleInfoCallback cb, + void *user_data); /** * PinosClientInfo: * @id: generic id of the client * @change_mask: bitfield of changed fields since last call - * @properties: extra properties + * @props: extra properties * * The client information. Extra information can be added in later * versions. */ -typedef struct { +struct _PinosClientInfo { uint32_t id; uint64_t change_mask; - PinosProperties *properties; -} PinosClientInfo; + SpaDict *props; +}; + +PinosClientInfo * pinos_client_info_update (PinosClientInfo *info, + const PinosClientInfo *update); +void pinos_client_info_free (PinosClientInfo *info); + /** * PinosClientInfoCallback: @@ -178,19 +240,23 @@ void pinos_context_get_client_info_by_id (PinosContext *co * @id: generic id of the node * @change_mask: bitfield of changed fields since last call * @name: name the node, suitable for display - * @properties: the properties of the node + * @props: the properties of the node * @state: the current state of the node * * The node information. Extra information can be added in later * versions. */ -typedef struct { +struct _PinosNodeInfo { uint32_t id; uint64_t change_mask; const char *name; - PinosProperties *properties; PinosNodeState state; -} PinosNodeInfo; + SpaDict *props; +}; + +PinosNodeInfo * pinos_node_info_update (PinosNodeInfo *info, + const PinosNodeInfo *update); +void pinos_node_info_free (PinosNodeInfo *info); /** * PinosNodeInfoCallback: @@ -226,14 +292,14 @@ void pinos_context_get_node_info_by_id (PinosContext *cont * The link information. Extra information can be added in later * versions. */ -typedef struct { +struct _PinosLinkInfo { uint32_t id; uint64_t change_mask; uint32_t output_node_id; uint32_t output_port_id; uint32_t input_node_id; uint32_t input_port_id; -} PinosLinkInfo; +}; /** diff --git a/pinos/client/meson.build b/pinos/client/meson.build index f6333f762..eba876bc1 100644 --- a/pinos/client/meson.build +++ b/pinos/client/meson.build @@ -14,6 +14,7 @@ pinos_headers = [ 'subscribe.h', 'thread-mainloop.h', 'transport.h', + 'uri.h', 'utils.h', ] @@ -33,6 +34,7 @@ pinos_sources = [ 'rtkit.c', 'thread-mainloop.c', 'transport.c', + 'uri.c', 'utils.c', ] diff --git a/pinos/client/properties.c b/pinos/client/properties.c index 09e3aa759..26326fb60 100644 --- a/pinos/client/properties.c +++ b/pinos/client/properties.c @@ -21,37 +21,40 @@ #include "pinos/client/properties.h" typedef struct { - char *key; - char *value; -} PropItem; + PinosProperties this; -struct _PinosProperties { PinosArray items; -}; +} PinosPropertiesImpl; static void -add_func (PinosProperties *props, char *key, char *value) +add_func (PinosProperties *this, char *key, char *value) { - PropItem *item; - item = pinos_array_add (&props->items, sizeof (PropItem)); + SpaDictItem *item; + PinosPropertiesImpl *impl = SPA_CONTAINER_OF (this, PinosPropertiesImpl, this); + + item = pinos_array_add (&impl->items, sizeof (SpaDictItem)); item->key = key; item->value = value; + + this->dict.items = impl->items.data; + this->dict.n_items = pinos_array_get_len (&impl->items, SpaDictItem); } static void -clear_item (PropItem *item) +clear_item (SpaDictItem *item) { - free (item->key); - free (item->value); + free ((char*)item->key); + free ((char*)item->value); } static int -find_index (PinosProperties *props, const char *key) +find_index (PinosProperties *this, const char *key) { - int i, len = pinos_array_get_len (&props->items, PropItem); + PinosPropertiesImpl *impl = SPA_CONTAINER_OF (this, PinosPropertiesImpl, this); + int i, len = pinos_array_get_len (&impl->items, SpaDictItem); for (i = 0; i < len; i++) { - PropItem *item = pinos_array_get_unchecked (&props->items, i, PropItem); + SpaDictItem *item = pinos_array_get_unchecked (&impl->items, i, SpaDictItem); if (strcmp (item->key, key) == 0) return i; } @@ -70,22 +73,22 @@ find_index (PinosProperties *props, const char *key) PinosProperties * pinos_properties_new (const char *key, ...) { - PinosProperties *props; + PinosPropertiesImpl *impl; va_list varargs; const char *value; - props = calloc (1, sizeof (PinosProperties)); - pinos_array_init (&props->items); + impl = calloc (1, sizeof (PinosPropertiesImpl)); + pinos_array_init (&impl->items); va_start (varargs, key); while (key != NULL) { value = va_arg (varargs, char *); - add_func (props, strdup (key), strdup (value)); + add_func (&impl->this, strdup (key), strdup (value)); key = va_arg (varargs, char *); } va_end (varargs); - return props; + return &impl->this; } /** @@ -99,11 +102,12 @@ pinos_properties_new (const char *key, ...) PinosProperties * pinos_properties_copy (PinosProperties *properties) { + PinosPropertiesImpl *impl = SPA_CONTAINER_OF (properties, PinosPropertiesImpl, this); PinosProperties *copy; - PropItem *item; + SpaDictItem *item; copy = pinos_properties_new (NULL, NULL); - pinos_array_for_each (item, &properties->items) + pinos_array_for_each (item, &impl->items) add_func (copy, strdup (item->key), strdup (item->value)); return copy; @@ -145,13 +149,14 @@ pinos_properties_merge (PinosProperties *oldprops, void pinos_properties_free (PinosProperties *properties) { - PropItem *item; + PinosPropertiesImpl *impl = SPA_CONTAINER_OF (properties, PinosPropertiesImpl, this); + SpaDictItem *item; - pinos_array_for_each (item, &properties->items) + pinos_array_for_each (item, &impl->items) clear_item (item); - pinos_array_clear (&properties->items); - free (properties); + pinos_array_clear (&impl->items); + free (impl); } static void @@ -159,21 +164,22 @@ do_replace (PinosProperties *properties, char *key, char *value) { + PinosPropertiesImpl *impl = SPA_CONTAINER_OF (properties, PinosPropertiesImpl, this); int index = find_index (properties, key); if (index == -1) { add_func (properties, key, value); } else { - PropItem *item = pinos_array_get_unchecked (&properties->items, index, PropItem); + SpaDictItem *item = pinos_array_get_unchecked (&impl->items, index, SpaDictItem); clear_item (item); if (value == NULL) { - PropItem *other = pinos_array_get_unchecked (&properties->items, - pinos_array_get_len (&properties->items, PropItem) - 1, - PropItem); + SpaDictItem *other = pinos_array_get_unchecked (&impl->items, + pinos_array_get_len (&impl->items, SpaDictItem) - 1, + SpaDictItem); item->key = other->key; item->value = other->value; - properties->items.size -= sizeof (PropItem); + impl->items.size -= sizeof (SpaDictItem); } else { item->key = key; item->value = value; @@ -238,12 +244,13 @@ const char * pinos_properties_get (PinosProperties *properties, const char *key) { + PinosPropertiesImpl *impl = SPA_CONTAINER_OF (properties, PinosPropertiesImpl, this); int index = find_index (properties, key); if (index == -1) return NULL; - return pinos_array_get_unchecked (&properties->items, index, PropItem)->value; + return pinos_array_get_unchecked (&impl->items, index, SpaDictItem)->value; } /** @@ -264,6 +271,7 @@ const char * pinos_properties_iterate (PinosProperties *properties, void **state) { + PinosPropertiesImpl *impl = SPA_CONTAINER_OF (properties, PinosPropertiesImpl, this); unsigned int index; if (*state == NULL) @@ -271,10 +279,10 @@ pinos_properties_iterate (PinosProperties *properties, else index = SPA_PTR_TO_INT (*state); - if (!pinos_array_check_index (&properties->items, index, PropItem)) + if (!pinos_array_check_index (&impl->items, index, SpaDictItem)) return NULL; *state = SPA_INT_TO_PTR (index + 1); - return pinos_array_get_unchecked (&properties->items, index, PropItem)->key; + return pinos_array_get_unchecked (&impl->items, index, SpaDictItem)->key; } diff --git a/pinos/client/properties.h b/pinos/client/properties.h index 0f4ed4853..e0bffd18f 100644 --- a/pinos/client/properties.h +++ b/pinos/client/properties.h @@ -26,6 +26,10 @@ extern "C" { typedef struct _PinosProperties PinosProperties; +struct _PinosProperties { + SpaDict dict; +}; + PinosProperties * pinos_properties_new (const char *key, ...); PinosProperties * pinos_properties_copy (PinosProperties *properties); PinosProperties * pinos_properties_merge (PinosProperties *oldprops, diff --git a/pinos/client/proxy.c b/pinos/client/proxy.c index 076e6836b..1311d7a30 100644 --- a/pinos/client/proxy.c +++ b/pinos/client/proxy.c @@ -63,12 +63,12 @@ pinos_proxy_destroy (PinosProxy *proxy) SpaResult pinos_proxy_send_message (PinosProxy *proxy, - PinosMessageType type, + uint32_t opcode, void *message, bool flush) { if (proxy->send_func) - return proxy->send_func (proxy, proxy->id, type, message, flush, proxy->send_data); + return proxy->send_func (proxy, proxy->id, opcode, message, flush, proxy->send_data); pinos_log_error ("proxy %p: send func not implemented", proxy); diff --git a/pinos/client/proxy.h b/pinos/client/proxy.h index 154baf529..9a4ace750 100644 --- a/pinos/client/proxy.h +++ b/pinos/client/proxy.h @@ -24,21 +24,20 @@ extern "C" { #endif -#include - typedef struct _PinosProxy PinosProxy; typedef SpaResult (*PinosSendFunc) (void *object, uint32_t id, - PinosMessageType type, + uint32_t opcode, void *message, bool flush, void *data); typedef SpaResult (*PinosDispatchFunc) (void *object, - PinosMessageType type, + uint32_t opcode, void *message, void *data); +#include #include struct _PinosProxy { @@ -53,6 +52,8 @@ struct _PinosProxy { PinosDispatchFunc dispatch_func; void *dispatch_data; + void *user_data; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosProxy *proxy)); }; @@ -63,7 +64,7 @@ PinosProxy * pinos_proxy_new (PinosContext *contex void pinos_proxy_destroy (PinosProxy *proxy); SpaResult pinos_proxy_send_message (PinosProxy *proxy, - PinosMessageType type, + uint32_t opcode, void *message, bool flush); diff --git a/pinos/client/stream.c b/pinos/client/stream.c index f413394ac..660914a7b 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -610,13 +610,18 @@ stream_dispatch_func (void *object, case PINOS_MESSAGE_GET_REGISTRY: case PINOS_MESSAGE_BIND: case PINOS_MESSAGE_DESTROY: - case PINOS_MESSAGE_DESTROY_DONE: + case PINOS_MESSAGE_REMOVE_ID: case PINOS_MESSAGE_CREATE_NODE: case PINOS_MESSAGE_CREATE_CLIENT_NODE: case PINOS_MESSAGE_NODE_UPDATE: case PINOS_MESSAGE_PORT_UPDATE: case PINOS_MESSAGE_PORT_STATUS_CHANGE: case PINOS_MESSAGE_NODE_STATE_CHANGE: + case PINOS_MESSAGE_CORE_INFO: + case PINOS_MESSAGE_MODULE_INFO: + case PINOS_MESSAGE_NODE_INFO: + case PINOS_MESSAGE_CLIENT_INFO: + case PINOS_MESSAGE_LINK_INFO: pinos_log_warn ("got unexpected message %d", type); break; diff --git a/pinos/client/subscribe.h b/pinos/client/subscribe.h index e8e14bec3..490fbe11b 100644 --- a/pinos/client/subscribe.h +++ b/pinos/client/subscribe.h @@ -26,21 +26,21 @@ extern "C" { #endif -typedef enum { - PINOS_SUBSCRIPTION_STATE_UNCONNECTED = 0, - PINOS_SUBSCRIPTION_STATE_CONNECTING = 1, - PINOS_SUBSCRIPTION_STATE_READY = 2, - PINOS_SUBSCRIPTION_STATE_ERROR = 3, -} PinosSubscriptionState; +#define PINOS_CORE_URI "http://pinos.org/ns/core" +#define PINOS_CORE_PREFIX PINOS_CORE_URI "#" +#define PINOS_CORE_REGISTRY PINOS_CORE_PREFIX "Registry" -typedef enum { - PINOS_SUBSCRIPTION_FLAG_DAEMON = (1 << 0), - PINOS_SUBSCRIPTION_FLAG_CLIENT = (1 << 1), - PINOS_SUBSCRIPTION_FLAG_NODE = (1 << 2), - PINOS_SUBSCRIPTION_FLAG_LINK = (1 << 3) -} PinosSubscriptionFlags; +#define PINOS_NODE_URI "http://pinos.org/ns/node" +#define PINOS_NODE_PREFIX PINOS_NODE_URI "#" -#define PINOS_SUBSCRIPTION_FLAGS_ALL 0x0f +#define PINOS_CLIENT_URI "http://pinos.org/ns/client" +#define PINOS_CLIENT_PREFIX PINOS_CLIENT_URI "#" + +#define PINOS_LINK_URI "http://pinos.org/ns/link" +#define PINOS_LINK_PREFIX PINOS_LINK_URI "#" + +#define PINOS_MODULE_URI "http://pinos.org/ns/module" +#define PINOS_MODULE_PREFIX PINOS_MODULE_URI "#" typedef enum { PINOS_SUBSCRIPTION_EVENT_NEW = 0, @@ -49,13 +49,12 @@ typedef enum { } PinosSubscriptionEvent; typedef void (*PinosSubscriptionFunc) (PinosContext *context, - PinosSubscriptionFlags flags, PinosSubscriptionEvent event, + uint32_t type, uint32_t id, void *data); void pinos_context_subscribe (PinosContext *context, - PinosSubscriptionFlags mask, PinosSubscriptionFunc func, void *data); diff --git a/pinos/server/uri.c b/pinos/client/uri.c similarity index 98% rename from pinos/server/uri.c rename to pinos/client/uri.c index 57f5b7776..bfb177704 100644 --- a/pinos/server/uri.c +++ b/pinos/client/uri.c @@ -20,8 +20,9 @@ #include #include "pinos/client/pinos.h" +#include "pinos/client/uri.h" + #include "pinos/server/core.h" -#include "pinos/server/uri.h" #include "pinos/server/node.h" #include "pinos/server/node-factory.h" #include "pinos/server/client.h" @@ -47,5 +48,4 @@ pinos_uri_init (PinosURI *uri) uri->spa_node = spa_id_map_get_id (uri->map, SPA_NODE_URI); uri->spa_clock = spa_id_map_get_id (uri->map, SPA_CLOCK_URI); uri->spa_monitor = spa_id_map_get_id (uri->map, SPA_MONITOR_URI); - } diff --git a/pinos/server/uri.h b/pinos/client/uri.h similarity index 100% rename from pinos/server/uri.h rename to pinos/client/uri.h diff --git a/pinos/daemon/pinos.conf.in b/pinos/daemon/pinos.conf.in index f29bd35b4..dffbbbf9c 100644 --- a/pinos/daemon/pinos.conf.in +++ b/pinos/daemon/pinos.conf.in @@ -1,5 +1,5 @@ #load-module libpinos-module-protocol-dbus load-module libpinos-module-protocol-native load-module libpinos-module-suspend-on-idle -load-module libpinos-module-spa +load-module libpinos-module-spa --pattern snow load-module libpinos-module-autolink diff --git a/pinos/gst/gstpinosdeviceprovider.c b/pinos/gst/gstpinosdeviceprovider.c index e425f6ac0..e421f4713 100644 --- a/pinos/gst/gstpinosdeviceprovider.c +++ b/pinos/gst/gstpinosdeviceprovider.c @@ -190,8 +190,8 @@ new_node (const PinosNodeInfo *info) { GstCaps *caps; GstStructure *props; - gpointer state = NULL; const gchar *klass; + SpaDictItem *item; /* FIXME, iterate ports */ #if 0 @@ -202,18 +202,10 @@ new_node (const PinosNodeInfo *info) caps = gst_caps_new_any(); props = gst_structure_new_empty ("pinos-proplist"); + spa_dict_for_each (item, info->props) + gst_structure_set (props, item->key, G_TYPE_STRING, item->value, NULL); - while (TRUE) { - const char *key, *val; - - if (!(key = pinos_properties_iterate (info->properties, &state))) - break; - - val = pinos_properties_get (info->properties, key); - gst_structure_set (props, key, G_TYPE_STRING, val, NULL); - } - - klass = pinos_properties_get (info->properties, "gstreamer.device.class"); + klass = spa_dict_lookup (info->props, "gstreamer.device.class"); if (klass == NULL) klass = "unknown/unknown"; @@ -263,8 +255,8 @@ find_device (GstDeviceProvider *provider, uint32_t id) static void context_subscribe_cb (PinosContext *context, - PinosSubscriptionFlags flags, - PinosSubscriptionEvent type, + PinosSubscriptionEvent event, + uint32_t type, uint32_t id, void *user_data) { @@ -272,19 +264,19 @@ context_subscribe_cb (PinosContext *context, GstDeviceProvider *provider = user_data; GstPinosDevice *dev; - if (flags != PINOS_SUBSCRIPTION_FLAG_NODE) + if (type != context->uri.node) return; dev = find_device (provider, id); - if (type == PINOS_SUBSCRIPTION_EVENT_NEW) { - if (flags == PINOS_SUBSCRIPTION_FLAG_NODE && dev == NULL) + if (event == PINOS_SUBSCRIPTION_EVENT_NEW) { + if (dev == NULL) pinos_context_get_node_info_by_id (context, id, get_node_info_cb, self); - } else if (type == PINOS_SUBSCRIPTION_EVENT_REMOVE) { - if (flags == PINOS_SUBSCRIPTION_FLAG_NODE && dev != NULL) { + } else if (event == PINOS_SUBSCRIPTION_EVENT_REMOVE) { + if (dev != NULL) { gst_device_provider_device_remove (GST_DEVICE_PROVIDER (self), GST_DEVICE (dev)); } @@ -313,15 +305,15 @@ list_node_info_cb (PinosContext *c, } static void -get_daemon_info_cb (PinosContext *c, - SpaResult res, - const PinosDaemonInfo *info, - void *user_data) +get_core_info_cb (PinosContext *c, + SpaResult res, + const PinosCoreInfo *info, + void *user_data) { GstDeviceProvider *provider = user_data; const gchar *value; - value = pinos_properties_get (info->properties, "gstreamer.deviceproviders"); + value = spa_dict_lookup (info->props, "gstreamer.deviceproviders"); if (value) { gchar **providers = g_strsplit (value, ",", -1); gint i; @@ -371,9 +363,9 @@ gst_pinos_device_provider_probe (GstDeviceProvider * provider) } GST_DEBUG_OBJECT (self, "connected"); - pinos_context_get_daemon_info (c, - get_daemon_info_cb, - self); + pinos_context_get_core_info (c, + get_core_info_cb, + self); data.end = FALSE; @@ -453,7 +445,6 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider) pinos_signal_add (&self->context->state_changed, &self->ctx_state_changed, on_context_state_changed); pinos_context_subscribe (self->context, - PINOS_SUBSCRIPTION_FLAGS_ALL, context_subscribe_cb, self); @@ -475,9 +466,9 @@ gst_pinos_device_provider_start (GstDeviceProvider * provider) pinos_thread_main_loop_wait (self->main_loop); } GST_DEBUG_OBJECT (self, "connected"); - pinos_context_get_daemon_info (self->context, - get_daemon_info_cb, - self); + pinos_context_get_core_info (self->context, + get_core_info_cb, + self); pinos_thread_main_loop_unlock (self->main_loop); return TRUE; diff --git a/pinos/modules/module-autolink.c b/pinos/modules/module-autolink.c index f29960b01..252469a79 100644 --- a/pinos/modules/module-autolink.c +++ b/pinos/modules/module-autolink.c @@ -29,14 +29,12 @@ typedef struct { PinosCore *core; PinosProperties *properties; - PinosGlobal *global; PinosListener global_added; PinosListener global_removed; PinosListener port_added; PinosListener port_removed; PinosListener port_unlinked; - PinosListener node_state_changed; PinosListener link_state_changed; } ModuleImpl; @@ -184,22 +182,6 @@ on_node_created (PinosNode *node, on_port_added (&impl->port_added, node, port); } -static void -on_node_state_changed (PinosListener *listener, - PinosNode *node, - PinosNodeState old, - PinosNodeState state) -{ - ModuleImpl *impl = SPA_CONTAINER_OF (listener, ModuleImpl, node_state_changed); - - pinos_log_debug ("module %p: node %p state change %s -> %s", impl, node, - pinos_node_state_as_string (old), - pinos_node_state_as_string (state)); - - if (old == PINOS_NODE_STATE_CREATING && state == PINOS_NODE_STATE_SUSPENDED) - on_node_created (node, impl); -} - static void on_node_added (ModuleImpl *impl, PinosNode *node) { @@ -264,15 +246,11 @@ module_new (PinosCore *core, pinos_signal_add (&core->global_added, &impl->global_added, on_global_added); pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed); - pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed); pinos_signal_add (&core->port_added, &impl->port_added, on_port_added); pinos_signal_add (&core->port_removed, &impl->port_removed, on_port_removed); pinos_signal_add (&core->port_unlinked, &impl->port_unlinked, on_link_port_unlinked); pinos_signal_add (&core->link_state_changed, &impl->link_state_changed, on_link_state_changed); - impl->global = pinos_core_add_global (core, - core->uri.module, - impl); return impl; } @@ -286,7 +264,6 @@ module_destroy (ModuleImpl *impl) pinos_signal_remove (&impl->global_added); pinos_signal_remove (&impl->global_removed); - pinos_signal_remove (&impl->node_state_changed); pinos_signal_remove (&impl->port_added); pinos_signal_remove (&impl->port_removed); pinos_signal_remove (&impl->port_unlinked); diff --git a/pinos/modules/module-protocol-dbus.c b/pinos/modules/module-protocol-dbus.c index 2868f466a..a07bb5dc0 100644 --- a/pinos/modules/module-protocol-dbus.c +++ b/pinos/modules/module-protocol-dbus.c @@ -53,7 +53,6 @@ typedef struct { PinosCore *core; SpaList link; - PinosGlobal *global; PinosProperties *properties; @@ -164,6 +163,7 @@ find_object (PinosProtocolDBus *impl, return NULL; } +#if 0 struct _PinosProperties { GHashTable *hashtable; }; @@ -173,13 +173,14 @@ add_to_variant (const gchar *key, const gchar *value, GVariantBuilder *b) { g_variant_builder_add (b, "{sv}", key, g_variant_new_string (value)); } +#endif static void pinos_properties_init_builder (PinosProperties *properties, GVariantBuilder *builder) { g_variant_builder_init (builder, G_VARIANT_TYPE ("a{sv}")); - g_hash_table_foreach (properties->hashtable, (GHFunc) add_to_variant, builder); +// g_hash_table_foreach (properties->hashtable, (GHFunc) add_to_variant, builder); } static GVariant * @@ -201,10 +202,10 @@ pinos_properties_from_variant (GVariant *variant) props = pinos_properties_new (NULL, NULL); g_variant_iter_init (&iter, variant); - while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) - g_hash_table_replace (props->hashtable, - g_strdup (key), - g_variant_dup_string (value, NULL)); +// while (g_variant_iter_loop (&iter, "{sv}", &key, &value)) + //g_hash_table_replace (props->hashtable, + // g_strdup (key), + // g_variant_dup_string (value, NULL)); return props; } @@ -684,9 +685,6 @@ pinos_protocol_dbus_new (PinosCore *core, impl->server_manager = g_dbus_object_manager_server_new (PINOS_DBUS_OBJECT_PREFIX); - impl->global = pinos_core_add_global (core, - core->uri.module, - impl); return impl; } diff --git a/pinos/modules/module-protocol-native.c b/pinos/modules/module-protocol-native.c index d595a3ba4..4577ef3bc 100644 --- a/pinos/modules/module-protocol-native.c +++ b/pinos/modules/module-protocol-native.c @@ -64,220 +64,33 @@ typedef struct { typedef struct { PinosCore *core; SpaList link; - PinosGlobal *global; PinosProperties *properties; SpaList socket_list; - SpaList client_list; - SpaList object_list; - - PinosListener global_added; - PinosListener global_removed; - PinosListener node_state_changed; } PinosProtocolNative; typedef struct { PinosProtocolNative *impl; SpaList link; - PinosGlobal *global; - PinosDestroy destroy; -} PinosProtocolNativeObject; - -typedef struct { - PinosProtocolNativeObject parent; - SpaList link; -} PinosProtocolNativeServer; - -typedef struct { - PinosProtocolNativeObject parent; - SpaList link; - int fd; - struct ucred ucred; - SpaSource *source; - PinosConnection *connection; - PinosResource *core_resource; + PinosClient *client; + int fd; + struct ucred ucred; + SpaSource *source; + PinosConnection *connection; } PinosProtocolNativeClient; -typedef struct { - PinosProtocolNativeObject parent; - PinosListener state_changed; -} PinosProtocolNativeNode; - -static void * -object_new (size_t size, - PinosProtocolNative *impl, - PinosGlobal *global, - PinosDestroy destroy) -{ - PinosProtocolNativeObject *this; - - this = calloc (1, size); - this->impl = impl; - this->global = global; - this->destroy = destroy; - - spa_list_insert (impl->object_list.prev, &this->link); - - return this; -} - -static void -sync_destroy (void *object, - void *data, - SpaResult res, - uint32_t id) -{ - PinosProtocolNativeObject *this = object; - - if (this->destroy) - this->destroy (this); - free (this); -} - -static void -object_destroy (PinosProtocolNativeObject *this) -{ - spa_list_remove (&this->link); - - pinos_main_loop_defer (this->impl->core->main_loop, - this, - SPA_RESULT_WAIT_SYNC, - sync_destroy, - this); -} - -static PinosProtocolNativeObject * -find_object (PinosProtocolNative *impl, - void *object) -{ - PinosProtocolNativeObject *obj; - spa_list_for_each (obj, &impl->object_list, link) { - if (obj->global->object == object) - return obj; - } - return NULL; -} - static void client_destroy (PinosProtocolNativeClient *this) { + pinos_client_destroy (this->client); spa_list_remove (&this->link); - if (this->source) - pinos_loop_destroy_source (this->parent.impl->core->main_loop->loop, - this->source); + pinos_loop_destroy_source (this->impl->core->main_loop->loop, + this->source); pinos_connection_destroy (this->connection); close (this->fd); -} - -static void -destroy_registry_resource (void *object) -{ - PinosResource *resource = object; - spa_list_remove (&resource->link); -} - -static SpaResult -registry_dispatch_func (void *object, - PinosMessageType type, - void *message, - void *data) -{ - switch (type) { - case PINOS_MESSAGE_BIND: - break; - default: - pinos_log_error ("unhandled message %d", type); - break; - } - return SPA_RESULT_OK; -} - -static SpaResult -core_dispatch_func (void *object, - PinosMessageType type, - void *message, - void *data) -{ - PinosProtocolNativeClient *client = data; - PinosProtocolNative *impl = client->parent.impl; - PinosClient *c = client->parent.global->object; - - switch (type) { - case PINOS_MESSAGE_GET_REGISTRY: - { - PinosMessageGetRegistry *m = message; - PinosGlobal *global; - PinosMessageNotifyDone nd; - PinosResource *registry_resource; - - registry_resource = pinos_resource_new (c, - SPA_ID_INVALID, - impl->core->uri.registry, - impl->core, - destroy_registry_resource); - - registry_resource->dispatch_func = registry_dispatch_func; - registry_resource->dispatch_data = client; - - spa_list_insert (impl->core->registry_resource_list.prev, ®istry_resource->link); - - spa_list_for_each (global, &impl->core->global_list, link) { - PinosMessageNotifyGlobal ng; - - ng.id = global->id; - ng.type = spa_id_map_get_uri (impl->core->uri.map, global->type); - pinos_resource_send_message (registry_resource, - PINOS_MESSAGE_NOTIFY_GLOBAL, - &ng, - false); - } - nd.seq = m->seq; - pinos_resource_send_message (client->core_resource, - PINOS_MESSAGE_NOTIFY_DONE, - &nd, - true); - break; - } - case PINOS_MESSAGE_CREATE_CLIENT_NODE: - { - PinosMessageCreateClientNode *m = message; - PinosClientNode *node; - SpaResult res; - int data_fd, i; - PinosMessageCreateClientNodeDone r; - PinosProperties *props; - - props = pinos_properties_new (NULL, NULL); - for (i = 0; i < m->props->n_items; i++) { - pinos_properties_set (props, m->props->items[i].key, - m->props->items[i].value); - } - - node = pinos_client_node_new (c, - m->new_id, - m->name, - props); - - if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0) { - pinos_log_error ("can't get data fd"); - break; - } - - r.seq = m->seq; - r.datafd = data_fd; - pinos_resource_send_message (node->resource, - PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE, - &r, - true); - break; - } - default: - pinos_log_error ("unhandled message %d", type); - break; - } - return SPA_RESULT_OK; + free (this); } static SpaResult @@ -290,7 +103,8 @@ client_send_func (void *object, { PinosProtocolNativeClient *client = data; - pinos_log_debug ("protocol-native %p: sending message %d to %u", client->parent.impl, type, id); + pinos_log_debug ("protocol-native %p: sending message %d to %u of client %p", + client->impl, type, id, client); pinos_connection_add_message (client->connection, id, @@ -313,14 +127,11 @@ connection_data (SpaSource *source, PinosMessageType type; uint32_t id; size_t size; - PinosClient *c = client->parent.global->object; + PinosClient *c = client->client; if (mask & (SPA_IO_ERR | SPA_IO_HUP)) { - pinos_log_debug ("protocol-native %p: got connection error", client->parent.impl); - pinos_loop_destroy_source (client->parent.impl->core->main_loop->loop, - client->source); - client->source = NULL; - pinos_client_destroy (client->parent.global->object); + pinos_log_debug ("protocol-native %p: got connection error", client->impl); + client_destroy (client); return; } @@ -328,16 +139,16 @@ connection_data (SpaSource *source, PinosResource *resource; void *message = alloca (size); - pinos_log_debug ("protocol-native %p: got message %d from %u", client->parent.impl, type, id); + 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->parent.impl); + pinos_log_error ("protocol-native %p: failed to parse message", client->impl); continue; } resource = pinos_map_lookup (&c->objects, id); if (resource == NULL) { - pinos_log_error ("protocol-native %p: unknown resource %u", client->parent.impl, id); + pinos_log_error ("protocol-native %p: unknown resource %u", client->impl, id); continue; } @@ -353,27 +164,14 @@ client_new (PinosProtocolNative *impl, int fd) { PinosProtocolNativeClient *this; - PinosClient *client; socklen_t len; - client = pinos_client_new (impl->core, NULL); - - if ((this = (PinosProtocolNativeClient *) find_object (impl, client)) == NULL) { - close (fd); - return NULL; + this = calloc (1, sizeof (PinosProtocolNativeClient)); + this->impl = impl; + len = sizeof (this->ucred); + if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &this->ucred, &len) < 0) { + pinos_log_error ("no peercred: %m"); } - client->send_func = client_send_func; - client->send_data = this; - - this->core_resource = pinos_resource_new (client, - 0, - impl->core->uri.core, - impl->core, - NULL); - - this->core_resource->dispatch_func = core_dispatch_func; - this->core_resource->dispatch_data = this; - this->fd = fd; this->source = pinos_loop_add_io (impl->core->main_loop->loop, this->fd, @@ -381,75 +179,23 @@ client_new (PinosProtocolNative *impl, false, connection_data, this); - - len = sizeof (this->ucred); - if (getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &this->ucred, &len) < 0) { - pinos_log_error ("no peercred: %m"); - } this->connection = pinos_connection_new (fd); spa_list_insert (impl->client_list.prev, &this->link); + this->client = pinos_client_new (impl->core, NULL); + this->client->send_func = client_send_func; + this->client->send_data = this; + + impl->core->global->bind (impl->core->global, + this->client, + 0, + 0); + return this; } -static void -on_global_added (PinosListener *listener, - PinosCore *core, - PinosGlobal *global) -{ - PinosProtocolNative *impl = SPA_CONTAINER_OF (listener, PinosProtocolNative, global_added); - PinosMessageNotifyGlobal ng; - PinosResource *registry; - - if (global->type == impl->core->uri.client) { - object_new (sizeof (PinosProtocolNativeClient), - impl, - global, - (PinosDestroy) client_destroy); - } else if (global->type == impl->core->uri.node) { - object_new (sizeof (PinosProtocolNativeNode), - impl, - global, - NULL); - } else if (global->type == impl->core->uri.link) { - } - - ng.id = global->id; - ng.type = spa_id_map_get_uri (impl->core->uri.map, global->type); - - spa_list_for_each (registry, &core->registry_resource_list, link) { - pinos_resource_send_message (registry, - PINOS_MESSAGE_NOTIFY_GLOBAL, - &ng, - true); - } -} - -static void -on_global_removed (PinosListener *listener, - PinosCore *core, - PinosGlobal *global) -{ - PinosProtocolNative *impl = SPA_CONTAINER_OF (listener, PinosProtocolNative, global_removed); - PinosProtocolNativeObject *object; - PinosMessageNotifyGlobalRemove ng; - PinosResource *registry; - - if ((object = find_object (impl, global->object))) { - object_destroy (object); - } - - ng.id = global->id; - spa_list_for_each (registry, &core->registry_resource_list, link) { - pinos_resource_send_message (registry, - PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE, - &ng, - true); - } -} - static Socket * create_socket (void) { @@ -628,7 +374,6 @@ pinos_protocol_native_new (PinosCore *core, spa_list_init (&impl->socket_list); spa_list_init (&impl->client_list); - spa_list_init (&impl->object_list); if (!init_socket_name (s, name)) goto error; @@ -639,12 +384,6 @@ pinos_protocol_native_new (PinosCore *core, if (!add_socket (impl, s)) goto error; - pinos_signal_add (&core->global_added, &impl->global_added, on_global_added); - pinos_signal_add (&core->global_removed, &impl->global_removed, on_global_removed); - - impl->global = pinos_core_add_global (core, - core->uri.module, - impl); return impl; error: @@ -666,10 +405,6 @@ pinos_protocol_native_destroy (PinosProtocolNative *impl) spa_list_for_each_safe (object, tmp, &impl->object_list, link) object_destroy (object); - pinos_signal_remove (&impl->global_added); - pinos_signal_remove (&impl->global_removed); - pinos_signal_remove (&impl->node_state_changed); - free (impl); } #endif diff --git a/pinos/modules/module-suspend-on-idle.c b/pinos/modules/module-suspend-on-idle.c index fe9aac47b..d060965c4 100644 --- a/pinos/modules/module-suspend-on-idle.c +++ b/pinos/modules/module-suspend-on-idle.c @@ -29,7 +29,6 @@ typedef struct { PinosCore *core; PinosProperties *properties; - PinosGlobal *global; PinosListener global_added; PinosListener global_removed; @@ -189,9 +188,6 @@ module_new (PinosCore *core, pinos_signal_add (&core->node_state_request, &impl->node_state_request, on_node_state_request); pinos_signal_add (&core->node_state_changed, &impl->node_state_changed, on_node_state_changed); - impl->global = pinos_core_add_global (core, - core->uri.module, - impl); return impl; } diff --git a/pinos/modules/spa/module.c b/pinos/modules/spa/module.c index e04d105bb..2374a0b0b 100644 --- a/pinos/modules/spa/module.c +++ b/pinos/modules/spa/module.c @@ -21,6 +21,8 @@ #include #include +#include + #include #include #include @@ -28,6 +30,43 @@ #include "spa-monitor.h" #include "spa-node.h" +static SpaResult +setup_video_node (SpaNode *spa_node, PinosProperties *pinos_props) { + SpaResult res; + SpaProps *props; + SpaPropValue value; + const char *pattern; + uint32_t pattern_int; + + /* Retrieve pattern property */ + pattern = pinos_properties_get (pinos_props, "pattern"); + if (strcmp (pattern, "smpte-snow") == 0) { + pattern_int = 0; + } else if (strcmp (pattern, "snow") == 0) { + pattern_int = 1; + } else { + pinos_log_debug ("Unrecognized pattern"); + return SPA_RESULT_ERROR; + } + + value.value = &pattern_int; + value.size = sizeof(uint32_t); + + if ((res = spa_node_get_props (spa_node, &props)) != SPA_RESULT_OK) { + pinos_log_debug ("spa_node_get_props failed: %d", res); + return SPA_RESULT_ERROR; + } + + spa_props_set_value (props, spa_props_index_for_name (props, "pattern"), &value); + + if ((res = spa_node_set_props (spa_node, props)) != SPA_RESULT_OK) { + pinos_log_debug ("spa_node_set_props failed: %d", res); + return SPA_RESULT_ERROR; + } + + return SPA_RESULT_OK; +} + bool pinos__module_init (PinosModule * module, const char * args) { @@ -82,12 +121,14 @@ pinos__module_init (PinosModule * module, const char * args) "build/spa/plugins/audiotestsrc/libspa-audiotestsrc.so", "audiotestsrc", "audiotestsrc", + NULL, NULL); pinos_spa_node_load (module->core, "build/spa/plugins/videotestsrc/libspa-videotestsrc.so", "videotestsrc", "videotestsrc", - video_props); + video_props, + setup_video_node); return true; } diff --git a/pinos/modules/spa/spa-node.c b/pinos/modules/spa/spa-node.c index 6965f77ef..2dec8dcad 100644 --- a/pinos/modules/spa/spa-node.c +++ b/pinos/modules/spa/spa-node.c @@ -37,7 +37,8 @@ pinos_spa_node_load (PinosCore *core, const char *lib, const char *factory_name, const char *name, - PinosProperties *properties) + PinosProperties *properties, + SetupNode setup_func) { PinosSpaNode *this; PinosSpaNodeImpl *impl; @@ -97,6 +98,13 @@ pinos_spa_node_load (PinosCore *core, impl->core = core; impl->hnd = hnd; this = &impl->this; + + if (setup_func != NULL) { + if (setup_func (spa_node, properties) != SPA_RESULT_OK) { + pinos_log_debug ("Unrecognized properties"); + } + } + this->node = pinos_node_new (core, name, spa_node, diff --git a/pinos/modules/spa/spa-node.h b/pinos/modules/spa/spa-node.h index b570e8434..c85770dd0 100644 --- a/pinos/modules/spa/spa-node.h +++ b/pinos/modules/spa/spa-node.h @@ -26,6 +26,7 @@ #ifdef __cplusplus extern "C" { #endif + typedef struct _PinosSpaNode PinosSpaNode; struct _PinosSpaNode { @@ -38,11 +39,15 @@ struct _PinosSpaNode { PinosSpaNode *node)); }; +typedef SpaResult (*SetupNode) (SpaNode *spa_node, + PinosProperties *pinos_props); + PinosSpaNode * pinos_spa_node_load (PinosCore *core, const char *lib, const char *factory_name, const char *name, - PinosProperties *properties); + PinosProperties *properties, + SetupNode setup_func); #ifdef __cplusplus } diff --git a/pinos/server/client.c b/pinos/server/client.c index e2854e64b..3f290c602 100644 --- a/pinos/server/client.c +++ b/pinos/server/client.c @@ -28,6 +28,57 @@ typedef struct PinosClient this; } PinosClientImpl; + +static SpaResult +client_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosResource *resource = object; + PinosClient *client = resource->object; + + switch (type) { + default: + pinos_log_warn ("client %p: unhandled message %d", client, type); + break; + } + return SPA_RESULT_OK; +} + +static void +client_bind_func (PinosGlobal *global, + PinosClient *client, + uint32_t version, + uint32_t id) +{ + PinosClient *this = global->object; + PinosResource *resource; + PinosMessageClientInfo m; + PinosClientInfo info; + + resource = pinos_resource_new (client, + id, + global->core->uri.client, + global->object, + NULL); + + resource->dispatch_func = client_dispatch_func; + resource->dispatch_data = global; + + pinos_log_debug ("client %p: bound to %d", global->object, resource->id); + + m.info = &info; + info.id = resource->id; + info.change_mask = ~0; + info.props = this->properties ? &this->properties->dict : NULL; + + pinos_resource_send_message (resource, + PINOS_MESSAGE_CLIENT_INFO, + &m, + true); +} + /** * pinos_client_new: * @daemon: a #PinosDaemon @@ -58,7 +109,9 @@ pinos_client_new (PinosCore *core, this->global = pinos_core_add_global (core, core->uri.client, - this); + 0, + this, + client_bind_func); return this; } diff --git a/pinos/server/client.h b/pinos/server/client.h index b52634fc0..07257d79a 100644 --- a/pinos/server/client.h +++ b/pinos/server/client.h @@ -24,9 +24,6 @@ extern "C" { #endif -#define PINOS_CLIENT_URI "http://pinos.org/ns/client" -#define PINOS_CLIENT_PREFIX PINOS_CLIENT_URI "#" - typedef struct _PinosClient PinosClient; #include @@ -44,6 +41,8 @@ struct _PinosClient { PinosProperties *properties; + PinosResource *core_resource; + PinosMap objects; PinosSendFunc send_func; diff --git a/pinos/server/core.c b/pinos/server/core.c index 7ac0b3410..b72e4c303 100644 --- a/pinos/server/core.c +++ b/pinos/server/core.c @@ -20,6 +20,7 @@ #include #include #include +#include typedef struct { PinosCore this; @@ -28,6 +29,179 @@ typedef struct { } PinosCoreImpl; +static SpaResult +registry_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosResource *resource = object; + PinosClient *client = resource->client; + PinosCore *this = data; + + switch (type) { + case PINOS_MESSAGE_BIND: + { + PinosMessageBind *m = message; + PinosGlobal *global; + + spa_list_for_each (global, &this->global_list, link) + if (global->id == m->id) + break; + + if (&global->link == &this->global_list) { + pinos_log_error ("unknown object id %d", m->id); + return SPA_RESULT_ERROR; + } + if (global->bind == NULL) { + pinos_log_error ("can't bind object id %d", m->id); + return SPA_RESULT_ERROR; + } + + pinos_log_error ("global %p: bind object id %d", global, m->id); + global->bind (global, client, 0, m->id); + break; + } + default: + pinos_log_error ("unhandled message %d", type); + break; + } + return SPA_RESULT_OK; +} + +static void +destroy_registry_resource (void *object) +{ + PinosResource *resource = object; + spa_list_remove (&resource->link); +} + +static SpaResult +core_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosResource *resource = object; + PinosClient *client = resource->client; + PinosCore *this = data; + + switch (type) { + case PINOS_MESSAGE_GET_REGISTRY: + { + PinosMessageGetRegistry *m = message; + PinosGlobal *global; + PinosMessageNotifyDone nd; + PinosResource *registry_resource; + + registry_resource = pinos_resource_new (resource->client, + SPA_ID_INVALID, + this->uri.registry, + this, + destroy_registry_resource); + + registry_resource->dispatch_func = registry_dispatch_func; + registry_resource->dispatch_data = this; + + spa_list_insert (this->registry_resource_list.prev, ®istry_resource->link); + + spa_list_for_each (global, &this->global_list, link) { + PinosMessageNotifyGlobal ng; + + ng.id = global->id; + ng.type = spa_id_map_get_uri (this->uri.map, global->type); + pinos_resource_send_message (registry_resource, + PINOS_MESSAGE_NOTIFY_GLOBAL, + &ng, + false); + } + nd.seq = m->seq; + pinos_resource_send_message (client->core_resource, + PINOS_MESSAGE_NOTIFY_DONE, + &nd, + true); + break; + } + case PINOS_MESSAGE_CREATE_CLIENT_NODE: + { + PinosMessageCreateClientNode *m = message; + PinosClientNode *node; + SpaResult res; + int data_fd, i; + PinosMessageCreateClientNodeDone r; + PinosProperties *props; + + props = pinos_properties_new (NULL, NULL); + for (i = 0; i < m->props->n_items; i++) { + pinos_properties_set (props, m->props->items[i].key, + m->props->items[i].value); + } + + node = pinos_client_node_new (client, + m->new_id, + m->name, + props); + + if ((res = pinos_client_node_get_data_socket (node, &data_fd)) < 0) { + pinos_log_error ("can't get data fd"); + break; + } + + r.seq = m->seq; + r.datafd = data_fd; + pinos_resource_send_message (node->resource, + PINOS_MESSAGE_CREATE_CLIENT_NODE_DONE, + &r, + true); + break; + } + default: + pinos_log_error ("unhandled message %d", type); + break; + } + return SPA_RESULT_OK; +} + +static void +core_bind_func (PinosGlobal *global, + PinosClient *client, + uint32_t version, + uint32_t id) +{ + PinosCore *this = global->object; + PinosResource *resource; + PinosMessageCoreInfo m; + PinosCoreInfo info; + + resource = pinos_resource_new (client, + id, + global->core->uri.core, + global->object, + NULL); + + resource->dispatch_func = core_dispatch_func; + resource->dispatch_data = this; + + client->core_resource = resource; + + pinos_log_debug ("core %p: bound to %d", global->object, resource->id); + + m.info = &info; + info.id = resource->id; + info.change_mask = ~0; + info.user_name = "wim"; + info.host_name = "wtay"; + info.version = 0; + info.name = "pinos-0"; + info.cookie = 0; + info.props = NULL; + + pinos_resource_send_message (resource, + PINOS_MESSAGE_CORE_INFO, + &m, + true); +} + PinosCore * pinos_core_new (PinosMainLoop *main_loop) { @@ -76,7 +250,9 @@ pinos_core_new (PinosMainLoop *main_loop) this->global = pinos_core_add_global (this, this->uri.core, - this); + 0, + this, + core_bind_func); return this; } @@ -96,14 +272,18 @@ pinos_core_destroy (PinosCore *core) PinosGlobal * pinos_core_add_global (PinosCore *core, uint32_t type, - void *object) + uint32_t version, + void *object, + PinosBindFunc bind) { PinosGlobal *global; global = calloc (1, sizeof (PinosGlobal)); global->core = core; global->type = type; + global->version = version; global->object = object; + global->bind = bind; pinos_signal_init (&global->destroy_signal); @@ -166,6 +346,9 @@ pinos_core_find_port (PinosCore *core, pinos_log_debug ("id \"%u\", %d", id, have_id); spa_list_for_each (n, &core->node_list, link) { + if (n->global == NULL) + continue; + pinos_log_debug ("node id \"%d\"", n->global->id); if (have_id) { diff --git a/pinos/server/core.h b/pinos/server/core.h index 45b195f02..ca17485e0 100644 --- a/pinos/server/core.h +++ b/pinos/server/core.h @@ -27,26 +27,31 @@ extern "C" { typedef struct _PinosCore PinosCore; typedef struct _PinosGlobal PinosGlobal; -#define PINOS_CORE_URI "http://pinos.org/ns/core" -#define PINOS_CORE_PREFIX PINOS_CORE_URI "#" -#define PINOS_CORE_REGISTRY PINOS_CORE_PREFIX "Registry" - #include +#include + #include #include -#include #include #include #include +typedef void (*PinosBindFunc) (PinosGlobal *global, + PinosClient *client, + uint32_t version, + uint32_t id); + struct _PinosGlobal { PinosCore *core; SpaList link; uint32_t id; uint32_t type; + uint32_t version; void *object; + PinosBindFunc bind; + PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosGlobal *global)); }; @@ -116,7 +121,9 @@ void pinos_core_destroy (PinosCore *core); PinosGlobal * pinos_core_add_global (PinosCore *core, uint32_t type, - void *object); + uint32_t version, + void *object, + PinosBindFunc bind); void pinos_global_destroy (PinosGlobal *global); diff --git a/pinos/server/link.c b/pinos/server/link.c index 9e923a32f..59a604a5d 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -668,6 +668,39 @@ pinos_pinos_link_deactivate (PinosLink *this) return true; } +static SpaResult +link_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + switch (type) { + default: + break; + } + return SPA_RESULT_OK; +} + +static void +link_bind_func (PinosGlobal *global, + PinosClient *client, + uint32_t version, + uint32_t id) +{ + PinosResource *resource; + + resource = pinos_resource_new (client, + id, + global->core->uri.link, + global->object, + NULL); + + resource->dispatch_func = link_dispatch_func; + resource->dispatch_data = client; + + pinos_log_debug ("link %p: bound to %d", global->object, resource->id); +} + PinosLink * pinos_link_new (PinosCore *core, PinosPort *output, @@ -717,7 +750,9 @@ pinos_link_new (PinosCore *core, this->global = pinos_core_add_global (core, core->uri.link, - this); + 0, + this, + link_bind_func); return this; } diff --git a/pinos/server/link.h b/pinos/server/link.h index 8a482dd34..8eefe4fe2 100644 --- a/pinos/server/link.h +++ b/pinos/server/link.h @@ -26,9 +26,6 @@ extern "C" { typedef struct _PinosLink PinosLink; -#define PINOS_LINK_URI "http://pinos.org/ns/link" -#define PINOS_LINK_PREFIX PINOS_LINK_URI "#" - #include #include diff --git a/pinos/server/meson.build b/pinos/server/meson.build index 31806a992..03965a44e 100644 --- a/pinos/server/meson.build +++ b/pinos/server/meson.build @@ -11,7 +11,6 @@ pinoscore_headers = [ 'node-factory.h', 'port.h', 'resource.h', - 'uri.h', ] pinoscore_sources = [ @@ -27,7 +26,6 @@ pinoscore_sources = [ 'node-factory.c', 'port.c', 'resource.c', - 'uri.c', ] libpinoscore_c_args = [ diff --git a/pinos/server/module.c b/pinos/server/module.c index 484394223..8cef364a8 100644 --- a/pinos/server/module.c +++ b/pinos/server/module.c @@ -90,6 +90,59 @@ find_module (const char * path, const char *name) return filename; } +static SpaResult +module_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosResource *resource = object; + PinosModule *module = resource->object; + + switch (type) { + default: + pinos_log_warn ("module %p: unhandled message %d", module, type); + break; + } + return SPA_RESULT_OK; +} + +static void +module_bind_func (PinosGlobal *global, + PinosClient *client, + uint32_t version, + uint32_t id) +{ + PinosModule *this = global->object; + PinosResource *resource; + PinosMessageModuleInfo m; + PinosModuleInfo info; + + resource = pinos_resource_new (client, + id, + global->core->uri.module, + global->object, + NULL); + + resource->dispatch_func = module_dispatch_func; + resource->dispatch_data = global; + + pinos_log_debug ("module %p: bound to %d", global->object, resource->id); + + m.info = &info; + info.id = resource->id; + info.change_mask = ~0; + info.name = this->name; + info.filename = this->filename; + info.args = this->args; + info.props = NULL; + + pinos_resource_send_message (resource, + PINOS_MESSAGE_MODULE_INFO, + &m, + true); +} + /** * pinos_module_load: * @core: a #PinosCore @@ -140,7 +193,6 @@ pinos_module_load (PinosCore *core, pinos_log_debug ("trying to load module: %s (%s)", name, filename); hnd = dlopen (filename, RTLD_NOW | RTLD_LOCAL); - free (filename); if (hnd == NULL) goto open_failed; @@ -152,7 +204,9 @@ pinos_module_load (PinosCore *core, impl->hnd = hnd; this = &impl->this; - this->name = strdup (name); + this->name = name ? strdup (name) : NULL; + this->filename = filename; + this->args = args ? strdup (args) : NULL; this->core = core; if (!init_func (this, (char *) args)) @@ -160,6 +214,12 @@ pinos_module_load (PinosCore *core, pinos_log_debug ("loaded module: %s", this->name); + this->global = pinos_core_add_global (core, + core->uri.module, + 0, + impl, + module_bind_func); + return this; not_found: @@ -170,12 +230,14 @@ not_found: open_failed: { asprintf (err, "Failed to open module: %s", dlerror ()); + free (filename); return NULL; } no_pinos_module: { asprintf (err, "\"%s\" is not a pinos module", name); dlclose (hnd); + free (filename); return NULL; } init_failed: @@ -193,7 +255,12 @@ pinos_module_destroy (PinosModule *this) pinos_signal_emit (&this->destroy_signal, this); - free (this->name); + if (this->name) + free (this->name); + if (this->filename) + free (this->filename); + if (this->args) + free (this->args); dlclose (impl->hnd); free (impl); } diff --git a/pinos/server/module.h b/pinos/server/module.h index 5ced81060..9fd78ee24 100644 --- a/pinos/server/module.h +++ b/pinos/server/module.h @@ -27,16 +27,16 @@ extern "C" { #include -#define PINOS_MODULE_URI "http://pinos.org/ns/module" -#define PINOS_MODULE_PREFIX PINOS_MODULE_URI "#" - typedef struct _PinosModule PinosModule; struct _PinosModule { PinosCore *core; SpaList link; + PinosGlobal *global; char *name; + char *filename; + char *args; PINOS_SIGNAL (destroy_signal, (PinosListener *listener, PinosModule *module)); diff --git a/pinos/server/node.c b/pinos/server/node.c index cdde53ea9..624277b8f 100644 --- a/pinos/server/node.c +++ b/pinos/server/node.c @@ -382,6 +382,68 @@ on_node_event (SpaNode *node, SpaNodeEvent *event, void *user_data) } } +static SpaResult +node_dispatch_func (void *object, + PinosMessageType type, + void *message, + void *data) +{ + PinosResource *resource = object; + PinosNode *node = resource->object; + + switch (type) { + default: + pinos_log_warn ("node %p: unhandled message %d", node, type); + break; + } + return SPA_RESULT_OK; +} + + +static void +node_unbind_func (void *data) +{ + PinosResource *resource = data; + spa_list_remove (&resource->link); +} + +static void +node_bind_func (PinosGlobal *global, + PinosClient *client, + uint32_t version, + uint32_t id) +{ + PinosNode *this = global->object; + PinosResource *resource; + PinosMessageNodeInfo m; + PinosNodeInfo info; + + resource = pinos_resource_new (client, + id, + global->core->uri.registry, + global->object, + node_unbind_func); + + resource->dispatch_func = node_dispatch_func; + resource->dispatch_data = global; + + pinos_log_debug ("node %p: bound to %d", this, resource->id); + + spa_list_insert (this->resource_list.prev, &resource->link); + + m.info = &info; + info.id = resource->id; + info.change_mask = ~0; + info.name = this->name; + info.state = this->state; + info.props = this->properties ? &this->properties->dict : NULL; + + pinos_resource_send_message (resource, + PINOS_MESSAGE_NODE_INFO, + &m, + true); +} + static void init_complete (PinosNode *this) { @@ -391,7 +453,15 @@ init_complete (PinosNode *this) pinos_log_debug ("node %p: init completed", this); impl->async_init = false; + spa_list_insert (this->core->node_list.prev, &this->link); + pinos_node_update_state (this, PINOS_NODE_STATE_SUSPENDED, NULL); + + this->global = pinos_core_add_global (this->core, + this->core->uri.node, + 0, + this, + node_bind_func); } void @@ -424,6 +494,8 @@ pinos_node_new (PinosCore *core, this->clock = clock; this->data_loop = core->data_loop; + spa_list_init (&this->resource_list); + if (spa_node_set_event_callback (this->node, on_node_event, this) < 0) pinos_log_warn ("node %p: error setting callback", this); @@ -459,11 +531,7 @@ pinos_node_new (PinosCore *core, (PinosDeferFunc) init_complete, NULL); } - spa_list_insert (core->node_list.prev, &this->link); - this->global = pinos_core_add_global (core, - core->uri.node, - this); return this; } @@ -724,6 +792,10 @@ pinos_node_update_state (PinosNode *node, old = node->state; if (old != state) { + PinosMessageNodeInfo m; + PinosNodeInfo info; + PinosResource *resource; + pinos_log_debug ("node %p: update state from %s -> %s", node, pinos_node_state_as_string (old), pinos_node_state_as_string (state)); @@ -732,6 +804,20 @@ pinos_node_update_state (PinosNode *node, free (node->error); node->error = error; node->state = state; + pinos_signal_emit (&node->core->node_state_changed, node, old, state); + + spa_zero (info); + m.info = &info; + info.change_mask = 1 << 1; + info.state = node->state; + + spa_list_for_each (resource, &node->resource_list, link) { + info.id = resource->id; + pinos_resource_send_message (resource, + PINOS_MESSAGE_NODE_INFO, + &m, + true); + } } } diff --git a/pinos/server/node.h b/pinos/server/node.h index 03c42fad7..ea26b4dd5 100644 --- a/pinos/server/node.h +++ b/pinos/server/node.h @@ -62,6 +62,8 @@ struct _PinosNode { bool live; SpaClock *clock; + SpaList resource_list; + SpaList input_ports; SpaList output_ports; diff --git a/pinos/server/resource.c b/pinos/server/resource.c index 14055a15e..c5963e402 100644 --- a/pinos/server/resource.c +++ b/pinos/server/resource.c @@ -82,14 +82,14 @@ pinos_resource_destroy (PinosResource *resource) SpaResult pinos_resource_send_message (PinosResource *resource, - PinosMessageType type, + uint32_t opcode, void *message, bool flush) { if (resource->send_func) return resource->send_func (resource, resource->id, - type, + opcode, message, flush, resource->send_data); diff --git a/pinos/server/resource.h b/pinos/server/resource.h index d13981ae8..7cbe929ea 100644 --- a/pinos/server/resource.h +++ b/pinos/server/resource.h @@ -35,13 +35,13 @@ typedef void (*PinosDestroy) (void *object); typedef SpaResult (*PinosSendFunc) (void *object, uint32_t id, - PinosMessageType type, + uint32_t opcode, void *message, bool flush, void *data); typedef SpaResult (*PinosDispatchFunc) (void *object, - PinosMessageType type, + uint32_t opcode, void *message, void *data); @@ -73,7 +73,7 @@ PinosResource * pinos_resource_new (PinosClient *client, SpaResult pinos_resource_destroy (PinosResource *resource); SpaResult pinos_resource_send_message (PinosResource *resource, - PinosMessageType type, + uint32_t opcode, void *message, bool flush); diff --git a/pinos/tools/pinos-monitor.c b/pinos/tools/pinos-monitor.c index 97bc8841d..280279444 100644 --- a/pinos/tools/pinos-monitor.c +++ b/pinos/tools/pinos-monitor.c @@ -31,17 +31,16 @@ typedef struct { } Data; static void -print_properties (PinosProperties *props, char mark) +print_properties (SpaDict *props, char mark) { - void *state = NULL; - const char *key; + SpaDictItem *item; if (props == NULL) return; printf ("%c\tproperties:\n", mark); - while ((key = pinos_properties_iterate (props, &state))) { - printf ("%c\t\t%s = \"%s\"\n", mark, key, pinos_properties_get (props, key)); + spa_dict_for_each (item, props) { + printf ("%c\t\t%s = \"%s\"\n", mark, item->key, item->value); } } @@ -53,51 +52,109 @@ typedef struct { #define MARK_CHANGE(f) ((data->print_mark && ((info)->change_mask & (1 << (f)))) ? '*' : ' ') static void -dump_daemon_info (PinosContext *c, const PinosDaemonInfo *info, void * user_data) +dump_core_info (PinosContext *c, + SpaResult res, + const PinosCoreInfo *info, + void *user_data) { DumpData *data = user_data; + if (info == NULL) + return; + printf ("\tid: %u\n", info->id); + printf ("\ttype: %s\n", PINOS_CORE_URI); if (data->print_all) { printf ("%c\tuser-name: \"%s\"\n", MARK_CHANGE (0), info->user_name); printf ("%c\thost-name: \"%s\"\n", MARK_CHANGE (1), info->host_name); printf ("%c\tversion: \"%s\"\n", MARK_CHANGE (2), info->version); printf ("%c\tname: \"%s\"\n", MARK_CHANGE (3), info->name); printf ("%c\tcookie: %u\n", MARK_CHANGE (4), info->cookie); - print_properties (info->properties, MARK_CHANGE (5)); + print_properties (info->props, MARK_CHANGE (5)); } } static void -dump_client_info (PinosContext *c, const PinosClientInfo *info, void * user_data) +dump_client_info (PinosContext *c, + SpaResult res, + const PinosClientInfo *info, + void *user_data) { DumpData *data = user_data; + if (info == NULL) + return; + printf ("\tid: %u\n", info->id); + printf ("\ttype: %s\n", PINOS_CLIENT_URI); if (data->print_all) { - print_properties (info->properties, MARK_CHANGE (0)); + print_properties (info->props, MARK_CHANGE (0)); } } static void -dump_node_info (PinosContext *c, const PinosNodeInfo *info, void * user_data) +dump_node_info (PinosContext *c, + SpaResult res, + const PinosNodeInfo *info, + void *user_data) { DumpData *data = user_data; + if (info == NULL) { + if (res != SPA_RESULT_ENUM_END) + printf ("\tError introspecting node: %d\n", res); + return; + } + printf ("\tid: %u\n", info->id); + printf ("\ttype: %s\n", PINOS_NODE_URI); if (data->print_all) { printf ("%c\tname: \"%s\"\n", MARK_CHANGE (0), info->name); - print_properties (info->properties, MARK_CHANGE (1)); - printf ("%c\tstate: \"%s\"\n", MARK_CHANGE (2), pinos_node_state_as_string (info->state)); + printf ("%c\tstate: \"%s\"\n", MARK_CHANGE (1), pinos_node_state_as_string (info->state)); + print_properties (info->props, MARK_CHANGE (2)); } } static void -dump_link_info (PinosContext *c, const PinosLinkInfo *info, void * user_data) +dump_module_info (PinosContext *c, + SpaResult res, + const PinosModuleInfo *info, + void *user_data) { DumpData *data = user_data; + if (info == NULL) { + if (res != SPA_RESULT_ENUM_END) + printf ("\tError introspecting module: %d\n", res); + return; + } + printf ("\tid: %u\n", info->id); + printf ("\ttype: %s\n", PINOS_MODULE_URI); + if (data->print_all) { + printf ("%c\tname: \"%s\"\n", MARK_CHANGE (0), info->name); + printf ("%c\tfilename: \"%s\"\n", MARK_CHANGE (1), info->filename); + printf ("%c\targs: \"%s\"\n", MARK_CHANGE (2), info->args); + print_properties (info->props, MARK_CHANGE (3)); + } +} + +static void +dump_link_info (PinosContext *c, + SpaResult res, + const PinosLinkInfo *info, + void *user_data) +{ + DumpData *data = user_data; + + if (info == NULL) { + if (res != SPA_RESULT_ENUM_END) + printf ("\tError introspecting link: %d\n", res); + return; + } + + printf ("\tid: %u\n", info->id); + printf ("\ttype: %s\n", PINOS_LINK_URI); if (data->print_all) { printf ("%c\toutput-node-id: %u\n", MARK_CHANGE (0), info->output_node_id); printf ("%c\toutput-port-id: %u\n", MARK_CHANGE (1), info->output_port_id); @@ -108,49 +165,66 @@ dump_link_info (PinosContext *c, const PinosLinkInfo *info, void * user_data) static void dump_object (PinosContext *context, + uint32_t type, uint32_t id, - PinosSubscriptionFlags flags, DumpData *data) { - if (flags & PINOS_SUBSCRIPTION_FLAG_DAEMON) { + if (type == context->uri.node) { + pinos_context_get_node_info_by_id (context, + id, + dump_node_info, + data); } - else if (flags & PINOS_SUBSCRIPTION_FLAG_CLIENT) { + if (type == context->uri.module) { + pinos_context_get_module_info_by_id (context, + id, + dump_module_info, + data); } - else if (flags & PINOS_SUBSCRIPTION_FLAG_NODE) { + if (type == context->uri.client) { + pinos_context_get_client_info_by_id (context, + id, + dump_client_info, + data); } - else if (flags & PINOS_SUBSCRIPTION_FLAG_LINK) { + if (type == context->uri.link) { + pinos_context_get_link_info_by_id (context, + id, + dump_link_info, + data); } + } static void subscription_cb (PinosContext *context, - PinosSubscriptionFlags flags, - PinosSubscriptionEvent type, + PinosSubscriptionEvent event, + uint32_t type, uint32_t id, void *data) { DumpData dd; - switch (type) { + switch (event) { case PINOS_SUBSCRIPTION_EVENT_NEW: printf ("added:\n"); dd.print_mark = false; dd.print_all = true; - dump_object (context, id, flags, &dd); + dump_object (context, type, id, &dd); break; case PINOS_SUBSCRIPTION_EVENT_CHANGE: printf ("changed:\n"); dd.print_mark = true; dd.print_all = true; - dump_object (context, id, flags, &dd); + dump_object (context, type, id, &dd); break; case PINOS_SUBSCRIPTION_EVENT_REMOVE: printf ("removed:\n"); dd.print_mark = false; dd.print_all = false; - dump_object (context, id, flags, &dd); + dump_object (context, type, id, &dd); break; } } @@ -189,7 +263,6 @@ main (int argc, char *argv[]) on_state_changed); pinos_context_subscribe (data.context, - PINOS_SUBSCRIPTION_FLAGS_ALL, subscription_cb, &data); diff --git a/spa/include/spa/defs.h b/spa/include/spa/defs.h index b0502c2b3..6ca35367e 100644 --- a/spa/include/spa/defs.h +++ b/spa/include/spa/defs.h @@ -65,6 +65,7 @@ typedef enum { SPA_RESULT_INVALID_BUFFER_ID = -28, SPA_RESULT_WRONG_STATE = -29, SPA_RESULT_ASYNC_BUSY = -30, + SPA_RESULT_INVALID_OBJECT_ID = -31, } SpaResult; #define SPA_ASYNC_MASK (3 << 30)