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 }