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