2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
36 #include <pulse/xmalloc.h>
37 #include <pulse/error.h>
39 #include <pulsecore/module.h>
40 #include <pulsecore/sink.h>
41 #include <pulsecore/source.h>
42 #include <pulsecore/client.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/source-output.h>
45 #include <pulsecore/tokenizer.h>
46 #include <pulsecore/strbuf.h>
47 #include <pulsecore/namereg.h>
48 #include <pulsecore/cli-text.h>
49 #include <pulsecore/core-scache.h>
50 #include <pulsecore/sample-util.h>
51 #include <pulsecore/sound-file.h>
52 #include <pulsecore/play-memchunk.h>
53 #include <pulsecore/sound-file-stream.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/core-util.h>
56 #include <pulsecore/core-error.h>
57 #include <pulsecore/modinfo.h>
58 #include <pulsecore/dynarray.h>
60 #include "cli-command.h"
64 int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, pa_bool_t *fail);
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"
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);
134 /* A method table for all available commands */
136 static const struct command commands[] = {
137 { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
138 { "help", pa_cli_command_help, "Show this help", 1 },
139 { "list-modules", pa_cli_command_modules, "List loaded modules", 1 },
140 { "list-sinks", pa_cli_command_sinks, "List loaded sinks", 1 },
141 { "list-sources", pa_cli_command_sources, "List loaded sources", 1 },
142 { "list-clients", pa_cli_command_clients, "List loaded clients", 1 },
143 { "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 },
144 { "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 },
145 { "list-cards", pa_cli_command_cards, "List cards", 1 },
146 { "stat", pa_cli_command_stat, "Show memory block statistics", 1 },
147 { "info", pa_cli_command_info, "Show comprehensive status", 1 },
148 { "ls", pa_cli_command_info, NULL, 1 },
149 { "list", pa_cli_command_info, NULL, 1 },
150 { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3},
151 { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2},
152 { "describe-module", pa_cli_command_describe, "Describe a module (arg: name)", 2},
153 { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3},
154 { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3},
155 { "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3},
156 { "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, bool)", 3},
157 { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3},
158 { "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, bool)", 3},
159 { "update-sink-proplist", pa_cli_command_update_sink_proplist, "Update the properties of a sink (args: index|name, properties)", 3},
160 { "update-source-proplist", pa_cli_command_update_source_proplist, "Update the properties of a source (args: index|name, properties)", 3},
161 { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist, "Update the properties of a sink input (args: index, properties)", 3},
162 { "update-source-output-proplist", pa_cli_command_update_source_output_proplist, "Update the properties of a source_output (args: index, properties)", 3},
163 { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2},
164 { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2},
165 { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
166 { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
167 { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
168 { "list-samples", pa_cli_command_scache_list, "List all entries in the sample cache", 1},
169 { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3},
170 { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2},
171 { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3},
172 { "load-sample-lazy", pa_cli_command_scache_load, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
173 { "load-sample-dir-lazy", pa_cli_command_scache_load_dir, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
174 { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3},
175 { "dump", pa_cli_command_dump, "Dump daemon configuration", 1},
176 { "shared", pa_cli_command_list_shared_props, NULL, 1},
177 { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3},
178 { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
179 { "vacuum", pa_cli_command_vacuum, NULL, 1},
180 { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3},
181 { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3},
182 { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2},
183 { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index, name)", 3},
184 { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index, name)", 3},
185 { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index, name)", 3},
186 { "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2},
187 { "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2},
188 { "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2},
189 { "set-log-backtrace", pa_cli_command_log_backtrace, "Show backtrace in log messages (args: frames)", 2},
190 { NULL, NULL, NULL, 0 }
193 static const char whitespace[] = " \t\n\r";
194 static const char linebreak[] = "\n\r";
196 static uint32_t parse_index(const char *n) {
199 if (pa_atou(n, &idx) < 0)
200 return (uint32_t) PA_IDXSET_INVALID;
205 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
206 pa_core_assert_ref(c);
211 if (pa_core_exit(c, FALSE, 0) < 0)
212 pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n");
217 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
218 const struct command*command;
220 pa_core_assert_ref(c);
225 pa_strbuf_puts(buf, "Available commands:\n");
227 for (command = commands; command->name; command++)
229 pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help);
233 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
236 pa_core_assert_ref(c);
241 pa_assert_se(s = pa_module_list_to_string(c));
242 pa_strbuf_puts(buf, s);
247 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
250 pa_core_assert_ref(c);
255 pa_assert_se(s = pa_client_list_to_string(c));
256 pa_strbuf_puts(buf, s);
261 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
264 pa_core_assert_ref(c);
269 pa_assert_se(s = pa_card_list_to_string(c));
270 pa_strbuf_puts(buf, s);
275 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
278 pa_core_assert_ref(c);
283 pa_assert_se(s = pa_sink_list_to_string(c));
284 pa_strbuf_puts(buf, s);
289 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
292 pa_core_assert_ref(c);
297 pa_assert_se(s = pa_source_list_to_string(c));
298 pa_strbuf_puts(buf, s);
303 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
306 pa_core_assert_ref(c);
311 pa_assert_se(s = pa_sink_input_list_to_string(c));
312 pa_strbuf_puts(buf, s);
317 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
320 pa_core_assert_ref(c);
325 pa_assert_se(s = pa_source_output_list_to_string(c));
326 pa_strbuf_puts(buf, s);
331 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
332 char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
333 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
334 char bytes[PA_BYTES_SNPRINT_MAX];
335 const pa_mempool_stat *mstat;
338 pa_source *def_source;
340 static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = {
341 [PA_MEMBLOCK_POOL] = "POOL",
342 [PA_MEMBLOCK_POOL_EXTERNAL] = "POOL_EXTERNAL",
343 [PA_MEMBLOCK_APPENDED] = "APPENDED",
344 [PA_MEMBLOCK_USER] = "USER",
345 [PA_MEMBLOCK_FIXED] = "FIXED",
346 [PA_MEMBLOCK_IMPORTED] = "IMPORTED",
349 pa_core_assert_ref(c);
354 mstat = pa_mempool_get_stat(c->mempool);
356 pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
357 (unsigned) pa_atomic_load(&mstat->n_allocated),
358 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->allocated_size)));
360 pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
361 (unsigned) pa_atomic_load(&mstat->n_accumulated),
362 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->accumulated_size)));
364 pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
365 (unsigned) pa_atomic_load(&mstat->n_imported),
366 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->imported_size)));
368 pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
369 (unsigned) pa_atomic_load(&mstat->n_exported),
370 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->exported_size)));
372 pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
373 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
375 pa_strbuf_printf(buf, "Default sample spec: %s\n",
376 pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
378 pa_strbuf_printf(buf, "Default channel map: %s\n",
379 pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
381 def_sink = pa_namereg_get_default_sink(c);
382 def_source = pa_namereg_get_default_source(c);
383 pa_strbuf_printf(buf, "Default sink name: %s\n"
384 "Default source name: %s\n",
385 def_sink ? def_sink->name : "none",
386 def_source ? def_source->name : "none");
388 for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++)
389 pa_strbuf_printf(buf,
390 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
392 (unsigned) pa_atomic_load(&mstat->n_allocated_by_type[k]),
393 (unsigned) pa_atomic_load(&mstat->n_accumulated_by_type[k]));
398 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
399 pa_core_assert_ref(c);
404 pa_cli_command_stat(c, t, buf, fail);
405 pa_cli_command_modules(c, t, buf, fail);
406 pa_cli_command_sinks(c, t, buf, fail);
407 pa_cli_command_sources(c, t, buf, fail);
408 pa_cli_command_clients(c, t, buf, fail);
409 pa_cli_command_cards(c, t, buf, fail);
410 pa_cli_command_sink_inputs(c, t, buf, fail);
411 pa_cli_command_source_outputs(c, t, buf, fail);
412 pa_cli_command_scache_list(c, t, buf, fail);
416 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
419 pa_core_assert_ref(c);
424 if (!(name = pa_tokenizer_get(t, 1))) {
425 pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
429 if (!pa_module_load(c, name, pa_tokenizer_get(t, 2))) {
430 pa_strbuf_puts(buf, "Module load failed.\n");
437 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
443 pa_core_assert_ref(c);
448 if (!(i = pa_tokenizer_get(t, 1))) {
449 pa_strbuf_puts(buf, "You need to specify the module index.\n");
453 idx = (uint32_t) strtoul(i, &e, 10);
454 if (*e || !(m = pa_idxset_get_by_index(c->modules, idx))) {
455 pa_strbuf_puts(buf, "Invalid module index.\n");
459 pa_module_unload_request(m, FALSE);
463 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
467 pa_core_assert_ref(c);
472 if (!(name = pa_tokenizer_get(t, 1))) {
473 pa_strbuf_puts(buf, "You need to specify the module name.\n");
477 if ((i = pa_modinfo_get_by_name(name))) {
479 pa_strbuf_printf(buf, "Name: %s\n", name);
481 if (!i->description && !i->version && !i->author && !i->usage)
482 pa_strbuf_printf(buf, "No module information available\n");
485 pa_strbuf_printf(buf, "Version: %s\n", i->version);
487 pa_strbuf_printf(buf, "Description: %s\n", i->description);
489 pa_strbuf_printf(buf, "Author: %s\n", i->author);
491 pa_strbuf_printf(buf, "Usage: %s\n", i->usage);
492 pa_strbuf_printf(buf, "Load Once: %s\n", pa_yes_no(i->load_once));
494 pa_strbuf_printf(buf, "Warning, deprecated: %s\n", i->deprecated);
499 pa_strbuf_puts(buf, "Failed to open module.\n");
504 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
510 pa_core_assert_ref(c);
515 if (!(n = pa_tokenizer_get(t, 1))) {
516 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
520 if (!(v = pa_tokenizer_get(t, 2))) {
521 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
525 if (pa_atou(v, &volume) < 0) {
526 pa_strbuf_puts(buf, "Failed to parse volume.\n");
530 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
531 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
535 pa_cvolume_set(&cvolume, 1, volume);
536 pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
540 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
547 pa_core_assert_ref(c);
552 if (!(n = pa_tokenizer_get(t, 1))) {
553 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
557 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
558 pa_strbuf_puts(buf, "Failed to parse index.\n");
562 if (!(v = pa_tokenizer_get(t, 2))) {
563 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
567 if (pa_atou(v, &volume) < 0) {
568 pa_strbuf_puts(buf, "Failed to parse volume.\n");
572 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
573 pa_strbuf_puts(buf, "No sink input found with this index.\n");
577 pa_cvolume_set(&cvolume, 1, volume);
578 pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
582 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
588 pa_core_assert_ref(c);
593 if (!(n = pa_tokenizer_get(t, 1))) {
594 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
598 if (!(v = pa_tokenizer_get(t, 2))) {
599 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
603 if (pa_atou(v, &volume) < 0) {
604 pa_strbuf_puts(buf, "Failed to parse volume.\n");
608 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
609 pa_strbuf_puts(buf, "No source found by this name or index.\n");
613 pa_cvolume_set(&cvolume, 1, volume);
614 pa_source_set_volume(source, &cvolume, TRUE);
618 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
623 pa_core_assert_ref(c);
628 if (!(n = pa_tokenizer_get(t, 1))) {
629 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
633 if (!(m = pa_tokenizer_get(t, 2))) {
634 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
638 if ((mute = pa_parse_boolean(m)) < 0) {
639 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
643 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
644 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
648 pa_sink_set_mute(sink, mute, TRUE);
652 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
657 pa_core_assert_ref(c);
662 if (!(n = pa_tokenizer_get(t, 1))) {
663 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
667 if (!(m = pa_tokenizer_get(t, 2))) {
668 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
672 if ((mute = pa_parse_boolean(m)) < 0) {
673 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
677 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
678 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
682 pa_source_set_mute(source, mute, TRUE);
686 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
691 pa_core_assert_ref(c);
696 if (!(n = pa_tokenizer_get(t, 1))) {
697 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
701 if (!(s = pa_tokenizer_get(t, 2))) {
702 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
706 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
707 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
711 if (!(p = pa_proplist_from_string(s))) {
712 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
716 pa_sink_update_proplist(sink, PA_UPDATE_REPLACE, p);
723 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
728 pa_core_assert_ref(c);
733 if (!(n = pa_tokenizer_get(t, 1))) {
734 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
738 if (!(s = pa_tokenizer_get(t, 2))) {
739 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
743 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
744 pa_strbuf_puts(buf, "No source found by this name or index.\n");
748 if (!(p = pa_proplist_from_string(s))) {
749 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
753 pa_source_update_proplist(source, PA_UPDATE_REPLACE, p);
760 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
766 pa_core_assert_ref(c);
771 if (!(n = pa_tokenizer_get(t, 1))) {
772 pa_strbuf_puts(buf, "You need to specify a sink input either by index.\n");
776 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
777 pa_strbuf_puts(buf, "Failed to parse index.\n");
781 if (!(s = pa_tokenizer_get(t, 2))) {
782 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
786 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
787 pa_strbuf_puts(buf, "No sink input found with this index.\n");
791 if (!(p = pa_proplist_from_string(s))) {
792 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
796 pa_sink_input_update_proplist(si, PA_UPDATE_REPLACE, p);
803 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
805 pa_source_output *so;
809 pa_core_assert_ref(c);
814 if (!(n = pa_tokenizer_get(t, 1))) {
815 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
819 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
820 pa_strbuf_puts(buf, "Failed to parse index.\n");
824 if (!(s = pa_tokenizer_get(t, 2))) {
825 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
829 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
830 pa_strbuf_puts(buf, "No source output found with this index.\n");
834 if (!(p = pa_proplist_from_string(s))) {
835 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
839 pa_source_output_update_proplist(so, PA_UPDATE_REPLACE, p);
846 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
852 pa_core_assert_ref(c);
857 if (!(n = pa_tokenizer_get(t, 1))) {
858 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
862 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
863 pa_strbuf_puts(buf, "Failed to parse index.\n");
867 if (!(v = pa_tokenizer_get(t, 2))) {
868 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
872 if ((mute = pa_parse_boolean(v)) < 0) {
873 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
877 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
878 pa_strbuf_puts(buf, "No sink input found with this index.\n");
882 pa_sink_input_set_mute(si, mute, TRUE);
886 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
890 pa_core_assert_ref(c);
895 if (!(n = pa_tokenizer_get(t, 1))) {
896 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
900 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
901 pa_namereg_set_default_sink(c, s);
903 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
908 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
912 pa_core_assert_ref(c);
917 if (!(n = pa_tokenizer_get(t, 1))) {
918 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
922 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SOURCE)))
923 pa_namereg_set_default_source(c, s);
925 pa_strbuf_printf(buf, "Source %s does not exist.\n", n);
929 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
934 pa_core_assert_ref(c);
939 if (!(n = pa_tokenizer_get(t, 1))) {
940 pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
944 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
945 pa_strbuf_puts(buf, "Failed to parse index.\n");
949 if (!(client = pa_idxset_get_by_index(c->clients, idx))) {
950 pa_strbuf_puts(buf, "No client found by this index.\n");
954 pa_client_kill(client);
958 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
960 pa_sink_input *sink_input;
963 pa_core_assert_ref(c);
968 if (!(n = pa_tokenizer_get(t, 1))) {
969 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
973 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
974 pa_strbuf_puts(buf, "Failed to parse index.\n");
978 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) {
979 pa_strbuf_puts(buf, "No sink input found by this index.\n");
983 pa_sink_input_kill(sink_input);
987 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
989 pa_source_output *source_output;
992 pa_core_assert_ref(c);
997 if (!(n = pa_tokenizer_get(t, 1))) {
998 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1002 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1003 pa_strbuf_puts(buf, "Failed to parse index.\n");
1007 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) {
1008 pa_strbuf_puts(buf, "No source output found by this index.\n");
1012 pa_source_output_kill(source_output);
1016 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1019 pa_core_assert_ref(c);
1024 pa_assert_se(s = pa_scache_list_to_string(c));
1025 pa_strbuf_puts(buf, s);
1031 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1032 const char *n, *sink_name;
1036 pa_core_assert_ref(c);
1041 if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1042 pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
1046 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1047 pa_strbuf_puts(buf, "No sink by that name.\n");
1051 if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
1052 pa_strbuf_puts(buf, "Failed to play sample.\n");
1056 pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
1061 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1064 pa_core_assert_ref(c);
1069 if (!(n = pa_tokenizer_get(t, 1))) {
1070 pa_strbuf_puts(buf, "You need to specify a sample name.\n");
1074 if (pa_scache_remove_item(c, n) < 0) {
1075 pa_strbuf_puts(buf, "Failed to remove sample.\n");
1082 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1083 const char *fname, *n;
1086 pa_core_assert_ref(c);
1091 if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
1092 pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
1096 if (strstr(pa_tokenizer_get(t, 0), "lazy"))
1097 r = pa_scache_add_file_lazy(c, n, fname, NULL);
1099 r = pa_scache_add_file(c, n, fname, NULL);
1102 pa_strbuf_puts(buf, "Failed to load sound file.\n");
1107 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1110 pa_core_assert_ref(c);
1115 if (!(pname = pa_tokenizer_get(t, 1))) {
1116 pa_strbuf_puts(buf, "You need to specify a path name.\n");
1120 if (pa_scache_add_directory_lazy(c, pname) < 0) {
1121 pa_strbuf_puts(buf, "Failed to load directory.\n");
1128 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1129 const char *fname, *sink_name;
1132 pa_core_assert_ref(c);
1137 if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1138 pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
1142 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1143 pa_strbuf_puts(buf, "No sink by that name.\n");
1148 return pa_play_file(sink, fname, NULL);
1151 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1152 pa_core_assert_ref(c);
1157 pa_shared_dump(c, buf);
1161 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1162 pa_core_assert_ref(c);
1167 pa_mempool_vacuum(c->mempool);
1172 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1178 pa_core_assert_ref(c);
1183 if (!(n = pa_tokenizer_get(t, 1))) {
1184 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1188 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1189 pa_strbuf_puts(buf, "Failed to parse index.\n");
1193 if (!(k = pa_tokenizer_get(t, 2))) {
1194 pa_strbuf_puts(buf, "You need to specify a sink.\n");
1198 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
1199 pa_strbuf_puts(buf, "No sink input found with this index.\n");
1203 if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK))) {
1204 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1208 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
1209 pa_strbuf_puts(buf, "Moved failed.\n");
1215 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1217 pa_source_output *so;
1221 pa_core_assert_ref(c);
1226 if (!(n = pa_tokenizer_get(t, 1))) {
1227 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1231 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1232 pa_strbuf_puts(buf, "Failed to parse index.\n");
1236 if (!(k = pa_tokenizer_get(t, 2))) {
1237 pa_strbuf_puts(buf, "You need to specify a source.\n");
1241 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1242 pa_strbuf_puts(buf, "No source output found with this index.\n");
1246 if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE))) {
1247 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1251 if (pa_source_output_move_to(so, source, TRUE) < 0) {
1252 pa_strbuf_puts(buf, "Moved failed.\n");
1258 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1263 pa_core_assert_ref(c);
1268 if (!(n = pa_tokenizer_get(t, 1))) {
1269 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1273 if (!(m = pa_tokenizer_get(t, 2))) {
1274 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1278 if ((suspend = pa_parse_boolean(m)) < 0) {
1279 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1283 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1284 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1288 if ((r = pa_sink_suspend(sink, suspend, PA_SUSPEND_USER)) < 0)
1289 pa_strbuf_printf(buf, "Failed to resume/suspend sink: %s\n", pa_strerror(r));
1294 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1299 pa_core_assert_ref(c);
1304 if (!(n = pa_tokenizer_get(t, 1))) {
1305 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1309 if (!(m = pa_tokenizer_get(t, 2))) {
1310 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1314 if ((suspend = pa_parse_boolean(m)) < 0) {
1315 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1319 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1320 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1324 if ((r = pa_source_suspend(source, suspend, PA_SUSPEND_USER)) < 0)
1325 pa_strbuf_printf(buf, "Failed to resume/suspend source: %s\n", pa_strerror(r));
1330 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1334 pa_core_assert_ref(c);
1339 if (!(m = pa_tokenizer_get(t, 1))) {
1340 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1344 if ((suspend = pa_parse_boolean(m)) < 0) {
1345 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1349 if ((r = pa_sink_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1350 pa_strbuf_printf(buf, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r));
1352 if ((r = pa_source_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1353 pa_strbuf_printf(buf, "Failed to resume/suspend all sources: %s\n", pa_strerror(r));
1358 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1362 pa_core_assert_ref(c);
1367 if (!(m = pa_tokenizer_get(t, 1))) {
1368 pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n");
1372 if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) {
1373 pa_strbuf_puts(buf, "Failed to parse log level.\n");
1377 pa_log_set_level(level);
1382 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1386 pa_core_assert_ref(c);
1391 if (!(m = pa_tokenizer_get(t, 1))) {
1392 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1396 if ((b = pa_parse_boolean(m)) < 0) {
1397 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1401 pa_log_set_flags(PA_LOG_PRINT_META, b ? PA_LOG_SET : PA_LOG_UNSET);
1406 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1410 pa_core_assert_ref(c);
1415 if (!(m = pa_tokenizer_get(t, 1))) {
1416 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1420 if ((b = pa_parse_boolean(m)) < 0) {
1421 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1425 pa_log_set_flags(PA_LOG_PRINT_TIME, b ? PA_LOG_SET : PA_LOG_UNSET);
1430 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1434 pa_core_assert_ref(c);
1439 if (!(m = pa_tokenizer_get(t, 1))) {
1440 pa_strbuf_puts(buf, "You need to specify a backtrace level.\n");
1444 if (pa_atou(m, &nframes) < 0 || nframes >= 1000) {
1445 pa_strbuf_puts(buf, "Failed to parse backtrace level.\n");
1449 pa_log_set_show_backtrace(nframes);
1454 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1458 pa_core_assert_ref(c);
1463 if (!(n = pa_tokenizer_get(t, 1))) {
1464 pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1468 if (!(p = pa_tokenizer_get(t, 2))) {
1469 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1473 if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1474 pa_strbuf_puts(buf, "No card found by this name or index.\n");
1478 if (pa_card_set_profile(card, p, TRUE) < 0) {
1479 pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
1486 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1490 pa_core_assert_ref(c);
1495 if (!(n = pa_tokenizer_get(t, 1))) {
1496 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1500 if (!(p = pa_tokenizer_get(t, 2))) {
1501 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1505 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1506 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1510 if (pa_sink_set_port(sink, p, TRUE) < 0) {
1511 pa_strbuf_printf(buf, "Failed to set sink port to '%s'.\n", p);
1518 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1522 pa_core_assert_ref(c);
1527 if (!(n = pa_tokenizer_get(t, 1))) {
1528 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1532 if (!(p = pa_tokenizer_get(t, 2))) {
1533 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1537 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1538 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1542 if (pa_source_set_port(source, p, TRUE) < 0) {
1543 pa_strbuf_printf(buf, "Failed to set source port to '%s'.\n", p);
1550 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1560 pa_core_assert_ref(c);
1568 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
1570 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
1573 PA_IDXSET_FOREACH(m, c->modules, idx) {
1575 pa_strbuf_printf(buf, "load-module %s", m->name);
1578 pa_strbuf_printf(buf, " %s", m->argument);
1580 pa_strbuf_puts(buf, "\n");
1584 PA_IDXSET_FOREACH(sink, c->sinks, idx) {
1587 pa_strbuf_puts(buf, "\n");
1591 pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, FALSE)));
1592 pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
1593 pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
1597 PA_IDXSET_FOREACH(source, c->sources, idx) {
1600 pa_strbuf_puts(buf, "\n");
1604 pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, FALSE)));
1605 pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
1606 pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
1610 PA_IDXSET_FOREACH(card, c->cards, idx) {
1613 pa_strbuf_puts(buf, "\n");
1617 if (card->active_profile)
1618 pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
1622 if ((sink = pa_namereg_get_default_sink(c))) {
1624 pa_strbuf_puts(buf, "\n");
1628 pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
1631 if ((source = pa_namereg_get_default_source(c))) {
1633 pa_strbuf_puts(buf, "\n");
1635 pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
1638 pa_strbuf_puts(buf, "\n### EOF\n");
1643 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) {
1650 cs = s+strspn(s, whitespace);
1652 if (*cs == '#' || !*cs)
1654 else if (*cs == '.') {
1655 if (!strcmp(cs, META_ELSE)) {
1656 if (!ifstate || *ifstate == IFSTATE_NONE) {
1657 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1659 } else if (*ifstate == IFSTATE_TRUE)
1660 *ifstate = IFSTATE_FALSE;
1662 *ifstate = IFSTATE_TRUE;
1664 } else if (!strcmp(cs, META_ENDIF)) {
1665 if (!ifstate || *ifstate == IFSTATE_NONE) {
1666 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1669 *ifstate = IFSTATE_NONE;
1672 if (ifstate && *ifstate == IFSTATE_FALSE)
1674 if (!strcmp(cs, META_FAIL))
1676 else if (!strcmp(cs, META_NOFAIL))
1680 l = strcspn(cs, whitespace);
1682 if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
1684 const char *filename = cs+l+strspn(cs+l, whitespace);
1686 if (stat(filename, &st) < 0) {
1687 pa_log_warn("stat('%s'): %s", filename, pa_cstrerror(errno));
1691 if (S_ISDIR(st.st_mode)) {
1694 if (!(d = opendir(filename))) {
1695 pa_log_warn("Failed to read '%s': %s", filename, pa_cstrerror(errno));
1700 char **sorted_files;
1702 pa_bool_t failed = FALSE;
1703 pa_dynarray *files = pa_dynarray_new();
1705 while ((de = readdir(d))) {
1707 size_t flen = strlen(de->d_name);
1712 extn = &de->d_name[flen-3];
1713 if (strncmp(extn, ".pa", 3) == 0)
1714 pa_dynarray_append(files, pa_sprintf_malloc("%s" PA_PATH_SEP "%s", filename, de->d_name));
1719 count = pa_dynarray_size(files);
1720 sorted_files = pa_xnew(char*, count);
1721 for (i = 0; i < count; ++i)
1722 sorted_files[i] = pa_dynarray_get(files, i);
1723 pa_dynarray_free(files, NULL, NULL);
1725 for (i = 0; i < count; ++i) {
1726 for (unsigned j = 0; j < count; ++j) {
1727 if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
1728 char *tmp = sorted_files[i];
1729 sorted_files[i] = sorted_files[j];
1730 sorted_files[j] = tmp;
1735 for (i = 0; i < count; ++i) {
1737 if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
1741 pa_xfree(sorted_files[i]);
1743 pa_xfree(sorted_files);
1747 } else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
1751 } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
1753 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1755 } else if (*ifstate != IFSTATE_NONE) {
1756 pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs);
1759 const char *filename = cs+l+strspn(cs+l, whitespace);
1761 /* Search DL_SEARCH_PATH unless the filename is absolute */
1762 if (filename[0] == PA_PATH_SEP_CHAR) {
1764 *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1765 pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1768 const char *paths, *state = NULL;
1771 if (!(paths = lt_dlgetsearchpath()))
1774 while ((p = pa_split(paths, ":", &state))) {
1777 pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
1780 *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1781 pa_log_debug("Checking for existance of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1785 if (*ifstate == IFSTATE_TRUE)
1792 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
1793 if (*fail) return -1;
1797 const struct command*command;
1801 if (ifstate && *ifstate == IFSTATE_FALSE)
1804 l = strcspn(cs, whitespace);
1806 for (command = commands; command->name; command++)
1807 if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
1809 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
1811 ret = command->proc(c, t, buf, fail);
1812 pa_tokenizer_free(t);
1815 if (ret < 0 && *fail)
1822 pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
1831 int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
1832 return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
1835 int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
1837 int ifstate = IFSTATE_NONE;
1839 pa_bool_t _fail = TRUE;
1848 while (fgets(line, sizeof(line), f)) {
1851 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
1862 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
1865 pa_bool_t _fail = TRUE;
1874 if (!(f = pa_fopen_cloexec(fn, "r"))) {
1875 pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
1881 pa_log_debug("Parsing script '%s'", fn);
1882 ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
1891 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
1893 int ifstate = IFSTATE_NONE;
1894 pa_bool_t _fail = TRUE;
1905 size_t l = strcspn(p, linebreak);
1906 char *line = pa_xstrndup(p, l);
1908 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) {
1915 p += strspn(p, linebreak);