]> code.delx.au - pulseaudio/blob - src/pulsecore/cli-command.c
cli: Validate volume before setting
[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, (uint32_t) idx))) {
583 pa_strbuf_puts(buf, "No sink input found with this index.\n");
584 return -1;
585 }
586
587 pa_cvolume_set(&cvolume, 1, volume);
588 pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
589 return 0;
590 }
591
592 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
593 const char *n, *v;
594 pa_source *source;
595 uint32_t volume;
596 pa_cvolume cvolume;
597
598 pa_core_assert_ref(c);
599 pa_assert(t);
600 pa_assert(buf);
601 pa_assert(fail);
602
603 if (!(n = pa_tokenizer_get(t, 1))) {
604 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
605 return -1;
606 }
607
608 if (!(v = pa_tokenizer_get(t, 2))) {
609 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
610 return -1;
611 }
612
613 if (pa_atou(v, &volume) < 0) {
614 pa_strbuf_puts(buf, "Failed to parse volume.\n");
615 return -1;
616 }
617
618 if (!PA_VOLUME_IS_VALID(volume)) {
619 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
620 return -1;
621 }
622
623 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
624 pa_strbuf_puts(buf, "No source found by this name or index.\n");
625 return -1;
626 }
627
628 pa_cvolume_set(&cvolume, 1, volume);
629 pa_source_set_volume(source, &cvolume, TRUE);
630 return 0;
631 }
632
633 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
634 const char *n, *m;
635 pa_sink *sink;
636 int mute;
637
638 pa_core_assert_ref(c);
639 pa_assert(t);
640 pa_assert(buf);
641 pa_assert(fail);
642
643 if (!(n = pa_tokenizer_get(t, 1))) {
644 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
645 return -1;
646 }
647
648 if (!(m = pa_tokenizer_get(t, 2))) {
649 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
650 return -1;
651 }
652
653 if ((mute = pa_parse_boolean(m)) < 0) {
654 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
655 return -1;
656 }
657
658 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
659 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
660 return -1;
661 }
662
663 pa_sink_set_mute(sink, mute, TRUE);
664 return 0;
665 }
666
667 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
668 const char *n, *m;
669 pa_source *source;
670 int mute;
671
672 pa_core_assert_ref(c);
673 pa_assert(t);
674 pa_assert(buf);
675 pa_assert(fail);
676
677 if (!(n = pa_tokenizer_get(t, 1))) {
678 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
679 return -1;
680 }
681
682 if (!(m = pa_tokenizer_get(t, 2))) {
683 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
684 return -1;
685 }
686
687 if ((mute = pa_parse_boolean(m)) < 0) {
688 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
689 return -1;
690 }
691
692 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
693 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
694 return -1;
695 }
696
697 pa_source_set_mute(source, mute, TRUE);
698 return 0;
699 }
700
701 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
702 const char *n, *s;
703 pa_sink *sink;
704 pa_proplist *p;
705
706 pa_core_assert_ref(c);
707 pa_assert(t);
708 pa_assert(buf);
709 pa_assert(fail);
710
711 if (!(n = pa_tokenizer_get(t, 1))) {
712 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
713 return -1;
714 }
715
716 if (!(s = pa_tokenizer_get(t, 2))) {
717 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
718 return -1;
719 }
720
721 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
722 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
723 return -1;
724 }
725
726 if (!(p = pa_proplist_from_string(s))) {
727 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
728 return -1;
729 }
730
731 pa_sink_update_proplist(sink, PA_UPDATE_REPLACE, p);
732
733 pa_proplist_free(p);
734
735 return 0;
736 }
737
738 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
739 const char *n, *s;
740 pa_source *source;
741 pa_proplist *p;
742
743 pa_core_assert_ref(c);
744 pa_assert(t);
745 pa_assert(buf);
746 pa_assert(fail);
747
748 if (!(n = pa_tokenizer_get(t, 1))) {
749 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
750 return -1;
751 }
752
753 if (!(s = pa_tokenizer_get(t, 2))) {
754 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
755 return -1;
756 }
757
758 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
759 pa_strbuf_puts(buf, "No source found by this name or index.\n");
760 return -1;
761 }
762
763 if (!(p = pa_proplist_from_string(s))) {
764 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
765 return -1;
766 }
767
768 pa_source_update_proplist(source, PA_UPDATE_REPLACE, p);
769
770 pa_proplist_free(p);
771
772 return 0;
773 }
774
775 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
776 const char *n, *s;
777 pa_sink_input *si;
778 uint32_t idx;
779 pa_proplist *p;
780
781 pa_core_assert_ref(c);
782 pa_assert(t);
783 pa_assert(buf);
784 pa_assert(fail);
785
786 if (!(n = pa_tokenizer_get(t, 1))) {
787 pa_strbuf_puts(buf, "You need to specify a sink input either by index.\n");
788 return -1;
789 }
790
791 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
792 pa_strbuf_puts(buf, "Failed to parse index.\n");
793 return -1;
794 }
795
796 if (!(s = pa_tokenizer_get(t, 2))) {
797 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
798 return -1;
799 }
800
801 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
802 pa_strbuf_puts(buf, "No sink input found with this index.\n");
803 return -1;
804 }
805
806 if (!(p = pa_proplist_from_string(s))) {
807 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
808 return -1;
809 }
810
811 pa_sink_input_update_proplist(si, PA_UPDATE_REPLACE, p);
812
813 pa_proplist_free(p);
814
815 return 0;
816 }
817
818 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
819 const char *n, *s;
820 pa_source_output *so;
821 uint32_t idx;
822 pa_proplist *p;
823
824 pa_core_assert_ref(c);
825 pa_assert(t);
826 pa_assert(buf);
827 pa_assert(fail);
828
829 if (!(n = pa_tokenizer_get(t, 1))) {
830 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
831 return -1;
832 }
833
834 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
835 pa_strbuf_puts(buf, "Failed to parse index.\n");
836 return -1;
837 }
838
839 if (!(s = pa_tokenizer_get(t, 2))) {
840 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
841 return -1;
842 }
843
844 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
845 pa_strbuf_puts(buf, "No source output found with this index.\n");
846 return -1;
847 }
848
849 if (!(p = pa_proplist_from_string(s))) {
850 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
851 return -1;
852 }
853
854 pa_source_output_update_proplist(so, PA_UPDATE_REPLACE, p);
855
856 pa_proplist_free(p);
857
858 return 0;
859 }
860
861 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
862 const char *n, *v;
863 pa_sink_input *si;
864 uint32_t idx;
865 int mute;
866
867 pa_core_assert_ref(c);
868 pa_assert(t);
869 pa_assert(buf);
870 pa_assert(fail);
871
872 if (!(n = pa_tokenizer_get(t, 1))) {
873 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
874 return -1;
875 }
876
877 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
878 pa_strbuf_puts(buf, "Failed to parse index.\n");
879 return -1;
880 }
881
882 if (!(v = pa_tokenizer_get(t, 2))) {
883 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
884 return -1;
885 }
886
887 if ((mute = pa_parse_boolean(v)) < 0) {
888 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
889 return -1;
890 }
891
892 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
893 pa_strbuf_puts(buf, "No sink input found with this index.\n");
894 return -1;
895 }
896
897 pa_sink_input_set_mute(si, mute, TRUE);
898 return 0;
899 }
900
901 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
902 const char *n;
903 pa_sink *s;
904
905 pa_core_assert_ref(c);
906 pa_assert(t);
907 pa_assert(buf);
908 pa_assert(fail);
909
910 if (!(n = pa_tokenizer_get(t, 1))) {
911 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
912 return -1;
913 }
914
915 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
916 pa_namereg_set_default_sink(c, s);
917 else
918 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
919
920 return 0;
921 }
922
923 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
924 const char *n;
925 pa_source *s;
926
927 pa_core_assert_ref(c);
928 pa_assert(t);
929 pa_assert(buf);
930 pa_assert(fail);
931
932 if (!(n = pa_tokenizer_get(t, 1))) {
933 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
934 return -1;
935 }
936
937 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SOURCE)))
938 pa_namereg_set_default_source(c, s);
939 else
940 pa_strbuf_printf(buf, "Source %s does not exist.\n", n);
941 return 0;
942 }
943
944 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
945 const char *n;
946 pa_client *client;
947 uint32_t idx;
948
949 pa_core_assert_ref(c);
950 pa_assert(t);
951 pa_assert(buf);
952 pa_assert(fail);
953
954 if (!(n = pa_tokenizer_get(t, 1))) {
955 pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
956 return -1;
957 }
958
959 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
960 pa_strbuf_puts(buf, "Failed to parse index.\n");
961 return -1;
962 }
963
964 if (!(client = pa_idxset_get_by_index(c->clients, idx))) {
965 pa_strbuf_puts(buf, "No client found by this index.\n");
966 return -1;
967 }
968
969 pa_client_kill(client);
970 return 0;
971 }
972
973 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
974 const char *n;
975 pa_sink_input *sink_input;
976 uint32_t idx;
977
978 pa_core_assert_ref(c);
979 pa_assert(t);
980 pa_assert(buf);
981 pa_assert(fail);
982
983 if (!(n = pa_tokenizer_get(t, 1))) {
984 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
985 return -1;
986 }
987
988 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
989 pa_strbuf_puts(buf, "Failed to parse index.\n");
990 return -1;
991 }
992
993 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) {
994 pa_strbuf_puts(buf, "No sink input found by this index.\n");
995 return -1;
996 }
997
998 pa_sink_input_kill(sink_input);
999 return 0;
1000 }
1001
1002 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1003 const char *n;
1004 pa_source_output *source_output;
1005 uint32_t idx;
1006
1007 pa_core_assert_ref(c);
1008 pa_assert(t);
1009 pa_assert(buf);
1010 pa_assert(fail);
1011
1012 if (!(n = pa_tokenizer_get(t, 1))) {
1013 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1014 return -1;
1015 }
1016
1017 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1018 pa_strbuf_puts(buf, "Failed to parse index.\n");
1019 return -1;
1020 }
1021
1022 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) {
1023 pa_strbuf_puts(buf, "No source output found by this index.\n");
1024 return -1;
1025 }
1026
1027 pa_source_output_kill(source_output);
1028 return 0;
1029 }
1030
1031 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1032 char *s;
1033
1034 pa_core_assert_ref(c);
1035 pa_assert(t);
1036 pa_assert(buf);
1037 pa_assert(fail);
1038
1039 pa_assert_se(s = pa_scache_list_to_string(c));
1040 pa_strbuf_puts(buf, s);
1041 pa_xfree(s);
1042
1043 return 0;
1044 }
1045
1046 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1047 const char *n, *sink_name;
1048 pa_sink *sink;
1049 uint32_t idx;
1050
1051 pa_core_assert_ref(c);
1052 pa_assert(t);
1053 pa_assert(buf);
1054 pa_assert(fail);
1055
1056 if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1057 pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
1058 return -1;
1059 }
1060
1061 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1062 pa_strbuf_puts(buf, "No sink by that name.\n");
1063 return -1;
1064 }
1065
1066 if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
1067 pa_strbuf_puts(buf, "Failed to play sample.\n");
1068 return -1;
1069 }
1070
1071 pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
1072
1073 return 0;
1074 }
1075
1076 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1077 const char *n;
1078
1079 pa_core_assert_ref(c);
1080 pa_assert(t);
1081 pa_assert(buf);
1082 pa_assert(fail);
1083
1084 if (!(n = pa_tokenizer_get(t, 1))) {
1085 pa_strbuf_puts(buf, "You need to specify a sample name.\n");
1086 return -1;
1087 }
1088
1089 if (pa_scache_remove_item(c, n) < 0) {
1090 pa_strbuf_puts(buf, "Failed to remove sample.\n");
1091 return -1;
1092 }
1093
1094 return 0;
1095 }
1096
1097 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1098 const char *fname, *n;
1099 int r;
1100
1101 pa_core_assert_ref(c);
1102 pa_assert(t);
1103 pa_assert(buf);
1104 pa_assert(fail);
1105
1106 if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
1107 pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
1108 return -1;
1109 }
1110
1111 if (strstr(pa_tokenizer_get(t, 0), "lazy"))
1112 r = pa_scache_add_file_lazy(c, n, fname, NULL);
1113 else
1114 r = pa_scache_add_file(c, n, fname, NULL);
1115
1116 if (r < 0)
1117 pa_strbuf_puts(buf, "Failed to load sound file.\n");
1118
1119 return 0;
1120 }
1121
1122 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1123 const char *pname;
1124
1125 pa_core_assert_ref(c);
1126 pa_assert(t);
1127 pa_assert(buf);
1128 pa_assert(fail);
1129
1130 if (!(pname = pa_tokenizer_get(t, 1))) {
1131 pa_strbuf_puts(buf, "You need to specify a path name.\n");
1132 return -1;
1133 }
1134
1135 if (pa_scache_add_directory_lazy(c, pname) < 0) {
1136 pa_strbuf_puts(buf, "Failed to load directory.\n");
1137 return -1;
1138 }
1139
1140 return 0;
1141 }
1142
1143 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1144 const char *fname, *sink_name;
1145 pa_sink *sink;
1146
1147 pa_core_assert_ref(c);
1148 pa_assert(t);
1149 pa_assert(buf);
1150 pa_assert(fail);
1151
1152 if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1153 pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
1154 return -1;
1155 }
1156
1157 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1158 pa_strbuf_puts(buf, "No sink by that name.\n");
1159 return -1;
1160 }
1161
1162
1163 return pa_play_file(sink, fname, NULL);
1164 }
1165
1166 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1167 pa_core_assert_ref(c);
1168 pa_assert(t);
1169 pa_assert(buf);
1170 pa_assert(fail);
1171
1172 pa_shared_dump(c, buf);
1173 return 0;
1174 }
1175
1176 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1177 pa_core_assert_ref(c);
1178 pa_assert(t);
1179 pa_assert(buf);
1180 pa_assert(fail);
1181
1182 pa_mempool_vacuum(c->mempool);
1183
1184 return 0;
1185 }
1186
1187 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1188 const char *n, *k;
1189 pa_sink_input *si;
1190 pa_sink *sink;
1191 uint32_t idx;
1192
1193 pa_core_assert_ref(c);
1194 pa_assert(t);
1195 pa_assert(buf);
1196 pa_assert(fail);
1197
1198 if (!(n = pa_tokenizer_get(t, 1))) {
1199 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1200 return -1;
1201 }
1202
1203 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1204 pa_strbuf_puts(buf, "Failed to parse index.\n");
1205 return -1;
1206 }
1207
1208 if (!(k = pa_tokenizer_get(t, 2))) {
1209 pa_strbuf_puts(buf, "You need to specify a sink.\n");
1210 return -1;
1211 }
1212
1213 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
1214 pa_strbuf_puts(buf, "No sink input found with this index.\n");
1215 return -1;
1216 }
1217
1218 if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK))) {
1219 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1220 return -1;
1221 }
1222
1223 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
1224 pa_strbuf_puts(buf, "Moved failed.\n");
1225 return -1;
1226 }
1227 return 0;
1228 }
1229
1230 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1231 const char *n, *k;
1232 pa_source_output *so;
1233 pa_source *source;
1234 uint32_t idx;
1235
1236 pa_core_assert_ref(c);
1237 pa_assert(t);
1238 pa_assert(buf);
1239 pa_assert(fail);
1240
1241 if (!(n = pa_tokenizer_get(t, 1))) {
1242 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1243 return -1;
1244 }
1245
1246 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1247 pa_strbuf_puts(buf, "Failed to parse index.\n");
1248 return -1;
1249 }
1250
1251 if (!(k = pa_tokenizer_get(t, 2))) {
1252 pa_strbuf_puts(buf, "You need to specify a source.\n");
1253 return -1;
1254 }
1255
1256 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1257 pa_strbuf_puts(buf, "No source output found with this index.\n");
1258 return -1;
1259 }
1260
1261 if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE))) {
1262 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1263 return -1;
1264 }
1265
1266 if (pa_source_output_move_to(so, source, TRUE) < 0) {
1267 pa_strbuf_puts(buf, "Moved failed.\n");
1268 return -1;
1269 }
1270 return 0;
1271 }
1272
1273 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1274 const char *n, *m;
1275 pa_sink *sink;
1276 int suspend, r;
1277
1278 pa_core_assert_ref(c);
1279 pa_assert(t);
1280 pa_assert(buf);
1281 pa_assert(fail);
1282
1283 if (!(n = pa_tokenizer_get(t, 1))) {
1284 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1285 return -1;
1286 }
1287
1288 if (!(m = pa_tokenizer_get(t, 2))) {
1289 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1290 return -1;
1291 }
1292
1293 if ((suspend = pa_parse_boolean(m)) < 0) {
1294 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1295 return -1;
1296 }
1297
1298 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1299 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1300 return -1;
1301 }
1302
1303 if ((r = pa_sink_suspend(sink, suspend, PA_SUSPEND_USER)) < 0)
1304 pa_strbuf_printf(buf, "Failed to resume/suspend sink: %s\n", pa_strerror(r));
1305
1306 return 0;
1307 }
1308
1309 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1310 const char *n, *m;
1311 pa_source *source;
1312 int suspend, r;
1313
1314 pa_core_assert_ref(c);
1315 pa_assert(t);
1316 pa_assert(buf);
1317 pa_assert(fail);
1318
1319 if (!(n = pa_tokenizer_get(t, 1))) {
1320 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1321 return -1;
1322 }
1323
1324 if (!(m = pa_tokenizer_get(t, 2))) {
1325 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1326 return -1;
1327 }
1328
1329 if ((suspend = pa_parse_boolean(m)) < 0) {
1330 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1331 return -1;
1332 }
1333
1334 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1335 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1336 return -1;
1337 }
1338
1339 if ((r = pa_source_suspend(source, suspend, PA_SUSPEND_USER)) < 0)
1340 pa_strbuf_printf(buf, "Failed to resume/suspend source: %s\n", pa_strerror(r));
1341
1342 return 0;
1343 }
1344
1345 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1346 const char *m;
1347 int suspend, r;
1348
1349 pa_core_assert_ref(c);
1350 pa_assert(t);
1351 pa_assert(buf);
1352 pa_assert(fail);
1353
1354 if (!(m = pa_tokenizer_get(t, 1))) {
1355 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1356 return -1;
1357 }
1358
1359 if ((suspend = pa_parse_boolean(m)) < 0) {
1360 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1361 return -1;
1362 }
1363
1364 if ((r = pa_sink_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1365 pa_strbuf_printf(buf, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r));
1366
1367 if ((r = pa_source_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1368 pa_strbuf_printf(buf, "Failed to resume/suspend all sources: %s\n", pa_strerror(r));
1369
1370 return 0;
1371 }
1372
1373 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1374 const char *m;
1375 uint32_t level;
1376
1377 pa_core_assert_ref(c);
1378 pa_assert(t);
1379 pa_assert(buf);
1380 pa_assert(fail);
1381
1382 if (!(m = pa_tokenizer_get(t, 1))) {
1383 pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n");
1384 return -1;
1385 }
1386
1387 if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) {
1388 pa_strbuf_puts(buf, "Failed to parse log level.\n");
1389 return -1;
1390 }
1391
1392 pa_log_set_level(level);
1393
1394 return 0;
1395 }
1396
1397 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1398 const char *m;
1399 pa_bool_t b;
1400
1401 pa_core_assert_ref(c);
1402 pa_assert(t);
1403 pa_assert(buf);
1404 pa_assert(fail);
1405
1406 if (!(m = pa_tokenizer_get(t, 1))) {
1407 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1408 return -1;
1409 }
1410
1411 if ((b = pa_parse_boolean(m)) < 0) {
1412 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1413 return -1;
1414 }
1415
1416 pa_log_set_flags(PA_LOG_PRINT_META, b ? PA_LOG_SET : PA_LOG_UNSET);
1417
1418 return 0;
1419 }
1420
1421 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1422 const char *m;
1423 pa_bool_t b;
1424
1425 pa_core_assert_ref(c);
1426 pa_assert(t);
1427 pa_assert(buf);
1428 pa_assert(fail);
1429
1430 if (!(m = pa_tokenizer_get(t, 1))) {
1431 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1432 return -1;
1433 }
1434
1435 if ((b = pa_parse_boolean(m)) < 0) {
1436 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1437 return -1;
1438 }
1439
1440 pa_log_set_flags(PA_LOG_PRINT_TIME, b ? PA_LOG_SET : PA_LOG_UNSET);
1441
1442 return 0;
1443 }
1444
1445 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1446 const char *m;
1447 uint32_t nframes;
1448
1449 pa_core_assert_ref(c);
1450 pa_assert(t);
1451 pa_assert(buf);
1452 pa_assert(fail);
1453
1454 if (!(m = pa_tokenizer_get(t, 1))) {
1455 pa_strbuf_puts(buf, "You need to specify a backtrace level.\n");
1456 return -1;
1457 }
1458
1459 if (pa_atou(m, &nframes) < 0 || nframes >= 1000) {
1460 pa_strbuf_puts(buf, "Failed to parse backtrace level.\n");
1461 return -1;
1462 }
1463
1464 pa_log_set_show_backtrace(nframes);
1465
1466 return 0;
1467 }
1468
1469 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1470 const char *n, *p;
1471 pa_card *card;
1472
1473 pa_core_assert_ref(c);
1474 pa_assert(t);
1475 pa_assert(buf);
1476 pa_assert(fail);
1477
1478 if (!(n = pa_tokenizer_get(t, 1))) {
1479 pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1480 return -1;
1481 }
1482
1483 if (!(p = pa_tokenizer_get(t, 2))) {
1484 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1485 return -1;
1486 }
1487
1488 if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1489 pa_strbuf_puts(buf, "No card found by this name or index.\n");
1490 return -1;
1491 }
1492
1493 if (pa_card_set_profile(card, p, TRUE) < 0) {
1494 pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
1495 return -1;
1496 }
1497
1498 return 0;
1499 }
1500
1501 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1502 const char *n, *p;
1503 pa_sink *sink;
1504
1505 pa_core_assert_ref(c);
1506 pa_assert(t);
1507 pa_assert(buf);
1508 pa_assert(fail);
1509
1510 if (!(n = pa_tokenizer_get(t, 1))) {
1511 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1512 return -1;
1513 }
1514
1515 if (!(p = pa_tokenizer_get(t, 2))) {
1516 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1517 return -1;
1518 }
1519
1520 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1521 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1522 return -1;
1523 }
1524
1525 if (pa_sink_set_port(sink, p, TRUE) < 0) {
1526 pa_strbuf_printf(buf, "Failed to set sink port to '%s'.\n", p);
1527 return -1;
1528 }
1529
1530 return 0;
1531 }
1532
1533 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1534 const char *n, *p;
1535 pa_source *source;
1536
1537 pa_core_assert_ref(c);
1538 pa_assert(t);
1539 pa_assert(buf);
1540 pa_assert(fail);
1541
1542 if (!(n = pa_tokenizer_get(t, 1))) {
1543 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1544 return -1;
1545 }
1546
1547 if (!(p = pa_tokenizer_get(t, 2))) {
1548 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1549 return -1;
1550 }
1551
1552 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1553 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1554 return -1;
1555 }
1556
1557 if (pa_source_set_port(source, p, TRUE) < 0) {
1558 pa_strbuf_printf(buf, "Failed to set source port to '%s'.\n", p);
1559 return -1;
1560 }
1561
1562 return 0;
1563 }
1564
1565 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1566 pa_module *m;
1567 pa_sink *sink;
1568 pa_source *source;
1569 pa_card *card;
1570 pa_bool_t nl;
1571 uint32_t idx;
1572 char txt[256];
1573 time_t now;
1574
1575 pa_core_assert_ref(c);
1576 pa_assert(t);
1577 pa_assert(buf);
1578 pa_assert(fail);
1579
1580 time(&now);
1581
1582 #ifdef HAVE_CTIME_R
1583 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
1584 #else
1585 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
1586 #endif
1587
1588 PA_IDXSET_FOREACH(m, c->modules, idx) {
1589
1590 pa_strbuf_printf(buf, "load-module %s", m->name);
1591
1592 if (m->argument)
1593 pa_strbuf_printf(buf, " %s", m->argument);
1594
1595 pa_strbuf_puts(buf, "\n");
1596 }
1597
1598 nl = FALSE;
1599 PA_IDXSET_FOREACH(sink, c->sinks, idx) {
1600
1601 if (!nl) {
1602 pa_strbuf_puts(buf, "\n");
1603 nl = TRUE;
1604 }
1605
1606 pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, FALSE)));
1607 pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
1608 pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
1609 }
1610
1611 nl = FALSE;
1612 PA_IDXSET_FOREACH(source, c->sources, idx) {
1613
1614 if (!nl) {
1615 pa_strbuf_puts(buf, "\n");
1616 nl = TRUE;
1617 }
1618
1619 pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, FALSE)));
1620 pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
1621 pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
1622 }
1623
1624 nl = FALSE;
1625 PA_IDXSET_FOREACH(card, c->cards, idx) {
1626
1627 if (!nl) {
1628 pa_strbuf_puts(buf, "\n");
1629 nl = TRUE;
1630 }
1631
1632 if (card->active_profile)
1633 pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
1634 }
1635
1636 nl = FALSE;
1637 if ((sink = pa_namereg_get_default_sink(c))) {
1638 if (!nl) {
1639 pa_strbuf_puts(buf, "\n");
1640 nl = TRUE;
1641 }
1642
1643 pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
1644 }
1645
1646 if ((source = pa_namereg_get_default_source(c))) {
1647 if (!nl)
1648 pa_strbuf_puts(buf, "\n");
1649
1650 pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
1651 }
1652
1653 pa_strbuf_puts(buf, "\n### EOF\n");
1654
1655 return 0;
1656 }
1657
1658 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) {
1659 const char *cs;
1660
1661 pa_assert(c);
1662 pa_assert(s);
1663 pa_assert(buf);
1664
1665 cs = s+strspn(s, whitespace);
1666
1667 if (*cs == '#' || !*cs)
1668 return 0;
1669 else if (*cs == '.') {
1670 if (!strcmp(cs, META_ELSE)) {
1671 if (!ifstate || *ifstate == IFSTATE_NONE) {
1672 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1673 return -1;
1674 } else if (*ifstate == IFSTATE_TRUE)
1675 *ifstate = IFSTATE_FALSE;
1676 else
1677 *ifstate = IFSTATE_TRUE;
1678 return 0;
1679 } else if (!strcmp(cs, META_ENDIF)) {
1680 if (!ifstate || *ifstate == IFSTATE_NONE) {
1681 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1682 return -1;
1683 } else
1684 *ifstate = IFSTATE_NONE;
1685 return 0;
1686 }
1687 if (ifstate && *ifstate == IFSTATE_FALSE)
1688 return 0;
1689 if (!strcmp(cs, META_FAIL))
1690 *fail = TRUE;
1691 else if (!strcmp(cs, META_NOFAIL))
1692 *fail = FALSE;
1693 else {
1694 size_t l;
1695 l = strcspn(cs, whitespace);
1696
1697 if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
1698 struct stat st;
1699 const char *filename = cs+l+strspn(cs+l, whitespace);
1700
1701 if (stat(filename, &st) < 0) {
1702 pa_log_warn("stat('%s'): %s", filename, pa_cstrerror(errno));
1703 if (*fail)
1704 return -1;
1705 } else {
1706 if (S_ISDIR(st.st_mode)) {
1707 DIR *d;
1708
1709 if (!(d = opendir(filename))) {
1710 pa_log_warn("Failed to read '%s': %s", filename, pa_cstrerror(errno));
1711 if (*fail)
1712 return -1;
1713 } else {
1714 unsigned i, count;
1715 char **sorted_files;
1716 struct dirent *de;
1717 pa_bool_t failed = FALSE;
1718 pa_dynarray *files = pa_dynarray_new();
1719
1720 while ((de = readdir(d))) {
1721 char *extn;
1722 size_t flen = strlen(de->d_name);
1723
1724 if (flen < 4)
1725 continue;
1726
1727 extn = &de->d_name[flen-3];
1728 if (strncmp(extn, ".pa", 3) == 0)
1729 pa_dynarray_append(files, pa_sprintf_malloc("%s" PA_PATH_SEP "%s", filename, de->d_name));
1730 }
1731
1732 closedir(d);
1733
1734 count = pa_dynarray_size(files);
1735 sorted_files = pa_xnew(char*, count);
1736 for (i = 0; i < count; ++i)
1737 sorted_files[i] = pa_dynarray_get(files, i);
1738 pa_dynarray_free(files, NULL, NULL);
1739
1740 for (i = 0; i < count; ++i) {
1741 for (unsigned j = 0; j < count; ++j) {
1742 if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
1743 char *tmp = sorted_files[i];
1744 sorted_files[i] = sorted_files[j];
1745 sorted_files[j] = tmp;
1746 }
1747 }
1748 }
1749
1750 for (i = 0; i < count; ++i) {
1751 if (!failed) {
1752 if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
1753 failed = TRUE;
1754 }
1755
1756 pa_xfree(sorted_files[i]);
1757 }
1758 pa_xfree(sorted_files);
1759 if (failed)
1760 return -1;
1761 }
1762 } else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
1763 return -1;
1764 }
1765 }
1766 } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
1767 if (!ifstate) {
1768 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1769 return -1;
1770 } else if (*ifstate != IFSTATE_NONE) {
1771 pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs);
1772 return -1;
1773 } else {
1774 const char *filename = cs+l+strspn(cs+l, whitespace);
1775
1776 /* Search DL_SEARCH_PATH unless the filename is absolute */
1777 if (filename[0] == PA_PATH_SEP_CHAR) {
1778
1779 *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1780 pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1781
1782 } else {
1783 const char *paths, *state = NULL;
1784 char *p;
1785
1786 if (!(paths = lt_dlgetsearchpath()))
1787 return -1;
1788
1789 while ((p = pa_split(paths, ":", &state))) {
1790 char *pathname;
1791
1792 pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
1793 pa_xfree(p);
1794
1795 *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1796 pa_log_debug("Checking for existance of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1797
1798 pa_xfree(pathname);
1799
1800 if (*ifstate == IFSTATE_TRUE)
1801 break;
1802 }
1803 }
1804
1805 }
1806 } else {
1807 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
1808 if (*fail) return -1;
1809 }
1810 }
1811 } else {
1812 const struct command*command;
1813 int unknown = 1;
1814 size_t l;
1815
1816 if (ifstate && *ifstate == IFSTATE_FALSE)
1817 return 0;
1818
1819 l = strcspn(cs, whitespace);
1820
1821 for (command = commands; command->name; command++)
1822 if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
1823 int ret;
1824 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
1825 pa_assert(t);
1826 ret = command->proc(c, t, buf, fail);
1827 pa_tokenizer_free(t);
1828 unknown = 0;
1829
1830 if (ret < 0 && *fail)
1831 return -1;
1832
1833 break;
1834 }
1835
1836 if (unknown) {
1837 pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
1838 if (*fail)
1839 return -1;
1840 }
1841 }
1842
1843 return 0;
1844 }
1845
1846 int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
1847 return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
1848 }
1849
1850 int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
1851 char line[2048];
1852 int ifstate = IFSTATE_NONE;
1853 int ret = -1;
1854 pa_bool_t _fail = TRUE;
1855
1856 pa_assert(c);
1857 pa_assert(f);
1858 pa_assert(buf);
1859
1860 if (!fail)
1861 fail = &_fail;
1862
1863 while (fgets(line, sizeof(line), f)) {
1864 pa_strip_nl(line);
1865
1866 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
1867 goto fail;
1868 }
1869
1870 ret = 0;
1871
1872 fail:
1873
1874 return ret;
1875 }
1876
1877 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
1878 FILE *f = NULL;
1879 int ret = -1;
1880 pa_bool_t _fail = TRUE;
1881
1882 pa_assert(c);
1883 pa_assert(fn);
1884 pa_assert(buf);
1885
1886 if (!fail)
1887 fail = &_fail;
1888
1889 if (!(f = pa_fopen_cloexec(fn, "r"))) {
1890 pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
1891 if (!*fail)
1892 ret = 0;
1893 goto fail;
1894 }
1895
1896 pa_log_debug("Parsing script '%s'", fn);
1897 ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
1898
1899 fail:
1900 if (f)
1901 fclose(f);
1902
1903 return ret;
1904 }
1905
1906 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
1907 const char *p;
1908 int ifstate = IFSTATE_NONE;
1909 pa_bool_t _fail = TRUE;
1910
1911 pa_assert(c);
1912 pa_assert(s);
1913 pa_assert(buf);
1914
1915 if (!fail)
1916 fail = &_fail;
1917
1918 p = s;
1919 while (*p) {
1920 size_t l = strcspn(p, linebreak);
1921 char *line = pa_xstrndup(p, l);
1922
1923 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) {
1924 pa_xfree(line);
1925 return -1;
1926 }
1927 pa_xfree(line);
1928
1929 p += l;
1930 p += strspn(p, linebreak);
1931 }
1932
1933 return 0;
1934 }