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