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