diff options
Diffstat (limited to 'src/modules/restart-module.c')
-rw-r--r-- | src/modules/restart-module.c | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/modules/restart-module.c b/src/modules/restart-module.c new file mode 100644 index 000000000..d7e855a5d --- /dev/null +++ b/src/modules/restart-module.c @@ -0,0 +1,88 @@ +/*** + This file is part of PulseAudio. + + Copyright 2022 Craig Howard + + PulseAudio is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published + by the Free Software Foundation; either version 2.1 of the License, + or (at your option) any later version. + + PulseAudio is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License + along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. +***/ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include "restart-module.h" + +#include <pulse/timeval.h> +#include <pulse/xmalloc.h> +#include <pulse/mainloop.h> + +#include <pulsecore/core.h> +#include <pulsecore/thread-mq.h> + +struct reinit_data { + init_cb do_init; + done_cb do_done; + + pa_usec_t restart_usec; + pa_module *module; +}; + +static void call_init(pa_mainloop_api *mainloop, pa_time_event *e, const struct timeval *tv, void *userdata) { + struct reinit_data *rd = userdata; + int ret; + + /* now that restart_usec has elapsed, we call do_init to restart the module */ + ret = rd->do_init(rd->module); + + /* if the init failed, we got here because the caller wanted to restart, so + * setup another restart */ + if (ret < 0) + pa_restart_module_reinit(rd->module, rd->do_init, rd->do_done, rd->restart_usec); + + pa_xfree(rd); +} + +static void do_reinit(pa_mainloop_api *mainloop, void *userdata) { + struct reinit_data *rd = userdata; + struct timeval tv; + + pa_assert_ctl_context(); + + /* call do_done on the module, which will effectively tear it down; all + * that remains is the pa_module */ + rd->do_done(rd->module); + + /* after restart_usec, call do_init to restart the module */ + pa_gettimeofday(&tv); + pa_timeval_add(&tv, rd->restart_usec); + mainloop->time_new(mainloop, &tv, call_init, rd); +} + +void pa_restart_module_reinit(pa_module *m, init_cb do_init, done_cb do_done, pa_usec_t restart_usec) { + struct reinit_data *rd; + + pa_assert_ctl_context(); + + pa_log_info("Starting reinit for %s", m->name); + + rd = pa_xnew0(struct reinit_data, 1); + rd->do_init = do_init; + rd->do_done = do_done; + rd->restart_usec = restart_usec; + rd->module = m; + + /* defer actually doing a reinit, so that we can safely exit whatever call + * chain we're in before we effectively reinit the module */ + pa_mainloop_api_once(m->core->mainloop, do_reinit, rd); +} |