diff --git a/pinos/client/context.c b/pinos/client/context.c index b61f45086..e7f2e01a3 100644 --- a/pinos/client/context.c +++ b/pinos/client/context.c @@ -255,6 +255,46 @@ client_dispatch_func (void *object, return SPA_RESULT_OK; } +static SpaResult +link_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_LINK_INFO: + { + PinosMessageLinkInfo *m = message; + PinosSubscriptionEvent event; + + pinos_log_debug ("got link info %d", type); + if (proxy->user_data == NULL) + event = PINOS_SUBSCRIPTION_EVENT_NEW; + else + event = PINOS_SUBSCRIPTION_EVENT_CHANGE; + + proxy->user_data = pinos_link_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 registry_dispatch_func (void *object, PinosMessageType type, @@ -291,6 +331,11 @@ registry_dispatch_func (void *object, proxy->dispatch_func = client_dispatch_func; proxy->dispatch_data = impl; } else if (!strcmp (ng->type, PINOS_LINK_URI)) { + proxy = pinos_proxy_new (this, + SPA_ID_INVALID, + this->uri.link); + proxy->dispatch_func = link_dispatch_func; + proxy->dispatch_data = impl; } if (proxy) { PinosMessageBind m; diff --git a/pinos/client/introspect.c b/pinos/client/introspect.c index 81727650f..806b294ef 100644 --- a/pinos/client/introspect.c +++ b/pinos/client/introspect.c @@ -277,3 +277,39 @@ pinos_client_info_free (PinosClientInfo *info) pinos_spa_dict_destroy (info->props); free (info); } + +PinosLinkInfo * +pinos_link_info_update (PinosLinkInfo *info, + const PinosLinkInfo *update) +{ + uint64_t change_mask; + + if (update == NULL) + return info; + + if (info == NULL) { + info = calloc (1, sizeof (PinosLinkInfo)); + 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)) + info->output_node_id = update->output_node_id; + if (update->change_mask & (1 << 1)) + info->output_port_id = update->output_port_id; + if (update->change_mask & (1 << 2)) + info->input_node_id = update->input_node_id; + if (update->change_mask & (1 << 3)) + info->input_port_id = update->input_port_id; + + return info; +} + +void +pinos_link_info_free (PinosLinkInfo *info) +{ + free (info); +} diff --git a/pinos/client/introspect.h b/pinos/client/introspect.h index fe714159a..1a20f27e8 100644 --- a/pinos/client/introspect.h +++ b/pinos/client/introspect.h @@ -301,6 +301,10 @@ struct _PinosLinkInfo { uint32_t input_port_id; }; +PinosLinkInfo * pinos_link_info_update (PinosLinkInfo *info, + const PinosLinkInfo *update); +void pinos_link_info_free (PinosLinkInfo *info); + /** * PinosLinkInfoCallback: diff --git a/pinos/client/stream.c b/pinos/client/stream.c index 660914a7b..41f53935f 100644 --- a/pinos/client/stream.c +++ b/pinos/client/stream.c @@ -606,37 +606,6 @@ stream_dispatch_func (void *object, PinosStreamImpl *impl = SPA_CONTAINER_OF (stream, PinosStreamImpl, this); switch (type) { - case PINOS_MESSAGE_SYNC: - case PINOS_MESSAGE_GET_REGISTRY: - case PINOS_MESSAGE_BIND: - case PINOS_MESSAGE_DESTROY: - 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; - - case PINOS_MESSAGE_NOTIFY_DONE: - pinos_log_warn ("notify done %d", type); - break; - - case PINOS_MESSAGE_NOTIFY_GLOBAL: - pinos_log_warn ("notify global %d", type); - break; - - case PINOS_MESSAGE_NOTIFY_GLOBAL_REMOVE: - pinos_log_warn ("notify global %d", type); - break; - case PINOS_MESSAGE_CREATE_NODE_DONE: pinos_log_warn ("create node done %d", type); break; @@ -838,6 +807,7 @@ stream_dispatch_func (void *object, pinos_log_debug ("transport update %d %p", impl->rtfd, impl->trans); break; } + default: case PINOS_MESSAGE_INVALID: pinos_log_warn ("unhandled message %d", type); break; diff --git a/pinos/modules/module-protocol-native.c b/pinos/modules/module-protocol-native.c index 4577ef3bc..8267f363a 100644 --- a/pinos/modules/module-protocol-native.c +++ b/pinos/modules/module-protocol-native.c @@ -82,17 +82,33 @@ typedef struct { } PinosProtocolNativeClient; static void -client_destroy (PinosProtocolNativeClient *this) +sync_destroy (void *object, + void *data, + SpaResult res, + uint32_t id) { - pinos_client_destroy (this->client); - spa_list_remove (&this->link); - pinos_loop_destroy_source (this->impl->core->main_loop->loop, - this->source); + PinosProtocolNativeClient *this = object; + pinos_connection_destroy (this->connection); close (this->fd); free (this); } +static void +client_destroy (PinosProtocolNativeClient *this) +{ + pinos_loop_destroy_source (this->impl->core->main_loop->loop, + this->source); + pinos_client_destroy (this->client); + spa_list_remove (&this->link); + + pinos_main_loop_defer (this->impl->core->main_loop, + this, + SPA_RESULT_WAIT_SYNC, + sync_destroy, + this); +} + static SpaResult client_send_func (void *object, uint32_t id, diff --git a/pinos/server/core.c b/pinos/server/core.c index b72e4c303..71a820a1c 100644 --- a/pinos/server/core.c +++ b/pinos/server/core.c @@ -277,6 +277,8 @@ pinos_core_add_global (PinosCore *core, PinosBindFunc bind) { PinosGlobal *global; + PinosResource *registry; + PinosMessageNotifyGlobal ng; global = calloc (1, sizeof (PinosGlobal)); global->core = core; @@ -294,6 +296,14 @@ pinos_core_add_global (PinosCore *core, pinos_log_debug ("global %p: new %u", global, global->id); + ng.id = global->id; + ng.type = spa_id_map_get_uri (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); + } return global; } @@ -313,6 +323,8 @@ void pinos_global_destroy (PinosGlobal *global) { PinosCore *core = global->core; + PinosResource *registry; + PinosMessageNotifyGlobalRemove ng; pinos_log_debug ("global %p: destroy", global); pinos_signal_emit (&global->destroy_signal, global); @@ -322,6 +334,14 @@ pinos_global_destroy (PinosGlobal *global) spa_list_remove (&global->link); pinos_signal_emit (&core->global_removed, core, global); + 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); + } + pinos_main_loop_defer (core->main_loop, global, SPA_RESULT_WAIT_SYNC, diff --git a/pinos/server/link.c b/pinos/server/link.c index 59a604a5d..35d62948a 100644 --- a/pinos/server/link.c +++ b/pinos/server/link.c @@ -681,24 +681,48 @@ link_dispatch_func (void *object, return SPA_RESULT_OK; } +static void +link_unbind_func (void *data) +{ + PinosResource *resource = data; + spa_list_remove (&resource->link); +} + static void link_bind_func (PinosGlobal *global, PinosClient *client, uint32_t version, uint32_t id) { + PinosLink *this = global->object; PinosResource *resource; + PinosMessageLinkInfo m; + PinosLinkInfo info; resource = pinos_resource_new (client, id, global->core->uri.link, global->object, - NULL); + link_unbind_func); resource->dispatch_func = link_dispatch_func; - resource->dispatch_data = client; + resource->dispatch_data = global; pinos_log_debug ("link %p: bound to %d", global->object, resource->id); + + spa_list_insert (this->resource_list.prev, &resource->link); + + m.info = &info; + info.id = resource->id; + info.change_mask = ~0; + info.output_node_id = this->output ? this->output->node->global->id : -1; + info.output_port_id = this->output ? this->output->port_id : -1; + info.input_node_id = this->input ? this->input->node->global->id : -1; + info.input_port_id = this->input ? this->input->port_id : -1; + pinos_resource_send_message (resource, + PINOS_MESSAGE_LINK_INFO, + &m, + true); } PinosLink * @@ -722,6 +746,7 @@ pinos_link_new (PinosCore *core, this->input = input; this->output = output; + spa_list_init (&this->resource_list); pinos_signal_init (&this->destroy_signal); impl->format_filter = format_filter; diff --git a/pinos/server/link.h b/pinos/server/link.h index 8eefe4fe2..d9f522e75 100644 --- a/pinos/server/link.h +++ b/pinos/server/link.h @@ -52,9 +52,10 @@ struct _PinosLink { PINOS_SIGNAL (destroy_signal, (PinosListener *, PinosLink *)); + SpaList resource_list; + PinosPort *output; SpaList output_link; - PinosPort *input; SpaList input_link;