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