diff --git a/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c b/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c index 03b1b5574..8da1b6ae8 100644 --- a/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c +++ b/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c @@ -85,6 +85,7 @@ struct service { struct pw_properties *props; char service_name[AVAHI_LABEL_MAX]; + unsigned published:1; }; struct module_zeroconf_publish_data { @@ -95,6 +96,7 @@ struct module_zeroconf_publish_data { struct spa_hook core_listener; struct spa_hook manager_listener; + struct spa_hook impl_listener; AvahiPoll *avahi_poll; AvahiClient *client; @@ -151,6 +153,7 @@ static void unpublish_service(struct service *s) { spa_list_remove(&s->link); spa_list_append(&s->userdata->pending, &s->link); + s->published = false; } static void unpublish_all_services(struct module_zeroconf_publish_data *d) @@ -315,6 +318,11 @@ static void service_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupStat struct service *s = userdata; spa_assert(s); + if (!s->published) { + pw_log_info("cancel unpublished service: %s", s->service_name); + clear_entry_group(s); + return; + } switch (state) { case AVAHI_ENTRY_GROUP_ESTABLISHED: @@ -418,15 +426,18 @@ static void publish_service(struct service *s) if (find_port(s, &proto, &port) < 0) return; + pw_log_debug("found proto:%d port:%d", proto, port); + if (!d->client || avahi_client_get_state(d->client) != AVAHI_CLIENT_S_RUNNING) return; + s->published = true; if (!s->entry_group) { s->entry_group = avahi_entry_group_new(d->client, service_entry_group_callback, s); if (s->entry_group == NULL) { pw_log_error("avahi_entry_group_new(): %s", avahi_strerror(avahi_client_errno(d->client))); - return; + goto error; } } else { avahi_entry_group_reset(s->entry_group); @@ -447,7 +458,7 @@ static void publish_service(struct service *s) s->txt) < 0) { pw_log_error("avahi_entry_group_add_service_strlst(): %s", avahi_strerror(avahi_client_errno(d->client))); - return; + goto error; } if (avahi_entry_group_add_service_subtype( @@ -462,7 +473,7 @@ static void publish_service(struct service *s) pw_log_error("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(d->client))); - return; + goto error; } if (!s->is_sink && s->subtype != SUBTYPE_MONITOR) { @@ -476,20 +487,25 @@ static void publish_service(struct service *s) SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) { pw_log_error("avahi_entry_group_add_service_subtype(): %s", avahi_strerror(avahi_client_errno(d->client))); - return; + goto error; } } if (avahi_entry_group_commit(s->entry_group) < 0) { pw_log_error("avahi_entry_group_commit(): %s", avahi_strerror(avahi_client_errno(d->client))); - return; + goto error; } spa_list_remove(&s->link); spa_list_append(&d->published, &s->link); pw_log_info("created service: %s", s->service_name); + return; + +error: + s->published = false; + return; } static void publish_pending(struct module_zeroconf_publish_data *data) @@ -598,6 +614,28 @@ static const struct pw_manager_events manager_events = { .removed = manager_removed, }; + +static void impl_server_started(void *data, struct server *server) +{ + struct module_zeroconf_publish_data *d = data; + pw_log_info("a new server is started, try publish"); + publish_pending(d); +} + +static void impl_server_stopped(void *data, struct server *server) +{ + struct module_zeroconf_publish_data *d = data; + pw_log_info("a server stopped, try republish"); + unpublish_all_services(d); + publish_pending(d); +} + +static const struct impl_events impl_events = { + VERSION_IMPL_EVENTS, + .server_started = impl_server_started, + .server_stopped = impl_server_stopped, +}; + static int module_zeroconf_publish_load(struct client *client, struct module *module) { struct module_zeroconf_publish_data *data = module->user_data; @@ -634,6 +672,8 @@ static int module_zeroconf_publish_load(struct client *client, struct module *mo pw_manager_add_listener(data->manager, &data->manager_listener, &manager_events, data); + impl_add_listener(module->impl, &data->impl_listener, &impl_events, data); + return 0; } @@ -642,6 +682,8 @@ static int module_zeroconf_publish_unload(struct module *module) struct module_zeroconf_publish_data *d = module->user_data; struct service *s; + spa_hook_remove(&d->impl_listener); + unpublish_all_services(d); spa_list_consume(s, &d->pending, link)