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, see <http://www.gnu.org/licenses/>.
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/message-handler.h>
57 #include <pulsecore/core-error.h>
58 #include <pulsecore/modinfo.h>
59 #include <pulsecore/dynarray.h>
61 #include "cli-command.h"
65 int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, bool *fail);
70 #define META_INCLUDE ".include"
71 #define META_FAIL ".fail"
72 #define META_NOFAIL ".nofail"
73 #define META_IFEXISTS ".ifexists"
74 #define META_ELSE ".else"
75 #define META_ENDIF ".endif"
83 /* Prototypes for all available commands */
84 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
85 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
86 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
87 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
88 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
89 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
90 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
91 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
92 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
93 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
94 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
95 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
96 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
97 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
98 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
99 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
100 static int pa_cli_command_source_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
101 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
102 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
103 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
104 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
105 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
106 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
107 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
108 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
109 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
110 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
111 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
112 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
113 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
114 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
115 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
116 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
117 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
118 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
119 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
120 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
121 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
122 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
123 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
124 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
125 static int pa_cli_command_log_target(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
126 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
127 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
128 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
129 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
130 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
131 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
132 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
133 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
134 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
135 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
136 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
137 static int pa_cli_command_port_offset(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
138 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
139 static int pa_cli_command_send_message_to_object(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail);
141 /* A method table for all available commands */
143 static const struct command commands[] = {
144 { "help", pa_cli_command_help, "Show this help", 1 },
145 { "list-modules", pa_cli_command_modules, "List loaded modules", 1 },
146 { "list-cards", pa_cli_command_cards, "List cards", 1 },
147 { "list-sinks", pa_cli_command_sinks, "List loaded sinks", 1 },
148 { "list-sources", pa_cli_command_sources, "List loaded sources", 1 },
149 { "list-clients", pa_cli_command_clients, "List loaded clients", 1 },
150 { "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 },
151 { "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 },
152 { "stat", pa_cli_command_stat, "Show memory block statistics", 1 },
153 { "info", pa_cli_command_info, "Show comprehensive status", 1 },
154 { "ls", pa_cli_command_info, NULL, 1 },
155 { "list", pa_cli_command_info, NULL, 1 },
156 { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3},
157 { "unload-module", pa_cli_command_unload, "Unload a module (args: index|name)", 2},
158 { "describe-module", pa_cli_command_describe, "Describe a module (arg: name)", 2},
159 { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3},
160 { "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3},
161 { "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, bool)", 3},
162 { "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, bool)", 3},
163 { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3},
164 { "set-source-output-volume",pa_cli_command_source_output_volume,"Set the volume of a source output (args: index, volume)", 3},
165 { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3},
166 { "set-source-output-mute", pa_cli_command_source_output_mute, "Set the mute switch of a source output (args: index, bool)", 3},
167 { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2},
168 { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2},
169 { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index|name, profile-name)", 3},
170 { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index|name, port-name)", 3},
171 { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index|name, port-name)", 3},
172 { "set-port-latency-offset", pa_cli_command_port_offset, "Change the latency of a port (args: card-index|card-name, port-name, latency-offset)", 4},
173 { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3},
174 { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3},
175 { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2},
176 { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3},
177 { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
178 { "update-sink-proplist", pa_cli_command_update_sink_proplist, "Update the properties of a sink (args: index|name, properties)", 3},
179 { "update-source-proplist", pa_cli_command_update_source_proplist, "Update the properties of a source (args: index|name, properties)", 3},
180 { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist, "Update the properties of a sink input (args: index, properties)", 3},
181 { "update-source-output-proplist", pa_cli_command_update_source_output_proplist, "Update the properties of a source output (args: index, properties)", 3},
182 { "list-samples", pa_cli_command_scache_list, "List all entries in the sample cache", 1},
183 { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3},
184 { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2},
185 { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3},
186 { "load-sample-lazy", pa_cli_command_scache_load, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
187 { "load-sample-dir-lazy", pa_cli_command_scache_load_dir, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
188 { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
189 { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
190 { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
192 { "set-log-target", pa_cli_command_log_target, "Change the log target (args: null|auto|syslog|stderr|file:PATH|newfile:PATH|dlog|dlog-color)", 2},
194 { "set-log-target", pa_cli_command_log_target, "Change the log target (args: null|auto|syslog|stderr|file:PATH|newfile:PATH)", 2},
196 { "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2},
197 { "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2},
198 { "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2},
199 { "set-log-backtrace", pa_cli_command_log_backtrace, "Show backtrace in log messages (args: frames)", 2},
200 { "send-message", pa_cli_command_send_message_to_object, "Send a message to an object (args: recipient, message, message_parameters)", 4},
201 { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3},
202 { "dump", pa_cli_command_dump, "Dump daemon configuration", 1},
203 { "dump-volumes", pa_cli_command_dump_volumes, "Debug: Show the state of all volumes", 1 },
204 { "shared", pa_cli_command_list_shared_props, "Debug: Show shared properties", 1},
205 { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
206 { "vacuum", pa_cli_command_vacuum, NULL, 1},
207 { NULL, NULL, NULL, 0 }
210 static const char whitespace[] = " \t\n\r";
211 static const char linebreak[] = "\n\r";
213 static uint32_t parse_index(const char *n) {
216 if (pa_atou(n, &idx) < 0)
217 return (uint32_t) PA_IDXSET_INVALID;
222 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
223 pa_core_assert_ref(c);
228 if (pa_core_exit(c, false, 0) < 0)
229 pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n");
234 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
235 const struct command*command;
237 pa_core_assert_ref(c);
242 pa_strbuf_puts(buf, "Available commands:\n");
244 for (command = commands; command->name; command++)
246 pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help);
250 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
253 pa_core_assert_ref(c);
258 pa_assert_se(s = pa_module_list_to_string(c));
259 pa_strbuf_puts(buf, s);
264 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
267 pa_core_assert_ref(c);
272 pa_assert_se(s = pa_client_list_to_string(c));
273 pa_strbuf_puts(buf, s);
278 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
281 pa_core_assert_ref(c);
286 pa_assert_se(s = pa_card_list_to_string(c));
287 pa_strbuf_puts(buf, s);
292 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
295 pa_core_assert_ref(c);
300 pa_assert_se(s = pa_sink_list_to_string(c));
301 pa_strbuf_puts(buf, s);
306 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
309 pa_core_assert_ref(c);
314 pa_assert_se(s = pa_source_list_to_string(c));
315 pa_strbuf_puts(buf, s);
320 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
323 pa_core_assert_ref(c);
328 pa_assert_se(s = pa_sink_input_list_to_string(c));
329 pa_strbuf_puts(buf, s);
334 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
337 pa_core_assert_ref(c);
342 pa_assert_se(s = pa_source_output_list_to_string(c));
343 pa_strbuf_puts(buf, s);
348 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
349 char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
350 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
351 char bytes[PA_BYTES_SNPRINT_MAX];
352 const pa_mempool_stat *mstat;
355 static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = {
356 [PA_MEMBLOCK_POOL] = "POOL",
357 [PA_MEMBLOCK_POOL_EXTERNAL] = "POOL_EXTERNAL",
358 [PA_MEMBLOCK_APPENDED] = "APPENDED",
359 [PA_MEMBLOCK_USER] = "USER",
360 [PA_MEMBLOCK_FIXED] = "FIXED",
361 [PA_MEMBLOCK_IMPORTED] = "IMPORTED",
364 pa_core_assert_ref(c);
369 mstat = pa_mempool_get_stat(c->mempool);
371 pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
372 (unsigned) pa_atomic_load(&mstat->n_allocated),
373 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->allocated_size)));
375 pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
376 (unsigned) pa_atomic_load(&mstat->n_accumulated),
377 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->accumulated_size)));
379 pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
380 (unsigned) pa_atomic_load(&mstat->n_imported),
381 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->imported_size)));
383 pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
384 (unsigned) pa_atomic_load(&mstat->n_exported),
385 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->exported_size)));
387 pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
388 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
390 pa_strbuf_printf(buf, "Default sample spec: %s\n",
391 pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
393 pa_strbuf_printf(buf, "Default channel map: %s\n",
394 pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
396 pa_strbuf_printf(buf, "Default sink name: %s\n"
397 "Default source name: %s\n",
398 c->default_sink ? c->default_sink->name : "none",
399 c->default_source ? c->default_source->name : "none");
401 for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++)
402 pa_strbuf_printf(buf,
403 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
405 (unsigned) pa_atomic_load(&mstat->n_allocated_by_type[k]),
406 (unsigned) pa_atomic_load(&mstat->n_accumulated_by_type[k]));
411 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
412 pa_core_assert_ref(c);
417 pa_cli_command_stat(c, t, buf, fail);
418 pa_cli_command_modules(c, t, buf, fail);
419 pa_cli_command_sinks(c, t, buf, fail);
420 pa_cli_command_sources(c, t, buf, fail);
421 pa_cli_command_clients(c, t, buf, fail);
422 pa_cli_command_cards(c, t, buf, fail);
423 pa_cli_command_sink_inputs(c, t, buf, fail);
424 pa_cli_command_source_outputs(c, t, buf, fail);
425 pa_cli_command_scache_list(c, t, buf, fail);
429 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
434 pa_core_assert_ref(c);
439 if (!(name = pa_tokenizer_get(t, 1))) {
440 pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
444 if ((err = pa_module_load(&m, c, name, pa_tokenizer_get(t, 2))) < 0) {
445 if (err == PA_ERR_EXIST) {
446 pa_strbuf_puts(buf, "Module already loaded; ignoring.\n");
448 pa_strbuf_puts(buf, "Module load failed.\n");
456 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
460 bool unloaded = false;
462 pa_core_assert_ref(c);
467 if (!(i = pa_tokenizer_get(t, 1))) {
468 pa_strbuf_puts(buf, "You need to specify the module index or name.\n");
472 if (pa_atou(i, &idx) >= 0) {
473 if (!(m = pa_idxset_get_by_index(c->modules, idx))) {
474 pa_strbuf_puts(buf, "Invalid module index.\n");
478 pa_module_unload(m, false);
481 PA_IDXSET_FOREACH(m, c->modules, idx)
482 if (pa_streq(i, m->name)) {
484 pa_module_unload(m, false);
487 if (unloaded == false) {
488 pa_strbuf_printf(buf, "Module %s not loaded.\n", i);
496 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
500 pa_core_assert_ref(c);
505 if (!(name = pa_tokenizer_get(t, 1))) {
506 pa_strbuf_puts(buf, "You need to specify the module name.\n");
510 if ((i = pa_modinfo_get_by_name(name))) {
512 pa_strbuf_printf(buf, "Name: %s\n", name);
514 if (!i->description && !i->version && !i->author && !i->usage)
515 pa_strbuf_printf(buf, "No module information available\n");
518 pa_strbuf_printf(buf, "Version: %s\n", i->version);
520 pa_strbuf_printf(buf, "Description: %s\n", i->description);
522 pa_strbuf_printf(buf, "Author: %s\n", i->author);
524 pa_strbuf_printf(buf, "Usage: %s\n", i->usage);
525 pa_strbuf_printf(buf, "Load Once: %s\n", pa_yes_no(i->load_once));
527 pa_strbuf_printf(buf, "Warning, deprecated: %s\n", i->deprecated);
532 pa_strbuf_puts(buf, "Failed to open module.\n");
537 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
543 pa_core_assert_ref(c);
548 if (!(n = pa_tokenizer_get(t, 1))) {
549 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
553 if (!(v = pa_tokenizer_get(t, 2))) {
554 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
558 if (pa_atou(v, &volume) < 0) {
559 pa_strbuf_puts(buf, "Failed to parse volume.\n");
563 if (!PA_VOLUME_IS_VALID(volume)) {
564 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
568 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
569 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
573 pa_cvolume_set(&cvolume, 1, volume);
574 pa_sink_set_volume(sink, &cvolume, true, true);
578 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
585 pa_core_assert_ref(c);
590 if (!(n = pa_tokenizer_get(t, 1))) {
591 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
595 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
596 pa_strbuf_puts(buf, "Failed to parse index.\n");
600 if (!(v = pa_tokenizer_get(t, 2))) {
601 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
605 if (pa_atou(v, &volume) < 0) {
606 pa_strbuf_puts(buf, "Failed to parse volume.\n");
610 if (!PA_VOLUME_IS_VALID(volume)) {
611 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
615 if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) {
616 pa_strbuf_puts(buf, "No sink input found with this index.\n");
620 if (!si->volume_writable) {
621 pa_strbuf_puts(buf, "This sink input's volume can't be changed.\n");
625 pa_cvolume_set(&cvolume, 1, volume);
626 pa_sink_input_set_volume(si, &cvolume, true, true);
630 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
636 pa_core_assert_ref(c);
641 if (!(n = pa_tokenizer_get(t, 1))) {
642 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
646 if (!(v = pa_tokenizer_get(t, 2))) {
647 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
651 if (pa_atou(v, &volume) < 0) {
652 pa_strbuf_puts(buf, "Failed to parse volume.\n");
656 if (!PA_VOLUME_IS_VALID(volume)) {
657 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
661 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
662 pa_strbuf_puts(buf, "No source found by this name or index.\n");
666 pa_cvolume_set(&cvolume, 1, volume);
667 pa_source_set_volume(source, &cvolume, true, true);
671 static int pa_cli_command_source_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
673 pa_source_output *so;
678 pa_core_assert_ref(c);
683 if (!(n = pa_tokenizer_get(t, 1))) {
684 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
688 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
689 pa_strbuf_puts(buf, "Failed to parse index.\n");
693 if (!(v = pa_tokenizer_get(t, 2))) {
694 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
698 if (pa_atou(v, &volume) < 0) {
699 pa_strbuf_puts(buf, "Failed to parse volume.\n");
703 if (!PA_VOLUME_IS_VALID(volume)) {
704 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
708 if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) {
709 pa_strbuf_puts(buf, "No source output found with this index.\n");
713 if (!so->volume_writable) {
714 pa_strbuf_puts(buf, "This source output's volume can't be changed.\n");
718 pa_cvolume_set(&cvolume, 1, volume);
719 pa_source_output_set_volume(so, &cvolume, true, true);
723 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *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 sink either by its name or its index.\n");
738 if (!(m = pa_tokenizer_get(t, 2))) {
739 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
743 if ((mute = pa_parse_boolean(m)) < 0) {
744 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
748 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
749 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
753 pa_sink_set_mute(sink, mute, true);
757 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
762 pa_core_assert_ref(c);
767 if (!(n = pa_tokenizer_get(t, 1))) {
768 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
772 if (!(m = pa_tokenizer_get(t, 2))) {
773 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
777 if ((mute = pa_parse_boolean(m)) < 0) {
778 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
782 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
783 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
787 pa_source_set_mute(source, mute, true);
791 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
796 pa_core_assert_ref(c);
801 if (!(n = pa_tokenizer_get(t, 1))) {
802 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
806 if (!(s = pa_tokenizer_get(t, 2))) {
807 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
811 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
812 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
816 if (!(p = pa_proplist_from_string(s))) {
817 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
821 pa_sink_update_proplist(sink, PA_UPDATE_REPLACE, p);
828 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
833 pa_core_assert_ref(c);
838 if (!(n = pa_tokenizer_get(t, 1))) {
839 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
843 if (!(s = pa_tokenizer_get(t, 2))) {
844 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
848 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
849 pa_strbuf_puts(buf, "No source found by this name or index.\n");
853 if (!(p = pa_proplist_from_string(s))) {
854 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
858 pa_source_update_proplist(source, PA_UPDATE_REPLACE, p);
865 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
871 pa_core_assert_ref(c);
876 if (!(n = pa_tokenizer_get(t, 1))) {
877 pa_strbuf_puts(buf, "You need to specify a sink input either by index.\n");
881 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
882 pa_strbuf_puts(buf, "Failed to parse index.\n");
886 if (!(s = pa_tokenizer_get(t, 2))) {
887 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
891 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
892 pa_strbuf_puts(buf, "No sink input found with this index.\n");
896 if (!(p = pa_proplist_from_string(s))) {
897 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
901 pa_sink_input_update_proplist(si, PA_UPDATE_REPLACE, p);
908 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
910 pa_source_output *so;
914 pa_core_assert_ref(c);
919 if (!(n = pa_tokenizer_get(t, 1))) {
920 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
924 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
925 pa_strbuf_puts(buf, "Failed to parse index.\n");
929 if (!(s = pa_tokenizer_get(t, 2))) {
930 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
934 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
935 pa_strbuf_puts(buf, "No source output found with this index.\n");
939 if (!(p = pa_proplist_from_string(s))) {
940 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
944 pa_source_output_update_proplist(so, PA_UPDATE_REPLACE, p);
951 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
957 pa_core_assert_ref(c);
962 if (!(n = pa_tokenizer_get(t, 1))) {
963 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
967 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
968 pa_strbuf_puts(buf, "Failed to parse index.\n");
972 if (!(v = pa_tokenizer_get(t, 2))) {
973 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
977 if ((mute = pa_parse_boolean(v)) < 0) {
978 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
982 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
983 pa_strbuf_puts(buf, "No sink input found with this index.\n");
987 pa_sink_input_set_mute(si, mute, true);
991 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
993 pa_source_output *so;
997 pa_core_assert_ref(c);
1002 if (!(n = pa_tokenizer_get(t, 1))) {
1003 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1007 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1008 pa_strbuf_puts(buf, "Failed to parse index.\n");
1012 if (!(v = pa_tokenizer_get(t, 2))) {
1013 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
1017 if ((mute = pa_parse_boolean(v)) < 0) {
1018 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
1022 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1023 pa_strbuf_puts(buf, "No source output found with this index.\n");
1027 pa_source_output_set_mute(so, mute, true);
1031 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1035 pa_core_assert_ref(c);
1040 if (!(n = pa_tokenizer_get(t, 1))) {
1041 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1045 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
1046 pa_core_set_configured_default_sink(c, s->name);
1048 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
1053 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1057 pa_core_assert_ref(c);
1062 if (!(n = pa_tokenizer_get(t, 1))) {
1063 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1067 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SOURCE)))
1068 pa_core_set_configured_default_source(c, s->name);
1070 pa_strbuf_printf(buf, "Source %s does not exist.\n", n);
1074 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1079 pa_core_assert_ref(c);
1084 if (!(n = pa_tokenizer_get(t, 1))) {
1085 pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
1089 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1090 pa_strbuf_puts(buf, "Failed to parse index.\n");
1094 if (!(client = pa_idxset_get_by_index(c->clients, idx))) {
1095 pa_strbuf_puts(buf, "No client found by this index.\n");
1099 pa_client_kill(client);
1103 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1105 pa_sink_input *sink_input;
1108 pa_core_assert_ref(c);
1113 if (!(n = pa_tokenizer_get(t, 1))) {
1114 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1118 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1119 pa_strbuf_puts(buf, "Failed to parse index.\n");
1123 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) {
1124 pa_strbuf_puts(buf, "No sink input found by this index.\n");
1128 pa_sink_input_kill(sink_input);
1132 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1134 pa_source_output *source_output;
1137 pa_core_assert_ref(c);
1142 if (!(n = pa_tokenizer_get(t, 1))) {
1143 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1147 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1148 pa_strbuf_puts(buf, "Failed to parse index.\n");
1152 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) {
1153 pa_strbuf_puts(buf, "No source output found by this index.\n");
1157 pa_source_output_kill(source_output);
1161 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1164 pa_core_assert_ref(c);
1169 pa_assert_se(s = pa_scache_list_to_string(c));
1170 pa_strbuf_puts(buf, s);
1176 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1177 const char *n, *sink_name;
1181 pa_core_assert_ref(c);
1186 if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1187 pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
1191 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1192 pa_strbuf_puts(buf, "No sink by that name.\n");
1196 if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
1197 pa_strbuf_puts(buf, "Failed to play sample.\n");
1201 pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
1206 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1209 pa_core_assert_ref(c);
1214 if (!(n = pa_tokenizer_get(t, 1))) {
1215 pa_strbuf_puts(buf, "You need to specify a sample name.\n");
1219 if (pa_scache_remove_item(c, n) < 0) {
1220 pa_strbuf_puts(buf, "Failed to remove sample.\n");
1227 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1228 const char *fname, *n;
1231 pa_core_assert_ref(c);
1236 if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
1237 pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
1241 if (strstr(pa_tokenizer_get(t, 0), "lazy"))
1242 r = pa_scache_add_file_lazy(c, n, fname, NULL);
1244 r = pa_scache_add_file(c, n, fname, NULL);
1247 pa_strbuf_puts(buf, "Failed to load sound file.\n");
1252 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1255 pa_core_assert_ref(c);
1260 if (!(pname = pa_tokenizer_get(t, 1))) {
1261 pa_strbuf_puts(buf, "You need to specify a path name.\n");
1265 if (pa_scache_add_directory_lazy(c, pname) < 0) {
1266 pa_strbuf_puts(buf, "Failed to load directory.\n");
1273 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1274 const char *fname, *sink_name;
1277 pa_core_assert_ref(c);
1282 if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1283 pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
1287 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1288 pa_strbuf_puts(buf, "No sink by that name.\n");
1292 if (pa_play_file(sink, fname, NULL) < 0) {
1293 pa_strbuf_puts(buf, "Failed to play sound file.\n");
1300 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1301 pa_core_assert_ref(c);
1306 pa_shared_dump(c, buf);
1310 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1311 pa_core_assert_ref(c);
1316 pa_mempool_vacuum(c->mempool);
1321 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1327 pa_core_assert_ref(c);
1332 if (!(n = pa_tokenizer_get(t, 1))) {
1333 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1337 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1338 pa_strbuf_puts(buf, "Failed to parse index.\n");
1342 if (!(k = pa_tokenizer_get(t, 2))) {
1343 pa_strbuf_puts(buf, "You need to specify a sink.\n");
1347 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
1348 pa_strbuf_puts(buf, "No sink input found with this index.\n");
1352 if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK))) {
1353 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1357 if (pa_sink_input_move_to(si, sink, true) < 0) {
1358 pa_strbuf_puts(buf, "Moved failed.\n");
1364 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1366 pa_source_output *so;
1370 pa_core_assert_ref(c);
1375 if (!(n = pa_tokenizer_get(t, 1))) {
1376 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1380 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1381 pa_strbuf_puts(buf, "Failed to parse index.\n");
1385 if (!(k = pa_tokenizer_get(t, 2))) {
1386 pa_strbuf_puts(buf, "You need to specify a source.\n");
1390 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1391 pa_strbuf_puts(buf, "No source output found with this index.\n");
1395 if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE))) {
1396 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1400 if (pa_source_output_move_to(so, source, true) < 0) {
1401 pa_strbuf_puts(buf, "Moved failed.\n");
1407 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1412 pa_core_assert_ref(c);
1417 if (!(n = pa_tokenizer_get(t, 1))) {
1418 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1422 if (!(m = pa_tokenizer_get(t, 2))) {
1423 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1427 if ((suspend = pa_parse_boolean(m)) < 0) {
1428 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1432 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1433 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1437 pa_log_debug("%s of sink %s requested via CLI.", suspend ? "Suspending" : "Resuming", sink->name);
1439 if ((r = pa_sink_suspend(sink, suspend, PA_SUSPEND_USER)) < 0)
1440 pa_strbuf_printf(buf, "Failed to resume/suspend sink: %s\n", pa_strerror(r));
1445 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1450 pa_core_assert_ref(c);
1455 if (!(n = pa_tokenizer_get(t, 1))) {
1456 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1460 if (!(m = pa_tokenizer_get(t, 2))) {
1461 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1465 if ((suspend = pa_parse_boolean(m)) < 0) {
1466 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1470 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1471 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1475 pa_log_debug("%s of source %s requested via CLI.", suspend ? "Suspending" : "Resuming", source->name);
1477 if ((r = pa_source_suspend(source, suspend, PA_SUSPEND_USER)) < 0)
1478 pa_strbuf_printf(buf, "Failed to resume/suspend source: %s\n", pa_strerror(r));
1483 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1487 pa_core_assert_ref(c);
1492 if (!(m = pa_tokenizer_get(t, 1))) {
1493 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1497 if ((suspend = pa_parse_boolean(m)) < 0) {
1498 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1502 pa_log_debug("%s of all sinks and sources requested via CLI.", suspend ? "Suspending" : "Resuming");
1504 if ((r = pa_sink_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1505 pa_strbuf_printf(buf, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r));
1507 if ((r = pa_source_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1508 pa_strbuf_printf(buf, "Failed to resume/suspend all sources: %s\n", pa_strerror(r));
1513 static int pa_cli_command_log_target(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1515 pa_log_target *log_target = NULL;
1517 pa_core_assert_ref(c);
1522 if (!(m = pa_tokenizer_get(t, 1))) {
1524 pa_strbuf_puts(buf, "You need to specify a log target (null|auto|syslog|stderr|file:PATH|newfile:PATH|dlog|dlog-color).\n");
1526 pa_strbuf_puts(buf, "You need to specify a log target (null|auto|syslog|stderr|file:PATH|newfile:PATH).\n");
1531 /* 'auto' is actually the effect with 'stderr' */
1532 if (pa_streq(m, "auto"))
1533 log_target = pa_log_target_new(PA_LOG_STDERR, NULL);
1535 log_target = pa_log_parse_target(m);
1538 pa_strbuf_puts(buf, "Invalid log target.\n");
1543 if (pa_log_set_target(log_target) < 0) {
1544 pa_strbuf_puts(buf, "Failed to set log target.\n");
1545 pa_log_target_free(log_target);
1549 pa_log_target_free(log_target);
1554 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1558 pa_core_assert_ref(c);
1563 if (!(m = pa_tokenizer_get(t, 1))) {
1564 pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n");
1568 if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) {
1569 pa_strbuf_puts(buf, "Failed to parse log level.\n");
1573 pa_log_set_level(level);
1578 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1582 pa_core_assert_ref(c);
1587 if (!(m = pa_tokenizer_get(t, 1))) {
1588 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1592 if ((b = pa_parse_boolean(m)) < 0) {
1593 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1597 pa_log_set_flags(PA_LOG_PRINT_META, b ? PA_LOG_SET : PA_LOG_UNSET);
1602 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1606 pa_core_assert_ref(c);
1611 if (!(m = pa_tokenizer_get(t, 1))) {
1612 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1616 if ((b = pa_parse_boolean(m)) < 0) {
1617 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1621 pa_log_set_flags(PA_LOG_PRINT_TIME, b ? PA_LOG_SET : PA_LOG_UNSET);
1626 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1630 pa_core_assert_ref(c);
1635 if (!(m = pa_tokenizer_get(t, 1))) {
1636 pa_strbuf_puts(buf, "You need to specify a backtrace level.\n");
1640 if (pa_atou(m, &nframes) < 0 || nframes >= 1000) {
1641 pa_strbuf_puts(buf, "Failed to parse backtrace level.\n");
1645 pa_log_set_show_backtrace(nframes);
1650 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1653 pa_card_profile *profile;
1655 pa_core_assert_ref(c);
1660 if (!(n = pa_tokenizer_get(t, 1))) {
1661 pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1665 if (!(p = pa_tokenizer_get(t, 2))) {
1666 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1670 if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1671 pa_strbuf_puts(buf, "No card found by this name or index.\n");
1675 if (!(profile = pa_hashmap_get(card->profiles, p))) {
1676 pa_strbuf_printf(buf, "No such profile: %s\n", p);
1680 if (pa_card_set_profile(card, profile, true) < 0) {
1681 pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
1688 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1692 pa_core_assert_ref(c);
1697 if (!(n = pa_tokenizer_get(t, 1))) {
1698 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1702 if (!(p = pa_tokenizer_get(t, 2))) {
1703 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1707 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1708 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1712 if (pa_sink_set_port(sink, p, true) < 0) {
1713 pa_strbuf_printf(buf, "Failed to set sink port to '%s'.\n", p);
1720 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1724 pa_core_assert_ref(c);
1729 if (!(n = pa_tokenizer_get(t, 1))) {
1730 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1734 if (!(p = pa_tokenizer_get(t, 2))) {
1735 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1739 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1740 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1744 if (pa_source_set_port(source, p, true) < 0) {
1745 pa_strbuf_printf(buf, "Failed to set source port to '%s'.\n", p);
1752 static int pa_cli_command_port_offset(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1753 const char *n, *p, *l;
1754 pa_device_port *port;
1758 pa_core_assert_ref(c);
1763 if (!(n = pa_tokenizer_get(t, 1))) {
1764 pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1768 if (!(p = pa_tokenizer_get(t, 2))) {
1769 pa_strbuf_puts(buf, "You need to specify a port by its name.\n");
1773 if (!(l = pa_tokenizer_get(t, 3))) {
1774 pa_strbuf_puts(buf, "You need to specify a latency offset.\n");
1778 if (pa_atoi(l, &offset) < 0) {
1779 pa_strbuf_puts(buf, "Failed to parse the latency offset.\n");
1783 if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1784 pa_strbuf_puts(buf, "No card found by this name or index.\n");
1788 if (!(port = pa_hashmap_get(card->ports, p))) {
1789 pa_strbuf_puts(buf, "No port found by this name.\n");
1793 pa_device_port_set_latency_offset(port, offset);
1798 static int pa_cli_command_send_message_to_object(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1799 const char *object_path, *message, *message_parameters;
1800 char *response = NULL;
1803 pa_core_assert_ref(c);
1809 if (!(object_path = pa_tokenizer_get(t, 1))) {
1810 pa_strbuf_puts(buf, "You need to specify an object path as recipient for the message.\n");
1814 if (!(message = pa_tokenizer_get(t, 2))) {
1815 pa_strbuf_puts(buf, "You need to specify a message name.\n");
1819 /* parameters may be NULL */
1820 message_parameters = pa_tokenizer_get(t, 3);
1822 ret = pa_message_handler_send_message(c, object_path, message, message_parameters, &response);
1825 pa_strbuf_printf(buf, "Send message failed: %s\n", pa_strerror(ret));
1830 pa_strbuf_puts(buf, response);
1831 pa_strbuf_puts(buf, "\n");
1839 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1851 pa_core_assert_ref(c);
1859 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
1861 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
1864 PA_IDXSET_FOREACH(m, c->modules, idx) {
1866 pa_strbuf_printf(buf, "load-module %s", m->name);
1869 pa_strbuf_printf(buf, " %s", m->argument);
1871 pa_strbuf_puts(buf, "\n");
1875 PA_IDXSET_FOREACH(sink, c->sinks, idx) {
1878 pa_strbuf_puts(buf, "\n");
1882 pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, false)));
1883 pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, false)));
1884 pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(sink->state == PA_SINK_SUSPENDED));
1888 PA_IDXSET_FOREACH(source, c->sources, idx) {
1891 pa_strbuf_puts(buf, "\n");
1895 pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, false)));
1896 pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, false)));
1897 pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(source->state == PA_SOURCE_SUSPENDED));
1901 PA_IDXSET_FOREACH(card, c->cards, idx) {
1904 pa_strbuf_puts(buf, "\n");
1908 pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
1912 if (c->default_sink) {
1914 pa_strbuf_puts(buf, "\n");
1918 pa_strbuf_printf(buf, "set-default-sink %s\n", c->default_sink->name);
1921 if (c->default_source) {
1923 pa_strbuf_puts(buf, "\n");
1925 pa_strbuf_printf(buf, "set-default-source %s\n", c->default_source->name);
1928 pa_strbuf_puts(buf, "\n### EOF\n");
1933 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, bool *fail) {
1937 pa_source_output *o;
1938 uint32_t s_idx, i_idx;
1939 char v_str[PA_CVOLUME_SNPRINT_VERBOSE_MAX];
1940 pa_channel_map *map;
1942 pa_core_assert_ref(c);
1947 PA_IDXSET_FOREACH(s, c->sinks, s_idx) {
1948 map = &s->channel_map;
1949 pa_strbuf_printf(buf, "Sink %d: ", s_idx);
1950 pa_strbuf_printf(buf,
1952 pa_cvolume_snprint_verbose(v_str,
1954 &s->reference_volume,
1956 s->flags & PA_SINK_DECIBEL_VOLUME));
1957 pa_strbuf_printf(buf,
1959 pa_cvolume_snprint_verbose(v_str,
1963 s->flags & PA_SINK_DECIBEL_VOLUME));
1964 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &s->soft_volume, map, true));
1965 pa_strbuf_printf(buf,
1966 "current_hw = %s, ",
1967 pa_cvolume_snprint_verbose(v_str,
1969 &s->thread_info.current_hw_volume,
1971 s->flags & PA_SINK_DECIBEL_VOLUME));
1972 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(s->save_volume));
1974 PA_IDXSET_FOREACH(i, s->inputs, i_idx) {
1975 map = &i->channel_map;
1976 pa_strbuf_printf(buf, "\tInput %d: ", i_idx);
1977 pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &i->volume, map, true));
1978 pa_strbuf_printf(buf,
1979 "reference_ratio = %s, ",
1980 pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &i->reference_ratio, map, true));
1981 pa_strbuf_printf(buf,
1982 "real_ratio = %s, ",
1983 pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &i->real_ratio, map, true));
1984 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &i->soft_volume, map, true));
1985 pa_strbuf_printf(buf,
1986 "volume_factor = %s, ",
1987 pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &i->volume_factor, map, true));
1988 pa_strbuf_printf(buf,
1989 "volume_factor_sink = %s, ",
1990 pa_cvolume_snprint_verbose(v_str,
1992 &i->volume_factor_sink,
1993 &i->sink->channel_map,
1995 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(i->save_volume));
1999 PA_IDXSET_FOREACH(so, c->sources, s_idx) {
2000 map = &so->channel_map;
2001 pa_strbuf_printf(buf, "Source %d: ", s_idx);
2002 pa_strbuf_printf(buf,
2004 pa_cvolume_snprint_verbose(v_str,
2006 &so->reference_volume,
2008 so->flags & PA_SOURCE_DECIBEL_VOLUME));
2009 pa_strbuf_printf(buf,
2011 pa_cvolume_snprint_verbose(v_str,
2015 so->flags & PA_SOURCE_DECIBEL_VOLUME));
2016 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &so->soft_volume, map, true));
2017 pa_strbuf_printf(buf,
2018 "current_hw = %s, ",
2019 pa_cvolume_snprint_verbose(v_str,
2021 &so->thread_info.current_hw_volume,
2023 so->flags & PA_SOURCE_DECIBEL_VOLUME));
2024 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(so->save_volume));
2026 PA_IDXSET_FOREACH(o, so->outputs, i_idx) {
2027 map = &o->channel_map;
2028 pa_strbuf_printf(buf, "\tOutput %d: ", i_idx);
2029 pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &o->volume, map, true));
2030 pa_strbuf_printf(buf,
2031 "reference_ratio = %s, ",
2032 pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &o->reference_ratio, map, true));
2033 pa_strbuf_printf(buf,
2034 "real_ratio = %s, ",
2035 pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &o->real_ratio, map, true));
2036 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &o->soft_volume, map, true));
2037 pa_strbuf_printf(buf,
2038 "volume_factor = %s, ",
2039 pa_cvolume_snprint_verbose(v_str, sizeof(v_str), &o->volume_factor, map, true));
2040 pa_strbuf_printf(buf,
2041 "volume_factor_source = %s, ",
2042 pa_cvolume_snprint_verbose(v_str,
2044 &o->volume_factor_source,
2045 &o->source->channel_map,
2047 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(o->save_volume));
2054 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, bool *fail, int *ifstate) {
2061 cs = s+strspn(s, whitespace);
2063 if (*cs == '#' || !*cs)
2065 else if (*cs == '.') {
2066 if (!strcmp(cs, META_ELSE)) {
2067 if (!ifstate || *ifstate == IFSTATE_NONE) {
2068 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
2070 } else if (*ifstate == IFSTATE_TRUE)
2071 *ifstate = IFSTATE_FALSE;
2073 *ifstate = IFSTATE_TRUE;
2075 } else if (!strcmp(cs, META_ENDIF)) {
2076 if (!ifstate || *ifstate == IFSTATE_NONE) {
2077 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
2080 *ifstate = IFSTATE_NONE;
2083 if (ifstate && *ifstate == IFSTATE_FALSE)
2085 if (!strcmp(cs, META_FAIL))
2087 else if (!strcmp(cs, META_NOFAIL))
2091 l = strcspn(cs, whitespace);
2093 if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
2095 const char *fn = cs+l+strspn(cs+l, whitespace);
2099 if (strncmp(fn, PA_DEFAULT_CONFIG_DIR, strlen(PA_DEFAULT_CONFIG_DIR)) == 0)
2100 filename = pa_sprintf_malloc("%s" PA_PATH_SEP "etc" PA_PATH_SEP "pulse" PA_PATH_SEP "%s",
2101 pa_win32_get_toplevel(NULL),
2102 fn + strlen(PA_DEFAULT_CONFIG_DIR));
2105 filename = pa_xstrdup(fn);
2107 if (stat(filename, &st) < 0) {
2108 pa_log_warn("stat('%s'): %s", filename, pa_cstrerror(errno));
2114 if (S_ISDIR(st.st_mode)) {
2117 if (!(d = opendir(filename))) {
2118 pa_log_warn("Failed to read '%s': %s", filename, pa_cstrerror(errno));
2125 char **sorted_files;
2127 bool failed = false;
2128 pa_dynarray *files = pa_dynarray_new(NULL);
2130 while ((de = readdir(d))) {
2132 size_t flen = strlen(de->d_name);
2137 extn = &de->d_name[flen-3];
2138 if (strncmp(extn, ".pa", 3) == 0)
2139 pa_dynarray_append(files, pa_sprintf_malloc("%s" PA_PATH_SEP "%s", filename, de->d_name));
2143 if ((count = pa_dynarray_size(files))) {
2144 sorted_files = pa_xnew(char*, count);
2145 for (i = 0; i < count; ++i)
2146 sorted_files[i] = pa_dynarray_get(files, i);
2147 pa_dynarray_free(files);
2149 for (i = 0; i < count; ++i) {
2150 for (unsigned j = 0; j < count; ++j) {
2151 if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
2152 char *tmp = sorted_files[i];
2153 sorted_files[i] = sorted_files[j];
2154 sorted_files[j] = tmp;
2159 for (i = 0; i < count; ++i) {
2161 if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
2165 pa_xfree(sorted_files[i]);
2167 pa_xfree(sorted_files);
2174 } else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
2180 } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
2182 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
2184 } else if (*ifstate != IFSTATE_NONE) {
2185 pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs);
2188 const char *filename = cs+l+strspn(cs+l, whitespace);
2189 *ifstate = pa_module_exists(filename) ? IFSTATE_TRUE : IFSTATE_FALSE;
2192 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
2193 if (*fail) return -1;
2197 const struct command*command;
2201 if (ifstate && *ifstate == IFSTATE_FALSE)
2204 l = strcspn(cs, whitespace);
2206 for (command = commands; command->name; command++)
2207 if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
2209 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
2211 ret = command->proc(c, t, buf, fail);
2212 pa_tokenizer_free(t);
2215 if (ret < 0 && *fail)
2222 pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
2231 int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, bool *fail) {
2232 return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
2235 int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, bool *fail) {
2237 int ifstate = IFSTATE_NONE;
2248 while (fgets(line, sizeof(line), f)) {
2251 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
2262 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, bool *fail) {
2274 if (!(f = pa_fopen_cloexec(fn, "r"))) {
2275 pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
2281 pa_log_debug("Parsing script '%s'", fn);
2282 ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
2291 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, bool *fail) {
2293 int ifstate = IFSTATE_NONE;
2305 size_t l = strcspn(p, linebreak);
2306 char *line = pa_xstrndup(p, l);
2308 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) {
2315 p += strspn(p, linebreak);