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