release: updated changelog.
[profile/ivi/pulseaudio.git] / src / pulsecore / cli-command.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 <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <ltdl.h>
33 #include <sys/stat.h>
34 #include <dirent.h>
35 #include <time.h>
36
37 #include <pulse/xmalloc.h>
38 #include <pulse/error.h>
39
40 #include <pulsecore/module.h>
41 #include <pulsecore/sink.h>
42 #include <pulsecore/source.h>
43 #include <pulsecore/client.h>
44 #include <pulsecore/sink-input.h>
45 #include <pulsecore/source-output.h>
46 #include <pulsecore/tokenizer.h>
47 #include <pulsecore/strbuf.h>
48 #include <pulsecore/namereg.h>
49 #include <pulsecore/cli-text.h>
50 #include <pulsecore/core-scache.h>
51 #include <pulsecore/sound-file.h>
52 #include <pulsecore/play-memchunk.h>
53 #include <pulsecore/sound-file-stream.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/core-util.h>
56 #include <pulsecore/core-error.h>
57 #include <pulsecore/modinfo.h>
58 #include <pulsecore/dynarray.h>
59
60 #include "cli-command.h"
61
62 struct command {
63     const char *name;
64     int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, pa_bool_t *fail);
65     const char *help;
66     unsigned args;
67 };
68
69 #define META_INCLUDE ".include"
70 #define META_FAIL ".fail"
71 #define META_NOFAIL ".nofail"
72 #define META_IFEXISTS ".ifexists"
73 #define META_ELSE ".else"
74 #define META_ENDIF ".endif"
75
76 enum {
77     IFSTATE_NONE = -1,
78     IFSTATE_FALSE = 0,
79     IFSTATE_TRUE = 1,
80 };
81
82 /* Prototypes for all available commands */
83 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
84 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
85 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
86 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
87 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
88 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
89 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
90 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
91 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
92 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
93 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
94 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
95 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
96 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
97 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
98 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
99 static int pa_cli_command_source_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
100 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
101 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
102 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
103 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
104 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
105 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
106 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
107 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
108 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
109 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
110 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
111 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
112 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
113 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
114 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
115 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
116 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
117 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
118 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
119 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
120 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
121 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
122 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
123 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
124 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
125 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
126 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
127 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
128 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
129 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
130 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
131 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
132 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
133 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
134 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
135 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
136
137 /* A method table for all available commands */
138
139 static const struct command commands[] = {
140     { "help",                    pa_cli_command_help,               "Show this help",               1 },
141     { "list-modules",            pa_cli_command_modules,            "List loaded modules",          1 },
142     { "list-cards",              pa_cli_command_cards,              "List cards",                   1 },
143     { "list-sinks",              pa_cli_command_sinks,              "List loaded sinks",            1 },
144     { "list-sources",            pa_cli_command_sources,            "List loaded sources",          1 },
145     { "list-clients",            pa_cli_command_clients,            "List loaded clients",          1 },
146     { "list-sink-inputs",        pa_cli_command_sink_inputs,        "List sink inputs",             1 },
147     { "list-source-outputs",     pa_cli_command_source_outputs,     "List source outputs",          1 },
148     { "stat",                    pa_cli_command_stat,               "Show memory block statistics", 1 },
149     { "info",                    pa_cli_command_info,               "Show comprehensive status",    1 },
150     { "ls",                      pa_cli_command_info,               NULL,                           1 },
151     { "list",                    pa_cli_command_info,               NULL,                           1 },
152     { "load-module",             pa_cli_command_load,               "Load a module (args: name, arguments)", 3},
153     { "unload-module",           pa_cli_command_unload,             "Unload a module (args: index)", 2},
154     { "describe-module",         pa_cli_command_describe,           "Describe a module (arg: name)", 2},
155     { "set-sink-volume",         pa_cli_command_sink_volume,        "Set the volume of a sink (args: index|name, volume)", 3},
156     { "set-source-volume",       pa_cli_command_source_volume,      "Set the volume of a source (args: index|name, volume)", 3},
157     { "set-sink-mute",           pa_cli_command_sink_mute,          "Set the mute switch of a sink (args: index|name, bool)", 3},
158     { "set-source-mute",         pa_cli_command_source_mute,        "Set the mute switch of a source (args: index|name, bool)", 3},
159     { "set-sink-input-volume",   pa_cli_command_sink_input_volume,  "Set the volume of a sink input (args: index, volume)", 3},
160     { "set-source-output-volume",pa_cli_command_source_output_volume,"Set the volume of a source output (args: index, volume)", 3},
161     { "set-sink-input-mute",     pa_cli_command_sink_input_mute,    "Set the mute switch of a sink input (args: index, bool)", 3},
162     { "set-source-output-mute",  pa_cli_command_source_output_mute, "Set the mute switch of a source output (args: index, bool)", 3},
163     { "set-default-sink",        pa_cli_command_sink_default,       "Set the default sink (args: index|name)", 2},
164     { "set-default-source",      pa_cli_command_source_default,     "Set the default source (args: index|name)", 2},
165     { "set-card-profile",        pa_cli_command_card_profile,       "Change the profile of a card (args: index|name, profile-name)", 3},
166     { "set-sink-port",           pa_cli_command_sink_port,          "Change the port of a sink (args: index|name, port-name)", 3},
167     { "set-source-port",         pa_cli_command_source_port,        "Change the port of a source (args: index|name, port-name)", 3},
168     { "suspend-sink",            pa_cli_command_suspend_sink,       "Suspend sink (args: index|name, bool)", 3},
169     { "suspend-source",          pa_cli_command_suspend_source,     "Suspend source (args: index|name, bool)", 3},
170     { "suspend",                 pa_cli_command_suspend,            "Suspend all sinks and all sources (args: bool)", 2},
171     { "move-sink-input",         pa_cli_command_move_sink_input,    "Move sink input to another sink (args: index, sink)", 3},
172     { "move-source-output",      pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
173     { "update-sink-proplist",    pa_cli_command_update_sink_proplist, "Update the properties of a sink (args: index|name, properties)", 3},
174     { "update-source-proplist",  pa_cli_command_update_source_proplist, "Update the properties of a source (args: index|name, properties)", 3},
175     { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist, "Update the properties of a sink input (args: index, properties)", 3},
176     { "update-source-output-proplist", pa_cli_command_update_source_output_proplist, "Update the properties of a source output (args: index, properties)", 3},
177     { "list-samples",            pa_cli_command_scache_list,        "List all entries in the sample cache", 1},
178     { "play-sample",             pa_cli_command_scache_play,        "Play a sample from the sample cache (args: name, sink|index)", 3},
179     { "remove-sample",           pa_cli_command_scache_remove,      "Remove a sample from the sample cache (args: name)", 2},
180     { "load-sample",             pa_cli_command_scache_load,        "Load a sound file into the sample cache (args: name, filename)", 3},
181     { "load-sample-lazy",        pa_cli_command_scache_load,        "Lazily load a sound file into the sample cache (args: name, filename)", 3},
182     { "load-sample-dir-lazy",    pa_cli_command_scache_load_dir,    "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
183     { "kill-client",             pa_cli_command_kill_client,        "Kill a client (args: index)", 2},
184     { "kill-sink-input",         pa_cli_command_kill_sink_input,    "Kill a sink input (args: index)", 2},
185     { "kill-source-output",      pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
186     { "set-log-level",           pa_cli_command_log_level,          "Change the log level (args: numeric level)", 2},
187     { "set-log-meta",            pa_cli_command_log_meta,           "Show source code location in log messages (args: bool)", 2},
188     { "set-log-time",            pa_cli_command_log_time,           "Show timestamps in log messages (args: bool)", 2},
189     { "set-log-backtrace",       pa_cli_command_log_backtrace,      "Show backtrace in log messages (args: frames)", 2},
190     { "play-file",               pa_cli_command_play_file,          "Play a sound file (args: filename, sink|index)", 3},
191     { "dump",                    pa_cli_command_dump,               "Dump daemon configuration", 1},
192     { "dump-volumes",            pa_cli_command_dump_volumes,       "Debug: Show the state of all volumes", 1 },
193     { "shared",                  pa_cli_command_list_shared_props,  "Debug: Show shared properties", 1},
194     { "exit",                    pa_cli_command_exit,               "Terminate the daemon",         1 },
195     { "vacuum",                  pa_cli_command_vacuum,             NULL, 1},
196     { NULL, NULL, NULL, 0 }
197 };
198
199 static const char whitespace[] = " \t\n\r";
200 static const char linebreak[] = "\n\r";
201
202 static uint32_t parse_index(const char *n) {
203     uint32_t idx;
204
205     if (pa_atou(n, &idx) < 0)
206         return (uint32_t) PA_IDXSET_INVALID;
207
208     return idx;
209 }
210
211 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
212     pa_core_assert_ref(c);
213     pa_assert(t);
214     pa_assert(buf);
215     pa_assert(fail);
216
217     if (pa_core_exit(c, FALSE, 0) < 0)
218         pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n");
219
220     return 0;
221 }
222
223 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
224     const struct command*command;
225
226     pa_core_assert_ref(c);
227     pa_assert(t);
228     pa_assert(buf);
229     pa_assert(fail);
230
231     pa_strbuf_puts(buf, "Available commands:\n");
232
233     for (command = commands; command->name; command++)
234         if (command->help)
235             pa_strbuf_printf(buf, "    %-25s %s\n", command->name, command->help);
236     return 0;
237 }
238
239 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
240     char *s;
241
242     pa_core_assert_ref(c);
243     pa_assert(t);
244     pa_assert(buf);
245     pa_assert(fail);
246
247     pa_assert_se(s = pa_module_list_to_string(c));
248     pa_strbuf_puts(buf, s);
249     pa_xfree(s);
250     return 0;
251 }
252
253 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
254     char *s;
255
256     pa_core_assert_ref(c);
257     pa_assert(t);
258     pa_assert(buf);
259     pa_assert(fail);
260
261     pa_assert_se(s = pa_client_list_to_string(c));
262     pa_strbuf_puts(buf, s);
263     pa_xfree(s);
264     return 0;
265 }
266
267 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
268     char *s;
269
270     pa_core_assert_ref(c);
271     pa_assert(t);
272     pa_assert(buf);
273     pa_assert(fail);
274
275     pa_assert_se(s = pa_card_list_to_string(c));
276     pa_strbuf_puts(buf, s);
277     pa_xfree(s);
278     return 0;
279 }
280
281 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
282     char *s;
283
284     pa_core_assert_ref(c);
285     pa_assert(t);
286     pa_assert(buf);
287     pa_assert(fail);
288
289     pa_assert_se(s = pa_sink_list_to_string(c));
290     pa_strbuf_puts(buf, s);
291     pa_xfree(s);
292     return 0;
293 }
294
295 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
296     char *s;
297
298     pa_core_assert_ref(c);
299     pa_assert(t);
300     pa_assert(buf);
301     pa_assert(fail);
302
303     pa_assert_se(s = pa_source_list_to_string(c));
304     pa_strbuf_puts(buf, s);
305     pa_xfree(s);
306     return 0;
307 }
308
309 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
310     char *s;
311
312     pa_core_assert_ref(c);
313     pa_assert(t);
314     pa_assert(buf);
315     pa_assert(fail);
316
317     pa_assert_se(s = pa_sink_input_list_to_string(c));
318     pa_strbuf_puts(buf, s);
319     pa_xfree(s);
320     return 0;
321 }
322
323 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
324     char *s;
325
326     pa_core_assert_ref(c);
327     pa_assert(t);
328     pa_assert(buf);
329     pa_assert(fail);
330
331     pa_assert_se(s = pa_source_output_list_to_string(c));
332     pa_strbuf_puts(buf, s);
333     pa_xfree(s);
334     return 0;
335 }
336
337 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
338     char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
339     char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
340     char bytes[PA_BYTES_SNPRINT_MAX];
341     const pa_mempool_stat *mstat;
342     unsigned k;
343     pa_sink *def_sink;
344     pa_source *def_source;
345
346     static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = {
347         [PA_MEMBLOCK_POOL] = "POOL",
348         [PA_MEMBLOCK_POOL_EXTERNAL] = "POOL_EXTERNAL",
349         [PA_MEMBLOCK_APPENDED] = "APPENDED",
350         [PA_MEMBLOCK_USER] = "USER",
351         [PA_MEMBLOCK_FIXED] = "FIXED",
352         [PA_MEMBLOCK_IMPORTED] = "IMPORTED",
353     };
354
355     pa_core_assert_ref(c);
356     pa_assert(t);
357     pa_assert(buf);
358     pa_assert(fail);
359
360     mstat = pa_mempool_get_stat(c->mempool);
361
362     pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
363                      (unsigned) pa_atomic_load(&mstat->n_allocated),
364                      pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->allocated_size)));
365
366     pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
367                      (unsigned) pa_atomic_load(&mstat->n_accumulated),
368                      pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->accumulated_size)));
369
370     pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
371                      (unsigned) pa_atomic_load(&mstat->n_imported),
372                      pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->imported_size)));
373
374     pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
375                      (unsigned) pa_atomic_load(&mstat->n_exported),
376                      pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->exported_size)));
377
378     pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
379                      pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
380
381     pa_strbuf_printf(buf, "Default sample spec: %s\n",
382                      pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
383
384     pa_strbuf_printf(buf, "Default channel map: %s\n",
385                      pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
386
387     def_sink = pa_namereg_get_default_sink(c);
388     def_source = pa_namereg_get_default_source(c);
389     pa_strbuf_printf(buf, "Default sink name: %s\n"
390                      "Default source name: %s\n",
391                      def_sink ? def_sink->name : "none",
392                      def_source ? def_source->name : "none");
393
394     for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++)
395         pa_strbuf_printf(buf,
396                          "Memory blocks of type %s: %u allocated/%u accumulated.\n",
397                          type_table[k],
398                          (unsigned) pa_atomic_load(&mstat->n_allocated_by_type[k]),
399                          (unsigned) pa_atomic_load(&mstat->n_accumulated_by_type[k]));
400
401     return 0;
402 }
403
404 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
405     pa_core_assert_ref(c);
406     pa_assert(t);
407     pa_assert(buf);
408     pa_assert(fail);
409
410     pa_cli_command_stat(c, t, buf, fail);
411     pa_cli_command_modules(c, t, buf, fail);
412     pa_cli_command_sinks(c, t, buf, fail);
413     pa_cli_command_sources(c, t, buf, fail);
414     pa_cli_command_clients(c, t, buf, fail);
415     pa_cli_command_cards(c, t, buf, fail);
416     pa_cli_command_sink_inputs(c, t, buf, fail);
417     pa_cli_command_source_outputs(c, t, buf, fail);
418     pa_cli_command_scache_list(c, t, buf, fail);
419     return 0;
420 }
421
422 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
423     const char *name;
424
425     pa_core_assert_ref(c);
426     pa_assert(t);
427     pa_assert(buf);
428     pa_assert(fail);
429
430     if (!(name = pa_tokenizer_get(t, 1))) {
431         pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
432         return -1;
433     }
434
435     if (!pa_module_load(c, name,  pa_tokenizer_get(t, 2))) {
436         pa_strbuf_puts(buf, "Module load failed.\n");
437         return -1;
438     }
439
440     return 0;
441 }
442
443 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
444     pa_module *m;
445     uint32_t idx;
446     const char *i;
447     char *e;
448
449     pa_core_assert_ref(c);
450     pa_assert(t);
451     pa_assert(buf);
452     pa_assert(fail);
453
454     if (!(i = pa_tokenizer_get(t, 1))) {
455         pa_strbuf_puts(buf, "You need to specify the module index.\n");
456         return -1;
457     }
458
459     idx = (uint32_t) strtoul(i, &e, 10);
460     if (*e || !(m = pa_idxset_get_by_index(c->modules, idx))) {
461         pa_strbuf_puts(buf, "Invalid module index.\n");
462         return -1;
463     }
464
465     pa_module_unload_request(m, FALSE);
466     return 0;
467 }
468
469 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
470     const char *name;
471     pa_modinfo *i;
472
473     pa_core_assert_ref(c);
474     pa_assert(t);
475     pa_assert(buf);
476     pa_assert(fail);
477
478     if (!(name = pa_tokenizer_get(t, 1))) {
479         pa_strbuf_puts(buf, "You need to specify the module name.\n");
480         return -1;
481     }
482
483     if ((i = pa_modinfo_get_by_name(name))) {
484
485         pa_strbuf_printf(buf, "Name: %s\n", name);
486
487         if (!i->description && !i->version && !i->author && !i->usage)
488             pa_strbuf_printf(buf, "No module information available\n");
489         else {
490             if (i->version)
491                 pa_strbuf_printf(buf, "Version: %s\n", i->version);
492             if (i->description)
493                 pa_strbuf_printf(buf, "Description: %s\n", i->description);
494             if (i->author)
495                 pa_strbuf_printf(buf, "Author: %s\n", i->author);
496             if (i->usage)
497                 pa_strbuf_printf(buf, "Usage: %s\n", i->usage);
498             pa_strbuf_printf(buf, "Load Once: %s\n", pa_yes_no(i->load_once));
499             if (i->deprecated)
500                 pa_strbuf_printf(buf, "Warning, deprecated: %s\n", i->deprecated);
501         }
502
503         pa_modinfo_free(i);
504     } else
505         pa_strbuf_puts(buf, "Failed to open module.\n");
506
507     return 0;
508 }
509
510 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
511     const char *n, *v;
512     pa_sink *sink;
513     uint32_t volume;
514     pa_cvolume cvolume;
515
516     pa_core_assert_ref(c);
517     pa_assert(t);
518     pa_assert(buf);
519     pa_assert(fail);
520
521     if (!(n = pa_tokenizer_get(t, 1))) {
522         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
523         return -1;
524     }
525
526     if (!(v = pa_tokenizer_get(t, 2))) {
527         pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
528         return -1;
529     }
530
531     if (pa_atou(v, &volume) < 0) {
532         pa_strbuf_puts(buf, "Failed to parse volume.\n");
533         return -1;
534     }
535
536     if (!PA_VOLUME_IS_VALID(volume)) {
537         pa_strbuf_puts(buf, "Volume outside permissible range.\n");
538         return -1;
539     }
540
541     if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
542         pa_strbuf_puts(buf, "No sink found by this name or index.\n");
543         return -1;
544     }
545
546     pa_cvolume_set(&cvolume, 1, volume);
547     pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
548     return 0;
549 }
550
551 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
552     const char *n, *v;
553     pa_sink_input *si;
554     pa_volume_t volume;
555     pa_cvolume cvolume;
556     uint32_t idx;
557
558     pa_core_assert_ref(c);
559     pa_assert(t);
560     pa_assert(buf);
561     pa_assert(fail);
562
563     if (!(n = pa_tokenizer_get(t, 1))) {
564         pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
565         return -1;
566     }
567
568     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
569         pa_strbuf_puts(buf, "Failed to parse index.\n");
570         return -1;
571     }
572
573     if (!(v = pa_tokenizer_get(t, 2))) {
574         pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
575         return -1;
576     }
577
578     if (pa_atou(v, &volume) < 0) {
579         pa_strbuf_puts(buf, "Failed to parse volume.\n");
580         return -1;
581     }
582
583     if (!PA_VOLUME_IS_VALID(volume)) {
584         pa_strbuf_puts(buf, "Volume outside permissible range.\n");
585         return -1;
586     }
587
588     if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) {
589         pa_strbuf_puts(buf, "No sink input found with this index.\n");
590         return -1;
591     }
592
593     if (!si->volume_writable) {
594         pa_strbuf_puts(buf, "This sink input's volume can't be changed.\n");
595         return -1;
596     }
597
598     pa_cvolume_set(&cvolume, 1, volume);
599     pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
600     return 0;
601 }
602
603 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
604     const char *n, *v;
605     pa_source *source;
606     uint32_t volume;
607     pa_cvolume cvolume;
608
609     pa_core_assert_ref(c);
610     pa_assert(t);
611     pa_assert(buf);
612     pa_assert(fail);
613
614     if (!(n = pa_tokenizer_get(t, 1))) {
615         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
616         return -1;
617     }
618
619     if (!(v = pa_tokenizer_get(t, 2))) {
620         pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
621         return -1;
622     }
623
624     if (pa_atou(v, &volume) < 0) {
625         pa_strbuf_puts(buf, "Failed to parse volume.\n");
626         return -1;
627     }
628
629     if (!PA_VOLUME_IS_VALID(volume)) {
630         pa_strbuf_puts(buf, "Volume outside permissible range.\n");
631         return -1;
632     }
633
634     if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
635         pa_strbuf_puts(buf, "No source found by this name or index.\n");
636         return -1;
637     }
638
639     pa_cvolume_set(&cvolume, 1, volume);
640     pa_source_set_volume(source, &cvolume, TRUE, TRUE);
641     return 0;
642 }
643
644 static int pa_cli_command_source_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
645     const char *n, *v;
646     pa_source_output *so;
647     pa_volume_t volume;
648     pa_cvolume cvolume;
649     uint32_t idx;
650
651     pa_core_assert_ref(c);
652     pa_assert(t);
653     pa_assert(buf);
654     pa_assert(fail);
655
656     if (!(n = pa_tokenizer_get(t, 1))) {
657         pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
658         return -1;
659     }
660
661     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
662         pa_strbuf_puts(buf, "Failed to parse index.\n");
663         return -1;
664     }
665
666     if (!(v = pa_tokenizer_get(t, 2))) {
667         pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
668         return -1;
669     }
670
671     if (pa_atou(v, &volume) < 0) {
672         pa_strbuf_puts(buf, "Failed to parse volume.\n");
673         return -1;
674     }
675
676     if (!PA_VOLUME_IS_VALID(volume)) {
677         pa_strbuf_puts(buf, "Volume outside permissible range.\n");
678         return -1;
679     }
680
681     if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) {
682         pa_strbuf_puts(buf, "No source output found with this index.\n");
683         return -1;
684     }
685
686     if (!so->volume_writable) {
687         pa_strbuf_puts(buf, "This source output's volume can't be changed.\n");
688         return -1;
689     }
690
691     pa_cvolume_set(&cvolume, 1, volume);
692     pa_source_output_set_volume(so, &cvolume, TRUE, TRUE);
693     return 0;
694 }
695
696 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
697     const char *n, *m;
698     pa_sink *sink;
699     int mute;
700
701     pa_core_assert_ref(c);
702     pa_assert(t);
703     pa_assert(buf);
704     pa_assert(fail);
705
706     if (!(n = pa_tokenizer_get(t, 1))) {
707         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
708         return -1;
709     }
710
711     if (!(m = pa_tokenizer_get(t, 2))) {
712         pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
713         return -1;
714     }
715
716     if ((mute = pa_parse_boolean(m)) < 0) {
717         pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
718         return -1;
719     }
720
721     if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
722         pa_strbuf_puts(buf, "No sink found by this name or index.\n");
723         return -1;
724     }
725
726     pa_sink_set_mute(sink, mute, TRUE);
727     return 0;
728 }
729
730 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
731     const char *n, *m;
732     pa_source *source;
733     int mute;
734
735     pa_core_assert_ref(c);
736     pa_assert(t);
737     pa_assert(buf);
738     pa_assert(fail);
739
740     if (!(n = pa_tokenizer_get(t, 1))) {
741         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
742         return -1;
743     }
744
745     if (!(m = pa_tokenizer_get(t, 2))) {
746         pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
747         return -1;
748     }
749
750     if ((mute = pa_parse_boolean(m)) < 0) {
751         pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
752         return -1;
753     }
754
755     if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
756         pa_strbuf_puts(buf, "No sink found by this name or index.\n");
757         return -1;
758     }
759
760     pa_source_set_mute(source, mute, TRUE);
761     return 0;
762 }
763
764 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
765     const char *n, *s;
766     pa_sink *sink;
767     pa_proplist *p;
768
769     pa_core_assert_ref(c);
770     pa_assert(t);
771     pa_assert(buf);
772     pa_assert(fail);
773
774     if (!(n = pa_tokenizer_get(t, 1))) {
775         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
776         return -1;
777     }
778
779     if (!(s = pa_tokenizer_get(t, 2))) {
780         pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
781         return -1;
782     }
783
784     if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
785         pa_strbuf_puts(buf, "No sink found by this name or index.\n");
786         return -1;
787     }
788
789     if (!(p = pa_proplist_from_string(s))) {
790         pa_strbuf_puts(buf, "Failed to parse proplist.\n");
791         return -1;
792     }
793
794     pa_sink_update_proplist(sink, PA_UPDATE_REPLACE, p);
795
796     pa_proplist_free(p);
797
798     return 0;
799 }
800
801 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
802     const char *n, *s;
803     pa_source *source;
804     pa_proplist *p;
805
806     pa_core_assert_ref(c);
807     pa_assert(t);
808     pa_assert(buf);
809     pa_assert(fail);
810
811     if (!(n = pa_tokenizer_get(t, 1))) {
812         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
813         return -1;
814     }
815
816     if (!(s = pa_tokenizer_get(t, 2))) {
817         pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
818         return -1;
819     }
820
821     if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
822         pa_strbuf_puts(buf, "No source found by this name or index.\n");
823         return -1;
824     }
825
826     if (!(p = pa_proplist_from_string(s))) {
827         pa_strbuf_puts(buf, "Failed to parse proplist.\n");
828         return -1;
829     }
830
831     pa_source_update_proplist(source, PA_UPDATE_REPLACE, p);
832
833     pa_proplist_free(p);
834
835     return 0;
836 }
837
838 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
839     const char *n, *s;
840     pa_sink_input *si;
841     uint32_t idx;
842     pa_proplist *p;
843
844     pa_core_assert_ref(c);
845     pa_assert(t);
846     pa_assert(buf);
847     pa_assert(fail);
848
849     if (!(n = pa_tokenizer_get(t, 1))) {
850         pa_strbuf_puts(buf, "You need to specify a sink input either by index.\n");
851         return -1;
852     }
853
854     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
855         pa_strbuf_puts(buf, "Failed to parse index.\n");
856         return -1;
857     }
858
859     if (!(s = pa_tokenizer_get(t, 2))) {
860         pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
861         return -1;
862     }
863
864     if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
865         pa_strbuf_puts(buf, "No sink input found with this index.\n");
866         return -1;
867     }
868
869     if (!(p = pa_proplist_from_string(s))) {
870         pa_strbuf_puts(buf, "Failed to parse proplist.\n");
871         return -1;
872     }
873
874     pa_sink_input_update_proplist(si, PA_UPDATE_REPLACE, p);
875
876     pa_proplist_free(p);
877
878     return 0;
879 }
880
881 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
882     const char *n, *s;
883     pa_source_output *so;
884     uint32_t idx;
885     pa_proplist *p;
886
887     pa_core_assert_ref(c);
888     pa_assert(t);
889     pa_assert(buf);
890     pa_assert(fail);
891
892     if (!(n = pa_tokenizer_get(t, 1))) {
893         pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
894         return -1;
895     }
896
897     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
898         pa_strbuf_puts(buf, "Failed to parse index.\n");
899         return -1;
900     }
901
902     if (!(s = pa_tokenizer_get(t, 2))) {
903         pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
904         return -1;
905     }
906
907     if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
908         pa_strbuf_puts(buf, "No source output found with this index.\n");
909         return -1;
910     }
911
912     if (!(p = pa_proplist_from_string(s))) {
913         pa_strbuf_puts(buf, "Failed to parse proplist.\n");
914         return -1;
915     }
916
917     pa_source_output_update_proplist(so, PA_UPDATE_REPLACE, p);
918
919     pa_proplist_free(p);
920
921     return 0;
922 }
923
924 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
925     const char *n, *v;
926     pa_sink_input *si;
927     uint32_t idx;
928     int mute;
929
930     pa_core_assert_ref(c);
931     pa_assert(t);
932     pa_assert(buf);
933     pa_assert(fail);
934
935     if (!(n = pa_tokenizer_get(t, 1))) {
936         pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
937         return -1;
938     }
939
940     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
941         pa_strbuf_puts(buf, "Failed to parse index.\n");
942         return -1;
943     }
944
945     if (!(v = pa_tokenizer_get(t, 2))) {
946         pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
947         return -1;
948     }
949
950     if ((mute = pa_parse_boolean(v)) < 0) {
951         pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
952         return -1;
953     }
954
955     if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
956         pa_strbuf_puts(buf, "No sink input found with this index.\n");
957         return -1;
958     }
959
960     pa_sink_input_set_mute(si, mute, TRUE);
961     return 0;
962 }
963
964 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
965     const char *n, *v;
966     pa_source_output *so;
967     uint32_t idx;
968     int mute;
969
970     pa_core_assert_ref(c);
971     pa_assert(t);
972     pa_assert(buf);
973     pa_assert(fail);
974
975     if (!(n = pa_tokenizer_get(t, 1))) {
976         pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
977         return -1;
978     }
979
980     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
981         pa_strbuf_puts(buf, "Failed to parse index.\n");
982         return -1;
983     }
984
985     if (!(v = pa_tokenizer_get(t, 2))) {
986         pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
987         return -1;
988     }
989
990     if ((mute = pa_parse_boolean(v)) < 0) {
991         pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
992         return -1;
993     }
994
995     if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
996         pa_strbuf_puts(buf, "No source output found with this index.\n");
997         return -1;
998     }
999
1000     pa_source_output_set_mute(so, mute, TRUE);
1001     return 0;
1002 }
1003
1004 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1005     const char *n;
1006     pa_sink *s;
1007
1008     pa_core_assert_ref(c);
1009     pa_assert(t);
1010     pa_assert(buf);
1011     pa_assert(fail);
1012
1013     if (!(n = pa_tokenizer_get(t, 1))) {
1014         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1015         return -1;
1016     }
1017
1018     if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
1019         pa_namereg_set_default_sink(c, s);
1020     else
1021         pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
1022
1023     return 0;
1024 }
1025
1026 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1027     const char *n;
1028     pa_source *s;
1029
1030     pa_core_assert_ref(c);
1031     pa_assert(t);
1032     pa_assert(buf);
1033     pa_assert(fail);
1034
1035     if (!(n = pa_tokenizer_get(t, 1))) {
1036         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1037         return -1;
1038     }
1039
1040     if ((s = pa_namereg_get(c, n, PA_NAMEREG_SOURCE)))
1041         pa_namereg_set_default_source(c, s);
1042     else
1043         pa_strbuf_printf(buf, "Source %s does not exist.\n", n);
1044     return 0;
1045 }
1046
1047 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1048     const char *n;
1049     pa_client *client;
1050     uint32_t idx;
1051
1052     pa_core_assert_ref(c);
1053     pa_assert(t);
1054     pa_assert(buf);
1055     pa_assert(fail);
1056
1057     if (!(n = pa_tokenizer_get(t, 1))) {
1058         pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
1059         return -1;
1060     }
1061
1062     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1063         pa_strbuf_puts(buf, "Failed to parse index.\n");
1064         return -1;
1065     }
1066
1067     if (!(client = pa_idxset_get_by_index(c->clients, idx))) {
1068         pa_strbuf_puts(buf, "No client found by this index.\n");
1069         return -1;
1070     }
1071
1072     pa_client_kill(client);
1073     return 0;
1074 }
1075
1076 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1077     const char *n;
1078     pa_sink_input *sink_input;
1079     uint32_t idx;
1080
1081     pa_core_assert_ref(c);
1082     pa_assert(t);
1083     pa_assert(buf);
1084     pa_assert(fail);
1085
1086     if (!(n = pa_tokenizer_get(t, 1))) {
1087         pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1088         return -1;
1089     }
1090
1091     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1092         pa_strbuf_puts(buf, "Failed to parse index.\n");
1093         return -1;
1094     }
1095
1096     if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) {
1097         pa_strbuf_puts(buf, "No sink input found by this index.\n");
1098         return -1;
1099     }
1100
1101     pa_sink_input_kill(sink_input);
1102     return 0;
1103 }
1104
1105 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1106     const char *n;
1107     pa_source_output *source_output;
1108     uint32_t idx;
1109
1110     pa_core_assert_ref(c);
1111     pa_assert(t);
1112     pa_assert(buf);
1113     pa_assert(fail);
1114
1115     if (!(n = pa_tokenizer_get(t, 1))) {
1116         pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1117         return -1;
1118     }
1119
1120     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1121         pa_strbuf_puts(buf, "Failed to parse index.\n");
1122         return -1;
1123     }
1124
1125     if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) {
1126         pa_strbuf_puts(buf, "No source output found by this index.\n");
1127         return -1;
1128     }
1129
1130     pa_source_output_kill(source_output);
1131     return 0;
1132 }
1133
1134 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1135     char *s;
1136
1137     pa_core_assert_ref(c);
1138     pa_assert(t);
1139     pa_assert(buf);
1140     pa_assert(fail);
1141
1142     pa_assert_se(s = pa_scache_list_to_string(c));
1143     pa_strbuf_puts(buf, s);
1144     pa_xfree(s);
1145
1146     return 0;
1147 }
1148
1149 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1150     const char *n, *sink_name;
1151     pa_sink *sink;
1152     uint32_t idx;
1153
1154     pa_core_assert_ref(c);
1155     pa_assert(t);
1156     pa_assert(buf);
1157     pa_assert(fail);
1158
1159     if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1160         pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
1161         return -1;
1162     }
1163
1164     if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1165         pa_strbuf_puts(buf, "No sink by that name.\n");
1166         return -1;
1167     }
1168
1169     if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
1170         pa_strbuf_puts(buf, "Failed to play sample.\n");
1171         return -1;
1172     }
1173
1174     pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
1175
1176     return 0;
1177 }
1178
1179 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1180     const char *n;
1181
1182     pa_core_assert_ref(c);
1183     pa_assert(t);
1184     pa_assert(buf);
1185     pa_assert(fail);
1186
1187     if (!(n = pa_tokenizer_get(t, 1))) {
1188         pa_strbuf_puts(buf, "You need to specify a sample name.\n");
1189         return -1;
1190     }
1191
1192     if (pa_scache_remove_item(c, n) < 0) {
1193         pa_strbuf_puts(buf, "Failed to remove sample.\n");
1194         return -1;
1195     }
1196
1197     return 0;
1198 }
1199
1200 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1201     const char *fname, *n;
1202     int r;
1203
1204     pa_core_assert_ref(c);
1205     pa_assert(t);
1206     pa_assert(buf);
1207     pa_assert(fail);
1208
1209     if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
1210         pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
1211         return -1;
1212     }
1213
1214     if (strstr(pa_tokenizer_get(t, 0), "lazy"))
1215         r = pa_scache_add_file_lazy(c, n, fname, NULL);
1216     else
1217         r = pa_scache_add_file(c, n, fname, NULL);
1218
1219     if (r < 0)
1220         pa_strbuf_puts(buf, "Failed to load sound file.\n");
1221
1222     return 0;
1223 }
1224
1225 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1226     const char *pname;
1227
1228     pa_core_assert_ref(c);
1229     pa_assert(t);
1230     pa_assert(buf);
1231     pa_assert(fail);
1232
1233     if (!(pname = pa_tokenizer_get(t, 1))) {
1234         pa_strbuf_puts(buf, "You need to specify a path name.\n");
1235         return -1;
1236     }
1237
1238     if (pa_scache_add_directory_lazy(c, pname) < 0) {
1239         pa_strbuf_puts(buf, "Failed to load directory.\n");
1240         return -1;
1241     }
1242
1243     return 0;
1244 }
1245
1246 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1247     const char *fname, *sink_name;
1248     pa_sink *sink;
1249
1250     pa_core_assert_ref(c);
1251     pa_assert(t);
1252     pa_assert(buf);
1253     pa_assert(fail);
1254
1255     if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1256         pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
1257         return -1;
1258     }
1259
1260     if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1261         pa_strbuf_puts(buf, "No sink by that name.\n");
1262         return -1;
1263     }
1264
1265
1266     return pa_play_file(sink, fname, NULL);
1267 }
1268
1269 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1270     pa_core_assert_ref(c);
1271     pa_assert(t);
1272     pa_assert(buf);
1273     pa_assert(fail);
1274
1275     pa_shared_dump(c, buf);
1276     return 0;
1277 }
1278
1279 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1280     pa_core_assert_ref(c);
1281     pa_assert(t);
1282     pa_assert(buf);
1283     pa_assert(fail);
1284
1285     pa_mempool_vacuum(c->mempool);
1286
1287     return 0;
1288 }
1289
1290 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1291     const char *n, *k;
1292     pa_sink_input *si;
1293     pa_sink *sink;
1294     uint32_t idx;
1295
1296     pa_core_assert_ref(c);
1297     pa_assert(t);
1298     pa_assert(buf);
1299     pa_assert(fail);
1300
1301     if (!(n = pa_tokenizer_get(t, 1))) {
1302         pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1303         return -1;
1304     }
1305
1306     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1307         pa_strbuf_puts(buf, "Failed to parse index.\n");
1308         return -1;
1309     }
1310
1311     if (!(k = pa_tokenizer_get(t, 2))) {
1312         pa_strbuf_puts(buf, "You need to specify a sink.\n");
1313         return -1;
1314     }
1315
1316     if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
1317         pa_strbuf_puts(buf, "No sink input found with this index.\n");
1318         return -1;
1319     }
1320
1321     if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK))) {
1322         pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1323         return -1;
1324     }
1325
1326     if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
1327         pa_strbuf_puts(buf, "Moved failed.\n");
1328         return -1;
1329     }
1330     return 0;
1331 }
1332
1333 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1334     const char *n, *k;
1335     pa_source_output *so;
1336     pa_source *source;
1337     uint32_t idx;
1338
1339     pa_core_assert_ref(c);
1340     pa_assert(t);
1341     pa_assert(buf);
1342     pa_assert(fail);
1343
1344     if (!(n = pa_tokenizer_get(t, 1))) {
1345         pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1346         return -1;
1347     }
1348
1349     if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1350         pa_strbuf_puts(buf, "Failed to parse index.\n");
1351         return -1;
1352     }
1353
1354     if (!(k = pa_tokenizer_get(t, 2))) {
1355         pa_strbuf_puts(buf, "You need to specify a source.\n");
1356         return -1;
1357     }
1358
1359     if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1360         pa_strbuf_puts(buf, "No source output found with this index.\n");
1361         return -1;
1362     }
1363
1364     if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE))) {
1365         pa_strbuf_puts(buf, "No source found by this name or index.\n");
1366         return -1;
1367     }
1368
1369     if (pa_source_output_move_to(so, source, TRUE) < 0) {
1370         pa_strbuf_puts(buf, "Moved failed.\n");
1371         return -1;
1372     }
1373     return 0;
1374 }
1375
1376 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1377     const char *n, *m;
1378     pa_sink *sink;
1379     int suspend, r;
1380
1381     pa_core_assert_ref(c);
1382     pa_assert(t);
1383     pa_assert(buf);
1384     pa_assert(fail);
1385
1386     if (!(n = pa_tokenizer_get(t, 1))) {
1387         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1388         return -1;
1389     }
1390
1391     if (!(m = pa_tokenizer_get(t, 2))) {
1392         pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1393         return -1;
1394     }
1395
1396     if ((suspend = pa_parse_boolean(m)) < 0) {
1397         pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1398         return -1;
1399     }
1400
1401     if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1402         pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1403         return -1;
1404     }
1405
1406     if ((r = pa_sink_suspend(sink, suspend, PA_SUSPEND_USER)) < 0)
1407         pa_strbuf_printf(buf, "Failed to resume/suspend sink: %s\n", pa_strerror(r));
1408
1409     return 0;
1410 }
1411
1412 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1413     const char *n, *m;
1414     pa_source *source;
1415     int suspend, r;
1416
1417     pa_core_assert_ref(c);
1418     pa_assert(t);
1419     pa_assert(buf);
1420     pa_assert(fail);
1421
1422     if (!(n = pa_tokenizer_get(t, 1))) {
1423         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1424         return -1;
1425     }
1426
1427     if (!(m = pa_tokenizer_get(t, 2))) {
1428         pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1429         return -1;
1430     }
1431
1432     if ((suspend = pa_parse_boolean(m)) < 0) {
1433         pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1434         return -1;
1435     }
1436
1437     if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1438         pa_strbuf_puts(buf, "No source found by this name or index.\n");
1439         return -1;
1440     }
1441
1442     if ((r = pa_source_suspend(source, suspend, PA_SUSPEND_USER)) < 0)
1443         pa_strbuf_printf(buf, "Failed to resume/suspend source: %s\n", pa_strerror(r));
1444
1445     return 0;
1446 }
1447
1448 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1449     const char *m;
1450     int suspend, r;
1451
1452     pa_core_assert_ref(c);
1453     pa_assert(t);
1454     pa_assert(buf);
1455     pa_assert(fail);
1456
1457     if (!(m = pa_tokenizer_get(t, 1))) {
1458         pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1459         return -1;
1460     }
1461
1462     if ((suspend = pa_parse_boolean(m)) < 0) {
1463         pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1464         return -1;
1465     }
1466
1467     if ((r = pa_sink_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1468         pa_strbuf_printf(buf, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r));
1469
1470     if ((r = pa_source_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1471         pa_strbuf_printf(buf, "Failed to resume/suspend all sources: %s\n", pa_strerror(r));
1472
1473     return 0;
1474 }
1475
1476 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1477     const char *m;
1478     uint32_t level;
1479
1480     pa_core_assert_ref(c);
1481     pa_assert(t);
1482     pa_assert(buf);
1483     pa_assert(fail);
1484
1485     if (!(m = pa_tokenizer_get(t, 1))) {
1486         pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n");
1487         return -1;
1488     }
1489
1490     if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) {
1491         pa_strbuf_puts(buf, "Failed to parse log level.\n");
1492         return -1;
1493     }
1494
1495     pa_log_set_level(level);
1496
1497     return 0;
1498 }
1499
1500 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1501     const char *m;
1502     pa_bool_t b;
1503
1504     pa_core_assert_ref(c);
1505     pa_assert(t);
1506     pa_assert(buf);
1507     pa_assert(fail);
1508
1509     if (!(m = pa_tokenizer_get(t, 1))) {
1510         pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1511         return -1;
1512     }
1513
1514     if ((b = pa_parse_boolean(m)) < 0) {
1515         pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1516         return -1;
1517     }
1518
1519     pa_log_set_flags(PA_LOG_PRINT_META, b ? PA_LOG_SET : PA_LOG_UNSET);
1520
1521     return 0;
1522 }
1523
1524 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1525     const char *m;
1526     pa_bool_t b;
1527
1528     pa_core_assert_ref(c);
1529     pa_assert(t);
1530     pa_assert(buf);
1531     pa_assert(fail);
1532
1533     if (!(m = pa_tokenizer_get(t, 1))) {
1534         pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1535         return -1;
1536     }
1537
1538     if ((b = pa_parse_boolean(m)) < 0) {
1539         pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1540         return -1;
1541     }
1542
1543     pa_log_set_flags(PA_LOG_PRINT_TIME, b ? PA_LOG_SET : PA_LOG_UNSET);
1544
1545     return 0;
1546 }
1547
1548 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1549     const char *m;
1550     uint32_t nframes;
1551
1552     pa_core_assert_ref(c);
1553     pa_assert(t);
1554     pa_assert(buf);
1555     pa_assert(fail);
1556
1557     if (!(m = pa_tokenizer_get(t, 1))) {
1558         pa_strbuf_puts(buf, "You need to specify a backtrace level.\n");
1559         return -1;
1560     }
1561
1562     if (pa_atou(m, &nframes) < 0 || nframes >= 1000) {
1563         pa_strbuf_puts(buf, "Failed to parse backtrace level.\n");
1564         return -1;
1565     }
1566
1567     pa_log_set_show_backtrace(nframes);
1568
1569     return 0;
1570 }
1571
1572 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1573     const char *n, *p;
1574     pa_card *card;
1575
1576     pa_core_assert_ref(c);
1577     pa_assert(t);
1578     pa_assert(buf);
1579     pa_assert(fail);
1580
1581     if (!(n = pa_tokenizer_get(t, 1))) {
1582         pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1583         return -1;
1584     }
1585
1586     if (!(p = pa_tokenizer_get(t, 2))) {
1587         pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1588         return -1;
1589     }
1590
1591     if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1592         pa_strbuf_puts(buf, "No card found by this name or index.\n");
1593         return -1;
1594     }
1595
1596     if (pa_card_set_profile(card, p, TRUE) < 0) {
1597         pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
1598         return -1;
1599     }
1600
1601     return 0;
1602 }
1603
1604 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1605     const char *n, *p;
1606     pa_sink *sink;
1607
1608     pa_core_assert_ref(c);
1609     pa_assert(t);
1610     pa_assert(buf);
1611     pa_assert(fail);
1612
1613     if (!(n = pa_tokenizer_get(t, 1))) {
1614         pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1615         return -1;
1616     }
1617
1618     if (!(p = pa_tokenizer_get(t, 2))) {
1619         pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1620         return -1;
1621     }
1622
1623     if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1624         pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1625         return -1;
1626     }
1627
1628     if (pa_sink_set_port(sink, p, TRUE) < 0) {
1629         pa_strbuf_printf(buf, "Failed to set sink port to '%s'.\n", p);
1630         return -1;
1631     }
1632
1633     return 0;
1634 }
1635
1636 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1637     const char *n, *p;
1638     pa_source *source;
1639
1640     pa_core_assert_ref(c);
1641     pa_assert(t);
1642     pa_assert(buf);
1643     pa_assert(fail);
1644
1645     if (!(n = pa_tokenizer_get(t, 1))) {
1646         pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1647         return -1;
1648     }
1649
1650     if (!(p = pa_tokenizer_get(t, 2))) {
1651         pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1652         return -1;
1653     }
1654
1655     if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1656         pa_strbuf_puts(buf, "No source found by this name or index.\n");
1657         return -1;
1658     }
1659
1660     if (pa_source_set_port(source, p, TRUE) < 0) {
1661         pa_strbuf_printf(buf, "Failed to set source port to '%s'.\n", p);
1662         return -1;
1663     }
1664
1665     return 0;
1666 }
1667
1668 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1669     pa_module *m;
1670     pa_sink *sink;
1671     pa_source *source;
1672     pa_card *card;
1673     pa_bool_t nl;
1674     uint32_t idx;
1675     time_t now;
1676 #ifdef HAVE_CTIME_R
1677     char txt[256];
1678 #endif
1679
1680     pa_core_assert_ref(c);
1681     pa_assert(t);
1682     pa_assert(buf);
1683     pa_assert(fail);
1684
1685     time(&now);
1686
1687 #ifdef HAVE_CTIME_R
1688     pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
1689 #else
1690     pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
1691 #endif
1692
1693     PA_IDXSET_FOREACH(m, c->modules, idx) {
1694
1695         pa_strbuf_printf(buf, "load-module %s", m->name);
1696
1697         if (m->argument)
1698             pa_strbuf_printf(buf, " %s", m->argument);
1699
1700         pa_strbuf_puts(buf, "\n");
1701     }
1702
1703     nl = FALSE;
1704     PA_IDXSET_FOREACH(sink, c->sinks, idx) {
1705
1706         if (!nl) {
1707             pa_strbuf_puts(buf, "\n");
1708             nl = TRUE;
1709         }
1710
1711         pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, FALSE)));
1712         pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
1713         pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
1714     }
1715
1716     nl = FALSE;
1717     PA_IDXSET_FOREACH(source, c->sources, idx) {
1718
1719         if (!nl) {
1720             pa_strbuf_puts(buf, "\n");
1721             nl = TRUE;
1722         }
1723
1724         pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, FALSE)));
1725         pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
1726         pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
1727     }
1728
1729     nl = FALSE;
1730     PA_IDXSET_FOREACH(card, c->cards, idx) {
1731
1732         if (!nl) {
1733             pa_strbuf_puts(buf, "\n");
1734             nl = TRUE;
1735         }
1736
1737         if (card->active_profile)
1738             pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
1739     }
1740
1741     nl = FALSE;
1742     if ((sink = pa_namereg_get_default_sink(c))) {
1743         if (!nl) {
1744             pa_strbuf_puts(buf, "\n");
1745             nl = TRUE;
1746         }
1747
1748         pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
1749     }
1750
1751     if ((source = pa_namereg_get_default_source(c))) {
1752         if (!nl)
1753             pa_strbuf_puts(buf, "\n");
1754
1755         pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
1756     }
1757
1758     pa_strbuf_puts(buf, "\n### EOF\n");
1759
1760     return 0;
1761 }
1762
1763 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1764     pa_sink *s;
1765     pa_source *so;
1766     pa_sink_input *i;
1767     pa_source_output *o;
1768     uint32_t s_idx, i_idx;
1769     char v_str[PA_CVOLUME_SNPRINT_MAX];
1770
1771     pa_core_assert_ref(c);
1772     pa_assert(t);
1773     pa_assert(buf);
1774     pa_assert(fail);
1775
1776     PA_IDXSET_FOREACH(s, c->sinks, s_idx) {
1777         pa_strbuf_printf(buf, "Sink %d: ", s_idx);
1778         pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->reference_volume));
1779         pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->real_volume));
1780         pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->soft_volume));
1781         pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->thread_info.current_hw_volume));
1782         pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(s->save_volume));
1783
1784         PA_IDXSET_FOREACH(i, s->inputs, i_idx) {
1785             pa_strbuf_printf(buf, "\tInput %d: ", i_idx);
1786             pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume));
1787             pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->reference_ratio));
1788             pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->real_ratio));
1789             pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->soft_volume));
1790             pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor));
1791             pa_strbuf_printf(buf, "volume_factor_sink = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor_sink));
1792             pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(i->save_volume));
1793         }
1794     }
1795
1796     PA_IDXSET_FOREACH(so, c->sources, s_idx) {
1797         pa_strbuf_printf(buf, "Source %d: ", s_idx);
1798         pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->reference_volume));
1799         pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->real_volume));
1800         pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->soft_volume));
1801         pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->thread_info.current_hw_volume));
1802         pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(so->save_volume));
1803
1804         PA_IDXSET_FOREACH(o, so->outputs, i_idx) {
1805             pa_strbuf_printf(buf, "\tOutput %d: ", i_idx);
1806             pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume));
1807             pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->reference_ratio));
1808             pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->real_ratio));
1809             pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->soft_volume));
1810             pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor));
1811             pa_strbuf_printf(buf, "volume_factor_source = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor_source));
1812             pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(o->save_volume));
1813         }
1814     }
1815
1816     return 0;
1817 }
1818
1819 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) {
1820     const char *cs;
1821
1822     pa_assert(c);
1823     pa_assert(s);
1824     pa_assert(buf);
1825
1826     cs = s+strspn(s, whitespace);
1827
1828     if (*cs == '#' || !*cs)
1829         return 0;
1830     else if (*cs == '.') {
1831         if (!strcmp(cs, META_ELSE)) {
1832             if (!ifstate || *ifstate == IFSTATE_NONE) {
1833                 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1834                 return -1;
1835             } else if (*ifstate == IFSTATE_TRUE)
1836                 *ifstate = IFSTATE_FALSE;
1837             else
1838                 *ifstate = IFSTATE_TRUE;
1839             return 0;
1840         } else if (!strcmp(cs, META_ENDIF)) {
1841             if (!ifstate || *ifstate == IFSTATE_NONE) {
1842                 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1843                 return -1;
1844             } else
1845                 *ifstate = IFSTATE_NONE;
1846             return 0;
1847         }
1848         if (ifstate && *ifstate == IFSTATE_FALSE)
1849             return 0;
1850         if (!strcmp(cs, META_FAIL))
1851             *fail = TRUE;
1852         else if (!strcmp(cs, META_NOFAIL))
1853             *fail = FALSE;
1854         else {
1855             size_t l;
1856             l = strcspn(cs, whitespace);
1857
1858             if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
1859                 struct stat st;
1860                 const char *filename = cs+l+strspn(cs+l, whitespace);
1861
1862                 if (stat(filename, &st) < 0) {
1863                     pa_log_warn("stat('%s'): %s", filename, pa_cstrerror(errno));
1864                     if (*fail)
1865                         return -1;
1866                 } else {
1867                     if (S_ISDIR(st.st_mode)) {
1868                         DIR *d;
1869
1870                         if (!(d = opendir(filename))) {
1871                             pa_log_warn("Failed to read '%s': %s", filename, pa_cstrerror(errno));
1872                             if (*fail)
1873                                 return -1;
1874                         } else {
1875                             unsigned i, count;
1876                             char **sorted_files;
1877                             struct dirent *de;
1878                             pa_bool_t failed = FALSE;
1879                             pa_dynarray *files = pa_dynarray_new();
1880
1881                             while ((de = readdir(d))) {
1882                                 char *extn;
1883                                 size_t flen = strlen(de->d_name);
1884
1885                                 if (flen < 4)
1886                                     continue;
1887
1888                                 extn = &de->d_name[flen-3];
1889                                 if (strncmp(extn, ".pa", 3) == 0)
1890                                     pa_dynarray_append(files, pa_sprintf_malloc("%s" PA_PATH_SEP "%s", filename, de->d_name));
1891                             }
1892
1893                             closedir(d);
1894
1895                             count = pa_dynarray_size(files);
1896                             sorted_files = pa_xnew(char*, count);
1897                             for (i = 0; i < count; ++i)
1898                                 sorted_files[i] = pa_dynarray_get(files, i);
1899                             pa_dynarray_free(files, NULL);
1900
1901                             for (i = 0; i < count; ++i) {
1902                                 for (unsigned j = 0; j < count; ++j) {
1903                                     if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
1904                                         char *tmp = sorted_files[i];
1905                                         sorted_files[i] = sorted_files[j];
1906                                         sorted_files[j] = tmp;
1907                                     }
1908                                 }
1909                             }
1910
1911                             for (i = 0; i < count; ++i) {
1912                                 if (!failed) {
1913                                     if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
1914                                         failed = TRUE;
1915                                 }
1916
1917                                 pa_xfree(sorted_files[i]);
1918                             }
1919                             pa_xfree(sorted_files);
1920                             if (failed)
1921                                 return -1;
1922                         }
1923                     } else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
1924                         return -1;
1925                     }
1926                 }
1927             } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
1928                 if (!ifstate) {
1929                     pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1930                     return -1;
1931                 } else if (*ifstate != IFSTATE_NONE) {
1932                     pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs);
1933                     return -1;
1934                 } else {
1935                     const char *filename = cs+l+strspn(cs+l, whitespace);
1936
1937                     /* Search DL_SEARCH_PATH unless the filename is absolute */
1938                     if (filename[0] == PA_PATH_SEP_CHAR) {
1939
1940                         *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1941                         pa_log_debug("Checking for existence of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1942
1943                     } else {
1944                         const char *paths, *state = NULL;
1945                         char *p;
1946
1947                         if (!(paths = lt_dlgetsearchpath()))
1948                             return -1;
1949
1950                         while ((p = pa_split(paths, ":", &state))) {
1951                             char *pathname;
1952
1953                             pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
1954                             pa_xfree(p);
1955
1956                             *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1957                             pa_log_debug("Checking for existence of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1958
1959                             pa_xfree(pathname);
1960
1961                             if (*ifstate == IFSTATE_TRUE)
1962                                 break;
1963                         }
1964                     }
1965
1966                 }
1967             } else {
1968                 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
1969                 if (*fail) return -1;
1970             }
1971         }
1972     } else {
1973         const struct command*command;
1974         int unknown = 1;
1975         size_t l;
1976
1977         if (ifstate && *ifstate == IFSTATE_FALSE)
1978             return 0;
1979
1980         l = strcspn(cs, whitespace);
1981
1982         for (command = commands; command->name; command++)
1983             if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
1984                 int ret;
1985                 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
1986                 pa_assert(t);
1987                 ret = command->proc(c, t, buf, fail);
1988                 pa_tokenizer_free(t);
1989                 unknown = 0;
1990
1991                 if (ret < 0 && *fail)
1992                     return -1;
1993
1994                 break;
1995             }
1996
1997         if (unknown) {
1998             pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
1999             if (*fail)
2000                 return -1;
2001         }
2002     }
2003
2004     return 0;
2005 }
2006
2007 int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
2008     return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
2009 }
2010
2011 int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
2012     char line[2048];
2013     int ifstate = IFSTATE_NONE;
2014     int ret = -1;
2015     pa_bool_t _fail = TRUE;
2016
2017     pa_assert(c);
2018     pa_assert(f);
2019     pa_assert(buf);
2020
2021     if (!fail)
2022         fail = &_fail;
2023
2024     while (fgets(line, sizeof(line), f)) {
2025         pa_strip_nl(line);
2026
2027         if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
2028             goto fail;
2029     }
2030
2031     ret = 0;
2032
2033 fail:
2034
2035     return ret;
2036 }
2037
2038 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
2039     FILE *f = NULL;
2040     int ret = -1;
2041     pa_bool_t _fail = TRUE;
2042
2043     pa_assert(c);
2044     pa_assert(fn);
2045     pa_assert(buf);
2046
2047     if (!fail)
2048         fail = &_fail;
2049
2050     if (!(f = pa_fopen_cloexec(fn, "r"))) {
2051         pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
2052         if (!*fail)
2053             ret = 0;
2054         goto fail;
2055     }
2056
2057     pa_log_debug("Parsing script '%s'", fn);
2058     ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
2059
2060 fail:
2061     if (f)
2062         fclose(f);
2063
2064     return ret;
2065 }
2066
2067 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
2068     const char *p;
2069     int ifstate = IFSTATE_NONE;
2070     pa_bool_t _fail = TRUE;
2071
2072     pa_assert(c);
2073     pa_assert(s);
2074     pa_assert(buf);
2075
2076     if (!fail)
2077         fail = &_fail;
2078
2079     p = s;
2080     while (*p) {
2081         size_t l = strcspn(p, linebreak);
2082         char *line = pa_xstrndup(p, l);
2083
2084         if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) {
2085             pa_xfree(line);
2086             return -1;
2087         }
2088         pa_xfree(line);
2089
2090         p += l;
2091         p += strspn(p, linebreak);
2092     }
2093
2094     return 0;
2095 }