Add default-monitor-time-sec
[platform/upstream/pulseaudio.git] / src / pulsecore / module.c
1 /***
2   This file is part of PulseAudio.
3
4   Copyright 2004-2006 Lennart Poettering
5   Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
7   PulseAudio is free software; you can redistribute it and/or modify
8   it under the terms of the GNU Lesser General Public License as published
9   by the Free Software Foundation; either version 2.1 of the License,
10   or (at your option) any later version.
11
12   PulseAudio is distributed in the hope that it will be useful, but
13   WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   General Public License for more details.
16
17   You should have received a copy of the GNU Lesser General Public License
18   along with PulseAudio; if not, see <http://www.gnu.org/licenses/>.
19 ***/
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <ltdl.h>
30
31 #include <pulse/xmalloc.h>
32 #include <pulse/proplist.h>
33
34 #include <pulsecore/core-subscribe.h>
35 #include <pulsecore/log.h>
36 #include <pulsecore/core-util.h>
37 #include <pulsecore/macro.h>
38 #include <pulsecore/ltdl-helper.h>
39 #include <pulsecore/modinfo.h>
40
41 #include "module.h"
42
43 #define PA_SYMBOL_INIT "pa__init"
44 #define PA_SYMBOL_DONE "pa__done"
45 #define PA_SYMBOL_LOAD_ONCE "pa__load_once"
46 #define PA_SYMBOL_GET_N_USED "pa__get_n_used"
47 #define PA_SYMBOL_GET_DEPRECATE "pa__get_deprecated"
48 #define PA_SYMBOL_GET_VERSION "pa__get_version"
49
50 bool pa_module_exists(const char *name) {
51     const char *paths, *state = NULL;
52     char *n, *p, *pathname;
53     bool result;
54
55     pa_assert(name);
56
57     if (name[0] == PA_PATH_SEP_CHAR) {
58         result = access(name, F_OK) == 0 ? true : false;
59         pa_log_debug("Checking for existence of '%s': %s", name, result ? "success" : "failure");
60         if (result)
61             return true;
62     }
63
64     if (!(paths = lt_dlgetsearchpath()))
65         return false;
66
67     /* strip .so from the end of name, if present */
68     n = pa_xstrdup(name);
69     p = strrchr(n, '.');
70     if (p && pa_streq(p, PA_SOEXT))
71         p[0] = 0;
72
73     while ((p = pa_split(paths, ":", &state))) {
74         pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s" PA_SOEXT, p, n);
75         result = access(pathname, F_OK) == 0 ? true : false;
76         pa_log_debug("Checking for existence of '%s': %s", pathname, result ? "success" : "failure");
77         pa_xfree(pathname);
78         pa_xfree(p);
79         if (result) {
80             pa_xfree(n);
81             return true;
82         }
83     }
84
85     state = NULL;
86     if (PA_UNLIKELY(pa_run_from_build_tree())) {
87         while ((p = pa_split(paths, ":", &state))) {
88 #ifdef MESON_BUILD
89             pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "src" PA_PATH_SEP "modules" PA_PATH_SEP "%s" PA_SOEXT, p, n);
90 #else
91             pathname = pa_sprintf_malloc("%s" PA_PATH_SEP ".libs" PA_PATH_SEP "%s" PA_SOEXT, p, n);
92 #endif
93             result = access(pathname, F_OK) == 0 ? true : false;
94             pa_log_debug("Checking for existence of '%s': %s", pathname, result ? "success" : "failure");
95             pa_xfree(pathname);
96             pa_xfree(p);
97             if (result) {
98                 pa_xfree(n);
99                 return true;
100             }
101         }
102     }
103
104     pa_xfree(n);
105     return false;
106 }
107
108 void pa_module_hook_connect(pa_module *m, pa_hook *hook, pa_hook_priority_t prio, pa_hook_cb_t cb, void *data) {
109     pa_assert(m);
110     pa_assert(hook);
111     pa_assert(m->hooks);
112     pa_dynarray_append(m->hooks, pa_hook_connect(hook, prio, cb, data));
113 }
114
115 int pa_module_load(pa_module** module, pa_core *c, const char *name, const char *argument) {
116     pa_module *m = NULL;
117     const char *(*get_version)(void);
118     bool (*load_once)(void);
119     const char* (*get_deprecated)(void);
120     pa_modinfo *mi;
121     int errcode, rval;
122
123     pa_assert(module);
124     pa_assert(c);
125     pa_assert(name);
126
127     if (c->disallow_module_loading) {
128         errcode = -PA_ERR_ACCESS;
129         goto fail;
130     }
131
132     m = pa_xnew(pa_module, 1);
133     m->name = pa_xstrdup(name);
134     m->argument = pa_xstrdup(argument);
135     m->load_once = false;
136     m->proplist = pa_proplist_new();
137     m->hooks = pa_dynarray_new((pa_free_cb_t) pa_hook_slot_free);
138     m->index = PA_IDXSET_INVALID;
139
140     if (!(m->dl = lt_dlopenext(name))) {
141         /* We used to print the error that is returned by lt_dlerror(), but
142          * lt_dlerror() is useless. It returns pretty much always "file not
143          * found". That's because if there are any problems with loading the
144          * module with normal loaders, libltdl falls back to the "preload"
145          * loader, which never finds anything, and therefore says "file not
146          * found". */
147         pa_log("Failed to open module \"%s\".", name);
148         errcode = -PA_ERR_IO;
149         goto fail;
150     }
151
152     if ((get_version = (const char *(*)(void)) pa_load_sym(m->dl, name, PA_SYMBOL_GET_VERSION))) {
153         const char *version = get_version();
154
155         if (!pa_safe_streq(version, PACKAGE_VERSION)) {
156             pa_log("Module \"%s\" version (%s) doesn't match the expected version (%s).",
157                    name, pa_strnull(version), PACKAGE_VERSION);
158             errcode = -PA_ERR_IO;
159             goto fail;
160         }
161     } else {
162         pa_log("Symbol \"%s\" not found in module \"%s\".", PA_SYMBOL_GET_VERSION, name);
163         errcode = -PA_ERR_IO;
164         goto fail;
165     }
166
167     if ((load_once = (bool (*)(void)) pa_load_sym(m->dl, name, PA_SYMBOL_LOAD_ONCE))) {
168
169         m->load_once = load_once();
170
171         if (m->load_once) {
172             pa_module *i;
173             uint32_t idx;
174             /* OK, the module only wants to be loaded once, let's make sure it is */
175
176             PA_IDXSET_FOREACH(i, c->modules, idx) {
177                 if (pa_streq(name, i->name)) {
178                     pa_log("Module \"%s\" should be loaded once at most. Refusing to load.", name);
179                     errcode = -PA_ERR_EXIST;
180                     goto fail;
181                 }
182             }
183         }
184     }
185
186     if ((get_deprecated = (const char* (*) (void)) pa_load_sym(m->dl, name, PA_SYMBOL_GET_DEPRECATE))) {
187         const char *t;
188
189         if ((t = get_deprecated()))
190             pa_log_warn("%s is deprecated: %s", name, t);
191     }
192
193     if (!(m->init = (int (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_INIT))) {
194         pa_log("Failed to load module \"%s\": symbol \""PA_SYMBOL_INIT"\" not found.", name);
195         errcode = -PA_ERR_IO;
196         goto fail;
197     }
198
199     m->done = (void (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_DONE);
200     m->get_n_used = (int (*)(pa_module*_m)) pa_load_sym(m->dl, name, PA_SYMBOL_GET_N_USED);
201     m->userdata = NULL;
202     m->core = c;
203     m->unload_requested = false;
204
205     pa_assert_se(pa_idxset_put(c->modules, m, &m->index) >= 0);
206     pa_assert(m->index != PA_IDXSET_INVALID);
207
208     if ((rval = m->init(m)) < 0) {
209         if (rval == -PA_MODULE_ERR_SKIP) {
210             errcode = -PA_ERR_NOENTITY;
211             goto fail;
212         }
213         pa_log_error("Failed to load module \"%s\" (argument: \"%s\"): initialization failed.", name, argument ? argument : "");
214         errcode = -PA_ERR_IO;
215         goto fail;
216     }
217
218     pa_log_info("Loaded \"%s\" (index: #%u; argument: \"%s\").", m->name, m->index, m->argument ? m->argument : "");
219
220     pa_subscription_post(c, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_NEW, m->index);
221
222     if ((mi = pa_modinfo_get_by_handle(m->dl, name))) {
223
224         if (mi->author && !pa_proplist_contains(m->proplist, PA_PROP_MODULE_AUTHOR))
225             pa_proplist_sets(m->proplist, PA_PROP_MODULE_AUTHOR, mi->author);
226
227         if (mi->description && !pa_proplist_contains(m->proplist, PA_PROP_MODULE_DESCRIPTION))
228             pa_proplist_sets(m->proplist, PA_PROP_MODULE_DESCRIPTION, mi->description);
229
230         if (mi->version && !pa_proplist_contains(m->proplist, PA_PROP_MODULE_VERSION))
231             pa_proplist_sets(m->proplist, PA_PROP_MODULE_VERSION, mi->version);
232
233         pa_modinfo_free(mi);
234     }
235
236     pa_hook_fire(&m->core->hooks[PA_CORE_HOOK_MODULE_NEW], m);
237
238     *module = m;
239
240     return 0;
241
242 fail:
243
244     if (m) {
245         if (m->index != PA_IDXSET_INVALID)
246             pa_idxset_remove_by_index(c->modules, m->index);
247
248         if (m->hooks)
249             pa_dynarray_free(m->hooks);
250
251         if (m->proplist)
252             pa_proplist_free(m->proplist);
253
254         pa_xfree(m->argument);
255         pa_xfree(m->name);
256
257         if (m->dl)
258             lt_dlclose(m->dl);
259
260         pa_xfree(m);
261     }
262
263     *module = NULL;
264
265     return errcode;
266 }
267
268 static void postponed_dlclose(pa_mainloop_api *api, void *userdata) {
269     lt_dlhandle dl = userdata;
270
271     lt_dlclose(dl);
272 }
273
274 static void pa_module_free(pa_module *m) {
275     pa_assert(m);
276     pa_assert(m->core);
277
278     pa_log_info("Unloading \"%s\" (index: #%u).", m->name, m->index);
279     pa_hook_fire(&m->core->hooks[PA_CORE_HOOK_MODULE_UNLINK], m);
280
281     if (m->hooks) {
282        pa_dynarray_free(m->hooks);
283        m->hooks = NULL;
284     }
285
286     if (m->done)
287         m->done(m);
288
289     if (m->proplist)
290         pa_proplist_free(m->proplist);
291
292     /* If a module unloads itself with pa_module_unload(), we can't call
293      * lt_dlclose() here, because otherwise pa_module_unload() may return to a
294      * code location that has been removed from memory. Therefore, let's
295      * postpone the lt_dlclose() call a bit.
296      *
297      * Apparently lt_dlclose() doesn't always remove the module from memory,
298      * but it can happen, as can be seen here:
299      * https://bugs.freedesktop.org/show_bug.cgi?id=96831 */
300     pa_mainloop_api_once(m->core->mainloop, postponed_dlclose, m->dl);
301
302     pa_hashmap_remove(m->core->modules_pending_unload, m);
303
304     pa_log_info("Unloaded \"%s\" (index: #%u).", m->name, m->index);
305
306     pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_REMOVE, m->index);
307
308     pa_xfree(m->name);
309     pa_xfree(m->argument);
310     pa_xfree(m);
311 }
312
313 void pa_module_unload(pa_module *m, bool force) {
314     pa_assert(m);
315
316     if (m->core->disallow_module_loading && !force)
317         return;
318
319     if (!(m = pa_idxset_remove_by_data(m->core->modules, m, NULL)))
320         return;
321
322     pa_module_free(m);
323 }
324
325 void pa_module_unload_by_index(pa_core *c, uint32_t idx, bool force) {
326     pa_module *m;
327     pa_assert(c);
328     pa_assert(idx != PA_IDXSET_INVALID);
329
330     if (c->disallow_module_loading && !force)
331         return;
332
333     if (!(m = pa_idxset_remove_by_index(c->modules, idx)))
334         return;
335
336     pa_module_free(m);
337 }
338
339 void pa_module_unload_all(pa_core *c) {
340     pa_module *m;
341     uint32_t *indices;
342     uint32_t state;
343     int i;
344
345     pa_assert(c);
346     pa_assert(c->modules);
347
348     if (pa_idxset_isempty(c->modules))
349         return;
350
351     /* Unload modules in reverse order by default */
352     indices = pa_xnew(uint32_t, pa_idxset_size(c->modules));
353     i = 0;
354     PA_IDXSET_FOREACH(m, c->modules, state)
355         indices[i++] = state;
356     pa_assert(i == (int) pa_idxset_size(c->modules));
357     i--;
358     for (; i >= 0; i--) {
359         m = pa_idxset_remove_by_index(c->modules, indices[i]);
360         if (m)
361             pa_module_free(m);
362     }
363     pa_xfree(indices);
364
365     /* Just in case module unloading caused more modules to load */
366     PA_IDXSET_FOREACH(m, c->modules, state)
367         pa_log_warn("After module unload, module '%s' was still loaded!", m->name);
368     c->disallow_module_loading = 1;
369     pa_idxset_remove_all(c->modules, (pa_free_cb_t) pa_module_free);
370     pa_assert(pa_idxset_isempty(c->modules));
371
372     if (c->module_defer_unload_event) {
373         c->mainloop->defer_free(c->module_defer_unload_event);
374         c->module_defer_unload_event = NULL;
375     }
376     pa_assert(pa_hashmap_isempty(c->modules_pending_unload));
377 }
378
379 static void defer_cb(pa_mainloop_api*api, pa_defer_event *e, void *userdata) {
380     pa_core *c = PA_CORE(userdata);
381     pa_module *m;
382
383     pa_core_assert_ref(c);
384     api->defer_enable(e, 0);
385
386     while ((m = pa_hashmap_first(c->modules_pending_unload)))
387         pa_module_unload(m, true);
388 }
389
390 void pa_module_unload_request(pa_module *m, bool force) {
391     pa_assert(m);
392
393     if (m->core->disallow_module_loading && !force)
394         return;
395
396     m->unload_requested = true;
397     pa_hashmap_put(m->core->modules_pending_unload, m, m);
398
399     if (!m->core->module_defer_unload_event)
400         m->core->module_defer_unload_event = m->core->mainloop->defer_new(m->core->mainloop, defer_cb, m->core);
401
402     m->core->mainloop->defer_enable(m->core->module_defer_unload_event, 1);
403 }
404
405 void pa_module_unload_request_by_index(pa_core *c, uint32_t idx, bool force) {
406     pa_module *m;
407     pa_assert(c);
408
409     if (!(m = pa_idxset_get_by_index(c->modules, idx)))
410         return;
411
412     pa_module_unload_request(m, force);
413 }
414
415 int pa_module_get_n_used(pa_module*m) {
416     pa_assert(m);
417
418     if (!m->get_n_used)
419         return -1;
420
421     return m->get_n_used(m);
422 }
423
424 void pa_module_update_proplist(pa_module *m, pa_update_mode_t mode, pa_proplist *p) {
425     pa_assert(m);
426
427     if (p)
428         pa_proplist_update(m->proplist, mode, p);
429
430     pa_subscription_post(m->core, PA_SUBSCRIPTION_EVENT_MODULE|PA_SUBSCRIPTION_EVENT_CHANGE, m->index);
431     pa_hook_fire(&m->core->hooks[PA_CORE_HOOK_MODULE_PROPLIST_CHANGED], m);
432 }