From 2799350a5945d2436f2fcfdfaba095f059bbdea3 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 26 Sep 2025 13:39:49 +0200 Subject: [PATCH] modules: use timer-queue in avahi-poll Pass the pw_context to get to the shared queue and loop. Patch up the users of avahi-poll. Fixes #4913 --- .../modules/module-zeroconf-publish.c | 4 +- src/modules/module-raop-discover.c | 4 +- src/modules/module-rtp-session.c | 2 +- src/modules/module-snapcast-discover.c | 6 +- src/modules/module-zeroconf-discover.c | 5 +- .../module-zeroconf-discover/avahi-poll.c | 65 ++++++++++++------- .../module-zeroconf-discover/avahi-poll.h | 4 +- 7 files changed, 49 insertions(+), 41 deletions(-) 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 414299467..d4425a3fe 100644 --- a/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c +++ b/src/modules/module-protocol-pulse/modules/module-zeroconf-publish.c @@ -637,7 +637,6 @@ static const struct impl_events impl_events = { static int module_zeroconf_publish_load(struct module *module) { struct module_zeroconf_publish_data *data = module->user_data; - struct pw_loop *loop; int error; data->core = pw_context_connect(module->impl->context, NULL, 0); @@ -650,8 +649,7 @@ static int module_zeroconf_publish_load(struct module *module) &data->core_listener, &core_events, data); - loop = pw_context_get_main_loop(module->impl->context); - data->avahi_poll = pw_avahi_poll_new(loop); + data->avahi_poll = pw_avahi_poll_new(module->impl->context); data->client = avahi_client_new(data->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, data, &error); diff --git a/src/modules/module-raop-discover.c b/src/modules/module-raop-discover.c index 9a1079a4e..c1859ab10 100644 --- a/src/modules/module-raop-discover.c +++ b/src/modules/module-raop-discover.c @@ -561,10 +561,8 @@ static int start_client(struct impl *impl) static int start_avahi(struct impl *impl) { - struct pw_loop *loop; - loop = pw_context_get_main_loop(impl->context); - impl->avahi_poll = pw_avahi_poll_new(loop); + impl->avahi_poll = pw_avahi_poll_new(impl->context); return start_client(impl); } diff --git a/src/modules/module-rtp-session.c b/src/modules/module-rtp-session.c index ab5e1d8a7..7b70683d8 100644 --- a/src/modules/module-rtp-session.c +++ b/src/modules/module-rtp-session.c @@ -1821,7 +1821,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args) if ((res = setup_apple_session(impl)) < 0) goto out; - impl->avahi_poll = pw_avahi_poll_new(impl->loop); + impl->avahi_poll = pw_avahi_poll_new(impl->context); if ((impl->client = avahi_client_new(impl->avahi_poll, AVAHI_CLIENT_NO_FAIL, client_callback, impl, diff --git a/src/modules/module-snapcast-discover.c b/src/modules/module-snapcast-discover.c index a11409169..bd50ec473 100644 --- a/src/modules/module-snapcast-discover.c +++ b/src/modules/module-snapcast-discover.c @@ -166,13 +166,13 @@ static const struct spa_dict_item module_props[] = { struct impl { struct pw_context *context; - struct pw_loop *loop; struct pw_impl_module *module; struct spa_hook module_listener; struct pw_properties *properties; bool discover_local; + struct pw_loop *loop; AvahiPoll *avahi_poll; AvahiClient *client; @@ -850,10 +850,8 @@ static int start_client(struct impl *impl) static int start_avahi(struct impl *impl) { - struct pw_loop *loop; - loop = pw_context_get_main_loop(impl->context); - impl->avahi_poll = pw_avahi_poll_new(loop); + impl->avahi_poll = pw_avahi_poll_new(impl->context); return start_client(impl); } diff --git a/src/modules/module-zeroconf-discover.c b/src/modules/module-zeroconf-discover.c index 68edd605c..d7791ac5f 100644 --- a/src/modules/module-zeroconf-discover.c +++ b/src/modules/module-zeroconf-discover.c @@ -487,10 +487,7 @@ static int start_client(struct impl *impl) static int start_avahi(struct impl *impl) { - struct pw_loop *loop; - - loop = pw_context_get_main_loop(impl->context); - impl->avahi_poll = pw_avahi_poll_new(loop); + impl->avahi_poll = pw_avahi_poll_new(impl->context); return start_client(impl); } diff --git a/src/modules/module-zeroconf-discover/avahi-poll.c b/src/modules/module-zeroconf-discover/avahi-poll.c index 65b64736a..4ead6427a 100644 --- a/src/modules/module-zeroconf-discover/avahi-poll.c +++ b/src/modules/module-zeroconf-discover/avahi-poll.c @@ -8,7 +8,9 @@ struct impl { AvahiPoll api; + struct pw_context *context; struct pw_loop *loop; + struct pw_timer_queue *timer_queue; }; struct AvahiWatch { @@ -22,7 +24,7 @@ struct AvahiWatch { struct AvahiTimeout { struct impl *impl; - struct spa_source *source; + struct pw_timer timer; AvahiTimeoutCallback callback; void *userdata; }; @@ -99,17 +101,40 @@ static void watch_free(AvahiWatch *w) free(w); } -static void timeout_callback(void *data, uint64_t expirations) +static void timeout_callback(void *data) { AvahiTimeout *w = data; w->callback(w, w->userdata); } +static int schedule_timeout(AvahiTimeout *t, const struct timeval *tv) +{ + struct timeval now; + int64_t timeout_ns; + + if (tv == NULL) + return 0; + + /* Get current REALTIME (same clock domain as Avahi) */ + if (gettimeofday(&now, NULL) < 0) + return -errno; + + /* Calculate relative timeout: target - now */ + timeout_ns = ((int64_t)tv->tv_sec - now.tv_sec) * SPA_NSEC_PER_SEC + + ((int64_t)tv->tv_usec - now.tv_usec) * 1000UL; + + /* Ensure minimum timeout */ + if (timeout_ns <= 0) + timeout_ns = 1; + + return pw_timer_queue_add(t->impl->timer_queue, &t->timer, NULL, + timeout_ns, timeout_callback, t); +} + static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, AvahiTimeoutCallback callback, void *userdata) { struct impl *impl = api->userdata; - struct timespec value; AvahiTimeout *w; w = calloc(1, sizeof(*w)); @@ -119,38 +144,27 @@ static AvahiTimeout* timeout_new(const AvahiPoll *api, const struct timeval *tv, w->impl = impl; w->callback = callback; w->userdata = userdata; - w->source = pw_loop_add_timer(impl->loop, timeout_callback, w); - if (w->source == NULL) { + + if (schedule_timeout(w, tv) < 0) { free(w); return NULL; } - if (tv != NULL) { - value.tv_sec = tv->tv_sec; - value.tv_nsec = tv->tv_usec * 1000UL; - pw_loop_update_timer(impl->loop, w->source, &value, NULL, true); - } + return w; } static void timeout_update(AvahiTimeout *t, const struct timeval *tv) { - struct impl *impl = t->impl; - struct timespec value, *v = NULL; + /* Cancel the existing timer */ + pw_timer_queue_cancel(&t->timer); - if (tv != NULL) { - value.tv_sec = tv->tv_sec; - value.tv_nsec = tv->tv_usec * 1000UL; - if (value.tv_sec == 0 && value.tv_nsec == 0) - value.tv_nsec = 1; - v = &value; - } - pw_loop_update_timer(impl->loop, t->source, v, NULL, true); + /* Schedule new timeout if provided */ + schedule_timeout(t, tv); } static void timeout_free(AvahiTimeout *t) { - struct impl *impl = t->impl; - pw_loop_destroy_source(impl->loop, t->source); + pw_timer_queue_cancel(&t->timer); free(t); } @@ -164,7 +178,7 @@ static const AvahiPoll avahi_poll_api = { .timeout_free = timeout_free, }; -AvahiPoll* pw_avahi_poll_new(struct pw_loop *loop) +AvahiPoll* pw_avahi_poll_new(struct pw_context *context) { struct impl *impl; @@ -172,7 +186,10 @@ AvahiPoll* pw_avahi_poll_new(struct pw_loop *loop) if (impl == NULL) return NULL; - impl->loop = loop; + impl->context = context; + impl->loop = pw_context_get_main_loop(context); + impl->timer_queue = pw_context_get_timer_queue(context); + impl->api = avahi_poll_api; impl->api.userdata = impl; diff --git a/src/modules/module-zeroconf-discover/avahi-poll.h b/src/modules/module-zeroconf-discover/avahi-poll.h index f651c5fd8..fce9b9d1b 100644 --- a/src/modules/module-zeroconf-discover/avahi-poll.h +++ b/src/modules/module-zeroconf-discover/avahi-poll.h @@ -4,8 +4,8 @@ #include -#include +#include -AvahiPoll* pw_avahi_poll_new(struct pw_loop *loop); +AvahiPoll* pw_avahi_poll_new(struct pw_context *context); void pw_avahi_poll_free(AvahiPoll *p);