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 f = filename ?
669 pa_fopen_cloexec(c->config_file = pa_xstrdup(filename), "r") :
670 pa_open_config_file(DEFAULT_CONFIG_FILE, DEFAULT_CONFIG_FILE_USER, ENV_CONFIG_FILE, &c->config_file);
671
672 if (!f && errno != ENOENT) {
673 pa_log_warn(_("Failed to open configuration file: %s"), pa_cstrerror(errno));
674 goto finish;
675 }
676
677 ci.default_channel_map_set = ci.default_sample_spec_set = false;
678 ci.conf = c;
679
680 r = f ? pa_config_parse(c->config_file, f, table, NULL, true, NULL) : 0;
681
682 if (r >= 0) {
683
684 /* Make sure that channel map and sample spec fit together */
685
686 if (ci.default_sample_spec_set &&
687 ci.default_channel_map_set &&
688 c->default_channel_map.channels != c->default_sample_spec.channels) {
689 pa_log_error(_("The specified default channel map has a different number of channels than the specified default number of channels."));
690 r = -1;
691 goto finish;
692 } else if (ci.default_sample_spec_set)
693 pa_channel_map_init_extend(&c->default_channel_map, c->default_sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
694 else if (ci.default_channel_map_set)
695 c->default_sample_spec.channels = c->default_channel_map.channels;
696 }
697
698 finish:
699 if (f)
700 fclose(f);
701
702 return r;
703 }
704
pa_daemon_conf_env(pa_daemon_conf * c)705 int pa_daemon_conf_env(pa_daemon_conf *c) {
706 char *e;
707 pa_assert(c);
708
709 if ((e = getenv(ENV_DL_SEARCH_PATH))) {
710 pa_xfree(c->dl_search_path);
711 c->dl_search_path = pa_xstrdup(e);
712 }
713 if ((e = getenv(ENV_SCRIPT_FILE))) {
714 pa_xfree(c->default_script_file);
715 c->default_script_file = pa_xstrdup(e);
716 }
717
718 return 0;
719 }
720
pa_daemon_conf_get_default_script_file(pa_daemon_conf * c)721 const char *pa_daemon_conf_get_default_script_file(pa_daemon_conf *c) {
722 pa_assert(c);
723
724 if (!c->default_script_file) {
725 if (c->system_instance)
726 c->default_script_file = pa_find_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE);
727 else
728 c->default_script_file = pa_find_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE);
729 }
730
731 return c->default_script_file;
732 }
733
pa_daemon_conf_open_default_script_file(pa_daemon_conf * c)734 FILE *pa_daemon_conf_open_default_script_file(pa_daemon_conf *c) {
735 FILE *f;
736 pa_assert(c);
737
738 if (!c->default_script_file) {
739 if (c->system_instance)
740 f = pa_open_config_file(DEFAULT_SYSTEM_SCRIPT_FILE, NULL, ENV_SCRIPT_FILE, &c->default_script_file);
741 else
742 f = pa_open_config_file(DEFAULT_SCRIPT_FILE, DEFAULT_SCRIPT_FILE_USER, ENV_SCRIPT_FILE, &c->default_script_file);
743 } else
744 f = pa_fopen_cloexec(c->default_script_file, "r");
745
746 return f;
747 }
748
pa_daemon_conf_dump(pa_daemon_conf * c)749 char *pa_daemon_conf_dump(pa_daemon_conf *c) {
750 static const char* const log_level_to_string[] = {
751 [PA_LOG_DEBUG] = "debug",
752 [PA_LOG_INFO] = "info",
753 [PA_LOG_NOTICE] = "notice",
754 [PA_LOG_WARN] = "warning",
755 [PA_LOG_ERROR] = "error"
756 };
757
758 #ifdef HAVE_DBUS
759 static const char* const server_type_to_string[] = {
760 [PA_SERVER_TYPE_UNSET] = "!!UNSET!!",
761 [PA_SERVER_TYPE_USER] = "user",
762 [PA_SERVER_TYPE_SYSTEM] = "system",
763 [PA_SERVER_TYPE_NONE] = "none"
764 };
765 #endif
766
767 pa_strbuf *s;
768 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
769 char *log_target = NULL;
770
771 pa_assert(c);
772
773 s = pa_strbuf_new();
774
775 if (c->config_file)
776 pa_strbuf_printf(s, _("### Read from configuration file: %s ###\n"), c->config_file);
777
778 pa_assert(c->log_level < PA_LOG_LEVEL_MAX);
779
780 if (c->log_target)
781 log_target = pa_log_target_to_string(c->log_target);
782
783 pa_strbuf_printf(s, "daemonize = %s\n", pa_yes_no(c->daemonize));
784 pa_strbuf_printf(s, "fail = %s\n", pa_yes_no(c->fail));
785 pa_strbuf_printf(s, "high-priority = %s\n", pa_yes_no(c->high_priority));
786 pa_strbuf_printf(s, "nice-level = %i\n", c->nice_level);
787 pa_strbuf_printf(s, "realtime-scheduling = %s\n", pa_yes_no(c->realtime_scheduling));
788 pa_strbuf_printf(s, "realtime-priority = %i\n", c->realtime_priority);
789 pa_strbuf_printf(s, "allow-module-loading = %s\n", pa_yes_no(!c->disallow_module_loading));
790 pa_strbuf_printf(s, "allow-exit = %s\n", pa_yes_no(!c->disallow_exit));
791 pa_strbuf_printf(s, "use-pid-file = %s\n", pa_yes_no(c->use_pid_file));
792 pa_strbuf_printf(s, "system-instance = %s\n", pa_yes_no(c->system_instance));
793 #ifdef HAVE_DBUS
794 pa_strbuf_printf(s, "local-server-type = %s\n", server_type_to_string[c->local_server_type]);
795 #endif
796 pa_strbuf_printf(s, "cpu-limit = %s\n", pa_yes_no(!c->no_cpu_limit));
797 pa_strbuf_printf(s, "enable-shm = %s\n", pa_yes_no(!c->disable_shm));
798 pa_strbuf_printf(s, "flat-volumes = %s\n", pa_yes_no(c->flat_volumes));
799 pa_strbuf_printf(s, "rescue-streams = %s\n", pa_yes_no(c->rescue_streams));
800 pa_strbuf_printf(s, "lock-memory = %s\n", pa_yes_no(c->lock_memory));
801 pa_strbuf_printf(s, "exit-idle-time = %i\n", c->exit_idle_time);
802 pa_strbuf_printf(s, "scache-idle-time = %i\n", c->scache_idle_time);
803 pa_strbuf_printf(s, "dl-search-path = %s\n", pa_strempty(c->dl_search_path));
804 pa_strbuf_printf(s, "default-script-file = %s\n", pa_strempty(pa_daemon_conf_get_default_script_file(c)));
805 pa_strbuf_printf(s, "load-default-script-file = %s\n", pa_yes_no(c->load_default_script_file));
806 pa_strbuf_printf(s, "log-target = %s\n", pa_strempty(log_target));
807 pa_strbuf_printf(s, "log-level = %s\n", log_level_to_string[c->log_level]);
808 pa_strbuf_printf(s, "resample-method = %s\n", pa_resample_method_to_string(c->resample_method));
809 pa_strbuf_printf(s, "avoid-resampling = %s\n", pa_yes_no(c->avoid_resampling));
810 pa_strbuf_printf(s, "enable-remixing = %s\n", pa_yes_no(!c->disable_remixing));
811 pa_strbuf_printf(s, "remixing-use-all-sink-channels = %s\n", pa_yes_no(c->remixing_use_all_sink_channels));
812 pa_strbuf_printf(s, "remixing-produce-lfe = %s\n", pa_yes_no(c->remixing_produce_lfe));
813 pa_strbuf_printf(s, "remixing-consume-lfe = %s\n", pa_yes_no(c->remixing_consume_lfe));
814 pa_strbuf_printf(s, "lfe-crossover-freq = %u\n", c->lfe_crossover_freq);
815 pa_strbuf_printf(s, "default-sample-format = %s\n", pa_sample_format_to_string(c->default_sample_spec.format));
816 pa_strbuf_printf(s, "default-sample-rate = %u\n", c->default_sample_spec.rate);
817 pa_strbuf_printf(s, "alternate-sample-rate = %u\n", c->alternate_sample_rate);
818 pa_strbuf_printf(s, "default-sample-channels = %u\n", c->default_sample_spec.channels);
819 pa_strbuf_printf(s, "default-channel-map = %s\n", pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
820 pa_strbuf_printf(s, "default-fragments = %u\n", c->default_n_fragments);
821 pa_strbuf_printf(s, "default-fragment-size-msec = %u\n", c->default_fragment_size_msec);
822 pa_strbuf_printf(s, "enable-deferred-volume = %s\n", pa_yes_no(c->deferred_volume));
823 pa_strbuf_printf(s, "deferred-volume-safety-margin-usec = %u\n", c->deferred_volume_safety_margin_usec);
824 pa_strbuf_printf(s, "deferred-volume-extra-delay-usec = %d\n", c->deferred_volume_extra_delay_usec);
825 pa_strbuf_printf(s, "shm-size-bytes = %lu\n", (unsigned long) c->shm_size);
826 pa_strbuf_printf(s, "log-meta = %s\n", pa_yes_no(c->log_meta));
827 pa_strbuf_printf(s, "log-time = %s\n", pa_yes_no(c->log_time));
828 pa_strbuf_printf(s, "log-backtrace = %u\n", c->log_backtrace);
829 #ifdef HAVE_SYS_RESOURCE_H
830 pa_strbuf_printf(s, "rlimit-fsize = %li\n", c->rlimit_fsize.is_set ? (long int) c->rlimit_fsize.value : -1);
831 pa_strbuf_printf(s, "rlimit-data = %li\n", c->rlimit_data.is_set ? (long int) c->rlimit_data.value : -1);
832 pa_strbuf_printf(s, "rlimit-stack = %li\n", c->rlimit_stack.is_set ? (long int) c->rlimit_stack.value : -1);
833 pa_strbuf_printf(s, "rlimit-core = %li\n", c->rlimit_core.is_set ? (long int) c->rlimit_core.value : -1);
834 #ifdef RLIMIT_RSS
835 pa_strbuf_printf(s, "rlimit-rss = %li\n", c->rlimit_rss.is_set ? (long int) c->rlimit_rss.value : -1);
836 #endif
837 #ifdef RLIMIT_AS
838 pa_strbuf_printf(s, "rlimit-as = %li\n", c->rlimit_as.is_set ? (long int) c->rlimit_as.value : -1);
839 #endif
840 #ifdef RLIMIT_NPROC
841 pa_strbuf_printf(s, "rlimit-nproc = %li\n", c->rlimit_nproc.is_set ? (long int) c->rlimit_nproc.value : -1);
842 #endif
843 #ifdef RLIMIT_NOFILE
844 pa_strbuf_printf(s, "rlimit-nofile = %li\n", c->rlimit_nofile.is_set ? (long int) c->rlimit_nofile.value : -1);
845 #endif
846 #ifdef RLIMIT_MEMLOCK
847 pa_strbuf_printf(s, "rlimit-memlock = %li\n", c->rlimit_memlock.is_set ? (long int) c->rlimit_memlock.value : -1);
848 #endif
849 #ifdef RLIMIT_LOCKS
850 pa_strbuf_printf(s, "rlimit-locks = %li\n", c->rlimit_locks.is_set ? (long int) c->rlimit_locks.value : -1);
851 #endif
852 #ifdef RLIMIT_SIGPENDING
853 pa_strbuf_printf(s, "rlimit-sigpending = %li\n", c->rlimit_sigpending.is_set ? (long int) c->rlimit_sigpending.value : -1);
854 #endif
855 #ifdef RLIMIT_MSGQUEUE
856 pa_strbuf_printf(s, "rlimit-msgqueue = %li\n", c->rlimit_msgqueue.is_set ? (long int) c->rlimit_msgqueue.value : -1);
857 #endif
858 #ifdef RLIMIT_NICE
859 pa_strbuf_printf(s, "rlimit-nice = %li\n", c->rlimit_nice.is_set ? (long int) c->rlimit_nice.value : -1);
860 #endif
861 #ifdef RLIMIT_RTPRIO
862 pa_strbuf_printf(s, "rlimit-rtprio = %li\n", c->rlimit_rtprio.is_set ? (long int) c->rlimit_rtprio.value : -1);
863 #endif
864 #ifdef RLIMIT_RTTIME
865 pa_strbuf_printf(s, "rlimit-rttime = %li\n", c->rlimit_rttime.is_set ? (long int) c->rlimit_rttime.value : -1);
866 #endif
867 #endif
868
869 pa_xfree(log_target);
870
871 return pa_strbuf_to_string_free(s);
872 }
873