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 <errno.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <unistd.h>
29 #include <fcntl.h>
30 #include <sys/stat.h>
31
32 #ifdef HAVE_SCHED_H
33 #include <sched.h>
34 #endif
35
36 #include <pulse/xmalloc.h>
37 #include <pulse/timeval.h>
38 #include <pulse/version.h>
39
40 #include <pulsecore/core-error.h>
41 #include <pulsecore/core-util.h>
42 #include <pulsecore/i18n.h>
43 #include <pulsecore/strbuf.h>
44 #include <pulsecore/conf-parser.h>
45 #include <pulsecore/resampler.h>
46 #include <pulsecore/macro.h>
47
48 #include "daemon-conf.h"
49
50 #define DEFAULT_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "default.pa"
51 #define DEFAULT_SCRIPT_FILE_USER PA_PATH_SEP "default.pa"
52 #define DEFAULT_SYSTEM_SCRIPT_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "system.pa"
53
54 #define DEFAULT_CONFIG_FILE PA_DEFAULT_CONFIG_DIR PA_PATH_SEP "daemon.conf"
55 #define DEFAULT_CONFIG_FILE_USER PA_PATH_SEP "daemon.conf"
56
57 #define ENV_SCRIPT_FILE "PULSE_SCRIPT"
58 #define ENV_CONFIG_FILE "PULSE_CONFIG"
59 #define ENV_DL_SEARCH_PATH "PULSE_DLPATH"
60
61 static const pa_daemon_conf default_conf = {
62 .cmd = PA_CMD_DAEMON,
63 .daemonize = false,
64 .fail = true,
65 .high_priority = true,
66 .nice_level = -11,
67 .realtime_scheduling = true,
68 .realtime_priority = 5, /* Half of JACK's default rtprio */
69 .disallow_module_loading = false,
70 .disallow_exit = false,
71 .flat_volumes = false,
72 .rescue_streams = true,
73 .exit_idle_time = 20,
74 .scache_idle_time = 20,
75 .script_commands = NULL,
76 .dl_search_path = NULL,
77 .load_default_script_file = true,
78 .default_script_file = NULL,
79 .log_target = NULL,
80 .log_level = PA_LOG_NOTICE,
81 .log_backtrace = 0,
82 .log_meta = false,
83 .log_time = false,
84 .resample_method = PA_RESAMPLER_AUTO,
85 .avoid_resampling = false,
86 .disable_remixing = false,
87 .remixing_use_all_sink_channels = true,
88 .remixing_produce_lfe = false,
89 .remixing_consume_lfe = false,
90 .lfe_crossover_freq = 0,
91 .config_file = NULL,
92 .use_pid_file = true,
93 .system_instance = false,
94 #ifdef HAVE_DBUS
95 .local_server_type = PA_SERVER_TYPE_UNSET, /* The actual default is _USER, but we have to detect when the user doesn't specify this option. */
96 #endif
97 .no_cpu_limit = true,
98 .disable_shm = false,
99 .disable_memfd = false,
100 .lock_memory = false,
101 .deferred_volume = true,
102 .default_n_fragments = 4,
103 .default_fragment_size_msec = 25,
104 .deferred_volume_safety_margin_usec = 8000,
105 .deferred_volume_extra_delay_usec = 0,
106 .default_sample_spec = { .format = PA_SAMPLE_S16NE, .rate = 44100, .channels = 2 },
107 .alternate_sample_rate = 48000,
108 .default_channel_map = { .channels = 2, .map = { PA_CHANNEL_POSITION_LEFT, PA_CHANNEL_POSITION_RIGHT } },
109 .shm_size = 0
110 #ifdef HAVE_SYS_RESOURCE_H
111 ,.rlimit_fsize = { .value = 0, .is_set = false },
112 .rlimit_data = { .value = 0, .is_set = false },
113 .rlimit_stack = { .value = 0, .is_set = false },
114 .rlimit_core = { .value = 0, .is_set = false }
115 #ifdef RLIMIT_RSS
116 ,.rlimit_rss = { .value = 0, .is_set = false }
117 #endif
118 #ifdef RLIMIT_NPROC
119 ,.rlimit_nproc = { .value = 0, .is_set = false }
120 #endif
121 #ifdef RLIMIT_NOFILE
122 ,.rlimit_nofile = { .value = 256, .is_set = true }
123 #endif
124 #ifdef RLIMIT_MEMLOCK
125 ,.rlimit_memlock = { .value = 0, .is_set = false }
126 #endif
127 #ifdef RLIMIT_AS
128 ,.rlimit_as = { .value = 0, .is_set = false }
129 #endif
130 #ifdef RLIMIT_LOCKS
131 ,.rlimit_locks = { .value = 0, .is_set = false }
132 #endif
133 #ifdef RLIMIT_SIGPENDING
134 ,.rlimit_sigpending = { .value = 0, .is_set = false }
135 #endif
136 #ifdef RLIMIT_MSGQUEUE
137 ,.rlimit_msgqueue = { .value = 0, .is_set = false }
138 #endif
139 #ifdef RLIMIT_NICE
140 ,.rlimit_nice = { .value = 31, .is_set = true } /* nice level of -11 */
141 #endif
142 #ifdef RLIMIT_RTPRIO
143 ,.rlimit_rtprio = { .value = 9, .is_set = true } /* One below JACK's default for the server */
144 #endif
145 #ifdef RLIMIT_RTTIME
146 ,.rlimit_rttime = { .value = 200*PA_USEC_PER_MSEC, .is_set = true } /* rtkit's limit is 200 ms */
147 #endif
148 #endif
149 };
150
pa_daemon_conf_new(void)151 pa_daemon_conf *pa_daemon_conf_new(void) {
152 pa_daemon_conf *c;
153
154 c = pa_xnewdup(pa_daemon_conf, &default_conf, 1);
155
156 #ifdef OS_IS_WIN32
157 c->dl_search_path = pa_sprintf_malloc("%s" PA_PATH_SEP "lib" PA_PATH_SEP "pulse-%d.%d" PA_PATH_SEP "modules",
158 pa_win32_get_toplevel(NULL), PA_MAJOR, PA_MINOR);
159 #else
160 #ifdef HAVE_RUNNING_FROM_BUILD_TREE
161 if (pa_run_from_build_tree()) {
162 pa_log_notice("Detected that we are run from the build tree, fixing search path.");
163 #ifdef MESON_BUILD
164 c->dl_search_path = pa_xstrdup(PA_BUILDDIR PA_PATH_SEP "src" PA_PATH_SEP "modules");
165 #else
166 c->dl_search_path = pa_xstrdup(PA_BUILDDIR);
167 #endif // Endof #ifdef MESON_BUILD
168 } else
169 #endif // Endof #ifdef HAVE_RUNNING_FROM_BUILD_TREE
170 c->dl_search_path = pa_xstrdup(PA_DLSEARCHPATH);
171 #endif // Endof #ifdef OS_IS_WIN32
172
173 return c;
174 }
175
pa_daemon_conf_free(pa_daemon_conf *c)176 void pa_daemon_conf_free(pa_daemon_conf *c) {
177 pa_assert(c);
178
179 pa_xfree(c->script_commands);
180 pa_xfree(c->dl_search_path);
181 pa_xfree(c->default_script_file);
182
183 if (c->log_target)
184 pa_log_target_free(c->log_target);
185
186 pa_xfree(c->config_file);
187 pa_xfree(c);
188 }
189
pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string)190 int pa_daemon_conf_set_log_target(pa_daemon_conf *c, const char *string) {
191 pa_log_target *log_target = NULL;
192
193 pa_assert(c);
194 pa_assert(string);
195
196 if (!pa_streq(string, "auto")) {
197 log_target = pa_log_parse_target(string);
198
199 if (!log_target)
200 return -1;
201 }
202
203 c->log_target = log_target;
204
205 return 0;
206 }
207
pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string)208 int pa_daemon_conf_set_log_level(pa_daemon_conf *c, const char *string) {
209 uint32_t u;
210 pa_assert(c);
211 pa_assert(string);
212
213 if (pa_atou(string, &u) >= 0) {
214 if (u >= PA_LOG_LEVEL_MAX)
215 return -1;
216
217 c->log_level = (pa_log_level_t) u;
218 } else if (pa_startswith(string, "debug"))
219 c->log_level = PA_LOG_DEBUG;
220 else if (pa_startswith(string, "info"))
221 c->log_level = PA_LOG_INFO;
222 else if (pa_startswith(string, "notice"))
223 c->log_level = PA_LOG_NOTICE;
224 else if (pa_startswith(string, "warn"))
225 c->log_level = PA_LOG_WARN;
226 else if (pa_startswith(string, "err"))
227 c->log_level = PA_LOG_ERROR;
228 else
229 return -1;
230
231 return 0;
232 }
233
pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string)234 int pa_daemon_conf_set_resample_method(pa_daemon_conf *c, const char *string) {
235 int m;
236 pa_assert(c);
237 pa_assert(string);
238
239 if ((m = pa_parse_resample_method(string)) < 0)
240 return -1;
241
242 c->resample_method = m;
243 return 0;
244 }
245
pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string)246 int pa_daemon_conf_set_local_server_type(pa_daemon_conf *c, const char *string) {
247 pa_assert(c);
248 pa_assert(string);
249
250 if (pa_streq(string, "user"))
251 c->local_server_type = PA_SERVER_TYPE_USER;
252 else if (pa_streq(string, "system")) {
253 c->local_server_type = PA_SERVER_TYPE_SYSTEM;
254 } else if (pa_streq(string, "none")) {
255 c->local_server_type = PA_SERVER_TYPE_NONE;
256 } else
257 return -1;
258
259 return 0;
260 }
261
parse_log_target(pa_config_parser_state *state)262 static int parse_log_target(pa_config_parser_state *state) {
263 pa_daemon_conf *c;
264
265 pa_assert(state);
266
267 c = state->data;
268
269 if (pa_daemon_conf_set_log_target(c, state->rvalue) < 0) {
270 pa_log(_("[%s:%u] Invalid log target '%s'."), state->filename, state->lineno, state->rvalue);
271 return -1;
272 }
273
274 return 0;
275 }
276
parse_log_level(pa_config_parser_state *state)277 static int parse_log_level(pa_config_parser_state *state) {
278 pa_daemon_conf *c;
279
280 pa_assert(state);
281
282 c = state->data;
283
284 if (pa_daemon_conf_set_log_level(c, state->rvalue) < 0) {
285 pa_log(_("[%s:%u] Invalid log level '%s'."), state->filename, state->lineno, state->rvalue);
286 return -1;
287 }
288
289 return 0;
290 }
291
parse_resample_method(pa_config_parser_state *state)292 static int parse_resample_method(pa_config_parser_state *state) {
293 pa_daemon_conf *c;
294
295 pa_assert(state);
296
297 c = state->data;
298
299 if (pa_daemon_conf_set_resample_method(c, state->rvalue) < 0) {
300 pa_log(_("[%s:%u] Invalid resample method '%s'."), state->filename, state->lineno, state->rvalue);
301 return -1;
302 }
303
304 return 0;
305 }
306
307 #ifdef HAVE_SYS_RESOURCE_H
parse_rlimit(pa_config_parser_state *state)308 static int parse_rlimit(pa_config_parser_state *state) {
309 struct pa_rlimit *r;
310
311 pa_assert(state);
312
313 r = state->data;
314
315 if (state->rvalue[strspn(state->rvalue, "\t ")] == 0) {
316 /* Empty string */
317 r->is_set = 0;
318 r->value = 0;
319 } else {
320 int32_t k;
321 if (pa_atoi(state->rvalue, &k) < 0) {
322 pa_log(_("[%s:%u] Invalid rlimit '%s'."), state->filename, state->lineno, state->rvalue);
323 return -1;
324 }
325 r->is_set = k >= 0;
326 r->value = k >= 0 ? (rlim_t) k : 0;
327 }
328
329 return 0;
330 }
331 #endif
332
parse_sample_format(pa_config_parser_state *state)333 static int parse_sample_format(pa_config_parser_state *state) {
334 pa_daemon_conf *c;
335 pa_sample_format_t f;
336
337 pa_assert(state);
338
339 c = state->data;
340
341 if ((f = pa_parse_sample_format(state->rvalue)) < 0) {
342 pa_log(_("[%s:%u] Invalid sample format '%s'."), state->filename, state->lineno, state->rvalue);
343 return -1;
344 }
345
346 c->default_sample_spec.format = f;
347 return 0;
348 }
349
parse_sample_rate(pa_config_parser_state *state)350 static int parse_sample_rate(pa_config_parser_state *state) {
351 pa_daemon_conf *c;
352 uint32_t r;
353
354 pa_assert(state);
355
356 c = state->data;
357
358 if (pa_atou(state->rvalue, &r) < 0 || !pa_sample_rate_valid(r)) {
359 pa_log(_("[%s:%u] Invalid sample rate '%s'."), state->filename, state->lineno, state->rvalue);
360 return -1;
361 }
362
363 c->default_sample_spec.rate = r;
364 return 0;
365 }
366
parse_alternate_sample_rate(pa_config_parser_state *state)367 static int parse_alternate_sample_rate(pa_config_parser_state *state) {
368 pa_daemon_conf *c;
369 uint32_t r;
370
371 pa_assert(state);
372
373 c = state->data;
374
375 if (pa_atou(state->rvalue, &r) < 0 || !pa_sample_rate_valid(r)) {
376 pa_log(_("[%s:%u] Invalid sample rate '%s'."), state->filename, state->lineno, state->rvalue);
377 return -1;
378 }
379
380 c->alternate_sample_rate = r;
381 return 0;
382 }
383
384 struct channel_conf_info {
385 pa_daemon_conf *conf;
386 bool default_sample_spec_set;
387 bool default_channel_map_set;
388 };
389
parse_sample_channels(pa_config_parser_state *state)390 static int parse_sample_channels(pa_config_parser_state *state) {
391 struct channel_conf_info *i;
392 int32_t n;
393
394 pa_assert(state);
395
396 i = state->data;
397
398 if (pa_atoi(state->rvalue, &n) < 0 || !pa_channels_valid(n)) {
399 pa_log(_("[%s:%u] Invalid sample channels '%s'."), state->filename, state->lineno, state->rvalue);
400 return -1;
401 }
402
403 i->conf->default_sample_spec.channels = (uint8_t) n;
404 i->default_sample_spec_set = true;
405 return 0;
406 }
407
parse_channel_map(pa_config_parser_state *state)408 static int parse_channel_map(pa_config_parser_state *state) {
409 struct channel_conf_info *i;
410
411 pa_assert(state);
412
413 i = state->data;
414
415 if (!pa_channel_map_parse(&i->conf->default_channel_map, state->rvalue)) {
416 pa_log(_("[%s:%u] Invalid channel map '%s'."), state->filename, state->lineno, state->rvalue);
417 return -1;
418 }
419
420 i->default_channel_map_set = true;
421 return 0;
422 }
423
parse_fragments(pa_config_parser_state *state)424 static int parse_fragments(pa_config_parser_state *state) {
425 pa_daemon_conf *c;
426 int32_t n;
427
428 pa_assert(state);
429
430 c = state->data;
431
432 if (pa_atoi(state->rvalue, &n) < 0 || n < 2) {
433 pa_log(_("[%s:%u] Invalid number of fragments '%s'."), state->filename, state->lineno, state->rvalue);
434 return -1;
435 }
436
437 c->default_n_fragments = (unsigned) n;
438 return 0;
439 }
440
parse_fragment_size_msec(pa_config_parser_state *state)441 static int parse_fragment_size_msec(pa_config_parser_state *state) {
442 pa_daemon_conf *c;
443 int32_t n;
444
445 pa_assert(state);
446
447 c = state->data;
448
449 if (pa_atoi(state->rvalue, &n) < 0 || n < 1) {
450 pa_log(_("[%s:%u] Invalid fragment size '%s'."), state->filename, state->lineno, state->rvalue);
451 return -1;
452 }
453
454 c->default_fragment_size_msec = (unsigned) n;
455 return 0;
456 }
457
parse_nice_level(pa_config_parser_state *state)458 static int parse_nice_level(pa_config_parser_state *state) {
459 pa_daemon_conf *c;
460 int32_t level;
461
462 pa_assert(state);
463
464 c = state->data;
465
466 if (pa_atoi(state->rvalue, &level) < 0 || level < -20 || level > 19) {
467 pa_log(_("[%s:%u] Invalid nice level '%s'."), state->filename, state->lineno, state->rvalue);
468 return -1;
469 }
470
471 c->nice_level = (int) level;
472 return 0;
473 }
474
parse_rtprio(pa_config_parser_state *state)475 static int parse_rtprio(pa_config_parser_state *state) {
476 #if !defined(OS_IS_WIN32) && defined(HAVE_SCHED_H)
477 pa_daemon_conf *c;
478 int32_t rtprio;
479 #endif
480
481 pa_assert(state);
482
483 #ifdef OS_IS_WIN32
484 pa_log("[%s:%u] Realtime priority not available on win32.", state->filename, state->lineno);
485 #else
486 # ifdef HAVE_SCHED_H
487 c = state->data;
488
489 if (pa_atoi(state->rvalue, &rtprio) < 0 || rtprio < sched_get_priority_min(SCHED_FIFO) || rtprio > sched_get_priority_max(SCHED_FIFO)) {
490 pa_log("[%s:%u] Invalid realtime priority '%s'.", state->filename, state->lineno, state->rvalue);
491 return -1;
492 }
493
494 c->realtime_priority = (int) rtprio;
495 # endif
496 #endif /* OS_IS_WIN32 */
497
498 return 0;
499 }
500
parse_disable_lfe_remix(pa_config_parser_state *state)501 static int parse_disable_lfe_remix(pa_config_parser_state *state) {
502 pa_daemon_conf *c;
503 int k;
504
505 pa_assert(state);
506 c = state->data;
507
508 if ((k = pa_parse_boolean(state->rvalue)) < 0) {
509 pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
510 return -1;
511 }
512
513 c->remixing_produce_lfe = c->remixing_consume_lfe = !k;
514
515 pa_log("[%s:%u] Deprecated option 'disable-lfe-remixing' found.", state->filename, state->lineno);
516 pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.",
517 state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe));
518
519 return 0;
520 }
521
parse_enable_lfe_remix(pa_config_parser_state *state)522 static int parse_enable_lfe_remix(pa_config_parser_state *state) {
523 pa_daemon_conf *c;
524 int k;
525
526 pa_assert(state);
527 c = state->data;
528
529 if ((k = pa_parse_boolean(state->rvalue)) < 0) {
530 pa_log("[%s:%u] Failed to parse boolean value: %s", state->filename, state->lineno, state->rvalue);
531 return -1;
532 }
533
534 c->remixing_produce_lfe = c->remixing_consume_lfe = k;
535
536 pa_log("[%s:%u] Deprecated option 'enable-lfe-remixing' found.", state->filename, state->lineno);
537 pa_log("[%s:%u] Please migrate to 'remixing-produce-lfe' and 'remixing-consume-lfe', set both to '%s'.",
538 state->filename, state->lineno, pa_yes_no(c->remixing_produce_lfe));
539
540 return 0;
541 }
542
543 #ifdef HAVE_DBUS
parse_server_type(pa_config_parser_state *state)544 static int parse_server_type(pa_config_parser_state *state) {
545 pa_daemon_conf *c;
546
547 pa_assert(state);
548
549 c = state->data;
550
551 if (pa_daemon_conf_set_local_server_type(c, state->rvalue) < 0) {
552 pa_log(_("[%s:%u] Invalid server type '%s'."), state->filename, state->lineno, state->rvalue);
553 return -1;
554 }
555
556 return 0;
557 }
558 #endif
559
pa_daemon_conf_load(pa_daemon_conf *c, const char *filename)560 int pa_daemon_conf_load(pa_daemon_conf *c, const char *filename) {
561 int r = -1;
562 FILE *f = NULL;
563 struct channel_conf_info ci;
564 pa_config_item table[] = {
565 { "daemonize", pa_config_parse_bool, &c->daemonize, NULL },
566 { "fail", pa_config_parse_bool, &c->fail, NULL },
567 { "high-priority", pa_config_parse_bool, &c->high_priority, NULL },
568 { "realtime-scheduling", pa_config_parse_bool, &c->realtime_scheduling, NULL },
569 { "disallow-module-loading", pa_config_parse_bool, &c->disallow_module_loading, NULL },
570 { "allow-module-loading", pa_config_parse_not_bool, &c->disallow_module_loading, NULL },
571 { "disallow-exit", pa_config_parse_bool, &c->disallow_exit, NULL },
572 { "allow-exit", pa_config_parse_not_bool, &c->disallow_exit, NULL },
573 { "use-pid-file", pa_config_parse_bool, &c->use_pid_file, NULL },
574 { "system-instance", pa_config_parse_bool, &c->system_instance, NULL },
575 #ifdef HAVE_DBUS
576 { "local-server-type", parse_server_type, c, NULL },
577 #endif
578 { "no-cpu-limit", pa_config_parse_bool, &c->no_cpu_limit, NULL },
579 { "cpu-limit", pa_config_parse_not_bool, &c->no_cpu_limit, NULL },
580 { "disable-shm", pa_config_parse_bool, &c->disable_shm, NULL },
581 { "enable-shm", pa_config_parse_not_bool, &c->disable_shm, NULL },
582 { "enable-memfd", pa_config_parse_not_bool, &c->disable_memfd, NULL },
583 { "flat-volumes", pa_config_parse_bool, &c->flat_volumes, NULL },
584 { "rescue-streams", pa_config_parse_bool, &c->rescue_streams, NULL },
585 { "lock-memory", pa_config_parse_bool, &c->lock_memory, NULL },
586 { "enable-deferred-volume", pa_config_parse_bool, &c->deferred_volume, NULL },
587 { "exit-idle-time", pa_config_parse_int, &c->exit_idle_time, NULL },
588 { "scache-idle-time", pa_config_parse_int, &c->scache_idle_time, NULL },
589 { "realtime-priority", parse_rtprio, c, NULL },
590 { "dl-search-path", pa_config_parse_string, &c->dl_search_path, NULL },
591 { "default-script-file", pa_config_parse_string, &c->default_script_file, NULL },
592 { "log-target", parse_log_target, c, NULL },
593 { "log-level", parse_log_level, c, NULL },
594 { "verbose", parse_log_level, c, NULL },
595 { "resample-method", parse_resample_method, c, NULL },
596 { "default-sample-format", parse_sample_format, c, NULL },
597 { "default-sample-rate", parse_sample_rate, c, NULL },
598 { "alternate-sample-rate", parse_alternate_sample_rate, c, NULL },
599 { "default-sample-channels", parse_sample_channels, &ci, NULL },
600 { "default-channel-map", parse_channel_map, &ci, NULL },
601 { "default-fragments", parse_fragments, c, NULL },
602 { "default-fragment-size-msec", parse_fragment_size_msec, c, NULL },
603 { "deferred-volume-safety-margin-usec",
604 pa_config_parse_unsigned, &c->deferred_volume_safety_margin_usec, NULL },
605 { "deferred-volume-extra-delay-usec",
606 pa_config_parse_int, &c->deferred_volume_extra_delay_usec, NULL },
607 { "nice-level", parse_nice_level, c, NULL },
608 { "avoid-resampling", pa_config_parse_bool, &c->avoid_resampling, NULL },
609 { "disable-remixing", pa_config_parse_bool, &c->disable_remixing, NULL },
610 { "enable-remixing", pa_config_parse_not_bool, &c->disable_remixing, NULL },
611 { "remixing-use-all-sink-channels",
612 pa_config_parse_bool, &c->remixing_use_all_sink_channels, NULL },
613 { "disable-lfe-remixing", parse_disable_lfe_remix, c, NULL },
614 { "enable-lfe-remixing", parse_enable_lfe_remix, c, NULL },
615 { "remixing-produce-lfe", pa_config_parse_bool, &c->remixing_produce_lfe, NULL },
616 { "remixing-consume-lfe", pa_config_parse_bool, &c->remixing_consume_lfe, NULL },
617 { "lfe-crossover-freq", pa_config_parse_unsigned, &c->lfe_crossover_freq, NULL },
618 { "load-default-script-file", pa_config_parse_bool, &c->load_default_script_file, NULL },
619 { "shm-size-bytes", pa_config_parse_size, &c->shm_size, NULL },
620 { "log-meta", pa_config_parse_bool, &c->log_meta, NULL },
621 { "log-time", pa_config_parse_bool, &c->log_time, NULL },
622 { "log-backtrace", pa_config_parse_unsigned, &c->log_backtrace, NULL },
623 #ifdef HAVE_SYS_RESOURCE_H
624 { "rlimit-fsize", parse_rlimit, &c->rlimit_fsize, NULL },
625 { "rlimit-data", parse_rlimit, &c->rlimit_data, NULL },
626 { "rlimit-stack", parse_rlimit, &c->rlimit_stack, NULL },
627 { "rlimit-core", parse_rlimit, &c->rlimit_core, NULL },
628 #ifdef RLIMIT_RSS
629 { "rlimit-rss", parse_rlimit, &c->rlimit_rss, NULL },
630 #endif
631 #ifdef RLIMIT_NOFILE
632 { "rlimit-nofile", parse_rlimit, &c->rlimit_nofile, NULL },
633 #endif
634 #ifdef RLIMIT_AS
635 { "rlimit-as", parse_rlimit, &c->rlimit_as, NULL },
636 #endif
637 #ifdef RLIMIT_NPROC
638 { "rlimit-nproc", parse_rlimit, &c->rlimit_nproc, NULL },
639 #endif
640 #ifdef RLIMIT_MEMLOCK
641 { "rlimit-memlock", parse_rlimit, &c->rlimit_memlock, NULL },
642 #endif
643 #ifdef RLIMIT_LOCKS
644 { "rlimit-locks", parse_rlimit, &c->rlimit_locks, NULL },
645 #endif
646 #ifdef RLIMIT_SIGPENDING
647 { "rlimit-sigpending", parse_rlimit, &c->rlimit_sigpending, NULL },
648 #endif
649 #ifdef RLIMIT_MSGQUEUE
650 { "rlimit-msgqueue", parse_rlimit, &c->rlimit_msgqueue, NULL },
651 #endif
652 #ifdef RLIMIT_NICE
653 { "rlimit-nice", parse_rlimit, &c->rlimit_nice, NULL },
654 #endif
655 #ifdef RLIMIT_RTPRIO
656 { "rlimit-rtprio", parse_rlimit, &c->rlimit_rtprio, NULL },
657 #endif
658 #ifdef RLIMIT_RTTIME
659 { "rlimit-rttime", parse_rlimit, &c->rlimit_rttime, NULL },
660 #endif
661 #endif
662 { NULL, NULL, NULL, NULL },
663 };
664
665 pa_xfree(c->config_file);
666 c->config_file = NULL;
667
668 const char *default_config_file = DEFAULT_CONFIG_FILE;
669 #ifdef HAVE_RUNNING_FROM_BUILD_TREE
670 if (pa_run_from_build_tree()) {
671 pa_log_notice("Detected that we are run from the build tree, fixing default daemon.conf file path.");
672 #ifdef MESON_BUILD
673 default_config_file = PA_BUILDDIR PA_PATH_SEP "src" PA_PATH_SEP "daemon" PA_PATH_SEP "daemon.conf";
674 #else
675 default_config_file = PA_BUILDDIR PA_PATH_SEP "daemon.conf";
676 #endif // Endof #ifdef MESON_BUILD
677 }
678 #endif // Endof #ifdef HAVE_RUNNING_FROM_BUILD_TREE
679
680 f = filename ?
681 pa_fopen_cloexec(c->config_file = pa_xstrdup(filename), "r") :
682 pa_open_config_file(default_config_file, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
683
684 if (!f && errno != ENOENT) {
685 pa_log_warn(_("Failed to open configuration file: %s"), pa_cstrerror(errno));
686 goto finish;
687 }
688
689 ci.default_channel_map_set = ci.default_sample_spec_set = false;
690 ci.conf = c;
691
692 r = f ? pa_config_parse(c->config_file, f, table, NULL, true, NULL) : 0;
693
694 if (r >= 0) {
695
696 /* Make sure that channel map and sample spec fit together */
697
698 if (ci.default_sample_spec_set &&
699 ci.default_channel_map_set &&
700 c->default_channel_map.channels != c->default_sample_spec.channels) {
701 pa_log_error(_("The specified default channel map has a different number of channels than the specified default number of channels."));
702 r = -1;
703 goto finish;
704 } else if (ci.default_sample_spec_set)
705 pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
706 else if (ci.default_channel_map_set)
707 c->default_sample_spec.channels = c->default_channel_map.channels;
708 }
709
710 finish:
711 if (f)
712 fclose(f);
713
714 return r;
715 }
716
pa_daemon_conf_env(pa_daemon_conf *c)717 int pa_daemon_conf_env(pa_daemon_conf *c) {
718 char *e;
719 pa_assert(c);
720
721 if ((e = getenv(ENV_DL_SEARCH_PATH))) {
722 pa_xfree(c->dl_search_path);
723 c->dl_search_path = pa_xstrdup(e);
724 }
725 if ((e = getenv(ENV_SCRIPT_FILE))) {
726 pa_xfree(c->default_script_file);
727 c->default_script_file = pa_xstrdup(e);
728 }
729
730 return 0;
731 }
732
pa_daemon_conf_get_default_script_file(pa_daemon_conf *c)733 const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c) {
734 pa_assert(c);
735
736 if (!c->default_script_file) {
737 if (c->system_instance)
738 c->default_script_file = pa_find_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE);
739 else
740 c->default_script_file = pa_find_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE);
741 }
742
743 return c->default_script_file;
744 }
745
pa_daemon_conf_open_default_script_file(pa_daemon_conf *c)746 FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) {
747 FILE *f;
748 pa_assert(c);
749
750 if (!c->default_script_file) {
751 if (c->system_instance)
752 f = pa_open_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE, &c->default_script_file);
753 else
754 f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file);
755 } else
756 f = pa_fopen_cloexec(c->default_script_file, "r");
757
758 return f;
759 }
760
pa_daemon_conf_dump(pa_daemon_conf *c)761 char *pa_daemon_conf_dump(pa_daemon_conf *c) {
762 static const char* const log_level_to_string[] = {
763 [PA_LOG_DEBUG] = "debug",
764 [PA_LOG_INFO] = "info",
765 [PA_LOG_NOTICE] = "notice",
766 [PA_LOG_WARN] = "warning",
767 [PA_LOG_ERROR] = "error"
768 };
769
770 #ifdef HAVE_DBUS
771 static const char* const server_type_to_string[] = {
772 [PA_SERVER_TYPE_UNSET] = "!!UNSET!!",
773 [PA_SERVER_TYPE_USER] = "user",
774 [PA_SERVER_TYPE_SYSTEM] = "system",
775 [PA_SERVER_TYPE_NONE] = "none"
776 };
777 #endif
778
779 pa_strbuf *s;
780 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
781 char *log_target = NULL;
782
783 pa_assert(c);
784
785 s = pa_strbuf_new();
786
787 if (c->config_file)
788 pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file);
789
790 pa_assert(c->log_level < PA_LOG_LEVEL_MAX);
791
792 if (c->log_target)
793 log_target = pa_log_target_to_string(c->log_target);
794
795 pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize));
796 pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail));
797 pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority));
798 pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level);
799 pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling));
800 pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority);
801 pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading));
802 pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit));
803 pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file));
804 pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance));
805 #ifdef HAVE_DBUS
806 pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]);
807 #endif
808 pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit));
809 pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm));
810 pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes));
811 pa_strbuf_printf(s, "rescue-streams = %s\n", pa_yes_no(c->rescue_streams));
812 pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory));
813 pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
814 pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
815 pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));
816 pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c)));
817 pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file));
818 pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target));
819 pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
820 pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
821 pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(c->avoid_resampling));
822 pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
823 pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels));
824 pa_strbuf_printf(s, "remixing-produce-lfe = %s\n", pa_yes_no(c->remixing_produce_lfe));
825 pa_strbuf_printf(s, "remixing-consume-lfe = %s\n", pa_yes_no(c->remixing_consume_lfe));
826 pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq);
827 pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
828 pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
829 pa_strbuf_printf(s, "alternate-sample-rate = %u\n", c->alternate_sample_rate);
830 pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
831 pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
832 pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
833 pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
834 pa_strbuf_printf(s, "enable-deferred-volume = %s\n", pa_yes_no(c->deferred_volume));
835 pa_strbuf_printf(s, "deferred-volume-safety-margin-usec = %u\n", c->deferred_volume_safety_margin_usec);
836 pa_strbuf_printf(s, "deferred-volume-extra-delay-usec = %d\n", c->deferred_volume_extra_delay_usec);
837 pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
838 pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta));
839 pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time));
840 pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace);
841 #ifdef HAVE_SYS_RESOURCE_H
842 pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
843 pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
844 pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1);
845 pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
846 #ifdef RLIMIT_RSS
847 pa_strbuf_printf(s, "rlimit-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1);
848 #endif
849 #ifdef RLIMIT_AS
850 pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
851 #endif
852 #ifdef RLIMIT_NPROC
853 pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1);
854 #endif
855 #ifdef RLIMIT_NOFILE
856 pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
857 #endif
858 #ifdef RLIMIT_MEMLOCK
859 pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
860 #endif
861 #ifdef RLIMIT_LOCKS
862 pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1);
863 #endif
864 #ifdef RLIMIT_SIGPENDING
865 pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1);
866 #endif
867 #ifdef RLIMIT_MSGQUEUE
868 pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1);
869 #endif
870 #ifdef RLIMIT_NICE
871 pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1);
872 #endif
873 #ifdef RLIMIT_RTPRIO
874 pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1);
875 #endif
876 #ifdef RLIMIT_RTTIME
877 pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1);
878 #endif
879 #endif
880
881 pa_xfree(log_target);
882
883 return pa_strbuf_to_string_free(s);
884 }
885