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