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