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_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
100 static int pa_cli_command_sink_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
101 static int pa_cli_command_source_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
102 static int pa_cli_command_sink_input_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
103 static int pa_cli_command_sink_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
104 static int pa_cli_command_source_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
105 static int pa_cli_command_kill_client(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
106 static int pa_cli_command_kill_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
107 static int pa_cli_command_kill_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
108 static int pa_cli_command_scache_play(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
109 static int pa_cli_command_scache_remove(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
110 static int pa_cli_command_scache_list(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
111 static int pa_cli_command_scache_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
112 static int pa_cli_command_scache_load_dir(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
113 static int pa_cli_command_play_file(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
114 static int pa_cli_command_dump(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
115 static int pa_cli_command_list_shared_props(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
116 static int pa_cli_command_move_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
117 static int pa_cli_command_move_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
118 static int pa_cli_command_vacuum(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
119 static int pa_cli_command_suspend_sink(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
120 static int pa_cli_command_suspend_source(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
121 static int pa_cli_command_suspend(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
122 static int pa_cli_command_log_level(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
123 static int pa_cli_command_log_meta(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
124 static int pa_cli_command_log_time(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
125 static int pa_cli_command_log_backtrace(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
126 static int pa_cli_command_update_sink_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
127 static int pa_cli_command_update_source_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
128 static int pa_cli_command_update_sink_input_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
129 static int pa_cli_command_update_source_output_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
130 static int pa_cli_command_card_profile(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
131 static int pa_cli_command_sink_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
132 static int pa_cli_command_source_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
133 static int pa_cli_command_dump_volumes(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
135 /* A method table for all available commands */
137 static const struct command commands
[] = {
138 { "exit", pa_cli_command_exit
, "Terminate the daemon", 1 },
139 { "help", pa_cli_command_help
, "Show this help", 1 },
140 { "list-modules", pa_cli_command_modules
, "List loaded modules", 1 },
141 { "list-sinks", pa_cli_command_sinks
, "List loaded sinks", 1 },
142 { "list-sources", pa_cli_command_sources
, "List loaded sources", 1 },
143 { "list-clients", pa_cli_command_clients
, "List loaded clients", 1 },
144 { "list-sink-inputs", pa_cli_command_sink_inputs
, "List sink inputs", 1 },
145 { "list-source-outputs", pa_cli_command_source_outputs
, "List source outputs", 1 },
146 { "list-cards", pa_cli_command_cards
, "List cards", 1 },
147 { "stat", pa_cli_command_stat
, "Show memory block statistics", 1 },
148 { "info", pa_cli_command_info
, "Show comprehensive status", 1 },
149 { "ls", pa_cli_command_info
, NULL
, 1 },
150 { "list", pa_cli_command_info
, NULL
, 1 },
151 { "load-module", pa_cli_command_load
, "Load a module (args: name, arguments)", 3},
152 { "unload-module", pa_cli_command_unload
, "Unload a module (args: index)", 2},
153 { "describe-module", pa_cli_command_describe
, "Describe a module (arg: name)", 2},
154 { "set-sink-volume", pa_cli_command_sink_volume
, "Set the volume of a sink (args: index|name, volume)", 3},
155 { "set-sink-input-volume", pa_cli_command_sink_input_volume
, "Set the volume of a sink input (args: index, volume)", 3},
156 { "set-source-volume", pa_cli_command_source_volume
, "Set the volume of a source (args: index|name, volume)", 3},
157 { "set-sink-mute", pa_cli_command_sink_mute
, "Set the mute switch of a sink (args: index|name, bool)", 3},
158 { "set-sink-input-mute", pa_cli_command_sink_input_mute
, "Set the mute switch of a sink input (args: index, bool)", 3},
159 { "set-source-mute", pa_cli_command_source_mute
, "Set the mute switch of a source (args: index|name, bool)", 3},
160 { "update-sink-proplist", pa_cli_command_update_sink_proplist
, "Update the properties of a sink (args: index|name, properties)", 3},
161 { "update-source-proplist", pa_cli_command_update_source_proplist
, "Update the properties of a source (args: index|name, properties)", 3},
162 { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist
, "Update the properties of a sink input (args: index, properties)", 3},
163 { "update-source-output-proplist", pa_cli_command_update_source_output_proplist
, "Update the properties of a source_output (args: index, properties)", 3},
164 { "set-default-sink", pa_cli_command_sink_default
, "Set the default sink (args: index|name)", 2},
165 { "set-default-source", pa_cli_command_source_default
, "Set the default source (args: index|name)", 2},
166 { "kill-client", pa_cli_command_kill_client
, "Kill a client (args: index)", 2},
167 { "kill-sink-input", pa_cli_command_kill_sink_input
, "Kill a sink input (args: index)", 2},
168 { "kill-source-output", pa_cli_command_kill_source_output
, "Kill a source output (args: index)", 2},
169 { "list-samples", pa_cli_command_scache_list
, "List all entries in the sample cache", 1},
170 { "play-sample", pa_cli_command_scache_play
, "Play a sample from the sample cache (args: name, sink|index)", 3},
171 { "remove-sample", pa_cli_command_scache_remove
, "Remove a sample from the sample cache (args: name)", 2},
172 { "load-sample", pa_cli_command_scache_load
, "Load a sound file into the sample cache (args: name, filename)", 3},
173 { "load-sample-lazy", pa_cli_command_scache_load
, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
174 { "load-sample-dir-lazy", pa_cli_command_scache_load_dir
, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
175 { "play-file", pa_cli_command_play_file
, "Play a sound file (args: filename, sink|index)", 3},
176 { "dump", pa_cli_command_dump
, "Dump daemon configuration", 1},
177 { "shared", pa_cli_command_list_shared_props
, NULL
, 1},
178 { "move-sink-input", pa_cli_command_move_sink_input
, "Move sink input to another sink (args: index, sink)", 3},
179 { "move-source-output", pa_cli_command_move_source_output
, "Move source output to another source (args: index, source)", 3},
180 { "vacuum", pa_cli_command_vacuum
, NULL
, 1},
181 { "suspend-sink", pa_cli_command_suspend_sink
, "Suspend sink (args: index|name, bool)", 3},
182 { "suspend-source", pa_cli_command_suspend_source
, "Suspend source (args: index|name, bool)", 3},
183 { "suspend", pa_cli_command_suspend
, "Suspend all sinks and all sources (args: bool)", 2},
184 { "set-card-profile", pa_cli_command_card_profile
, "Change the profile of a card (args: index, name)", 3},
185 { "set-sink-port", pa_cli_command_sink_port
, "Change the port of a sink (args: index, name)", 3},
186 { "set-source-port", pa_cli_command_source_port
, "Change the port of a source (args: index, name)", 3},
187 { "set-log-level", pa_cli_command_log_level
, "Change the log level (args: numeric level)", 2},
188 { "set-log-meta", pa_cli_command_log_meta
, "Show source code location in log messages (args: bool)", 2},
189 { "set-log-time", pa_cli_command_log_time
, "Show timestamps in log messages (args: bool)", 2},
190 { "set-log-backtrace", pa_cli_command_log_backtrace
, "Show backtrace in log messages (args: frames)", 2},
191 { "dump-volumes", pa_cli_command_dump_volumes
, NULL
, 1 },
192 { NULL
, NULL
, NULL
, 0 }
195 static const char whitespace
[] = " \t\n\r";
196 static const char linebreak
[] = "\n\r";
198 static uint32_t parse_index(const char *n
) {
201 if (pa_atou(n
, &idx
) < 0)
202 return (uint32_t) PA_IDXSET_INVALID
;
207 static int pa_cli_command_exit(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
208 pa_core_assert_ref(c
);
213 if (pa_core_exit(c
, FALSE
, 0) < 0)
214 pa_strbuf_puts(buf
, "Not allowed to terminate daemon.\n");
219 static int pa_cli_command_help(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
220 const struct command
*command
;
222 pa_core_assert_ref(c
);
227 pa_strbuf_puts(buf
, "Available commands:\n");
229 for (command
= commands
; command
->name
; command
++)
231 pa_strbuf_printf(buf
, " %-25s %s\n", command
->name
, command
->help
);
235 static int pa_cli_command_modules(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
238 pa_core_assert_ref(c
);
243 pa_assert_se(s
= pa_module_list_to_string(c
));
244 pa_strbuf_puts(buf
, s
);
249 static int pa_cli_command_clients(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
252 pa_core_assert_ref(c
);
257 pa_assert_se(s
= pa_client_list_to_string(c
));
258 pa_strbuf_puts(buf
, s
);
263 static int pa_cli_command_cards(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
266 pa_core_assert_ref(c
);
271 pa_assert_se(s
= pa_card_list_to_string(c
));
272 pa_strbuf_puts(buf
, s
);
277 static int pa_cli_command_sinks(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
280 pa_core_assert_ref(c
);
285 pa_assert_se(s
= pa_sink_list_to_string(c
));
286 pa_strbuf_puts(buf
, s
);
291 static int pa_cli_command_sources(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
294 pa_core_assert_ref(c
);
299 pa_assert_se(s
= pa_source_list_to_string(c
));
300 pa_strbuf_puts(buf
, s
);
305 static int pa_cli_command_sink_inputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
308 pa_core_assert_ref(c
);
313 pa_assert_se(s
= pa_sink_input_list_to_string(c
));
314 pa_strbuf_puts(buf
, s
);
319 static int pa_cli_command_source_outputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
322 pa_core_assert_ref(c
);
327 pa_assert_se(s
= pa_source_output_list_to_string(c
));
328 pa_strbuf_puts(buf
, s
);
333 static int pa_cli_command_stat(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
334 char ss
[PA_SAMPLE_SPEC_SNPRINT_MAX
];
335 char cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
336 char bytes
[PA_BYTES_SNPRINT_MAX
];
337 const pa_mempool_stat
*mstat
;
340 pa_source
*def_source
;
342 static const char* const type_table
[PA_MEMBLOCK_TYPE_MAX
] = {
343 [PA_MEMBLOCK_POOL
] = "POOL",
344 [PA_MEMBLOCK_POOL_EXTERNAL
] = "POOL_EXTERNAL",
345 [PA_MEMBLOCK_APPENDED
] = "APPENDED",
346 [PA_MEMBLOCK_USER
] = "USER",
347 [PA_MEMBLOCK_FIXED
] = "FIXED",
348 [PA_MEMBLOCK_IMPORTED
] = "IMPORTED",
351 pa_core_assert_ref(c
);
356 mstat
= pa_mempool_get_stat(c
->mempool
);
358 pa_strbuf_printf(buf
, "Memory blocks currently allocated: %u, size: %s.\n",
359 (unsigned) pa_atomic_load(&mstat
->n_allocated
),
360 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->allocated_size
)));
362 pa_strbuf_printf(buf
, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
363 (unsigned) pa_atomic_load(&mstat
->n_accumulated
),
364 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->accumulated_size
)));
366 pa_strbuf_printf(buf
, "Memory blocks imported from other processes: %u, size: %s.\n",
367 (unsigned) pa_atomic_load(&mstat
->n_imported
),
368 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->imported_size
)));
370 pa_strbuf_printf(buf
, "Memory blocks exported to other processes: %u, size: %s.\n",
371 (unsigned) pa_atomic_load(&mstat
->n_exported
),
372 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->exported_size
)));
374 pa_strbuf_printf(buf
, "Total sample cache size: %s.\n",
375 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_scache_total_size(c
)));
377 pa_strbuf_printf(buf
, "Default sample spec: %s\n",
378 pa_sample_spec_snprint(ss
, sizeof(ss
), &c
->default_sample_spec
));
380 pa_strbuf_printf(buf
, "Default channel map: %s\n",
381 pa_channel_map_snprint(cm
, sizeof(cm
), &c
->default_channel_map
));
383 def_sink
= pa_namereg_get_default_sink(c
);
384 def_source
= pa_namereg_get_default_source(c
);
385 pa_strbuf_printf(buf
, "Default sink name: %s\n"
386 "Default source name: %s\n",
387 def_sink
? def_sink
->name
: "none",
388 def_source
? def_source
->name
: "none");
390 for (k
= 0; k
< PA_MEMBLOCK_TYPE_MAX
; k
++)
391 pa_strbuf_printf(buf
,
392 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
394 (unsigned) pa_atomic_load(&mstat
->n_allocated_by_type
[k
]),
395 (unsigned) pa_atomic_load(&mstat
->n_accumulated_by_type
[k
]));
400 static int pa_cli_command_info(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
401 pa_core_assert_ref(c
);
406 pa_cli_command_stat(c
, t
, buf
, fail
);
407 pa_cli_command_modules(c
, t
, buf
, fail
);
408 pa_cli_command_sinks(c
, t
, buf
, fail
);
409 pa_cli_command_sources(c
, t
, buf
, fail
);
410 pa_cli_command_clients(c
, t
, buf
, fail
);
411 pa_cli_command_cards(c
, t
, buf
, fail
);
412 pa_cli_command_sink_inputs(c
, t
, buf
, fail
);
413 pa_cli_command_source_outputs(c
, t
, buf
, fail
);
414 pa_cli_command_scache_list(c
, t
, buf
, fail
);
418 static int pa_cli_command_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
421 pa_core_assert_ref(c
);
426 if (!(name
= pa_tokenizer_get(t
, 1))) {
427 pa_strbuf_puts(buf
, "You need to specify the module name and optionally arguments.\n");
431 if (!pa_module_load(c
, name
, pa_tokenizer_get(t
, 2))) {
432 pa_strbuf_puts(buf
, "Module load failed.\n");
439 static int pa_cli_command_unload(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
445 pa_core_assert_ref(c
);
450 if (!(i
= pa_tokenizer_get(t
, 1))) {
451 pa_strbuf_puts(buf
, "You need to specify the module index.\n");
455 idx
= (uint32_t) strtoul(i
, &e
, 10);
456 if (*e
|| !(m
= pa_idxset_get_by_index(c
->modules
, idx
))) {
457 pa_strbuf_puts(buf
, "Invalid module index.\n");
461 pa_module_unload_request(m
, FALSE
);
465 static int pa_cli_command_describe(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
469 pa_core_assert_ref(c
);
474 if (!(name
= pa_tokenizer_get(t
, 1))) {
475 pa_strbuf_puts(buf
, "You need to specify the module name.\n");
479 if ((i
= pa_modinfo_get_by_name(name
))) {
481 pa_strbuf_printf(buf
, "Name: %s\n", name
);
483 if (!i
->description
&& !i
->version
&& !i
->author
&& !i
->usage
)
484 pa_strbuf_printf(buf
, "No module information available\n");
487 pa_strbuf_printf(buf
, "Version: %s\n", i
->version
);
489 pa_strbuf_printf(buf
, "Description: %s\n", i
->description
);
491 pa_strbuf_printf(buf
, "Author: %s\n", i
->author
);
493 pa_strbuf_printf(buf
, "Usage: %s\n", i
->usage
);
494 pa_strbuf_printf(buf
, "Load Once: %s\n", pa_yes_no(i
->load_once
));
496 pa_strbuf_printf(buf
, "Warning, deprecated: %s\n", i
->deprecated
);
501 pa_strbuf_puts(buf
, "Failed to open module.\n");
506 static int pa_cli_command_sink_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
512 pa_core_assert_ref(c
);
517 if (!(n
= pa_tokenizer_get(t
, 1))) {
518 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
522 if (!(v
= pa_tokenizer_get(t
, 2))) {
523 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
527 if (pa_atou(v
, &volume
) < 0) {
528 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
532 if (!PA_VOLUME_IS_VALID(volume
)) {
533 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
537 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
538 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
542 pa_cvolume_set(&cvolume
, 1, volume
);
543 pa_sink_set_volume(sink
, &cvolume
, TRUE
, TRUE
);
547 static int pa_cli_command_sink_input_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
554 pa_core_assert_ref(c
);
559 if (!(n
= pa_tokenizer_get(t
, 1))) {
560 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
564 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
565 pa_strbuf_puts(buf
, "Failed to parse index.\n");
569 if (!(v
= pa_tokenizer_get(t
, 2))) {
570 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
574 if (pa_atou(v
, &volume
) < 0) {
575 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
579 if (!PA_VOLUME_IS_VALID(volume
)) {
580 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
584 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
585 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
589 if (!si
->volume_writable
) {
590 pa_strbuf_puts(buf
, "This sink input's volume can't be changed.\n");
594 pa_cvolume_set(&cvolume
, 1, volume
);
595 pa_sink_input_set_volume(si
, &cvolume
, TRUE
, TRUE
);
599 static int pa_cli_command_source_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
605 pa_core_assert_ref(c
);
610 if (!(n
= pa_tokenizer_get(t
, 1))) {
611 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
615 if (!(v
= pa_tokenizer_get(t
, 2))) {
616 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
620 if (pa_atou(v
, &volume
) < 0) {
621 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
625 if (!PA_VOLUME_IS_VALID(volume
)) {
626 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
630 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
631 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
635 pa_cvolume_set(&cvolume
, 1, volume
);
636 pa_source_set_volume(source
, &cvolume
, TRUE
, TRUE
);
640 static int pa_cli_command_sink_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
645 pa_core_assert_ref(c
);
650 if (!(n
= pa_tokenizer_get(t
, 1))) {
651 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
655 if (!(m
= pa_tokenizer_get(t
, 2))) {
656 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
660 if ((mute
= pa_parse_boolean(m
)) < 0) {
661 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
665 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
666 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
670 pa_sink_set_mute(sink
, mute
, TRUE
);
674 static int pa_cli_command_source_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
679 pa_core_assert_ref(c
);
684 if (!(n
= pa_tokenizer_get(t
, 1))) {
685 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
689 if (!(m
= pa_tokenizer_get(t
, 2))) {
690 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
694 if ((mute
= pa_parse_boolean(m
)) < 0) {
695 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
699 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
700 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
704 pa_source_set_mute(source
, mute
, TRUE
);
708 static int pa_cli_command_update_sink_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
713 pa_core_assert_ref(c
);
718 if (!(n
= pa_tokenizer_get(t
, 1))) {
719 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
723 if (!(s
= pa_tokenizer_get(t
, 2))) {
724 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
728 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
729 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
733 if (!(p
= pa_proplist_from_string(s
))) {
734 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
738 pa_sink_update_proplist(sink
, PA_UPDATE_REPLACE
, p
);
745 static int pa_cli_command_update_source_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
750 pa_core_assert_ref(c
);
755 if (!(n
= pa_tokenizer_get(t
, 1))) {
756 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
760 if (!(s
= pa_tokenizer_get(t
, 2))) {
761 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
765 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
766 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
770 if (!(p
= pa_proplist_from_string(s
))) {
771 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
775 pa_source_update_proplist(source
, PA_UPDATE_REPLACE
, p
);
782 static int pa_cli_command_update_sink_input_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
788 pa_core_assert_ref(c
);
793 if (!(n
= pa_tokenizer_get(t
, 1))) {
794 pa_strbuf_puts(buf
, "You need to specify a sink input either by index.\n");
798 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
799 pa_strbuf_puts(buf
, "Failed to parse index.\n");
803 if (!(s
= pa_tokenizer_get(t
, 2))) {
804 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
808 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
809 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
813 if (!(p
= pa_proplist_from_string(s
))) {
814 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
818 pa_sink_input_update_proplist(si
, PA_UPDATE_REPLACE
, p
);
825 static int pa_cli_command_update_source_output_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
827 pa_source_output
*so
;
831 pa_core_assert_ref(c
);
836 if (!(n
= pa_tokenizer_get(t
, 1))) {
837 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
841 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
842 pa_strbuf_puts(buf
, "Failed to parse index.\n");
846 if (!(s
= pa_tokenizer_get(t
, 2))) {
847 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
851 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
852 pa_strbuf_puts(buf
, "No source output found with this index.\n");
856 if (!(p
= pa_proplist_from_string(s
))) {
857 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
861 pa_source_output_update_proplist(so
, PA_UPDATE_REPLACE
, p
);
868 static int pa_cli_command_sink_input_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
874 pa_core_assert_ref(c
);
879 if (!(n
= pa_tokenizer_get(t
, 1))) {
880 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
884 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
885 pa_strbuf_puts(buf
, "Failed to parse index.\n");
889 if (!(v
= pa_tokenizer_get(t
, 2))) {
890 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
894 if ((mute
= pa_parse_boolean(v
)) < 0) {
895 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
899 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
900 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
904 pa_sink_input_set_mute(si
, mute
, TRUE
);
908 static int pa_cli_command_sink_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
912 pa_core_assert_ref(c
);
917 if (!(n
= pa_tokenizer_get(t
, 1))) {
918 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
922 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
)))
923 pa_namereg_set_default_sink(c
, s
);
925 pa_strbuf_printf(buf
, "Sink %s does not exist.\n", n
);
930 static int pa_cli_command_source_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
934 pa_core_assert_ref(c
);
939 if (!(n
= pa_tokenizer_get(t
, 1))) {
940 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
944 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
)))
945 pa_namereg_set_default_source(c
, s
);
947 pa_strbuf_printf(buf
, "Source %s does not exist.\n", n
);
951 static int pa_cli_command_kill_client(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
956 pa_core_assert_ref(c
);
961 if (!(n
= pa_tokenizer_get(t
, 1))) {
962 pa_strbuf_puts(buf
, "You need to specify a client by its index.\n");
966 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
967 pa_strbuf_puts(buf
, "Failed to parse index.\n");
971 if (!(client
= pa_idxset_get_by_index(c
->clients
, idx
))) {
972 pa_strbuf_puts(buf
, "No client found by this index.\n");
976 pa_client_kill(client
);
980 static int pa_cli_command_kill_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
982 pa_sink_input
*sink_input
;
985 pa_core_assert_ref(c
);
990 if (!(n
= pa_tokenizer_get(t
, 1))) {
991 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
995 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
996 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1000 if (!(sink_input
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
1001 pa_strbuf_puts(buf
, "No sink input found by this index.\n");
1005 pa_sink_input_kill(sink_input
);
1009 static int pa_cli_command_kill_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1011 pa_source_output
*source_output
;
1014 pa_core_assert_ref(c
);
1019 if (!(n
= pa_tokenizer_get(t
, 1))) {
1020 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1024 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1025 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1029 if (!(source_output
= pa_idxset_get_by_index(c
->source_outputs
, idx
))) {
1030 pa_strbuf_puts(buf
, "No source output found by this index.\n");
1034 pa_source_output_kill(source_output
);
1038 static int pa_cli_command_scache_list(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1041 pa_core_assert_ref(c
);
1046 pa_assert_se(s
= pa_scache_list_to_string(c
));
1047 pa_strbuf_puts(buf
, s
);
1053 static int pa_cli_command_scache_play(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1054 const char *n
, *sink_name
;
1058 pa_core_assert_ref(c
);
1063 if (!(n
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1064 pa_strbuf_puts(buf
, "You need to specify a sample name and a sink name.\n");
1068 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1069 pa_strbuf_puts(buf
, "No sink by that name.\n");
1073 if (pa_scache_play_item(c
, n
, sink
, PA_VOLUME_NORM
, NULL
, &idx
) < 0) {
1074 pa_strbuf_puts(buf
, "Failed to play sample.\n");
1078 pa_strbuf_printf(buf
, "Playing on sink input #%i\n", idx
);
1083 static int pa_cli_command_scache_remove(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1086 pa_core_assert_ref(c
);
1091 if (!(n
= pa_tokenizer_get(t
, 1))) {
1092 pa_strbuf_puts(buf
, "You need to specify a sample name.\n");
1096 if (pa_scache_remove_item(c
, n
) < 0) {
1097 pa_strbuf_puts(buf
, "Failed to remove sample.\n");
1104 static int pa_cli_command_scache_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1105 const char *fname
, *n
;
1108 pa_core_assert_ref(c
);
1113 if (!(fname
= pa_tokenizer_get(t
, 2)) || !(n
= pa_tokenizer_get(t
, 1))) {
1114 pa_strbuf_puts(buf
, "You need to specify a file name and a sample name.\n");
1118 if (strstr(pa_tokenizer_get(t
, 0), "lazy"))
1119 r
= pa_scache_add_file_lazy(c
, n
, fname
, NULL
);
1121 r
= pa_scache_add_file(c
, n
, fname
, NULL
);
1124 pa_strbuf_puts(buf
, "Failed to load sound file.\n");
1129 static int pa_cli_command_scache_load_dir(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1132 pa_core_assert_ref(c
);
1137 if (!(pname
= pa_tokenizer_get(t
, 1))) {
1138 pa_strbuf_puts(buf
, "You need to specify a path name.\n");
1142 if (pa_scache_add_directory_lazy(c
, pname
) < 0) {
1143 pa_strbuf_puts(buf
, "Failed to load directory.\n");
1150 static int pa_cli_command_play_file(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1151 const char *fname
, *sink_name
;
1154 pa_core_assert_ref(c
);
1159 if (!(fname
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1160 pa_strbuf_puts(buf
, "You need to specify a file name and a sink name.\n");
1164 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1165 pa_strbuf_puts(buf
, "No sink by that name.\n");
1170 return pa_play_file(sink
, fname
, NULL
);
1173 static int pa_cli_command_list_shared_props(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1174 pa_core_assert_ref(c
);
1179 pa_shared_dump(c
, buf
);
1183 static int pa_cli_command_vacuum(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1184 pa_core_assert_ref(c
);
1189 pa_mempool_vacuum(c
->mempool
);
1194 static int pa_cli_command_move_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1200 pa_core_assert_ref(c
);
1205 if (!(n
= pa_tokenizer_get(t
, 1))) {
1206 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
1210 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1211 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1215 if (!(k
= pa_tokenizer_get(t
, 2))) {
1216 pa_strbuf_puts(buf
, "You need to specify a sink.\n");
1220 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
1221 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
1225 if (!(sink
= pa_namereg_get(c
, k
, PA_NAMEREG_SINK
))) {
1226 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1230 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
1231 pa_strbuf_puts(buf
, "Moved failed.\n");
1237 static int pa_cli_command_move_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1239 pa_source_output
*so
;
1243 pa_core_assert_ref(c
);
1248 if (!(n
= pa_tokenizer_get(t
, 1))) {
1249 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1253 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1254 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1258 if (!(k
= pa_tokenizer_get(t
, 2))) {
1259 pa_strbuf_puts(buf
, "You need to specify a source.\n");
1263 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
1264 pa_strbuf_puts(buf
, "No source output found with this index.\n");
1268 if (!(source
= pa_namereg_get(c
, k
, PA_NAMEREG_SOURCE
))) {
1269 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1273 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
1274 pa_strbuf_puts(buf
, "Moved failed.\n");
1280 static int pa_cli_command_suspend_sink(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1285 pa_core_assert_ref(c
);
1290 if (!(n
= pa_tokenizer_get(t
, 1))) {
1291 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1295 if (!(m
= pa_tokenizer_get(t
, 2))) {
1296 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1300 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1301 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1305 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1306 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1310 if ((r
= pa_sink_suspend(sink
, suspend
, PA_SUSPEND_USER
)) < 0)
1311 pa_strbuf_printf(buf
, "Failed to resume/suspend sink: %s\n", pa_strerror(r
));
1316 static int pa_cli_command_suspend_source(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1321 pa_core_assert_ref(c
);
1326 if (!(n
= pa_tokenizer_get(t
, 1))) {
1327 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1331 if (!(m
= pa_tokenizer_get(t
, 2))) {
1332 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1336 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1337 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1341 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1342 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1346 if ((r
= pa_source_suspend(source
, suspend
, PA_SUSPEND_USER
)) < 0)
1347 pa_strbuf_printf(buf
, "Failed to resume/suspend source: %s\n", pa_strerror(r
));
1352 static int pa_cli_command_suspend(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1356 pa_core_assert_ref(c
);
1361 if (!(m
= pa_tokenizer_get(t
, 1))) {
1362 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1366 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1367 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1371 if ((r
= pa_sink_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1372 pa_strbuf_printf(buf
, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r
));
1374 if ((r
= pa_source_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1375 pa_strbuf_printf(buf
, "Failed to resume/suspend all sources: %s\n", pa_strerror(r
));
1380 static int pa_cli_command_log_level(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1384 pa_core_assert_ref(c
);
1389 if (!(m
= pa_tokenizer_get(t
, 1))) {
1390 pa_strbuf_puts(buf
, "You need to specify a log level (0..4).\n");
1394 if (pa_atou(m
, &level
) < 0 || level
>= PA_LOG_LEVEL_MAX
) {
1395 pa_strbuf_puts(buf
, "Failed to parse log level.\n");
1399 pa_log_set_level(level
);
1404 static int pa_cli_command_log_meta(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1408 pa_core_assert_ref(c
);
1413 if (!(m
= pa_tokenizer_get(t
, 1))) {
1414 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1418 if ((b
= pa_parse_boolean(m
)) < 0) {
1419 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1423 pa_log_set_flags(PA_LOG_PRINT_META
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1428 static int pa_cli_command_log_time(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1432 pa_core_assert_ref(c
);
1437 if (!(m
= pa_tokenizer_get(t
, 1))) {
1438 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1442 if ((b
= pa_parse_boolean(m
)) < 0) {
1443 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1447 pa_log_set_flags(PA_LOG_PRINT_TIME
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1452 static int pa_cli_command_log_backtrace(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1456 pa_core_assert_ref(c
);
1461 if (!(m
= pa_tokenizer_get(t
, 1))) {
1462 pa_strbuf_puts(buf
, "You need to specify a backtrace level.\n");
1466 if (pa_atou(m
, &nframes
) < 0 || nframes
>= 1000) {
1467 pa_strbuf_puts(buf
, "Failed to parse backtrace level.\n");
1471 pa_log_set_show_backtrace(nframes
);
1476 static int pa_cli_command_card_profile(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1480 pa_core_assert_ref(c
);
1485 if (!(n
= pa_tokenizer_get(t
, 1))) {
1486 pa_strbuf_puts(buf
, "You need to specify a card either by its name or its index.\n");
1490 if (!(p
= pa_tokenizer_get(t
, 2))) {
1491 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1495 if (!(card
= pa_namereg_get(c
, n
, PA_NAMEREG_CARD
))) {
1496 pa_strbuf_puts(buf
, "No card found by this name or index.\n");
1500 if (pa_card_set_profile(card
, p
, TRUE
) < 0) {
1501 pa_strbuf_printf(buf
, "Failed to set card profile to '%s'.\n", p
);
1508 static int pa_cli_command_sink_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1512 pa_core_assert_ref(c
);
1517 if (!(n
= pa_tokenizer_get(t
, 1))) {
1518 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1522 if (!(p
= pa_tokenizer_get(t
, 2))) {
1523 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1527 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1528 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1532 if (pa_sink_set_port(sink
, p
, TRUE
) < 0) {
1533 pa_strbuf_printf(buf
, "Failed to set sink port to '%s'.\n", p
);
1540 static int pa_cli_command_source_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1544 pa_core_assert_ref(c
);
1549 if (!(n
= pa_tokenizer_get(t
, 1))) {
1550 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1554 if (!(p
= pa_tokenizer_get(t
, 2))) {
1555 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1559 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1560 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1564 if (pa_source_set_port(source
, p
, TRUE
) < 0) {
1565 pa_strbuf_printf(buf
, "Failed to set source port to '%s'.\n", p
);
1572 static int pa_cli_command_dump(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1584 pa_core_assert_ref(c
);
1592 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime_r(&now
, txt
));
1594 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime(&now
));
1597 PA_IDXSET_FOREACH(m
, c
->modules
, idx
) {
1599 pa_strbuf_printf(buf
, "load-module %s", m
->name
);
1602 pa_strbuf_printf(buf
, " %s", m
->argument
);
1604 pa_strbuf_puts(buf
, "\n");
1608 PA_IDXSET_FOREACH(sink
, c
->sinks
, idx
) {
1611 pa_strbuf_puts(buf
, "\n");
1615 pa_strbuf_printf(buf
, "set-sink-volume %s 0x%03x\n", sink
->name
, pa_cvolume_max(pa_sink_get_volume(sink
, FALSE
)));
1616 pa_strbuf_printf(buf
, "set-sink-mute %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_mute(sink
, FALSE
)));
1617 pa_strbuf_printf(buf
, "suspend-sink %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_state(sink
) == PA_SINK_SUSPENDED
));
1621 PA_IDXSET_FOREACH(source
, c
->sources
, idx
) {
1624 pa_strbuf_puts(buf
, "\n");
1628 pa_strbuf_printf(buf
, "set-source-volume %s 0x%03x\n", source
->name
, pa_cvolume_max(pa_source_get_volume(source
, FALSE
)));
1629 pa_strbuf_printf(buf
, "set-source-mute %s %s\n", source
->name
, pa_yes_no(pa_source_get_mute(source
, FALSE
)));
1630 pa_strbuf_printf(buf
, "suspend-source %s %s\n", source
->name
, pa_yes_no(pa_source_get_state(source
) == PA_SOURCE_SUSPENDED
));
1634 PA_IDXSET_FOREACH(card
, c
->cards
, idx
) {
1637 pa_strbuf_puts(buf
, "\n");
1641 if (card
->active_profile
)
1642 pa_strbuf_printf(buf
, "set-card-profile %s %s\n", card
->name
, card
->active_profile
->name
);
1646 if ((sink
= pa_namereg_get_default_sink(c
))) {
1648 pa_strbuf_puts(buf
, "\n");
1652 pa_strbuf_printf(buf
, "set-default-sink %s\n", sink
->name
);
1655 if ((source
= pa_namereg_get_default_source(c
))) {
1657 pa_strbuf_puts(buf
, "\n");
1659 pa_strbuf_printf(buf
, "set-default-source %s\n", source
->name
);
1662 pa_strbuf_puts(buf
, "\n### EOF\n");
1667 static int pa_cli_command_dump_volumes(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1671 pa_source_output
*o
;
1672 uint32_t s_idx
, i_idx
;
1673 char v_str
[PA_CVOLUME_SNPRINT_MAX
];
1675 pa_core_assert_ref(c
);
1680 PA_IDXSET_FOREACH(s
, c
->sinks
, s_idx
) {
1681 pa_strbuf_printf(buf
, "Sink %d: ", s_idx
);
1682 pa_strbuf_printf(buf
, "reference = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->reference_volume
));
1683 pa_strbuf_printf(buf
, "real = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->real_volume
));
1684 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->soft_volume
));
1685 pa_strbuf_printf(buf
, "current_hw = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->thread_info
.current_hw_volume
));
1686 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(s
->save_volume
));
1688 PA_IDXSET_FOREACH(i
, s
->inputs
, i_idx
) {
1689 pa_strbuf_printf(buf
, "\tInput %d: ", i_idx
);
1690 pa_strbuf_printf(buf
, "volume = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->volume
));
1691 pa_strbuf_printf(buf
, "reference_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->reference_ratio
));
1692 pa_strbuf_printf(buf
, "real_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->real_ratio
));
1693 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->soft_volume
));
1694 pa_strbuf_printf(buf
, "volume_factor = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->volume_factor
));
1695 pa_strbuf_printf(buf
, "volume_factor_sink = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->volume_factor_sink
));
1696 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(i
->save_volume
));
1700 PA_IDXSET_FOREACH(so
, c
->sources
, s_idx
) {
1701 pa_strbuf_printf(buf
, "Source %d: ", s_idx
);
1702 pa_strbuf_printf(buf
, "reference = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->reference_volume
));
1703 pa_strbuf_printf(buf
, "real = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->real_volume
));
1704 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->soft_volume
));
1705 pa_strbuf_printf(buf
, "current_hw = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->thread_info
.current_hw_volume
));
1706 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(so
->save_volume
));
1708 PA_IDXSET_FOREACH(o
, so
->outputs
, i_idx
) {
1709 pa_strbuf_printf(buf
, "\tOutput %d: ", i_idx
);
1710 pa_strbuf_printf(buf
, "volume = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->volume
));
1711 pa_strbuf_printf(buf
, "reference_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->reference_ratio
));
1712 pa_strbuf_printf(buf
, "real_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->real_ratio
));
1713 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->soft_volume
));
1714 pa_strbuf_printf(buf
, "volume_factor = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->volume_factor
));
1715 pa_strbuf_printf(buf
, "volume_factor_source = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->volume_factor_source
));
1716 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(o
->save_volume
));
1723 int pa_cli_command_execute_line_stateful(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
, int *ifstate
) {
1730 cs
= s
+strspn(s
, whitespace
);
1732 if (*cs
== '#' || !*cs
)
1734 else if (*cs
== '.') {
1735 if (!strcmp(cs
, META_ELSE
)) {
1736 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1737 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1739 } else if (*ifstate
== IFSTATE_TRUE
)
1740 *ifstate
= IFSTATE_FALSE
;
1742 *ifstate
= IFSTATE_TRUE
;
1744 } else if (!strcmp(cs
, META_ENDIF
)) {
1745 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1746 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1749 *ifstate
= IFSTATE_NONE
;
1752 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
1754 if (!strcmp(cs
, META_FAIL
))
1756 else if (!strcmp(cs
, META_NOFAIL
))
1760 l
= strcspn(cs
, whitespace
);
1762 if (l
== sizeof(META_INCLUDE
)-1 && !strncmp(cs
, META_INCLUDE
, l
)) {
1764 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
1766 if (stat(filename
, &st
) < 0) {
1767 pa_log_warn("stat('%s'): %s", filename
, pa_cstrerror(errno
));
1771 if (S_ISDIR(st
.st_mode
)) {
1774 if (!(d
= opendir(filename
))) {
1775 pa_log_warn("Failed to read '%s': %s", filename
, pa_cstrerror(errno
));
1780 char **sorted_files
;
1782 pa_bool_t failed
= FALSE
;
1783 pa_dynarray
*files
= pa_dynarray_new();
1785 while ((de
= readdir(d
))) {
1787 size_t flen
= strlen(de
->d_name
);
1792 extn
= &de
->d_name
[flen
-3];
1793 if (strncmp(extn
, ".pa", 3) == 0)
1794 pa_dynarray_append(files
, pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", filename
, de
->d_name
));
1799 count
= pa_dynarray_size(files
);
1800 sorted_files
= pa_xnew(char*, count
);
1801 for (i
= 0; i
< count
; ++i
)
1802 sorted_files
[i
] = pa_dynarray_get(files
, i
);
1803 pa_dynarray_free(files
, NULL
);
1805 for (i
= 0; i
< count
; ++i
) {
1806 for (unsigned j
= 0; j
< count
; ++j
) {
1807 if (strcmp(sorted_files
[i
], sorted_files
[j
]) < 0) {
1808 char *tmp
= sorted_files
[i
];
1809 sorted_files
[i
] = sorted_files
[j
];
1810 sorted_files
[j
] = tmp
;
1815 for (i
= 0; i
< count
; ++i
) {
1817 if (pa_cli_command_execute_file(c
, sorted_files
[i
], buf
, fail
) < 0 && *fail
)
1821 pa_xfree(sorted_files
[i
]);
1823 pa_xfree(sorted_files
);
1827 } else if (pa_cli_command_execute_file(c
, filename
, buf
, fail
) < 0 && *fail
) {
1831 } else if (l
== sizeof(META_IFEXISTS
)-1 && !strncmp(cs
, META_IFEXISTS
, l
)) {
1833 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1835 } else if (*ifstate
!= IFSTATE_NONE
) {
1836 pa_strbuf_printf(buf
, "Nested %s commands not supported\n", cs
);
1839 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
1841 /* Search DL_SEARCH_PATH unless the filename is absolute */
1842 if (filename
[0] == PA_PATH_SEP_CHAR
) {
1844 *ifstate
= access(filename
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
1845 pa_log_debug("Checking for existence of '%s': %s", filename
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
1848 const char *paths
, *state
= NULL
;
1851 if (!(paths
= lt_dlgetsearchpath()))
1854 while ((p
= pa_split(paths
, ":", &state
))) {
1857 pathname
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", p
, filename
);
1860 *ifstate
= access(pathname
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
1861 pa_log_debug("Checking for existence of '%s': %s", pathname
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
1865 if (*ifstate
== IFSTATE_TRUE
)
1872 pa_strbuf_printf(buf
, "Invalid meta command: %s\n", cs
);
1873 if (*fail
) return -1;
1877 const struct command
*command
;
1881 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
1884 l
= strcspn(cs
, whitespace
);
1886 for (command
= commands
; command
->name
; command
++)
1887 if (strlen(command
->name
) == l
&& !strncmp(cs
, command
->name
, l
)) {
1889 pa_tokenizer
*t
= pa_tokenizer_new(cs
, command
->args
);
1891 ret
= command
->proc(c
, t
, buf
, fail
);
1892 pa_tokenizer_free(t
);
1895 if (ret
< 0 && *fail
)
1902 pa_strbuf_printf(buf
, "Unknown command: %s\n", cs
);
1911 int pa_cli_command_execute_line(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1912 return pa_cli_command_execute_line_stateful(c
, s
, buf
, fail
, NULL
);
1915 int pa_cli_command_execute_file_stream(pa_core
*c
, FILE *f
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1917 int ifstate
= IFSTATE_NONE
;
1919 pa_bool_t _fail
= TRUE
;
1928 while (fgets(line
, sizeof(line
), f
)) {
1931 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
)
1942 int pa_cli_command_execute_file(pa_core
*c
, const char *fn
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1945 pa_bool_t _fail
= TRUE
;
1954 if (!(f
= pa_fopen_cloexec(fn
, "r"))) {
1955 pa_strbuf_printf(buf
, "open('%s') failed: %s\n", fn
, pa_cstrerror(errno
));
1961 pa_log_debug("Parsing script '%s'", fn
);
1962 ret
= pa_cli_command_execute_file_stream(c
, f
, buf
, fail
);
1971 int pa_cli_command_execute(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1973 int ifstate
= IFSTATE_NONE
;
1974 pa_bool_t _fail
= TRUE
;
1985 size_t l
= strcspn(p
, linebreak
);
1986 char *line
= pa_xstrndup(p
, l
);
1988 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
) {
1995 p
+= strspn(p
, linebreak
);