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
37 #include <pulse/xmalloc.h>
38 #include <pulse/error.h>
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>
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_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
100 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
101 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
102 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
103 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
104 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
105 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
106 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
107 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
108 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
109 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
110 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
111 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
112 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
113 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
114 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
115 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
116 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
117 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
118 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
119 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
120 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
121 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
122 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
123 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
124 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
125 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
126 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
127 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
128 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
129 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
130 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
131 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
132 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
133 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
134 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
135 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
137 /* A method table for all available commands */
139 static const struct command commands[] = {
140 { "help", pa_cli_command_help, "Show this help", 1 },
141 { "list-modules", pa_cli_command_modules, "List loaded modules", 1 },
142 { "list-cards", pa_cli_command_cards, "List cards", 1 },
143 { "list-sinks", pa_cli_command_sinks, "List loaded sinks", 1 },
144 { "list-sources", pa_cli_command_sources, "List loaded sources", 1 },
145 { "list-clients", pa_cli_command_clients, "List loaded clients", 1 },
146 { "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 },
147 { "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 },
148 { "stat", pa_cli_command_stat, "Show memory block statistics", 1 },
149 { "info", pa_cli_command_info, "Show comprehensive status", 1 },
150 { "ls", pa_cli_command_info, NULL, 1 },
151 { "list", pa_cli_command_info, NULL, 1 },
152 { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3},
153 { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2},
154 { "describe-module", pa_cli_command_describe, "Describe a module (arg: name)", 2},
155 { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, 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-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, bool)", 3},
159 { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3},
160 { "set-source-output-volume",pa_cli_command_source_output_volume,"Set the volume of a source output (args: index, volume)", 3},
161 { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3},
162 { "set-source-output-mute", pa_cli_command_source_output_mute, "Set the mute switch of a source output (args: index, bool)", 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 { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index|name, profile-name)", 3},
166 { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index|name, port-name)", 3},
167 { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index|name, port-name)", 3},
168 { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3},
169 { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3},
170 { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2},
171 { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3},
172 { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
173 { "update-sink-proplist", pa_cli_command_update_sink_proplist, "Update the properties of a sink (args: index|name, properties)", 3},
174 { "update-source-proplist", pa_cli_command_update_source_proplist, "Update the properties of a source (args: index|name, properties)", 3},
175 { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist, "Update the properties of a sink input (args: index, properties)", 3},
176 { "update-source-output-proplist", pa_cli_command_update_source_output_proplist, "Update the properties of a source output (args: index, properties)", 3},
177 { "list-samples", pa_cli_command_scache_list, "List all entries in the sample cache", 1},
178 { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3},
179 { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2},
180 { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3},
181 { "load-sample-lazy", pa_cli_command_scache_load, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
182 { "load-sample-dir-lazy", pa_cli_command_scache_load_dir, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
183 { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
184 { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
185 { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
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 { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3},
191 { "dump", pa_cli_command_dump, "Dump daemon configuration", 1},
192 { "dump-volumes", pa_cli_command_dump_volumes, "Debug: Show the state of all volumes", 1 },
193 { "shared", pa_cli_command_list_shared_props, "Debug: Show shared properties", 1},
194 { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
195 { "vacuum", pa_cli_command_vacuum, NULL, 1},
196 { NULL, NULL, NULL, 0 }
199 static const char whitespace[] = " \t\n\r";
200 static const char linebreak[] = "\n\r";
202 static uint32_t parse_index(const char *n) {
205 if (pa_atou(n, &idx) < 0)
206 return (uint32_t) PA_IDXSET_INVALID;
211 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
212 pa_core_assert_ref(c);
217 if (pa_core_exit(c, FALSE, 0) < 0)
218 pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n");
223 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
224 const struct command*command;
226 pa_core_assert_ref(c);
231 pa_strbuf_puts(buf, "Available commands:\n");
233 for (command = commands; command->name; command++)
235 pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help);
239 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
242 pa_core_assert_ref(c);
247 pa_assert_se(s = pa_module_list_to_string(c));
248 pa_strbuf_puts(buf, s);
253 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
256 pa_core_assert_ref(c);
261 pa_assert_se(s = pa_client_list_to_string(c));
262 pa_strbuf_puts(buf, s);
267 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
270 pa_core_assert_ref(c);
275 pa_assert_se(s = pa_card_list_to_string(c));
276 pa_strbuf_puts(buf, s);
281 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
284 pa_core_assert_ref(c);
289 pa_assert_se(s = pa_sink_list_to_string(c));
290 pa_strbuf_puts(buf, s);
295 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
298 pa_core_assert_ref(c);
303 pa_assert_se(s = pa_source_list_to_string(c));
304 pa_strbuf_puts(buf, s);
309 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
312 pa_core_assert_ref(c);
317 pa_assert_se(s = pa_sink_input_list_to_string(c));
318 pa_strbuf_puts(buf, s);
323 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
326 pa_core_assert_ref(c);
331 pa_assert_se(s = pa_source_output_list_to_string(c));
332 pa_strbuf_puts(buf, s);
337 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
338 char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
339 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
340 char bytes[PA_BYTES_SNPRINT_MAX];
341 const pa_mempool_stat *mstat;
344 pa_source *def_source;
346 static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = {
347 [PA_MEMBLOCK_POOL] = "POOL",
348 [PA_MEMBLOCK_POOL_EXTERNAL] = "POOL_EXTERNAL",
349 [PA_MEMBLOCK_APPENDED] = "APPENDED",
350 [PA_MEMBLOCK_USER] = "USER",
351 [PA_MEMBLOCK_FIXED] = "FIXED",
352 [PA_MEMBLOCK_IMPORTED] = "IMPORTED",
355 pa_core_assert_ref(c);
360 mstat = pa_mempool_get_stat(c->mempool);
362 pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
363 (unsigned) pa_atomic_load(&mstat->n_allocated),
364 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->allocated_size)));
366 pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
367 (unsigned) pa_atomic_load(&mstat->n_accumulated),
368 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->accumulated_size)));
370 pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
371 (unsigned) pa_atomic_load(&mstat->n_imported),
372 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->imported_size)));
374 pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
375 (unsigned) pa_atomic_load(&mstat->n_exported),
376 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->exported_size)));
378 pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
379 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
381 pa_strbuf_printf(buf, "Default sample spec: %s\n",
382 pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
384 pa_strbuf_printf(buf, "Default channel map: %s\n",
385 pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
387 def_sink = pa_namereg_get_default_sink(c);
388 def_source = pa_namereg_get_default_source(c);
389 pa_strbuf_printf(buf, "Default sink name: %s\n"
390 "Default source name: %s\n",
391 def_sink ? def_sink->name : "none",
392 def_source ? def_source->name : "none");
394 for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++)
395 pa_strbuf_printf(buf,
396 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
398 (unsigned) pa_atomic_load(&mstat->n_allocated_by_type[k]),
399 (unsigned) pa_atomic_load(&mstat->n_accumulated_by_type[k]));
404 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
405 pa_core_assert_ref(c);
410 pa_cli_command_stat(c, t, buf, fail);
411 pa_cli_command_modules(c, t, buf, fail);
412 pa_cli_command_sinks(c, t, buf, fail);
413 pa_cli_command_sources(c, t, buf, fail);
414 pa_cli_command_clients(c, t, buf, fail);
415 pa_cli_command_cards(c, t, buf, fail);
416 pa_cli_command_sink_inputs(c, t, buf, fail);
417 pa_cli_command_source_outputs(c, t, buf, fail);
418 pa_cli_command_scache_list(c, t, buf, fail);
422 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
425 pa_core_assert_ref(c);
430 if (!(name = pa_tokenizer_get(t, 1))) {
431 pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
435 if (!pa_module_load(c, name, pa_tokenizer_get(t, 2))) {
436 pa_strbuf_puts(buf, "Module load failed.\n");
443 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
449 pa_core_assert_ref(c);
454 if (!(i = pa_tokenizer_get(t, 1))) {
455 pa_strbuf_puts(buf, "You need to specify the module index.\n");
459 idx = (uint32_t) strtoul(i, &e, 10);
460 if (*e || !(m = pa_idxset_get_by_index(c->modules, idx))) {
461 pa_strbuf_puts(buf, "Invalid module index.\n");
465 pa_module_unload_request(m, FALSE);
469 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
473 pa_core_assert_ref(c);
478 if (!(name = pa_tokenizer_get(t, 1))) {
479 pa_strbuf_puts(buf, "You need to specify the module name.\n");
483 if ((i = pa_modinfo_get_by_name(name))) {
485 pa_strbuf_printf(buf, "Name: %s\n", name);
487 if (!i->description && !i->version && !i->author && !i->usage)
488 pa_strbuf_printf(buf, "No module information available\n");
491 pa_strbuf_printf(buf, "Version: %s\n", i->version);
493 pa_strbuf_printf(buf, "Description: %s\n", i->description);
495 pa_strbuf_printf(buf, "Author: %s\n", i->author);
497 pa_strbuf_printf(buf, "Usage: %s\n", i->usage);
498 pa_strbuf_printf(buf, "Load Once: %s\n", pa_yes_no(i->load_once));
500 pa_strbuf_printf(buf, "Warning, deprecated: %s\n", i->deprecated);
505 pa_strbuf_puts(buf, "Failed to open module.\n");
510 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
516 pa_core_assert_ref(c);
521 if (!(n = pa_tokenizer_get(t, 1))) {
522 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
526 if (!(v = pa_tokenizer_get(t, 2))) {
527 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
531 if (pa_atou(v, &volume) < 0) {
532 pa_strbuf_puts(buf, "Failed to parse volume.\n");
536 if (!PA_VOLUME_IS_VALID(volume)) {
537 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
541 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
542 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
546 pa_cvolume_set(&cvolume, 1, volume);
547 pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
551 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
558 pa_core_assert_ref(c);
563 if (!(n = pa_tokenizer_get(t, 1))) {
564 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
568 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
569 pa_strbuf_puts(buf, "Failed to parse index.\n");
573 if (!(v = pa_tokenizer_get(t, 2))) {
574 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
578 if (pa_atou(v, &volume) < 0) {
579 pa_strbuf_puts(buf, "Failed to parse volume.\n");
583 if (!PA_VOLUME_IS_VALID(volume)) {
584 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
588 if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) {
589 pa_strbuf_puts(buf, "No sink input found with this index.\n");
593 if (!si->volume_writable) {
594 pa_strbuf_puts(buf, "This sink input's volume can't be changed.\n");
598 pa_cvolume_set(&cvolume, 1, volume);
599 pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
603 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
609 pa_core_assert_ref(c);
614 if (!(n = pa_tokenizer_get(t, 1))) {
615 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
619 if (!(v = pa_tokenizer_get(t, 2))) {
620 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
624 if (pa_atou(v, &volume) < 0) {
625 pa_strbuf_puts(buf, "Failed to parse volume.\n");
629 if (!PA_VOLUME_IS_VALID(volume)) {
630 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
634 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
635 pa_strbuf_puts(buf, "No source found by this name or index.\n");
639 pa_cvolume_set(&cvolume, 1, volume);
640 pa_source_set_volume(source, &cvolume, TRUE, TRUE);
644 static int pa_cli_command_source_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
646 pa_source_output *so;
651 pa_core_assert_ref(c);
656 if (!(n = pa_tokenizer_get(t, 1))) {
657 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
661 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
662 pa_strbuf_puts(buf, "Failed to parse index.\n");
666 if (!(v = pa_tokenizer_get(t, 2))) {
667 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
671 if (pa_atou(v, &volume) < 0) {
672 pa_strbuf_puts(buf, "Failed to parse volume.\n");
676 if (!PA_VOLUME_IS_VALID(volume)) {
677 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
681 if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) {
682 pa_strbuf_puts(buf, "No source output found with this index.\n");
686 if (!so->volume_writable) {
687 pa_strbuf_puts(buf, "This source output's volume can't be changed.\n");
691 pa_cvolume_set(&cvolume, 1, volume);
692 pa_source_output_set_volume(so, &cvolume, TRUE, TRUE);
696 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
701 pa_core_assert_ref(c);
706 if (!(n = pa_tokenizer_get(t, 1))) {
707 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
711 if (!(m = pa_tokenizer_get(t, 2))) {
712 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
716 if ((mute = pa_parse_boolean(m)) < 0) {
717 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
721 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
722 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
726 pa_sink_set_mute(sink, mute, TRUE);
730 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
735 pa_core_assert_ref(c);
740 if (!(n = pa_tokenizer_get(t, 1))) {
741 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
745 if (!(m = pa_tokenizer_get(t, 2))) {
746 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
750 if ((mute = pa_parse_boolean(m)) < 0) {
751 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
755 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
756 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
760 pa_source_set_mute(source, mute, TRUE);
764 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
769 pa_core_assert_ref(c);
774 if (!(n = pa_tokenizer_get(t, 1))) {
775 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
779 if (!(s = pa_tokenizer_get(t, 2))) {
780 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
784 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
785 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
789 if (!(p = pa_proplist_from_string(s))) {
790 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
794 pa_sink_update_proplist(sink, PA_UPDATE_REPLACE, p);
801 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
806 pa_core_assert_ref(c);
811 if (!(n = pa_tokenizer_get(t, 1))) {
812 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
816 if (!(s = pa_tokenizer_get(t, 2))) {
817 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
821 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
822 pa_strbuf_puts(buf, "No source found by this name or index.\n");
826 if (!(p = pa_proplist_from_string(s))) {
827 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
831 pa_source_update_proplist(source, PA_UPDATE_REPLACE, p);
838 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
844 pa_core_assert_ref(c);
849 if (!(n = pa_tokenizer_get(t, 1))) {
850 pa_strbuf_puts(buf, "You need to specify a sink input either by index.\n");
854 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
855 pa_strbuf_puts(buf, "Failed to parse index.\n");
859 if (!(s = pa_tokenizer_get(t, 2))) {
860 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
864 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
865 pa_strbuf_puts(buf, "No sink input found with this index.\n");
869 if (!(p = pa_proplist_from_string(s))) {
870 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
874 pa_sink_input_update_proplist(si, PA_UPDATE_REPLACE, p);
881 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
883 pa_source_output *so;
887 pa_core_assert_ref(c);
892 if (!(n = pa_tokenizer_get(t, 1))) {
893 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
897 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
898 pa_strbuf_puts(buf, "Failed to parse index.\n");
902 if (!(s = pa_tokenizer_get(t, 2))) {
903 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
907 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
908 pa_strbuf_puts(buf, "No source output found with this index.\n");
912 if (!(p = pa_proplist_from_string(s))) {
913 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
917 pa_source_output_update_proplist(so, PA_UPDATE_REPLACE, p);
924 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
930 pa_core_assert_ref(c);
935 if (!(n = pa_tokenizer_get(t, 1))) {
936 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
940 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
941 pa_strbuf_puts(buf, "Failed to parse index.\n");
945 if (!(v = pa_tokenizer_get(t, 2))) {
946 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
950 if ((mute = pa_parse_boolean(v)) < 0) {
951 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
955 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
956 pa_strbuf_puts(buf, "No sink input found with this index.\n");
960 pa_sink_input_set_mute(si, mute, TRUE);
964 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
966 pa_source_output *so;
970 pa_core_assert_ref(c);
975 if (!(n = pa_tokenizer_get(t, 1))) {
976 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
980 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
981 pa_strbuf_puts(buf, "Failed to parse index.\n");
985 if (!(v = pa_tokenizer_get(t, 2))) {
986 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
990 if ((mute = pa_parse_boolean(v)) < 0) {
991 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
995 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
996 pa_strbuf_puts(buf, "No source output found with this index.\n");
1000 pa_source_output_set_mute(so, mute, TRUE);
1004 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1008 pa_core_assert_ref(c);
1013 if (!(n = pa_tokenizer_get(t, 1))) {
1014 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1018 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
1019 pa_namereg_set_default_sink(c, s);
1021 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
1026 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1030 pa_core_assert_ref(c);
1035 if (!(n = pa_tokenizer_get(t, 1))) {
1036 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1040 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SOURCE)))
1041 pa_namereg_set_default_source(c, s);
1043 pa_strbuf_printf(buf, "Source %s does not exist.\n", n);
1047 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1052 pa_core_assert_ref(c);
1057 if (!(n = pa_tokenizer_get(t, 1))) {
1058 pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
1062 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1063 pa_strbuf_puts(buf, "Failed to parse index.\n");
1067 if (!(client = pa_idxset_get_by_index(c->clients, idx))) {
1068 pa_strbuf_puts(buf, "No client found by this index.\n");
1072 pa_client_kill(client);
1076 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1078 pa_sink_input *sink_input;
1081 pa_core_assert_ref(c);
1086 if (!(n = pa_tokenizer_get(t, 1))) {
1087 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1091 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1092 pa_strbuf_puts(buf, "Failed to parse index.\n");
1096 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) {
1097 pa_strbuf_puts(buf, "No sink input found by this index.\n");
1101 pa_sink_input_kill(sink_input);
1105 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1107 pa_source_output *source_output;
1110 pa_core_assert_ref(c);
1115 if (!(n = pa_tokenizer_get(t, 1))) {
1116 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1120 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1121 pa_strbuf_puts(buf, "Failed to parse index.\n");
1125 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) {
1126 pa_strbuf_puts(buf, "No source output found by this index.\n");
1130 pa_source_output_kill(source_output);
1134 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1137 pa_core_assert_ref(c);
1142 pa_assert_se(s = pa_scache_list_to_string(c));
1143 pa_strbuf_puts(buf, s);
1149 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1150 const char *n, *sink_name;
1154 pa_core_assert_ref(c);
1159 if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1160 pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
1164 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1165 pa_strbuf_puts(buf, "No sink by that name.\n");
1169 if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
1170 pa_strbuf_puts(buf, "Failed to play sample.\n");
1174 pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
1179 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1182 pa_core_assert_ref(c);
1187 if (!(n = pa_tokenizer_get(t, 1))) {
1188 pa_strbuf_puts(buf, "You need to specify a sample name.\n");
1192 if (pa_scache_remove_item(c, n) < 0) {
1193 pa_strbuf_puts(buf, "Failed to remove sample.\n");
1200 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1201 const char *fname, *n;
1204 pa_core_assert_ref(c);
1209 if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
1210 pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
1214 if (strstr(pa_tokenizer_get(t, 0), "lazy"))
1215 r = pa_scache_add_file_lazy(c, n, fname, NULL);
1217 r = pa_scache_add_file(c, n, fname, NULL);
1220 pa_strbuf_puts(buf, "Failed to load sound file.\n");
1225 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1228 pa_core_assert_ref(c);
1233 if (!(pname = pa_tokenizer_get(t, 1))) {
1234 pa_strbuf_puts(buf, "You need to specify a path name.\n");
1238 if (pa_scache_add_directory_lazy(c, pname) < 0) {
1239 pa_strbuf_puts(buf, "Failed to load directory.\n");
1246 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1247 const char *fname, *sink_name;
1250 pa_core_assert_ref(c);
1255 if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1256 pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
1260 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1261 pa_strbuf_puts(buf, "No sink by that name.\n");
1266 return pa_play_file(sink, fname, NULL);
1269 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1270 pa_core_assert_ref(c);
1275 pa_shared_dump(c, buf);
1279 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1280 pa_core_assert_ref(c);
1285 pa_mempool_vacuum(c->mempool);
1290 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1296 pa_core_assert_ref(c);
1301 if (!(n = pa_tokenizer_get(t, 1))) {
1302 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1306 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1307 pa_strbuf_puts(buf, "Failed to parse index.\n");
1311 if (!(k = pa_tokenizer_get(t, 2))) {
1312 pa_strbuf_puts(buf, "You need to specify a sink.\n");
1316 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
1317 pa_strbuf_puts(buf, "No sink input found with this index.\n");
1321 if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK))) {
1322 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1326 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
1327 pa_strbuf_puts(buf, "Moved failed.\n");
1333 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1335 pa_source_output *so;
1339 pa_core_assert_ref(c);
1344 if (!(n = pa_tokenizer_get(t, 1))) {
1345 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1349 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1350 pa_strbuf_puts(buf, "Failed to parse index.\n");
1354 if (!(k = pa_tokenizer_get(t, 2))) {
1355 pa_strbuf_puts(buf, "You need to specify a source.\n");
1359 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1360 pa_strbuf_puts(buf, "No source output found with this index.\n");
1364 if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE))) {
1365 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1369 if (pa_source_output_move_to(so, source, TRUE) < 0) {
1370 pa_strbuf_puts(buf, "Moved failed.\n");
1376 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1381 pa_core_assert_ref(c);
1386 if (!(n = pa_tokenizer_get(t, 1))) {
1387 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1391 if (!(m = pa_tokenizer_get(t, 2))) {
1392 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1396 if ((suspend = pa_parse_boolean(m)) < 0) {
1397 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1401 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1402 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1406 if ((r = pa_sink_suspend(sink, suspend, PA_SUSPEND_USER)) < 0)
1407 pa_strbuf_printf(buf, "Failed to resume/suspend sink: %s\n", pa_strerror(r));
1412 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1417 pa_core_assert_ref(c);
1422 if (!(n = pa_tokenizer_get(t, 1))) {
1423 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1427 if (!(m = pa_tokenizer_get(t, 2))) {
1428 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1432 if ((suspend = pa_parse_boolean(m)) < 0) {
1433 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1437 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1438 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1442 if ((r = pa_source_suspend(source, suspend, PA_SUSPEND_USER)) < 0)
1443 pa_strbuf_printf(buf, "Failed to resume/suspend source: %s\n", pa_strerror(r));
1448 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1452 pa_core_assert_ref(c);
1457 if (!(m = pa_tokenizer_get(t, 1))) {
1458 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1462 if ((suspend = pa_parse_boolean(m)) < 0) {
1463 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1467 if ((r = pa_sink_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1468 pa_strbuf_printf(buf, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r));
1470 if ((r = pa_source_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1471 pa_strbuf_printf(buf, "Failed to resume/suspend all sources: %s\n", pa_strerror(r));
1476 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1480 pa_core_assert_ref(c);
1485 if (!(m = pa_tokenizer_get(t, 1))) {
1486 pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n");
1490 if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) {
1491 pa_strbuf_puts(buf, "Failed to parse log level.\n");
1495 pa_log_set_level(level);
1500 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1504 pa_core_assert_ref(c);
1509 if (!(m = pa_tokenizer_get(t, 1))) {
1510 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1514 if ((b = pa_parse_boolean(m)) < 0) {
1515 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1519 pa_log_set_flags(PA_LOG_PRINT_META, b ? PA_LOG_SET : PA_LOG_UNSET);
1524 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1528 pa_core_assert_ref(c);
1533 if (!(m = pa_tokenizer_get(t, 1))) {
1534 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1538 if ((b = pa_parse_boolean(m)) < 0) {
1539 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1543 pa_log_set_flags(PA_LOG_PRINT_TIME, b ? PA_LOG_SET : PA_LOG_UNSET);
1548 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1552 pa_core_assert_ref(c);
1557 if (!(m = pa_tokenizer_get(t, 1))) {
1558 pa_strbuf_puts(buf, "You need to specify a backtrace level.\n");
1562 if (pa_atou(m, &nframes) < 0 || nframes >= 1000) {
1563 pa_strbuf_puts(buf, "Failed to parse backtrace level.\n");
1567 pa_log_set_show_backtrace(nframes);
1572 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1576 pa_core_assert_ref(c);
1581 if (!(n = pa_tokenizer_get(t, 1))) {
1582 pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1586 if (!(p = pa_tokenizer_get(t, 2))) {
1587 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1591 if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1592 pa_strbuf_puts(buf, "No card found by this name or index.\n");
1596 if (pa_card_set_profile(card, p, TRUE) < 0) {
1597 pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
1604 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1608 pa_core_assert_ref(c);
1613 if (!(n = pa_tokenizer_get(t, 1))) {
1614 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1618 if (!(p = pa_tokenizer_get(t, 2))) {
1619 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1623 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1624 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1628 if (pa_sink_set_port(sink, p, TRUE) < 0) {
1629 pa_strbuf_printf(buf, "Failed to set sink port to '%s'.\n", p);
1636 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1640 pa_core_assert_ref(c);
1645 if (!(n = pa_tokenizer_get(t, 1))) {
1646 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1650 if (!(p = pa_tokenizer_get(t, 2))) {
1651 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1655 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1656 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1660 if (pa_source_set_port(source, p, TRUE) < 0) {
1661 pa_strbuf_printf(buf, "Failed to set source port to '%s'.\n", p);
1668 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1680 pa_core_assert_ref(c);
1688 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
1690 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
1693 PA_IDXSET_FOREACH(m, c->modules, idx) {
1695 pa_strbuf_printf(buf, "load-module %s", m->name);
1698 pa_strbuf_printf(buf, " %s", m->argument);
1700 pa_strbuf_puts(buf, "\n");
1704 PA_IDXSET_FOREACH(sink, c->sinks, idx) {
1707 pa_strbuf_puts(buf, "\n");
1711 pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, FALSE)));
1712 pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
1713 pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
1717 PA_IDXSET_FOREACH(source, c->sources, idx) {
1720 pa_strbuf_puts(buf, "\n");
1724 pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, FALSE)));
1725 pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
1726 pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
1730 PA_IDXSET_FOREACH(card, c->cards, idx) {
1733 pa_strbuf_puts(buf, "\n");
1737 if (card->active_profile)
1738 pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
1742 if ((sink = pa_namereg_get_default_sink(c))) {
1744 pa_strbuf_puts(buf, "\n");
1748 pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
1751 if ((source = pa_namereg_get_default_source(c))) {
1753 pa_strbuf_puts(buf, "\n");
1755 pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
1758 pa_strbuf_puts(buf, "\n### EOF\n");
1763 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1767 pa_source_output *o;
1768 uint32_t s_idx, i_idx;
1769 char v_str[PA_CVOLUME_SNPRINT_MAX];
1771 pa_core_assert_ref(c);
1776 PA_IDXSET_FOREACH(s, c->sinks, s_idx) {
1777 pa_strbuf_printf(buf, "Sink %d: ", s_idx);
1778 pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->reference_volume));
1779 pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->real_volume));
1780 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->soft_volume));
1781 pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->thread_info.current_hw_volume));
1782 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(s->save_volume));
1784 PA_IDXSET_FOREACH(i, s->inputs, i_idx) {
1785 pa_strbuf_printf(buf, "\tInput %d: ", i_idx);
1786 pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume));
1787 pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->reference_ratio));
1788 pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->real_ratio));
1789 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->soft_volume));
1790 pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor));
1791 pa_strbuf_printf(buf, "volume_factor_sink = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor_sink));
1792 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(i->save_volume));
1796 PA_IDXSET_FOREACH(so, c->sources, s_idx) {
1797 pa_strbuf_printf(buf, "Source %d: ", s_idx);
1798 pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->reference_volume));
1799 pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->real_volume));
1800 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->soft_volume));
1801 pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->thread_info.current_hw_volume));
1802 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(so->save_volume));
1804 PA_IDXSET_FOREACH(o, so->outputs, i_idx) {
1805 pa_strbuf_printf(buf, "\tOutput %d: ", i_idx);
1806 pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume));
1807 pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->reference_ratio));
1808 pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->real_ratio));
1809 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->soft_volume));
1810 pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor));
1811 pa_strbuf_printf(buf, "volume_factor_source = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor_source));
1812 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(o->save_volume));
1819 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) {
1826 cs = s+strspn(s, whitespace);
1828 if (*cs == '#' || !*cs)
1830 else if (*cs == '.') {
1831 if (!strcmp(cs, META_ELSE)) {
1832 if (!ifstate || *ifstate == IFSTATE_NONE) {
1833 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1835 } else if (*ifstate == IFSTATE_TRUE)
1836 *ifstate = IFSTATE_FALSE;
1838 *ifstate = IFSTATE_TRUE;
1840 } else if (!strcmp(cs, META_ENDIF)) {
1841 if (!ifstate || *ifstate == IFSTATE_NONE) {
1842 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1845 *ifstate = IFSTATE_NONE;
1848 if (ifstate && *ifstate == IFSTATE_FALSE)
1850 if (!strcmp(cs, META_FAIL))
1852 else if (!strcmp(cs, META_NOFAIL))
1856 l = strcspn(cs, whitespace);
1858 if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
1860 const char *filename = cs+l+strspn(cs+l, whitespace);
1862 if (stat(filename, &st) < 0) {
1863 pa_log_warn("stat('%s'): %s", filename, pa_cstrerror(errno));
1867 if (S_ISDIR(st.st_mode)) {
1870 if (!(d = opendir(filename))) {
1871 pa_log_warn("Failed to read '%s': %s", filename, pa_cstrerror(errno));
1876 char **sorted_files;
1878 pa_bool_t failed = FALSE;
1879 pa_dynarray *files = pa_dynarray_new();
1881 while ((de = readdir(d))) {
1883 size_t flen = strlen(de->d_name);
1888 extn = &de->d_name[flen-3];
1889 if (strncmp(extn, ".pa", 3) == 0)
1890 pa_dynarray_append(files, pa_sprintf_malloc("%s" PA_PATH_SEP "%s", filename, de->d_name));
1895 count = pa_dynarray_size(files);
1896 sorted_files = pa_xnew(char*, count);
1897 for (i = 0; i < count; ++i)
1898 sorted_files[i] = pa_dynarray_get(files, i);
1899 pa_dynarray_free(files, NULL);
1901 for (i = 0; i < count; ++i) {
1902 for (unsigned j = 0; j < count; ++j) {
1903 if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
1904 char *tmp = sorted_files[i];
1905 sorted_files[i] = sorted_files[j];
1906 sorted_files[j] = tmp;
1911 for (i = 0; i < count; ++i) {
1913 if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
1917 pa_xfree(sorted_files[i]);
1919 pa_xfree(sorted_files);
1923 } else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
1927 } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
1929 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1931 } else if (*ifstate != IFSTATE_NONE) {
1932 pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs);
1935 const char *filename = cs+l+strspn(cs+l, whitespace);
1937 /* Search DL_SEARCH_PATH unless the filename is absolute */
1938 if (filename[0] == PA_PATH_SEP_CHAR) {
1940 *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1941 pa_log_debug("Checking for existence of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1944 const char *paths, *state = NULL;
1947 if (!(paths = lt_dlgetsearchpath()))
1950 while ((p = pa_split(paths, ":", &state))) {
1953 pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
1956 *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1957 pa_log_debug("Checking for existence of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1961 if (*ifstate == IFSTATE_TRUE)
1968 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
1969 if (*fail) return -1;
1973 const struct command*command;
1977 if (ifstate && *ifstate == IFSTATE_FALSE)
1980 l = strcspn(cs, whitespace);
1982 for (command = commands; command->name; command++)
1983 if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
1985 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
1987 ret = command->proc(c, t, buf, fail);
1988 pa_tokenizer_free(t);
1991 if (ret < 0 && *fail)
1998 pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
2007 int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
2008 return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
2011 int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
2013 int ifstate = IFSTATE_NONE;
2015 pa_bool_t _fail = TRUE;
2024 while (fgets(line, sizeof(line), f)) {
2027 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
2038 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
2041 pa_bool_t _fail = TRUE;
2050 if (!(f = pa_fopen_cloexec(fn, "r"))) {
2051 pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
2057 pa_log_debug("Parsing script '%s'", fn);
2058 ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
2067 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
2069 int ifstate = IFSTATE_NONE;
2070 pa_bool_t _fail = TRUE;
2081 size_t l = strcspn(p, linebreak);
2082 char *line = pa_xstrndup(p, l);
2084 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) {
2091 p += strspn(p, linebreak);