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