2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
36 #include <pulse/xmalloc.h>
37 #include <pulse/error.h>
39 #include <pulsecore/module.h>
40 #include <pulsecore/sink.h>
41 #include <pulsecore/source.h>
42 #include <pulsecore/client.h>
43 #include <pulsecore/sink-input.h>
44 #include <pulsecore/source-output.h>
45 #include <pulsecore/tokenizer.h>
46 #include <pulsecore/strbuf.h>
47 #include <pulsecore/namereg.h>
48 #include <pulsecore/cli-text.h>
49 #include <pulsecore/core-scache.h>
50 #include <pulsecore/sample-util.h>
51 #include <pulsecore/sound-file.h>
52 #include <pulsecore/play-memchunk.h>
53 #include <pulsecore/sound-file-stream.h>
54 #include <pulsecore/shared.h>
55 #include <pulsecore/core-util.h>
56 #include <pulsecore/core-error.h>
57 #include <pulsecore/modinfo.h>
58 #include <pulsecore/dynarray.h>
60 #include "cli-command.h"
64 int (*proc
) (pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
69 #define META_INCLUDE ".include"
70 #define META_FAIL ".fail"
71 #define META_NOFAIL ".nofail"
72 #define META_IFEXISTS ".ifexists"
73 #define META_ELSE ".else"
74 #define META_ENDIF ".endif"
82 /* Prototypes for all available commands */
83 static int pa_cli_command_exit(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
84 static int pa_cli_command_help(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
85 static int pa_cli_command_modules(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
86 static int pa_cli_command_clients(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
87 static int pa_cli_command_cards(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
88 static int pa_cli_command_sinks(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
89 static int pa_cli_command_sources(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
90 static int pa_cli_command_sink_inputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
91 static int pa_cli_command_source_outputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
92 static int pa_cli_command_stat(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
93 static int pa_cli_command_info(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
94 static int pa_cli_command_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
95 static int pa_cli_command_unload(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
96 static int pa_cli_command_describe(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
97 static int pa_cli_command_sink_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
98 static int pa_cli_command_sink_input_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
99 static int pa_cli_command_source_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
100 static int pa_cli_command_sink_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
101 static int pa_cli_command_source_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
102 static int pa_cli_command_sink_input_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
103 static int pa_cli_command_sink_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
104 static int pa_cli_command_source_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
105 static int pa_cli_command_kill_client(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
106 static int pa_cli_command_kill_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
107 static int pa_cli_command_kill_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
108 static int pa_cli_command_scache_play(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
109 static int pa_cli_command_scache_remove(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
110 static int pa_cli_command_scache_list(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
111 static int pa_cli_command_scache_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
112 static int pa_cli_command_scache_load_dir(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
113 static int pa_cli_command_play_file(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
114 static int pa_cli_command_dump(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
115 static int pa_cli_command_list_shared_props(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
116 static int pa_cli_command_move_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
117 static int pa_cli_command_move_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
118 static int pa_cli_command_vacuum(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
119 static int pa_cli_command_suspend_sink(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
120 static int pa_cli_command_suspend_source(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
121 static int pa_cli_command_suspend(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
122 static int pa_cli_command_log_level(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
123 static int pa_cli_command_log_meta(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
124 static int pa_cli_command_log_time(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
125 static int pa_cli_command_log_backtrace(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
126 static int pa_cli_command_update_sink_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
127 static int pa_cli_command_update_source_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
128 static int pa_cli_command_update_sink_input_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
129 static int pa_cli_command_update_source_output_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
130 static int pa_cli_command_card_profile(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
131 static int pa_cli_command_sink_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
132 static int pa_cli_command_source_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
134 /* A method table for all available commands */
136 static const struct command commands
[] = {
137 { "exit", pa_cli_command_exit
, "Terminate the daemon", 1 },
138 { "help", pa_cli_command_help
, "Show this help", 1 },
139 { "list-modules", pa_cli_command_modules
, "List loaded modules", 1 },
140 { "list-sinks", pa_cli_command_sinks
, "List loaded sinks", 1 },
141 { "list-sources", pa_cli_command_sources
, "List loaded sources", 1 },
142 { "list-clients", pa_cli_command_clients
, "List loaded clients", 1 },
143 { "list-sink-inputs", pa_cli_command_sink_inputs
, "List sink inputs", 1 },
144 { "list-source-outputs", pa_cli_command_source_outputs
, "List source outputs", 1 },
145 { "list-cards", pa_cli_command_cards
, "List cards", 1 },
146 { "stat", pa_cli_command_stat
, "Show memory block statistics", 1 },
147 { "info", pa_cli_command_info
, "Show comprehensive status", 1 },
148 { "ls", pa_cli_command_info
, NULL
, 1 },
149 { "list", pa_cli_command_info
, NULL
, 1 },
150 { "load-module", pa_cli_command_load
, "Load a module (args: name, arguments)", 3},
151 { "unload-module", pa_cli_command_unload
, "Unload a module (args: index)", 2},
152 { "describe-module", pa_cli_command_describe
, "Describe a module (arg: name)", 2},
153 { "set-sink-volume", pa_cli_command_sink_volume
, "Set the volume of a sink (args: index|name, volume)", 3},
154 { "set-sink-input-volume", pa_cli_command_sink_input_volume
, "Set the volume of a sink input (args: index, volume)", 3},
155 { "set-source-volume", pa_cli_command_source_volume
, "Set the volume of a source (args: index|name, volume)", 3},
156 { "set-sink-mute", pa_cli_command_sink_mute
, "Set the mute switch of a sink (args: index|name, bool)", 3},
157 { "set-sink-input-mute", pa_cli_command_sink_input_mute
, "Set the mute switch of a sink input (args: index, bool)", 3},
158 { "set-source-mute", pa_cli_command_source_mute
, "Set the mute switch of a source (args: index|name, bool)", 3},
159 { "update-sink-proplist", pa_cli_command_update_sink_proplist
, "Update the properties of a sink (args: index|name, properties)", 3},
160 { "update-source-proplist", pa_cli_command_update_source_proplist
, "Update the properties of a source (args: index|name, properties)", 3},
161 { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist
, "Update the properties of a sink input (args: index, properties)", 3},
162 { "update-source-output-proplist", pa_cli_command_update_source_output_proplist
, "Update the properties of a source_output (args: index, properties)", 3},
163 { "set-default-sink", pa_cli_command_sink_default
, "Set the default sink (args: index|name)", 2},
164 { "set-default-source", pa_cli_command_source_default
, "Set the default source (args: index|name)", 2},
165 { "kill-client", pa_cli_command_kill_client
, "Kill a client (args: index)", 2},
166 { "kill-sink-input", pa_cli_command_kill_sink_input
, "Kill a sink input (args: index)", 2},
167 { "kill-source-output", pa_cli_command_kill_source_output
, "Kill a source output (args: index)", 2},
168 { "list-samples", pa_cli_command_scache_list
, "List all entries in the sample cache", 1},
169 { "play-sample", pa_cli_command_scache_play
, "Play a sample from the sample cache (args: name, sink|index)", 3},
170 { "remove-sample", pa_cli_command_scache_remove
, "Remove a sample from the sample cache (args: name)", 2},
171 { "load-sample", pa_cli_command_scache_load
, "Load a sound file into the sample cache (args: name, filename)", 3},
172 { "load-sample-lazy", pa_cli_command_scache_load
, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
173 { "load-sample-dir-lazy", pa_cli_command_scache_load_dir
, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
174 { "play-file", pa_cli_command_play_file
, "Play a sound file (args: filename, sink|index)", 3},
175 { "dump", pa_cli_command_dump
, "Dump daemon configuration", 1},
176 { "shared", pa_cli_command_list_shared_props
, NULL
, 1},
177 { "move-sink-input", pa_cli_command_move_sink_input
, "Move sink input to another sink (args: index, sink)", 3},
178 { "move-source-output", pa_cli_command_move_source_output
, "Move source output to another source (args: index, source)", 3},
179 { "vacuum", pa_cli_command_vacuum
, NULL
, 1},
180 { "suspend-sink", pa_cli_command_suspend_sink
, "Suspend sink (args: index|name, bool)", 3},
181 { "suspend-source", pa_cli_command_suspend_source
, "Suspend source (args: index|name, bool)", 3},
182 { "suspend", pa_cli_command_suspend
, "Suspend all sinks and all sources (args: bool)", 2},
183 { "set-card-profile", pa_cli_command_card_profile
, "Change the profile of a card (args: index, name)", 3},
184 { "set-sink-port", pa_cli_command_sink_port
, "Change the port of a sink (args: index, name)", 3},
185 { "set-source-port", pa_cli_command_source_port
, "Change the port of a source (args: index, name)", 3},
186 { "set-log-level", pa_cli_command_log_level
, "Change the log level (args: numeric level)", 2},
187 { "set-log-meta", pa_cli_command_log_meta
, "Show source code location in log messages (args: bool)", 2},
188 { "set-log-time", pa_cli_command_log_time
, "Show timestamps in log messages (args: bool)", 2},
189 { "set-log-backtrace", pa_cli_command_log_backtrace
, "Show backtrace in log messages (args: frames)", 2},
190 { NULL
, NULL
, NULL
, 0 }
193 static const char whitespace
[] = " \t\n\r";
194 static const char linebreak
[] = "\n\r";
196 static uint32_t parse_index(const char *n
) {
199 if (pa_atou(n
, &idx
) < 0)
200 return (uint32_t) PA_IDXSET_INVALID
;
205 static int pa_cli_command_exit(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
206 pa_core_assert_ref(c
);
211 if (pa_core_exit(c
, FALSE
, 0) < 0)
212 pa_strbuf_puts(buf
, "Not allowed to terminate daemon.\n");
217 static int pa_cli_command_help(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
218 const struct command
*command
;
220 pa_core_assert_ref(c
);
225 pa_strbuf_puts(buf
, "Available commands:\n");
227 for (command
= commands
; command
->name
; command
++)
229 pa_strbuf_printf(buf
, " %-25s %s\n", command
->name
, command
->help
);
233 static int pa_cli_command_modules(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
236 pa_core_assert_ref(c
);
241 pa_assert_se(s
= pa_module_list_to_string(c
));
242 pa_strbuf_puts(buf
, s
);
247 static int pa_cli_command_clients(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
250 pa_core_assert_ref(c
);
255 pa_assert_se(s
= pa_client_list_to_string(c
));
256 pa_strbuf_puts(buf
, s
);
261 static int pa_cli_command_cards(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
264 pa_core_assert_ref(c
);
269 pa_assert_se(s
= pa_card_list_to_string(c
));
270 pa_strbuf_puts(buf
, s
);
275 static int pa_cli_command_sinks(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
278 pa_core_assert_ref(c
);
283 pa_assert_se(s
= pa_sink_list_to_string(c
));
284 pa_strbuf_puts(buf
, s
);
289 static int pa_cli_command_sources(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
292 pa_core_assert_ref(c
);
297 pa_assert_se(s
= pa_source_list_to_string(c
));
298 pa_strbuf_puts(buf
, s
);
303 static int pa_cli_command_sink_inputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
306 pa_core_assert_ref(c
);
311 pa_assert_se(s
= pa_sink_input_list_to_string(c
));
312 pa_strbuf_puts(buf
, s
);
317 static int pa_cli_command_source_outputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
320 pa_core_assert_ref(c
);
325 pa_assert_se(s
= pa_source_output_list_to_string(c
));
326 pa_strbuf_puts(buf
, s
);
331 static int pa_cli_command_stat(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
332 char ss
[PA_SAMPLE_SPEC_SNPRINT_MAX
];
333 char cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
334 char bytes
[PA_BYTES_SNPRINT_MAX
];
335 const pa_mempool_stat
*mstat
;
338 pa_source
*def_source
;
340 static const char* const type_table
[PA_MEMBLOCK_TYPE_MAX
] = {
341 [PA_MEMBLOCK_POOL
] = "POOL",
342 [PA_MEMBLOCK_POOL_EXTERNAL
] = "POOL_EXTERNAL",
343 [PA_MEMBLOCK_APPENDED
] = "APPENDED",
344 [PA_MEMBLOCK_USER
] = "USER",
345 [PA_MEMBLOCK_FIXED
] = "FIXED",
346 [PA_MEMBLOCK_IMPORTED
] = "IMPORTED",
349 pa_core_assert_ref(c
);
354 mstat
= pa_mempool_get_stat(c
->mempool
);
356 pa_strbuf_printf(buf
, "Memory blocks currently allocated: %u, size: %s.\n",
357 (unsigned) pa_atomic_load(&mstat
->n_allocated
),
358 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->allocated_size
)));
360 pa_strbuf_printf(buf
, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
361 (unsigned) pa_atomic_load(&mstat
->n_accumulated
),
362 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->accumulated_size
)));
364 pa_strbuf_printf(buf
, "Memory blocks imported from other processes: %u, size: %s.\n",
365 (unsigned) pa_atomic_load(&mstat
->n_imported
),
366 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->imported_size
)));
368 pa_strbuf_printf(buf
, "Memory blocks exported to other processes: %u, size: %s.\n",
369 (unsigned) pa_atomic_load(&mstat
->n_exported
),
370 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->exported_size
)));
372 pa_strbuf_printf(buf
, "Total sample cache size: %s.\n",
373 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_scache_total_size(c
)));
375 pa_strbuf_printf(buf
, "Default sample spec: %s\n",
376 pa_sample_spec_snprint(ss
, sizeof(ss
), &c
->default_sample_spec
));
378 pa_strbuf_printf(buf
, "Default channel map: %s\n",
379 pa_channel_map_snprint(cm
, sizeof(cm
), &c
->default_channel_map
));
381 def_sink
= pa_namereg_get_default_sink(c
);
382 def_source
= pa_namereg_get_default_source(c
);
383 pa_strbuf_printf(buf
, "Default sink name: %s\n"
384 "Default source name: %s\n",
385 def_sink
? def_sink
->name
: "none",
386 def_source
? def_source
->name
: "none");
388 for (k
= 0; k
< PA_MEMBLOCK_TYPE_MAX
; k
++)
389 pa_strbuf_printf(buf
,
390 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
392 (unsigned) pa_atomic_load(&mstat
->n_allocated_by_type
[k
]),
393 (unsigned) pa_atomic_load(&mstat
->n_accumulated_by_type
[k
]));
398 static int pa_cli_command_info(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
399 pa_core_assert_ref(c
);
404 pa_cli_command_stat(c
, t
, buf
, fail
);
405 pa_cli_command_modules(c
, t
, buf
, fail
);
406 pa_cli_command_sinks(c
, t
, buf
, fail
);
407 pa_cli_command_sources(c
, t
, buf
, fail
);
408 pa_cli_command_clients(c
, t
, buf
, fail
);
409 pa_cli_command_cards(c
, t
, buf
, fail
);
410 pa_cli_command_sink_inputs(c
, t
, buf
, fail
);
411 pa_cli_command_source_outputs(c
, t
, buf
, fail
);
412 pa_cli_command_scache_list(c
, t
, buf
, fail
);
416 static int pa_cli_command_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
419 pa_core_assert_ref(c
);
424 if (!(name
= pa_tokenizer_get(t
, 1))) {
425 pa_strbuf_puts(buf
, "You need to specify the module name and optionally arguments.\n");
429 if (!pa_module_load(c
, name
, pa_tokenizer_get(t
, 2))) {
430 pa_strbuf_puts(buf
, "Module load failed.\n");
437 static int pa_cli_command_unload(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
443 pa_core_assert_ref(c
);
448 if (!(i
= pa_tokenizer_get(t
, 1))) {
449 pa_strbuf_puts(buf
, "You need to specify the module index.\n");
453 idx
= (uint32_t) strtoul(i
, &e
, 10);
454 if (*e
|| !(m
= pa_idxset_get_by_index(c
->modules
, idx
))) {
455 pa_strbuf_puts(buf
, "Invalid module index.\n");
459 pa_module_unload_request(m
, FALSE
);
463 static int pa_cli_command_describe(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
467 pa_core_assert_ref(c
);
472 if (!(name
= pa_tokenizer_get(t
, 1))) {
473 pa_strbuf_puts(buf
, "You need to specify the module name.\n");
477 if ((i
= pa_modinfo_get_by_name(name
))) {
479 pa_strbuf_printf(buf
, "Name: %s\n", name
);
481 if (!i
->description
&& !i
->version
&& !i
->author
&& !i
->usage
)
482 pa_strbuf_printf(buf
, "No module information available\n");
485 pa_strbuf_printf(buf
, "Version: %s\n", i
->version
);
487 pa_strbuf_printf(buf
, "Description: %s\n", i
->description
);
489 pa_strbuf_printf(buf
, "Author: %s\n", i
->author
);
491 pa_strbuf_printf(buf
, "Usage: %s\n", i
->usage
);
492 pa_strbuf_printf(buf
, "Load Once: %s\n", pa_yes_no(i
->load_once
));
494 pa_strbuf_printf(buf
, "Warning, deprecated: %s\n", i
->deprecated
);
499 pa_strbuf_puts(buf
, "Failed to open module.\n");
504 static int pa_cli_command_sink_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
510 pa_core_assert_ref(c
);
515 if (!(n
= pa_tokenizer_get(t
, 1))) {
516 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
520 if (!(v
= pa_tokenizer_get(t
, 2))) {
521 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
525 if (pa_atou(v
, &volume
) < 0) {
526 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
530 if (!PA_VOLUME_IS_VALID(volume
)) {
531 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
535 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
536 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
540 pa_cvolume_set(&cvolume
, 1, volume
);
541 pa_sink_set_volume(sink
, &cvolume
, TRUE
, TRUE
);
545 static int pa_cli_command_sink_input_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
552 pa_core_assert_ref(c
);
557 if (!(n
= pa_tokenizer_get(t
, 1))) {
558 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
562 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
563 pa_strbuf_puts(buf
, "Failed to parse index.\n");
567 if (!(v
= pa_tokenizer_get(t
, 2))) {
568 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
572 if (pa_atou(v
, &volume
) < 0) {
573 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
577 if (!PA_VOLUME_IS_VALID(volume
)) {
578 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
582 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
583 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
587 if (!pa_sink_input_is_volume_writable(si
)) {
588 pa_strbuf_puts(buf
, "This sink input's volume can't be changed.\n");
592 pa_cvolume_set(&cvolume
, 1, volume
);
593 pa_sink_input_set_volume(si
, &cvolume
, TRUE
, TRUE
);
597 static int pa_cli_command_source_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
603 pa_core_assert_ref(c
);
608 if (!(n
= pa_tokenizer_get(t
, 1))) {
609 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
613 if (!(v
= pa_tokenizer_get(t
, 2))) {
614 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
618 if (pa_atou(v
, &volume
) < 0) {
619 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
623 if (!PA_VOLUME_IS_VALID(volume
)) {
624 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
628 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
629 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
633 pa_cvolume_set(&cvolume
, 1, volume
);
634 pa_source_set_volume(source
, &cvolume
, TRUE
);
638 static int pa_cli_command_sink_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
643 pa_core_assert_ref(c
);
648 if (!(n
= pa_tokenizer_get(t
, 1))) {
649 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
653 if (!(m
= pa_tokenizer_get(t
, 2))) {
654 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
658 if ((mute
= pa_parse_boolean(m
)) < 0) {
659 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
663 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
664 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
668 pa_sink_set_mute(sink
, mute
, TRUE
);
672 static int pa_cli_command_source_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
677 pa_core_assert_ref(c
);
682 if (!(n
= pa_tokenizer_get(t
, 1))) {
683 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
687 if (!(m
= pa_tokenizer_get(t
, 2))) {
688 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
692 if ((mute
= pa_parse_boolean(m
)) < 0) {
693 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
697 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
698 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
702 pa_source_set_mute(source
, mute
, TRUE
);
706 static int pa_cli_command_update_sink_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
711 pa_core_assert_ref(c
);
716 if (!(n
= pa_tokenizer_get(t
, 1))) {
717 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
721 if (!(s
= pa_tokenizer_get(t
, 2))) {
722 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
726 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
727 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
731 if (!(p
= pa_proplist_from_string(s
))) {
732 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
736 pa_sink_update_proplist(sink
, PA_UPDATE_REPLACE
, p
);
743 static int pa_cli_command_update_source_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
748 pa_core_assert_ref(c
);
753 if (!(n
= pa_tokenizer_get(t
, 1))) {
754 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
758 if (!(s
= pa_tokenizer_get(t
, 2))) {
759 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
763 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
764 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
768 if (!(p
= pa_proplist_from_string(s
))) {
769 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
773 pa_source_update_proplist(source
, PA_UPDATE_REPLACE
, p
);
780 static int pa_cli_command_update_sink_input_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
786 pa_core_assert_ref(c
);
791 if (!(n
= pa_tokenizer_get(t
, 1))) {
792 pa_strbuf_puts(buf
, "You need to specify a sink input either by index.\n");
796 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
797 pa_strbuf_puts(buf
, "Failed to parse index.\n");
801 if (!(s
= pa_tokenizer_get(t
, 2))) {
802 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
806 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
807 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
811 if (!(p
= pa_proplist_from_string(s
))) {
812 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
816 pa_sink_input_update_proplist(si
, PA_UPDATE_REPLACE
, p
);
823 static int pa_cli_command_update_source_output_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
825 pa_source_output
*so
;
829 pa_core_assert_ref(c
);
834 if (!(n
= pa_tokenizer_get(t
, 1))) {
835 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
839 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
840 pa_strbuf_puts(buf
, "Failed to parse index.\n");
844 if (!(s
= pa_tokenizer_get(t
, 2))) {
845 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
849 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
850 pa_strbuf_puts(buf
, "No source output found with this index.\n");
854 if (!(p
= pa_proplist_from_string(s
))) {
855 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
859 pa_source_output_update_proplist(so
, PA_UPDATE_REPLACE
, p
);
866 static int pa_cli_command_sink_input_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
872 pa_core_assert_ref(c
);
877 if (!(n
= pa_tokenizer_get(t
, 1))) {
878 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
882 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
883 pa_strbuf_puts(buf
, "Failed to parse index.\n");
887 if (!(v
= pa_tokenizer_get(t
, 2))) {
888 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
892 if ((mute
= pa_parse_boolean(v
)) < 0) {
893 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
897 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
898 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
902 pa_sink_input_set_mute(si
, mute
, TRUE
);
906 static int pa_cli_command_sink_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
910 pa_core_assert_ref(c
);
915 if (!(n
= pa_tokenizer_get(t
, 1))) {
916 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
920 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
)))
921 pa_namereg_set_default_sink(c
, s
);
923 pa_strbuf_printf(buf
, "Sink %s does not exist.\n", n
);
928 static int pa_cli_command_source_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
932 pa_core_assert_ref(c
);
937 if (!(n
= pa_tokenizer_get(t
, 1))) {
938 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
942 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
)))
943 pa_namereg_set_default_source(c
, s
);
945 pa_strbuf_printf(buf
, "Source %s does not exist.\n", n
);
949 static int pa_cli_command_kill_client(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
954 pa_core_assert_ref(c
);
959 if (!(n
= pa_tokenizer_get(t
, 1))) {
960 pa_strbuf_puts(buf
, "You need to specify a client by its index.\n");
964 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
965 pa_strbuf_puts(buf
, "Failed to parse index.\n");
969 if (!(client
= pa_idxset_get_by_index(c
->clients
, idx
))) {
970 pa_strbuf_puts(buf
, "No client found by this index.\n");
974 pa_client_kill(client
);
978 static int pa_cli_command_kill_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
980 pa_sink_input
*sink_input
;
983 pa_core_assert_ref(c
);
988 if (!(n
= pa_tokenizer_get(t
, 1))) {
989 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
993 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
994 pa_strbuf_puts(buf
, "Failed to parse index.\n");
998 if (!(sink_input
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
999 pa_strbuf_puts(buf
, "No sink input found by this index.\n");
1003 pa_sink_input_kill(sink_input
);
1007 static int pa_cli_command_kill_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1009 pa_source_output
*source_output
;
1012 pa_core_assert_ref(c
);
1017 if (!(n
= pa_tokenizer_get(t
, 1))) {
1018 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1022 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1023 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1027 if (!(source_output
= pa_idxset_get_by_index(c
->source_outputs
, idx
))) {
1028 pa_strbuf_puts(buf
, "No source output found by this index.\n");
1032 pa_source_output_kill(source_output
);
1036 static int pa_cli_command_scache_list(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1039 pa_core_assert_ref(c
);
1044 pa_assert_se(s
= pa_scache_list_to_string(c
));
1045 pa_strbuf_puts(buf
, s
);
1051 static int pa_cli_command_scache_play(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1052 const char *n
, *sink_name
;
1056 pa_core_assert_ref(c
);
1061 if (!(n
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1062 pa_strbuf_puts(buf
, "You need to specify a sample name and a sink name.\n");
1066 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1067 pa_strbuf_puts(buf
, "No sink by that name.\n");
1071 if (pa_scache_play_item(c
, n
, sink
, PA_VOLUME_NORM
, NULL
, &idx
) < 0) {
1072 pa_strbuf_puts(buf
, "Failed to play sample.\n");
1076 pa_strbuf_printf(buf
, "Playing on sink input #%i\n", idx
);
1081 static int pa_cli_command_scache_remove(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1084 pa_core_assert_ref(c
);
1089 if (!(n
= pa_tokenizer_get(t
, 1))) {
1090 pa_strbuf_puts(buf
, "You need to specify a sample name.\n");
1094 if (pa_scache_remove_item(c
, n
) < 0) {
1095 pa_strbuf_puts(buf
, "Failed to remove sample.\n");
1102 static int pa_cli_command_scache_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1103 const char *fname
, *n
;
1106 pa_core_assert_ref(c
);
1111 if (!(fname
= pa_tokenizer_get(t
, 2)) || !(n
= pa_tokenizer_get(t
, 1))) {
1112 pa_strbuf_puts(buf
, "You need to specify a file name and a sample name.\n");
1116 if (strstr(pa_tokenizer_get(t
, 0), "lazy"))
1117 r
= pa_scache_add_file_lazy(c
, n
, fname
, NULL
);
1119 r
= pa_scache_add_file(c
, n
, fname
, NULL
);
1122 pa_strbuf_puts(buf
, "Failed to load sound file.\n");
1127 static int pa_cli_command_scache_load_dir(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1130 pa_core_assert_ref(c
);
1135 if (!(pname
= pa_tokenizer_get(t
, 1))) {
1136 pa_strbuf_puts(buf
, "You need to specify a path name.\n");
1140 if (pa_scache_add_directory_lazy(c
, pname
) < 0) {
1141 pa_strbuf_puts(buf
, "Failed to load directory.\n");
1148 static int pa_cli_command_play_file(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1149 const char *fname
, *sink_name
;
1152 pa_core_assert_ref(c
);
1157 if (!(fname
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1158 pa_strbuf_puts(buf
, "You need to specify a file name and a sink name.\n");
1162 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1163 pa_strbuf_puts(buf
, "No sink by that name.\n");
1168 return pa_play_file(sink
, fname
, NULL
);
1171 static int pa_cli_command_list_shared_props(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1172 pa_core_assert_ref(c
);
1177 pa_shared_dump(c
, buf
);
1181 static int pa_cli_command_vacuum(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1182 pa_core_assert_ref(c
);
1187 pa_mempool_vacuum(c
->mempool
);
1192 static int pa_cli_command_move_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1198 pa_core_assert_ref(c
);
1203 if (!(n
= pa_tokenizer_get(t
, 1))) {
1204 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
1208 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1209 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1213 if (!(k
= pa_tokenizer_get(t
, 2))) {
1214 pa_strbuf_puts(buf
, "You need to specify a sink.\n");
1218 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
1219 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
1223 if (!(sink
= pa_namereg_get(c
, k
, PA_NAMEREG_SINK
))) {
1224 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1228 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
1229 pa_strbuf_puts(buf
, "Moved failed.\n");
1235 static int pa_cli_command_move_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1237 pa_source_output
*so
;
1241 pa_core_assert_ref(c
);
1246 if (!(n
= pa_tokenizer_get(t
, 1))) {
1247 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1251 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1252 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1256 if (!(k
= pa_tokenizer_get(t
, 2))) {
1257 pa_strbuf_puts(buf
, "You need to specify a source.\n");
1261 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
1262 pa_strbuf_puts(buf
, "No source output found with this index.\n");
1266 if (!(source
= pa_namereg_get(c
, k
, PA_NAMEREG_SOURCE
))) {
1267 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1271 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
1272 pa_strbuf_puts(buf
, "Moved failed.\n");
1278 static int pa_cli_command_suspend_sink(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1283 pa_core_assert_ref(c
);
1288 if (!(n
= pa_tokenizer_get(t
, 1))) {
1289 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1293 if (!(m
= pa_tokenizer_get(t
, 2))) {
1294 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1298 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1299 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1303 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1304 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1308 if ((r
= pa_sink_suspend(sink
, suspend
, PA_SUSPEND_USER
)) < 0)
1309 pa_strbuf_printf(buf
, "Failed to resume/suspend sink: %s\n", pa_strerror(r
));
1314 static int pa_cli_command_suspend_source(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1319 pa_core_assert_ref(c
);
1324 if (!(n
= pa_tokenizer_get(t
, 1))) {
1325 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1329 if (!(m
= pa_tokenizer_get(t
, 2))) {
1330 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1334 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1335 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1339 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1340 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1344 if ((r
= pa_source_suspend(source
, suspend
, PA_SUSPEND_USER
)) < 0)
1345 pa_strbuf_printf(buf
, "Failed to resume/suspend source: %s\n", pa_strerror(r
));
1350 static int pa_cli_command_suspend(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1354 pa_core_assert_ref(c
);
1359 if (!(m
= pa_tokenizer_get(t
, 1))) {
1360 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1364 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1365 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1369 if ((r
= pa_sink_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1370 pa_strbuf_printf(buf
, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r
));
1372 if ((r
= pa_source_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1373 pa_strbuf_printf(buf
, "Failed to resume/suspend all sources: %s\n", pa_strerror(r
));
1378 static int pa_cli_command_log_level(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1382 pa_core_assert_ref(c
);
1387 if (!(m
= pa_tokenizer_get(t
, 1))) {
1388 pa_strbuf_puts(buf
, "You need to specify a log level (0..4).\n");
1392 if (pa_atou(m
, &level
) < 0 || level
>= PA_LOG_LEVEL_MAX
) {
1393 pa_strbuf_puts(buf
, "Failed to parse log level.\n");
1397 pa_log_set_level(level
);
1402 static int pa_cli_command_log_meta(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1406 pa_core_assert_ref(c
);
1411 if (!(m
= pa_tokenizer_get(t
, 1))) {
1412 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1416 if ((b
= pa_parse_boolean(m
)) < 0) {
1417 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1421 pa_log_set_flags(PA_LOG_PRINT_META
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1426 static int pa_cli_command_log_time(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1430 pa_core_assert_ref(c
);
1435 if (!(m
= pa_tokenizer_get(t
, 1))) {
1436 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1440 if ((b
= pa_parse_boolean(m
)) < 0) {
1441 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1445 pa_log_set_flags(PA_LOG_PRINT_TIME
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1450 static int pa_cli_command_log_backtrace(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1454 pa_core_assert_ref(c
);
1459 if (!(m
= pa_tokenizer_get(t
, 1))) {
1460 pa_strbuf_puts(buf
, "You need to specify a backtrace level.\n");
1464 if (pa_atou(m
, &nframes
) < 0 || nframes
>= 1000) {
1465 pa_strbuf_puts(buf
, "Failed to parse backtrace level.\n");
1469 pa_log_set_show_backtrace(nframes
);
1474 static int pa_cli_command_card_profile(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1478 pa_core_assert_ref(c
);
1483 if (!(n
= pa_tokenizer_get(t
, 1))) {
1484 pa_strbuf_puts(buf
, "You need to specify a card either by its name or its index.\n");
1488 if (!(p
= pa_tokenizer_get(t
, 2))) {
1489 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1493 if (!(card
= pa_namereg_get(c
, n
, PA_NAMEREG_CARD
))) {
1494 pa_strbuf_puts(buf
, "No card found by this name or index.\n");
1498 if (pa_card_set_profile(card
, p
, TRUE
) < 0) {
1499 pa_strbuf_printf(buf
, "Failed to set card profile to '%s'.\n", p
);
1506 static int pa_cli_command_sink_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1510 pa_core_assert_ref(c
);
1515 if (!(n
= pa_tokenizer_get(t
, 1))) {
1516 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1520 if (!(p
= pa_tokenizer_get(t
, 2))) {
1521 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1525 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1526 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1530 if (pa_sink_set_port(sink
, p
, TRUE
) < 0) {
1531 pa_strbuf_printf(buf
, "Failed to set sink port to '%s'.\n", p
);
1538 static int pa_cli_command_source_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1542 pa_core_assert_ref(c
);
1547 if (!(n
= pa_tokenizer_get(t
, 1))) {
1548 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1552 if (!(p
= pa_tokenizer_get(t
, 2))) {
1553 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1557 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1558 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1562 if (pa_source_set_port(source
, p
, TRUE
) < 0) {
1563 pa_strbuf_printf(buf
, "Failed to set source port to '%s'.\n", p
);
1570 static int pa_cli_command_dump(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1580 pa_core_assert_ref(c
);
1588 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime_r(&now
, txt
));
1590 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime(&now
));
1593 PA_IDXSET_FOREACH(m
, c
->modules
, idx
) {
1595 pa_strbuf_printf(buf
, "load-module %s", m
->name
);
1598 pa_strbuf_printf(buf
, " %s", m
->argument
);
1600 pa_strbuf_puts(buf
, "\n");
1604 PA_IDXSET_FOREACH(sink
, c
->sinks
, idx
) {
1607 pa_strbuf_puts(buf
, "\n");
1611 pa_strbuf_printf(buf
, "set-sink-volume %s 0x%03x\n", sink
->name
, pa_cvolume_max(pa_sink_get_volume(sink
, FALSE
)));
1612 pa_strbuf_printf(buf
, "set-sink-mute %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_mute(sink
, FALSE
)));
1613 pa_strbuf_printf(buf
, "suspend-sink %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_state(sink
) == PA_SINK_SUSPENDED
));
1617 PA_IDXSET_FOREACH(source
, c
->sources
, idx
) {
1620 pa_strbuf_puts(buf
, "\n");
1624 pa_strbuf_printf(buf
, "set-source-volume %s 0x%03x\n", source
->name
, pa_cvolume_max(pa_source_get_volume(source
, FALSE
)));
1625 pa_strbuf_printf(buf
, "set-source-mute %s %s\n", source
->name
, pa_yes_no(pa_source_get_mute(source
, FALSE
)));
1626 pa_strbuf_printf(buf
, "suspend-source %s %s\n", source
->name
, pa_yes_no(pa_source_get_state(source
) == PA_SOURCE_SUSPENDED
));
1630 PA_IDXSET_FOREACH(card
, c
->cards
, idx
) {
1633 pa_strbuf_puts(buf
, "\n");
1637 if (card
->active_profile
)
1638 pa_strbuf_printf(buf
, "set-card-profile %s %s\n", card
->name
, card
->active_profile
->name
);
1642 if ((sink
= pa_namereg_get_default_sink(c
))) {
1644 pa_strbuf_puts(buf
, "\n");
1648 pa_strbuf_printf(buf
, "set-default-sink %s\n", sink
->name
);
1651 if ((source
= pa_namereg_get_default_source(c
))) {
1653 pa_strbuf_puts(buf
, "\n");
1655 pa_strbuf_printf(buf
, "set-default-source %s\n", source
->name
);
1658 pa_strbuf_puts(buf
, "\n### EOF\n");
1663 int pa_cli_command_execute_line_stateful(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
, int *ifstate
) {
1670 cs
= s
+strspn(s
, whitespace
);
1672 if (*cs
== '#' || !*cs
)
1674 else if (*cs
== '.') {
1675 if (!strcmp(cs
, META_ELSE
)) {
1676 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1677 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1679 } else if (*ifstate
== IFSTATE_TRUE
)
1680 *ifstate
= IFSTATE_FALSE
;
1682 *ifstate
= IFSTATE_TRUE
;
1684 } else if (!strcmp(cs
, META_ENDIF
)) {
1685 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1686 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1689 *ifstate
= IFSTATE_NONE
;
1692 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
1694 if (!strcmp(cs
, META_FAIL
))
1696 else if (!strcmp(cs
, META_NOFAIL
))
1700 l
= strcspn(cs
, whitespace
);
1702 if (l
== sizeof(META_INCLUDE
)-1 && !strncmp(cs
, META_INCLUDE
, l
)) {
1704 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
1706 if (stat(filename
, &st
) < 0) {
1707 pa_log_warn("stat('%s'): %s", filename
, pa_cstrerror(errno
));
1711 if (S_ISDIR(st
.st_mode
)) {
1714 if (!(d
= opendir(filename
))) {
1715 pa_log_warn("Failed to read '%s': %s", filename
, pa_cstrerror(errno
));
1720 char **sorted_files
;
1722 pa_bool_t failed
= FALSE
;
1723 pa_dynarray
*files
= pa_dynarray_new();
1725 while ((de
= readdir(d
))) {
1727 size_t flen
= strlen(de
->d_name
);
1732 extn
= &de
->d_name
[flen
-3];
1733 if (strncmp(extn
, ".pa", 3) == 0)
1734 pa_dynarray_append(files
, pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", filename
, de
->d_name
));
1739 count
= pa_dynarray_size(files
);
1740 sorted_files
= pa_xnew(char*, count
);
1741 for (i
= 0; i
< count
; ++i
)
1742 sorted_files
[i
] = pa_dynarray_get(files
, i
);
1743 pa_dynarray_free(files
, NULL
, NULL
);
1745 for (i
= 0; i
< count
; ++i
) {
1746 for (unsigned j
= 0; j
< count
; ++j
) {
1747 if (strcmp(sorted_files
[i
], sorted_files
[j
]) < 0) {
1748 char *tmp
= sorted_files
[i
];
1749 sorted_files
[i
] = sorted_files
[j
];
1750 sorted_files
[j
] = tmp
;
1755 for (i
= 0; i
< count
; ++i
) {
1757 if (pa_cli_command_execute_file(c
, sorted_files
[i
], buf
, fail
) < 0 && *fail
)
1761 pa_xfree(sorted_files
[i
]);
1763 pa_xfree(sorted_files
);
1767 } else if (pa_cli_command_execute_file(c
, filename
, buf
, fail
) < 0 && *fail
) {
1771 } else if (l
== sizeof(META_IFEXISTS
)-1 && !strncmp(cs
, META_IFEXISTS
, l
)) {
1773 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1775 } else if (*ifstate
!= IFSTATE_NONE
) {
1776 pa_strbuf_printf(buf
, "Nested %s commands not supported\n", cs
);
1779 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
1781 /* Search DL_SEARCH_PATH unless the filename is absolute */
1782 if (filename
[0] == PA_PATH_SEP_CHAR
) {
1784 *ifstate
= access(filename
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
1785 pa_log_debug("Checking for existance of '%s': %s", filename
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
1788 const char *paths
, *state
= NULL
;
1791 if (!(paths
= lt_dlgetsearchpath()))
1794 while ((p
= pa_split(paths
, ":", &state
))) {
1797 pathname
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", p
, filename
);
1800 *ifstate
= access(pathname
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
1801 pa_log_debug("Checking for existance of '%s': %s", pathname
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
1805 if (*ifstate
== IFSTATE_TRUE
)
1812 pa_strbuf_printf(buf
, "Invalid meta command: %s\n", cs
);
1813 if (*fail
) return -1;
1817 const struct command
*command
;
1821 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
1824 l
= strcspn(cs
, whitespace
);
1826 for (command
= commands
; command
->name
; command
++)
1827 if (strlen(command
->name
) == l
&& !strncmp(cs
, command
->name
, l
)) {
1829 pa_tokenizer
*t
= pa_tokenizer_new(cs
, command
->args
);
1831 ret
= command
->proc(c
, t
, buf
, fail
);
1832 pa_tokenizer_free(t
);
1835 if (ret
< 0 && *fail
)
1842 pa_strbuf_printf(buf
, "Unknown command: %s\n", cs
);
1851 int pa_cli_command_execute_line(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1852 return pa_cli_command_execute_line_stateful(c
, s
, buf
, fail
, NULL
);
1855 int pa_cli_command_execute_file_stream(pa_core
*c
, FILE *f
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1857 int ifstate
= IFSTATE_NONE
;
1859 pa_bool_t _fail
= TRUE
;
1868 while (fgets(line
, sizeof(line
), f
)) {
1871 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
)
1882 int pa_cli_command_execute_file(pa_core
*c
, const char *fn
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1885 pa_bool_t _fail
= TRUE
;
1894 if (!(f
= pa_fopen_cloexec(fn
, "r"))) {
1895 pa_strbuf_printf(buf
, "open('%s') failed: %s\n", fn
, pa_cstrerror(errno
));
1901 pa_log_debug("Parsing script '%s'", fn
);
1902 ret
= pa_cli_command_execute_file_stream(c
, f
, buf
, fail
);
1911 int pa_cli_command_execute(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1913 int ifstate
= IFSTATE_NONE
;
1914 pa_bool_t _fail
= TRUE
;
1925 size_t l
= strcspn(p
, linebreak
);
1926 char *line
= pa_xstrndup(p
, l
);
1928 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
) {
1935 p
+= strspn(p
, linebreak
);