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