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