• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #ifndef LOG_TAG
26 #define LOG_TAG "Core"
27 #endif
28 
29 #include <stdlib.h>
30 #include <stdio.h>
31 #include <signal.h>
32 
33 #include <pulse/rtclock.h>
34 #include <pulse/timeval.h>
35 #include <pulse/xmalloc.h>
36 
37 #include <pulsecore/module.h>
38 #include <pulsecore/core-rtclock.h>
39 #include <pulsecore/core-util.h>
40 #include <pulsecore/message-handler.h>
41 #include <pulsecore/core-scache.h>
42 #include <pulsecore/core-subscribe.h>
43 #include <pulsecore/random.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/macro.h>
46 #include <pulsecore/strbuf.h>
47 #include <pulsecore/namereg.h>
48 
49 #include "core.h"
50 
51 PA_DEFINE_PUBLIC_CLASS(pa_core, pa_msgobject);
52 
core_process_msg(pa_msgobject * o,int code,void * userdata,int64_t offset,pa_memchunk * chunk)53 static int core_process_msg(pa_msgobject *o, int code, void *userdata, int64_t offset, pa_memchunk *chunk) {
54     pa_core *c = PA_CORE(o);
55 
56     pa_core_assert_ref(c);
57 
58     switch (code) {
59 
60         case PA_CORE_MESSAGE_UNLOAD_MODULE:
61             pa_module_unload(userdata, true);
62             return 0;
63 
64         default:
65             return -1;
66     }
67 }
68 
69 static void core_free(pa_object *o);
70 
71 /* Returns a list of handlers. */
message_handler_list(pa_core * c)72 static char *message_handler_list(pa_core *c) {
73     pa_json_encoder *encoder;
74     void *state = NULL;
75     struct pa_message_handler *handler;
76 
77     encoder = pa_json_encoder_new();
78 
79     pa_json_encoder_begin_element_array(encoder);
80     PA_HASHMAP_FOREACH(handler, c->message_handlers, state) {
81         pa_json_encoder_begin_element_object(encoder);
82 
83         pa_json_encoder_add_member_string(encoder, "name", handler->object_path);
84         pa_json_encoder_add_member_string(encoder, "description", handler->description);
85 
86         pa_json_encoder_end_object(encoder);
87     }
88     pa_json_encoder_end_array(encoder);
89 
90     return pa_json_encoder_to_string_free(encoder);
91 }
92 
core_message_handler(const char * object_path,const char * message,const pa_json_object * parameters,char ** response,void * userdata)93 static int core_message_handler(const char *object_path, const char *message, const pa_json_object *parameters, char **response, void *userdata) {
94     pa_core *c = userdata;
95 
96     pa_assert(c);
97     pa_assert(message);
98     pa_assert(response);
99     pa_assert(pa_safe_streq(object_path, "/core"));
100 
101     if (pa_streq(message, "list-handlers")) {
102         *response = message_handler_list(c);
103         return PA_OK;
104     }
105 
106     return -PA_ERR_NOTIMPLEMENTED;
107 }
108 
pa_core_new(pa_mainloop_api * m,bool shared,bool enable_memfd,size_t shm_size)109 pa_core* pa_core_new(pa_mainloop_api *m, bool shared, bool enable_memfd, size_t shm_size) {
110     pa_log_info("start pa_core_new, shared: %d, enable_memfd: %d", shared, enable_memfd);
111     pa_core* c;
112     pa_mempool *pool;
113     pa_mem_type_t type;
114     int j;
115 
116     pa_assert(m);
117 
118     if (shared) {
119         type = (enable_memfd) ? PA_MEM_TYPE_SHARED_MEMFD : PA_MEM_TYPE_SHARED_POSIX;
120         if (!(pool = pa_mempool_new(type, shm_size, false))) {
121             pa_log_warn("Failed to allocate %s memory pool. Falling back to a normal memory pool.",
122                         pa_mem_type_to_string(type));
123             shared = false;
124         }
125     }
126 
127     if (!shared) {
128         if (!(pool = pa_mempool_new(PA_MEM_TYPE_PRIVATE, shm_size, false))) {
129             pa_log_error("pa_mempool_new() failed.");
130             return NULL;
131         }
132     }
133 
134     c = pa_msgobject_new(pa_core);
135     c->parent.parent.free = core_free;
136     c->parent.process_msg = core_process_msg;
137 
138     c->state = PA_CORE_STARTUP;
139     c->mainloop = m;
140 
141     c->clients = pa_idxset_new(NULL, NULL);
142     c->cards = pa_idxset_new(NULL, NULL);
143     c->sinks = pa_idxset_new(NULL, NULL);
144     c->sources = pa_idxset_new(NULL, NULL);
145     c->sink_inputs = pa_idxset_new(NULL, NULL);
146     c->source_outputs = pa_idxset_new(NULL, NULL);
147     c->modules = pa_idxset_new(NULL, NULL);
148     c->scache = pa_idxset_new(NULL, NULL);
149 
150     c->namereg = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
151     c->shared = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
152     c->message_handlers = pa_hashmap_new(pa_idxset_string_hash_func, pa_idxset_string_compare_func);
153 
154     pa_message_handler_register(c, "/core", "Core message handler", core_message_handler, (void *) c);
155 
156     c->default_source = NULL;
157     c->default_sink = NULL;
158     c->configured_default_source = NULL;
159     c->configured_default_sink = NULL;
160     c->policy_default_source = NULL;
161     c->policy_default_sink = NULL;
162 
163     c->default_sample_spec.format = PA_SAMPLE_S16NE;
164     c->default_sample_spec.rate = 44100;
165     c->default_sample_spec.channels = 2;
166     pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
167     c->default_n_fragments = 4;
168     c->default_fragment_size_msec = 25;
169 
170     c->deferred_volume_safety_margin_usec = 8000;
171     c->deferred_volume_extra_delay_usec = 0;
172 
173     c->module_defer_unload_event = NULL;
174     c->modules_pending_unload = pa_hashmap_new(NULL, NULL);
175 
176     c->subscription_defer_event = NULL;
177     PA_LLIST_HEAD_INIT(pa_subscription, c->subscriptions);
178     PA_LLIST_HEAD_INIT(pa_subscription_event, c->subscription_event_queue);
179     c->subscription_event_last = NULL;
180 
181     c->mempool = pool;
182     c->shm_size = shm_size;
183     pa_silence_cache_init(&c->silence_cache);
184 
185     c->exit_event = NULL;
186     c->scache_auto_unload_event = NULL;
187 
188     c->exit_idle_time = -1;
189     c->scache_idle_time = 20;
190 
191     c->flat_volumes = true;
192     c->disallow_module_loading = false;
193     c->disallow_exit = false;
194     c->running_as_daemon = false;
195     c->realtime_scheduling = false;
196     c->realtime_priority = 5;
197     c->disable_remixing = false;
198     c->remixing_use_all_sink_channels = true;
199     c->remixing_produce_lfe = false;
200     c->remixing_consume_lfe = false;
201     c->lfe_crossover_freq = 0;
202     c->deferred_volume = true;
203     c->resample_method = PA_RESAMPLER_SPEEX_FLOAT_BASE + 1;
204 
205     for (j = 0; j < PA_CORE_HOOK_MAX; j++)
206         pa_hook_init(&c->hooks[j], c);
207 
208     pa_random(&c->cookie, sizeof(c->cookie));
209 
210 #ifdef SIGPIPE
211     pa_check_signal_is_blocked(SIGPIPE);
212 #endif
213 
214     return c;
215 }
216 
core_free(pa_object * o)217 static void core_free(pa_object *o) {
218     pa_core *c = PA_CORE(o);
219     int j;
220     pa_assert(c);
221 
222     c->state = PA_CORE_SHUTDOWN;
223 
224     /* Note: All modules and samples in the cache should be unloaded before
225      * we get here */
226 
227     pa_assert(pa_idxset_isempty(c->scache));
228     pa_idxset_free(c->scache, NULL);
229 
230     pa_assert(pa_idxset_isempty(c->modules));
231     pa_idxset_free(c->modules, NULL);
232 
233     pa_assert(pa_idxset_isempty(c->clients));
234     pa_idxset_free(c->clients, NULL);
235 
236     pa_assert(pa_idxset_isempty(c->cards));
237     pa_idxset_free(c->cards, NULL);
238 
239     pa_assert(pa_idxset_isempty(c->sinks));
240     pa_idxset_free(c->sinks, NULL);
241 
242     pa_assert(pa_idxset_isempty(c->sources));
243     pa_idxset_free(c->sources, NULL);
244 
245     pa_assert(pa_idxset_isempty(c->source_outputs));
246     pa_idxset_free(c->source_outputs, NULL);
247 
248     pa_assert(pa_idxset_isempty(c->sink_inputs));
249     pa_idxset_free(c->sink_inputs, NULL);
250 
251     pa_assert(pa_hashmap_isempty(c->namereg));
252     pa_hashmap_free(c->namereg);
253 
254     pa_assert(pa_hashmap_isempty(c->shared));
255     pa_hashmap_free(c->shared);
256 
257     pa_message_handler_unregister(c, "/core");
258 
259     pa_assert(pa_hashmap_isempty(c->message_handlers));
260     pa_hashmap_free(c->message_handlers);
261 
262     pa_assert(pa_hashmap_isempty(c->modules_pending_unload));
263     pa_hashmap_free(c->modules_pending_unload);
264 
265     pa_subscription_free_all(c);
266 
267     if (c->exit_event)
268         c->mainloop->time_free(c->exit_event);
269 
270     pa_assert(!c->default_source);
271     pa_assert(!c->default_sink);
272     pa_xfree(c->configured_default_source);
273     pa_xfree(c->configured_default_sink);
274     pa_xfree(c->policy_default_source);
275     pa_xfree(c->policy_default_sink);
276 
277     pa_silence_cache_done(&c->silence_cache);
278     pa_mempool_unref(c->mempool);
279 
280     for (j = 0; j < PA_CORE_HOOK_MAX; j++)
281         pa_hook_done(&c->hooks[j]);
282 
283     pa_xfree(c);
284 }
285 
is_sink_available(pa_core * core,const char * sink_name)286 static bool is_sink_available(pa_core *core, const char *sink_name) {
287     pa_sink *sink;
288 
289     if (!(sink = pa_namereg_get(core, sink_name, PA_NAMEREG_SINK)))
290         return false;
291 
292     if (!PA_SINK_IS_LINKED(sink->state))
293         return false;
294 
295     if (sink->active_port && sink->active_port->available == PA_AVAILABLE_NO)
296         return false;
297 
298     return true;
299 }
300 
is_source_available(pa_core * core,const char * source_name)301 static bool is_source_available(pa_core *core, const char *source_name) {
302     pa_source *source;
303 
304     if (!(source = pa_namereg_get(core, source_name, PA_NAMEREG_SOURCE)))
305         return false;
306 
307     if (!PA_SOURCE_IS_LINKED(source->state))
308         return false;
309 
310     if (source->active_port && source->active_port->available == PA_AVAILABLE_NO)
311         return false;
312 
313     return true;
314 }
315 
pa_core_set_configured_default_sink(pa_core * core,const char * sink)316 void pa_core_set_configured_default_sink(pa_core *core, const char *sink) {
317     char *old_sink;
318 
319     pa_assert(core);
320 
321     old_sink = pa_xstrdup(core->configured_default_sink);
322 
323     /* The default sink was overwritten by the policy default sink, but the user is
324      * now setting a new default manually. Clear the policy default sink. */
325     if (core->policy_default_sink && is_sink_available(core, core->policy_default_sink)) {
326         pa_xfree(core->policy_default_sink);
327         core->policy_default_sink = NULL;
328 
329     } else if (pa_safe_streq(sink, old_sink))
330         goto finish;
331 
332     pa_xfree(core->configured_default_sink);
333     core->configured_default_sink = pa_xstrdup(sink);
334     if (!pa_safe_streq(sink, old_sink)) {
335         pa_log_info("configured_default_sink: %s -> %s",
336                     old_sink ? old_sink : "(unset)", sink ? sink : "(unset)");
337     }
338     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
339 
340     pa_core_update_default_sink(core);
341 
342 finish:
343     pa_xfree(old_sink);
344 }
345 
pa_core_set_configured_default_source(pa_core * core,const char * source)346 void pa_core_set_configured_default_source(pa_core *core, const char *source) {
347     char *old_source;
348 
349     pa_assert(core);
350 
351     old_source = pa_xstrdup(core->configured_default_source);
352 
353     /* The default source was overwritten by the policy default source, but the user is
354      * now setting a new default manually. Clear the policy default source. */
355     if (core->policy_default_source && is_source_available(core, core->policy_default_source)) {
356         pa_xfree(core->policy_default_source);
357         core->policy_default_source = NULL;
358 
359     } else if (pa_safe_streq(source, old_source))
360         goto finish;
361 
362     pa_xfree(core->configured_default_source);
363     core->configured_default_source = pa_xstrdup(source);
364     if (!pa_safe_streq(source, old_source)) {
365         pa_log_info("configured_default_source: %s -> %s",
366                     old_source ? old_source : "(unset)", source ? source : "(unset)");
367     }
368     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
369 
370     pa_core_update_default_source(core);
371 
372 finish:
373     pa_xfree(old_source);
374 }
375 
pa_core_set_policy_default_sink(pa_core * core,const char * sink)376 void pa_core_set_policy_default_sink(pa_core *core, const char *sink) {
377     char *old_sink;
378 
379     pa_assert(core);
380 
381     old_sink = pa_xstrdup(core->policy_default_sink);
382 
383     if (pa_safe_streq(sink, old_sink))
384         goto finish;
385 
386     pa_xfree(core->policy_default_sink);
387     core->policy_default_sink = pa_xstrdup(sink);
388     pa_log_info("policy_default_sink: %s -> %s",
389                 old_sink ? old_sink : "(unset)", sink ? sink : "(unset)");
390     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
391 
392     pa_core_update_default_sink(core);
393 
394 finish:
395     pa_xfree(old_sink);
396 }
397 
pa_core_set_policy_default_source(pa_core * core,const char * source)398 void pa_core_set_policy_default_source(pa_core *core, const char *source) {
399     char *old_source;
400 
401     pa_assert(core);
402 
403     old_source = pa_xstrdup(core->policy_default_source);
404 
405     if (pa_safe_streq(source, old_source))
406         goto finish;
407 
408     pa_xfree(core->policy_default_source);
409     core->policy_default_source = pa_xstrdup(source);
410     pa_log_info("policy_default_source: %s -> %s",
411                 old_source ? old_source : "(unset)", source ? source : "(unset)");
412     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
413 
414     pa_core_update_default_source(core);
415 
416 finish:
417     pa_xfree(old_source);
418 }
419 
420 /* a  < b  ->  return -1
421  * a == b  ->  return  0
422  * a  > b  ->  return  1 */
compare_sinks(pa_sink * a,pa_sink * b)423 static int compare_sinks(pa_sink *a, pa_sink *b) {
424     pa_core *core;
425 
426     core = a->core;
427 
428     /* Available sinks always beat unavailable sinks. */
429     if (a->active_port && a->active_port->available == PA_AVAILABLE_NO
430             && (!b->active_port || b->active_port->available != PA_AVAILABLE_NO))
431         return -1;
432     if (b->active_port && b->active_port->available == PA_AVAILABLE_NO
433             && (!a->active_port || a->active_port->available != PA_AVAILABLE_NO))
434         return 1;
435 
436     /* The policy default sink is preferred over any other sink. */
437     if (pa_safe_streq(b->name, core->policy_default_sink))
438         return -1;
439     if (pa_safe_streq(a->name, core->policy_default_sink))
440         return 1;
441 
442     /* The configured default sink is preferred over any other sink
443      * except the policy default sink. */
444     if (pa_safe_streq(b->name, core->configured_default_sink))
445         return -1;
446     if (pa_safe_streq(a->name, core->configured_default_sink))
447         return 1;
448 
449     if (a->priority < b->priority)
450         return -1;
451     if (a->priority > b->priority)
452         return 1;
453 
454     /* It's hard to find any difference between these sinks, but maybe one of
455      * them is already the default sink? If so, it's best to keep it as the
456      * default to avoid changing the routing for no good reason. */
457     if (b == core->default_sink)
458         return -1;
459     if (a == core->default_sink)
460         return 1;
461 
462     return 0;
463 }
464 
pa_core_update_default_sink(pa_core * core)465 void pa_core_update_default_sink(pa_core *core) {
466     pa_sink *best = NULL;
467     pa_sink *sink;
468     uint32_t idx;
469     pa_sink *old_default_sink;
470 
471     pa_assert(core);
472 
473     PA_IDXSET_FOREACH(sink, core->sinks, idx) {
474         if (!PA_SINK_IS_LINKED(sink->state))
475             continue;
476 
477         if (!best) {
478             best = sink;
479             continue;
480         }
481 
482         if (compare_sinks(sink, best) > 0)
483             best = sink;
484     }
485 
486     old_default_sink = core->default_sink;
487 
488     if (best == old_default_sink)
489         return;
490 
491     core->default_sink = best;
492     pa_log_info("default_sink: %s -> %s",
493                 old_default_sink ? old_default_sink->name : "(unset)", best ? best->name : "(unset)");
494 
495     /* If the default sink changed, it may be that the default source has to be
496      * changed too, because monitor sources are prioritized partly based on the
497      * priorities of the monitored sinks. */
498     pa_core_update_default_source(core);
499 
500     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
501     pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SINK_CHANGED], core->default_sink);
502 
503     /* try to move the streams from old_default_sink to the new default_sink conditionally */
504     if (old_default_sink)
505         pa_sink_move_streams_to_default_sink(core, old_default_sink, true);
506 }
507 
508 /* a  < b  ->  return -1
509  * a == b  ->  return  0
510  * a  > b  ->  return  1 */
compare_sources(pa_source * a,pa_source * b)511 static int compare_sources(pa_source *a, pa_source *b) {
512     pa_core *core;
513 
514     core = a->core;
515 
516     /* Available sources always beat unavailable sources. */
517     if (a->active_port && a->active_port->available == PA_AVAILABLE_NO
518             && (!b->active_port || b->active_port->available != PA_AVAILABLE_NO))
519         return -1;
520     if (b->active_port && b->active_port->available == PA_AVAILABLE_NO
521             && (!a->active_port || a->active_port->available != PA_AVAILABLE_NO))
522         return 1;
523 
524     /* The policy default source is preferred over any other source. */
525     if (pa_safe_streq(b->name, core->policy_default_source))
526         return -1;
527     if (pa_safe_streq(a->name, core->policy_default_source))
528         return 1;
529 
530     /* The configured default source is preferred over any other source
531      * except the policy default source. */
532     if (pa_safe_streq(b->name, core->configured_default_source))
533         return -1;
534     if (pa_safe_streq(a->name, core->configured_default_source))
535         return 1;
536 
537     /* Monitor sources lose to non-monitor sources. */
538     if (a->monitor_of && !b->monitor_of)
539         return -1;
540     if (!a->monitor_of && b->monitor_of)
541         return 1;
542 
543     if (a->priority < b->priority)
544         return -1;
545     if (a->priority > b->priority)
546         return 1;
547 
548     /* If the sources are monitors, we can compare the monitored sinks. */
549     if (a->monitor_of)
550         return compare_sinks(a->monitor_of, b->monitor_of);
551 
552     /* It's hard to find any difference between these sources, but maybe one of
553      * them is already the default source? If so, it's best to keep it as the
554      * default to avoid changing the routing for no good reason. */
555     if (b == core->default_source)
556         return -1;
557     if (a == core->default_source)
558         return 1;
559 
560     return 0;
561 }
562 
pa_core_update_default_source(pa_core * core)563 void pa_core_update_default_source(pa_core *core) {
564     pa_source *best = NULL;
565     pa_source *source;
566     uint32_t idx;
567     pa_source *old_default_source;
568 
569     pa_assert(core);
570 
571     PA_IDXSET_FOREACH(source, core->sources, idx) {
572         if (!PA_SOURCE_IS_LINKED(source->state))
573             continue;
574 
575         if (!best) {
576             best = source;
577             continue;
578         }
579 
580         if (compare_sources(source, best) > 0)
581             best = source;
582     }
583 
584     old_default_source = core->default_source;
585 
586     if (best == old_default_source)
587         return;
588 
589     core->default_source = best;
590     pa_log_info("default_source: %s -> %s",
591                 old_default_source ? old_default_source->name : "(unset)", best ? best->name : "(unset)");
592     pa_subscription_post(core, PA_SUBSCRIPTION_EVENT_SERVER | PA_SUBSCRIPTION_EVENT_CHANGE, PA_INVALID_INDEX);
593     pa_hook_fire(&core->hooks[PA_CORE_HOOK_DEFAULT_SOURCE_CHANGED], core->default_source);
594 
595     /* try to move the streams from old_default_source to the new default_source conditionally */
596     if (old_default_source)
597 	pa_source_move_streams_to_default_source(core, old_default_source, true);
598 }
599 
pa_core_set_exit_idle_time(pa_core * core,int time)600 void pa_core_set_exit_idle_time(pa_core *core, int time) {
601     pa_assert(core);
602 
603     if (time == core->exit_idle_time)
604         return;
605 
606     pa_log_info("exit_idle_time: %i -> %i", core->exit_idle_time, time);
607     core->exit_idle_time = time;
608 }
609 
exit_callback(pa_mainloop_api * m,pa_time_event * e,const struct timeval * t,void * userdata)610 static void exit_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
611     pa_core *c = userdata;
612     pa_assert(c->exit_event == e);
613 
614     pa_log_info("We are idle, quitting...");
615     pa_core_exit(c, true, 0);
616 }
617 
pa_core_check_idle(pa_core * c)618 void pa_core_check_idle(pa_core *c) {
619     pa_assert(c);
620 
621     if (!c->exit_event &&
622         c->exit_idle_time >= 0 &&
623         pa_idxset_size(c->clients) == 0) {
624 
625         c->exit_event = pa_core_rttime_new(c, pa_rtclock_now() + c->exit_idle_time * PA_USEC_PER_SEC, exit_callback, c);
626 
627     } else if (c->exit_event && pa_idxset_size(c->clients) > 0) {
628         c->mainloop->time_free(c->exit_event);
629         c->exit_event = NULL;
630     }
631 }
632 
pa_core_exit(pa_core * c,bool force,int retval)633 int pa_core_exit(pa_core *c, bool force, int retval) {
634     pa_assert(c);
635 
636     if (c->disallow_exit && !force)
637         return -1;
638 
639     c->mainloop->quit(c->mainloop, retval);
640     return 0;
641 }
642 
pa_core_maybe_vacuum(pa_core * c)643 void pa_core_maybe_vacuum(pa_core *c) {
644     pa_assert(c);
645 
646     if (pa_idxset_isempty(c->sink_inputs) && pa_idxset_isempty(c->source_outputs)) {
647         pa_log_debug("Hmm, no streams around, trying to vacuum.");
648     } else {
649         pa_sink *si;
650         pa_source *so;
651         uint32_t idx;
652 
653         idx = 0;
654         PA_IDXSET_FOREACH(si, c->sinks, idx)
655             if (si->state != PA_SINK_SUSPENDED)
656                 return;
657 
658         idx = 0;
659         PA_IDXSET_FOREACH(so, c->sources, idx)
660             if (so->state != PA_SOURCE_SUSPENDED)
661                 return;
662 
663         pa_log_info("All sinks and sources are suspended, vacuuming memory");
664     }
665 
666     pa_mempool_vacuum(c->mempool);
667 }
668 
pa_core_rttime_new(pa_core * c,pa_usec_t usec,pa_time_event_cb_t cb,void * userdata)669 pa_time_event* pa_core_rttime_new(pa_core *c, pa_usec_t usec, pa_time_event_cb_t cb, void *userdata) {
670     struct timeval tv;
671 
672     pa_assert(c);
673     pa_assert(c->mainloop);
674 
675     return c->mainloop->time_new(c->mainloop, pa_timeval_rtstore(&tv, usec, true), cb, userdata);
676 }
677 
pa_core_rttime_restart(pa_core * c,pa_time_event * e,pa_usec_t usec)678 void pa_core_rttime_restart(pa_core *c, pa_time_event *e, pa_usec_t usec) {
679     struct timeval tv;
680 
681     pa_assert(c);
682     pa_assert(c->mainloop);
683 
684     c->mainloop->time_restart(e, pa_timeval_rtstore(&tv, usec, true));
685 }
686 
pa_core_move_streams_to_newly_available_preferred_sink(pa_core * c,pa_sink * s)687 void pa_core_move_streams_to_newly_available_preferred_sink(pa_core *c, pa_sink *s) {
688     pa_sink_input *si;
689     uint32_t idx;
690 
691     pa_assert(c);
692     pa_assert(s);
693 
694     PA_IDXSET_FOREACH(si, c->sink_inputs, idx) {
695         if (si->sink == s)
696             continue;
697 
698         if (!si->sink)
699             continue;
700 
701         /* Skip this sink input if it is connecting a filter sink to
702          * the master */
703         if (si->origin_sink)
704             continue;
705 
706         /* It might happen that a stream and a sink are set up at the
707            same time, in which case we want to make sure we don't
708            interfere with that */
709         if (!PA_SINK_INPUT_IS_LINKED(si->state))
710             continue;
711 
712         if (pa_safe_streq(si->preferred_sink, s->name))
713             pa_sink_input_move_to(si, s, false);
714     }
715 
716 }
717 
pa_core_move_streams_to_newly_available_preferred_source(pa_core * c,pa_source * s)718 void pa_core_move_streams_to_newly_available_preferred_source(pa_core *c, pa_source *s) {
719     pa_source_output *so;
720     uint32_t idx;
721 
722     pa_assert(c);
723     pa_assert(s);
724 
725     PA_IDXSET_FOREACH(so, c->source_outputs, idx) {
726         if (so->source == s)
727             continue;
728 
729         if (so->direct_on_input)
730             continue;
731 
732         if (!so->source)
733             continue;
734 
735         /* Skip this source output if it is connecting a filter source to
736          * the master */
737         if (so->destination_source)
738             continue;
739 
740         /* It might happen that a stream and a source are set up at the
741            same time, in which case we want to make sure we don't
742            interfere with that */
743         if (!PA_SOURCE_OUTPUT_IS_LINKED(so->state))
744             continue;
745 
746         if (pa_safe_streq(so->preferred_source, s->name))
747             pa_source_output_move_to(so, s, false);
748     }
749 
750 }
751 
752 
753 /* Helper macro to reduce repetition in pa_suspend_cause_to_string().
754  * Parameters:
755  *   char *p: the current position in the write buffer
756  *   bool first: is cause_to_check the first cause to be written?
757  *   pa_suspend_cause_t cause_bitfield: the causes given to pa_suspend_cause_to_string()
758  *   pa_suspend_cause_t cause_to_check: the cause whose presence in cause_bitfield is to be checked
759  */
760 #define CHECK_CAUSE(p, first, cause_bitfield, cause_to_check) \
761     if (cause_bitfield & PA_SUSPEND_##cause_to_check) {       \
762         size_t len = sizeof(#cause_to_check) - 1;             \
763         if (!first) {                                         \
764             *p = '|';                                         \
765             p++;                                              \
766         }                                                     \
767         first = false;                                        \
768         memcpy(p, #cause_to_check, len);                      \
769         p += len;                                             \
770     }
771 
pa_suspend_cause_to_string(pa_suspend_cause_t cause_bitfield,char buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE])772 const char *pa_suspend_cause_to_string(pa_suspend_cause_t cause_bitfield, char buf[PA_SUSPEND_CAUSE_TO_STRING_BUF_SIZE]) {
773     char *p = buf;
774     bool first = true;
775 
776     CHECK_CAUSE(p, first, cause_bitfield, USER);
777     CHECK_CAUSE(p, first, cause_bitfield, APPLICATION);
778     CHECK_CAUSE(p, first, cause_bitfield, IDLE);
779     CHECK_CAUSE(p, first, cause_bitfield, SESSION);
780     CHECK_CAUSE(p, first, cause_bitfield, PASSTHROUGH);
781     CHECK_CAUSE(p, first, cause_bitfield, INTERNAL);
782     CHECK_CAUSE(p, first, cause_bitfield, UNAVAILABLE);
783 
784     if (p == buf) {
785         memcpy(p, "(none)", 6);
786         p += 6;
787     }
788 
789     *p = 0;
790 
791     return buf;
792 }