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/sample-util.h>
52 #include <pulsecore/sound-file.h>
53 #include <pulsecore/play-memchunk.h>
54 #include <pulsecore/sound-file-stream.h>
55 #include <pulsecore/shared.h>
56 #include <pulsecore/core-util.h>
57 #include <pulsecore/core-error.h>
58 #include <pulsecore/modinfo.h>
59 #include <pulsecore/dynarray.h>
61 #include "cli-command.h"
65 int (*proc
) (pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
70 #define META_INCLUDE ".include"
71 #define META_FAIL ".fail"
72 #define META_NOFAIL ".nofail"
73 #define META_IFEXISTS ".ifexists"
74 #define META_ELSE ".else"
75 #define META_ENDIF ".endif"
83 /* Prototypes for all available commands */
84 static int pa_cli_command_exit(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
85 static int pa_cli_command_help(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
86 static int pa_cli_command_modules(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
87 static int pa_cli_command_clients(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
88 static int pa_cli_command_cards(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
89 static int pa_cli_command_sinks(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
90 static int pa_cli_command_sources(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
91 static int pa_cli_command_sink_inputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
92 static int pa_cli_command_source_outputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
93 static int pa_cli_command_stat(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
94 static int pa_cli_command_info(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
95 static int pa_cli_command_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
96 static int pa_cli_command_unload(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
97 static int pa_cli_command_describe(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
98 static int pa_cli_command_sink_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
99 static int pa_cli_command_sink_input_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
100 static int pa_cli_command_source_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
101 static int pa_cli_command_sink_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
102 static int pa_cli_command_source_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
103 static int pa_cli_command_sink_input_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
104 static int pa_cli_command_sink_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
105 static int pa_cli_command_source_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
106 static int pa_cli_command_kill_client(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
107 static int pa_cli_command_kill_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
108 static int pa_cli_command_kill_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
109 static int pa_cli_command_scache_play(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
110 static int pa_cli_command_scache_remove(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
111 static int pa_cli_command_scache_list(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
112 static int pa_cli_command_scache_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
113 static int pa_cli_command_scache_load_dir(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
114 static int pa_cli_command_play_file(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
115 static int pa_cli_command_dump(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
116 static int pa_cli_command_list_shared_props(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
117 static int pa_cli_command_move_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
118 static int pa_cli_command_move_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
119 static int pa_cli_command_vacuum(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
120 static int pa_cli_command_suspend_sink(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
121 static int pa_cli_command_suspend_source(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
122 static int pa_cli_command_suspend(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
123 static int pa_cli_command_log_level(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
124 static int pa_cli_command_log_meta(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
125 static int pa_cli_command_log_time(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
126 static int pa_cli_command_log_backtrace(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
127 static int pa_cli_command_update_sink_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
128 static int pa_cli_command_update_source_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
129 static int pa_cli_command_update_sink_input_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
130 static int pa_cli_command_update_source_output_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
131 static int pa_cli_command_card_profile(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
132 static int pa_cli_command_sink_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
133 static int pa_cli_command_source_port(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 { NULL
, NULL
, NULL
, 0 }
194 static const char whitespace
[] = " \t\n\r";
195 static const char linebreak
[] = "\n\r";
197 static uint32_t parse_index(const char *n
) {
200 if (pa_atou(n
, &idx
) < 0)
201 return (uint32_t) PA_IDXSET_INVALID
;
206 static int pa_cli_command_exit(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
207 pa_core_assert_ref(c
);
212 if (pa_core_exit(c
, FALSE
, 0) < 0)
213 pa_strbuf_puts(buf
, "Not allowed to terminate daemon.\n");
218 static int pa_cli_command_help(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
219 const struct command
*command
;
221 pa_core_assert_ref(c
);
226 pa_strbuf_puts(buf
, "Available commands:\n");
228 for (command
= commands
; command
->name
; command
++)
230 pa_strbuf_printf(buf
, " %-25s %s\n", command
->name
, command
->help
);
234 static int pa_cli_command_modules(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
237 pa_core_assert_ref(c
);
242 pa_assert_se(s
= pa_module_list_to_string(c
));
243 pa_strbuf_puts(buf
, s
);
248 static int pa_cli_command_clients(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
251 pa_core_assert_ref(c
);
256 pa_assert_se(s
= pa_client_list_to_string(c
));
257 pa_strbuf_puts(buf
, s
);
262 static int pa_cli_command_cards(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
265 pa_core_assert_ref(c
);
270 pa_assert_se(s
= pa_card_list_to_string(c
));
271 pa_strbuf_puts(buf
, s
);
276 static int pa_cli_command_sinks(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
279 pa_core_assert_ref(c
);
284 pa_assert_se(s
= pa_sink_list_to_string(c
));
285 pa_strbuf_puts(buf
, s
);
290 static int pa_cli_command_sources(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
293 pa_core_assert_ref(c
);
298 pa_assert_se(s
= pa_source_list_to_string(c
));
299 pa_strbuf_puts(buf
, s
);
304 static int pa_cli_command_sink_inputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
307 pa_core_assert_ref(c
);
312 pa_assert_se(s
= pa_sink_input_list_to_string(c
));
313 pa_strbuf_puts(buf
, s
);
318 static int pa_cli_command_source_outputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
321 pa_core_assert_ref(c
);
326 pa_assert_se(s
= pa_source_output_list_to_string(c
));
327 pa_strbuf_puts(buf
, s
);
332 static int pa_cli_command_stat(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
333 char ss
[PA_SAMPLE_SPEC_SNPRINT_MAX
];
334 char cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
335 char bytes
[PA_BYTES_SNPRINT_MAX
];
336 const pa_mempool_stat
*mstat
;
339 pa_source
*def_source
;
341 static const char* const type_table
[PA_MEMBLOCK_TYPE_MAX
] = {
342 [PA_MEMBLOCK_POOL
] = "POOL",
343 [PA_MEMBLOCK_POOL_EXTERNAL
] = "POOL_EXTERNAL",
344 [PA_MEMBLOCK_APPENDED
] = "APPENDED",
345 [PA_MEMBLOCK_USER
] = "USER",
346 [PA_MEMBLOCK_FIXED
] = "FIXED",
347 [PA_MEMBLOCK_IMPORTED
] = "IMPORTED",
350 pa_core_assert_ref(c
);
355 mstat
= pa_mempool_get_stat(c
->mempool
);
357 pa_strbuf_printf(buf
, "Memory blocks currently allocated: %u, size: %s.\n",
358 (unsigned) pa_atomic_load(&mstat
->n_allocated
),
359 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->allocated_size
)));
361 pa_strbuf_printf(buf
, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
362 (unsigned) pa_atomic_load(&mstat
->n_accumulated
),
363 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->accumulated_size
)));
365 pa_strbuf_printf(buf
, "Memory blocks imported from other processes: %u, size: %s.\n",
366 (unsigned) pa_atomic_load(&mstat
->n_imported
),
367 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->imported_size
)));
369 pa_strbuf_printf(buf
, "Memory blocks exported to other processes: %u, size: %s.\n",
370 (unsigned) pa_atomic_load(&mstat
->n_exported
),
371 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->exported_size
)));
373 pa_strbuf_printf(buf
, "Total sample cache size: %s.\n",
374 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_scache_total_size(c
)));
376 pa_strbuf_printf(buf
, "Default sample spec: %s\n",
377 pa_sample_spec_snprint(ss
, sizeof(ss
), &c
->default_sample_spec
));
379 pa_strbuf_printf(buf
, "Default channel map: %s\n",
380 pa_channel_map_snprint(cm
, sizeof(cm
), &c
->default_channel_map
));
382 def_sink
= pa_namereg_get_default_sink(c
);
383 def_source
= pa_namereg_get_default_source(c
);
384 pa_strbuf_printf(buf
, "Default sink name: %s\n"
385 "Default source name: %s\n",
386 def_sink
? def_sink
->name
: "none",
387 def_source
? def_source
->name
: "none");
389 for (k
= 0; k
< PA_MEMBLOCK_TYPE_MAX
; k
++)
390 pa_strbuf_printf(buf
,
391 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
393 (unsigned) pa_atomic_load(&mstat
->n_allocated_by_type
[k
]),
394 (unsigned) pa_atomic_load(&mstat
->n_accumulated_by_type
[k
]));
399 static int pa_cli_command_info(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
400 pa_core_assert_ref(c
);
405 pa_cli_command_stat(c
, t
, buf
, fail
);
406 pa_cli_command_modules(c
, t
, buf
, fail
);
407 pa_cli_command_sinks(c
, t
, buf
, fail
);
408 pa_cli_command_sources(c
, t
, buf
, fail
);
409 pa_cli_command_clients(c
, t
, buf
, fail
);
410 pa_cli_command_cards(c
, t
, buf
, fail
);
411 pa_cli_command_sink_inputs(c
, t
, buf
, fail
);
412 pa_cli_command_source_outputs(c
, t
, buf
, fail
);
413 pa_cli_command_scache_list(c
, t
, buf
, fail
);
417 static int pa_cli_command_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
420 pa_core_assert_ref(c
);
425 if (!(name
= pa_tokenizer_get(t
, 1))) {
426 pa_strbuf_puts(buf
, "You need to specify the module name and optionally arguments.\n");
430 if (!pa_module_load(c
, name
, pa_tokenizer_get(t
, 2))) {
431 pa_strbuf_puts(buf
, "Module load failed.\n");
438 static int pa_cli_command_unload(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
444 pa_core_assert_ref(c
);
449 if (!(i
= pa_tokenizer_get(t
, 1))) {
450 pa_strbuf_puts(buf
, "You need to specify the module index.\n");
454 idx
= (uint32_t) strtoul(i
, &e
, 10);
455 if (*e
|| !(m
= pa_idxset_get_by_index(c
->modules
, idx
))) {
456 pa_strbuf_puts(buf
, "Invalid module index.\n");
460 pa_module_unload_request(m
, FALSE
);
464 static int pa_cli_command_describe(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
468 pa_core_assert_ref(c
);
473 if (!(name
= pa_tokenizer_get(t
, 1))) {
474 pa_strbuf_puts(buf
, "You need to specify the module name.\n");
478 if ((i
= pa_modinfo_get_by_name(name
))) {
480 pa_strbuf_printf(buf
, "Name: %s\n", name
);
482 if (!i
->description
&& !i
->version
&& !i
->author
&& !i
->usage
)
483 pa_strbuf_printf(buf
, "No module information available\n");
486 pa_strbuf_printf(buf
, "Version: %s\n", i
->version
);
488 pa_strbuf_printf(buf
, "Description: %s\n", i
->description
);
490 pa_strbuf_printf(buf
, "Author: %s\n", i
->author
);
492 pa_strbuf_printf(buf
, "Usage: %s\n", i
->usage
);
493 pa_strbuf_printf(buf
, "Load Once: %s\n", pa_yes_no(i
->load_once
));
495 pa_strbuf_printf(buf
, "Warning, deprecated: %s\n", i
->deprecated
);
500 pa_strbuf_puts(buf
, "Failed to open module.\n");
505 static int pa_cli_command_sink_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
511 pa_core_assert_ref(c
);
516 if (!(n
= pa_tokenizer_get(t
, 1))) {
517 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
521 if (!(v
= pa_tokenizer_get(t
, 2))) {
522 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
526 if (pa_atou(v
, &volume
) < 0) {
527 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
531 if (!PA_VOLUME_IS_VALID(volume
)) {
532 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
536 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
537 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
541 pa_cvolume_set(&cvolume
, 1, volume
);
542 pa_sink_set_volume(sink
, &cvolume
, TRUE
, TRUE
);
546 static int pa_cli_command_sink_input_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
553 pa_core_assert_ref(c
);
558 if (!(n
= pa_tokenizer_get(t
, 1))) {
559 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
563 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
564 pa_strbuf_puts(buf
, "Failed to parse index.\n");
568 if (!(v
= pa_tokenizer_get(t
, 2))) {
569 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
573 if (pa_atou(v
, &volume
) < 0) {
574 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
578 if (!PA_VOLUME_IS_VALID(volume
)) {
579 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
583 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
584 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
588 if (!si
->volume_writable
) {
589 pa_strbuf_puts(buf
, "This sink input's volume can't be changed.\n");
593 pa_cvolume_set(&cvolume
, 1, volume
);
594 pa_sink_input_set_volume(si
, &cvolume
, TRUE
, TRUE
);
598 static int pa_cli_command_source_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
604 pa_core_assert_ref(c
);
609 if (!(n
= pa_tokenizer_get(t
, 1))) {
610 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
614 if (!(v
= pa_tokenizer_get(t
, 2))) {
615 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
619 if (pa_atou(v
, &volume
) < 0) {
620 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
624 if (!PA_VOLUME_IS_VALID(volume
)) {
625 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
629 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
630 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
634 pa_cvolume_set(&cvolume
, 1, volume
);
635 pa_source_set_volume(source
, &cvolume
, TRUE
);
639 static int pa_cli_command_sink_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
644 pa_core_assert_ref(c
);
649 if (!(n
= pa_tokenizer_get(t
, 1))) {
650 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
654 if (!(m
= pa_tokenizer_get(t
, 2))) {
655 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
659 if ((mute
= pa_parse_boolean(m
)) < 0) {
660 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
664 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
665 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
669 pa_sink_set_mute(sink
, mute
, TRUE
);
673 static int pa_cli_command_source_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
678 pa_core_assert_ref(c
);
683 if (!(n
= pa_tokenizer_get(t
, 1))) {
684 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
688 if (!(m
= pa_tokenizer_get(t
, 2))) {
689 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
693 if ((mute
= pa_parse_boolean(m
)) < 0) {
694 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
698 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
699 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
703 pa_source_set_mute(source
, mute
, TRUE
);
707 static int pa_cli_command_update_sink_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
712 pa_core_assert_ref(c
);
717 if (!(n
= pa_tokenizer_get(t
, 1))) {
718 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
722 if (!(s
= pa_tokenizer_get(t
, 2))) {
723 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
727 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
728 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
732 if (!(p
= pa_proplist_from_string(s
))) {
733 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
737 pa_sink_update_proplist(sink
, PA_UPDATE_REPLACE
, p
);
744 static int pa_cli_command_update_source_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
749 pa_core_assert_ref(c
);
754 if (!(n
= pa_tokenizer_get(t
, 1))) {
755 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
759 if (!(s
= pa_tokenizer_get(t
, 2))) {
760 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
764 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
765 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
769 if (!(p
= pa_proplist_from_string(s
))) {
770 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
774 pa_source_update_proplist(source
, PA_UPDATE_REPLACE
, p
);
781 static int pa_cli_command_update_sink_input_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
787 pa_core_assert_ref(c
);
792 if (!(n
= pa_tokenizer_get(t
, 1))) {
793 pa_strbuf_puts(buf
, "You need to specify a sink input either by index.\n");
797 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
798 pa_strbuf_puts(buf
, "Failed to parse index.\n");
802 if (!(s
= pa_tokenizer_get(t
, 2))) {
803 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
807 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
808 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
812 if (!(p
= pa_proplist_from_string(s
))) {
813 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
817 pa_sink_input_update_proplist(si
, PA_UPDATE_REPLACE
, p
);
824 static int pa_cli_command_update_source_output_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
826 pa_source_output
*so
;
830 pa_core_assert_ref(c
);
835 if (!(n
= pa_tokenizer_get(t
, 1))) {
836 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
840 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
841 pa_strbuf_puts(buf
, "Failed to parse index.\n");
845 if (!(s
= pa_tokenizer_get(t
, 2))) {
846 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
850 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
851 pa_strbuf_puts(buf
, "No source output found with this index.\n");
855 if (!(p
= pa_proplist_from_string(s
))) {
856 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
860 pa_source_output_update_proplist(so
, PA_UPDATE_REPLACE
, p
);
867 static int pa_cli_command_sink_input_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
873 pa_core_assert_ref(c
);
878 if (!(n
= pa_tokenizer_get(t
, 1))) {
879 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
883 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
884 pa_strbuf_puts(buf
, "Failed to parse index.\n");
888 if (!(v
= pa_tokenizer_get(t
, 2))) {
889 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
893 if ((mute
= pa_parse_boolean(v
)) < 0) {
894 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
898 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
899 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
903 pa_sink_input_set_mute(si
, mute
, TRUE
);
907 static int pa_cli_command_sink_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
911 pa_core_assert_ref(c
);
916 if (!(n
= pa_tokenizer_get(t
, 1))) {
917 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
921 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
)))
922 pa_namereg_set_default_sink(c
, s
);
924 pa_strbuf_printf(buf
, "Sink %s does not exist.\n", n
);
929 static int pa_cli_command_source_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
933 pa_core_assert_ref(c
);
938 if (!(n
= pa_tokenizer_get(t
, 1))) {
939 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
943 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
)))
944 pa_namereg_set_default_source(c
, s
);
946 pa_strbuf_printf(buf
, "Source %s does not exist.\n", n
);
950 static int pa_cli_command_kill_client(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
955 pa_core_assert_ref(c
);
960 if (!(n
= pa_tokenizer_get(t
, 1))) {
961 pa_strbuf_puts(buf
, "You need to specify a client by its index.\n");
965 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
966 pa_strbuf_puts(buf
, "Failed to parse index.\n");
970 if (!(client
= pa_idxset_get_by_index(c
->clients
, idx
))) {
971 pa_strbuf_puts(buf
, "No client found by this index.\n");
975 pa_client_kill(client
);
979 static int pa_cli_command_kill_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
981 pa_sink_input
*sink_input
;
984 pa_core_assert_ref(c
);
989 if (!(n
= pa_tokenizer_get(t
, 1))) {
990 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
994 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
995 pa_strbuf_puts(buf
, "Failed to parse index.\n");
999 if (!(sink_input
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
1000 pa_strbuf_puts(buf
, "No sink input found by this index.\n");
1004 pa_sink_input_kill(sink_input
);
1008 static int pa_cli_command_kill_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1010 pa_source_output
*source_output
;
1013 pa_core_assert_ref(c
);
1018 if (!(n
= pa_tokenizer_get(t
, 1))) {
1019 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1023 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1024 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1028 if (!(source_output
= pa_idxset_get_by_index(c
->source_outputs
, idx
))) {
1029 pa_strbuf_puts(buf
, "No source output found by this index.\n");
1033 pa_source_output_kill(source_output
);
1037 static int pa_cli_command_scache_list(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1040 pa_core_assert_ref(c
);
1045 pa_assert_se(s
= pa_scache_list_to_string(c
));
1046 pa_strbuf_puts(buf
, s
);
1052 static int pa_cli_command_scache_play(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1053 const char *n
, *sink_name
;
1057 pa_core_assert_ref(c
);
1062 if (!(n
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1063 pa_strbuf_puts(buf
, "You need to specify a sample name and a sink name.\n");
1067 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1068 pa_strbuf_puts(buf
, "No sink by that name.\n");
1072 if (pa_scache_play_item(c
, n
, sink
, PA_VOLUME_NORM
, NULL
, &idx
) < 0) {
1073 pa_strbuf_puts(buf
, "Failed to play sample.\n");
1077 pa_strbuf_printf(buf
, "Playing on sink input #%i\n", idx
);
1082 static int pa_cli_command_scache_remove(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1085 pa_core_assert_ref(c
);
1090 if (!(n
= pa_tokenizer_get(t
, 1))) {
1091 pa_strbuf_puts(buf
, "You need to specify a sample name.\n");
1095 if (pa_scache_remove_item(c
, n
) < 0) {
1096 pa_strbuf_puts(buf
, "Failed to remove sample.\n");
1103 static int pa_cli_command_scache_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1104 const char *fname
, *n
;
1107 pa_core_assert_ref(c
);
1112 if (!(fname
= pa_tokenizer_get(t
, 2)) || !(n
= pa_tokenizer_get(t
, 1))) {
1113 pa_strbuf_puts(buf
, "You need to specify a file name and a sample name.\n");
1117 if (strstr(pa_tokenizer_get(t
, 0), "lazy"))
1118 r
= pa_scache_add_file_lazy(c
, n
, fname
, NULL
);
1120 r
= pa_scache_add_file(c
, n
, fname
, NULL
);
1123 pa_strbuf_puts(buf
, "Failed to load sound file.\n");
1128 static int pa_cli_command_scache_load_dir(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1131 pa_core_assert_ref(c
);
1136 if (!(pname
= pa_tokenizer_get(t
, 1))) {
1137 pa_strbuf_puts(buf
, "You need to specify a path name.\n");
1141 if (pa_scache_add_directory_lazy(c
, pname
) < 0) {
1142 pa_strbuf_puts(buf
, "Failed to load directory.\n");
1149 static int pa_cli_command_play_file(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1150 const char *fname
, *sink_name
;
1153 pa_core_assert_ref(c
);
1158 if (!(fname
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1159 pa_strbuf_puts(buf
, "You need to specify a file name and a sink name.\n");
1163 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1164 pa_strbuf_puts(buf
, "No sink by that name.\n");
1169 return pa_play_file(sink
, fname
, NULL
);
1172 static int pa_cli_command_list_shared_props(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1173 pa_core_assert_ref(c
);
1178 pa_shared_dump(c
, buf
);
1182 static int pa_cli_command_vacuum(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1183 pa_core_assert_ref(c
);
1188 pa_mempool_vacuum(c
->mempool
);
1193 static int pa_cli_command_move_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1199 pa_core_assert_ref(c
);
1204 if (!(n
= pa_tokenizer_get(t
, 1))) {
1205 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
1209 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1210 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1214 if (!(k
= pa_tokenizer_get(t
, 2))) {
1215 pa_strbuf_puts(buf
, "You need to specify a sink.\n");
1219 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
1220 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
1224 if (!(sink
= pa_namereg_get(c
, k
, PA_NAMEREG_SINK
))) {
1225 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1229 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
1230 pa_strbuf_puts(buf
, "Moved failed.\n");
1236 static int pa_cli_command_move_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1238 pa_source_output
*so
;
1242 pa_core_assert_ref(c
);
1247 if (!(n
= pa_tokenizer_get(t
, 1))) {
1248 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1252 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1253 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1257 if (!(k
= pa_tokenizer_get(t
, 2))) {
1258 pa_strbuf_puts(buf
, "You need to specify a source.\n");
1262 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
1263 pa_strbuf_puts(buf
, "No source output found with this index.\n");
1267 if (!(source
= pa_namereg_get(c
, k
, PA_NAMEREG_SOURCE
))) {
1268 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1272 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
1273 pa_strbuf_puts(buf
, "Moved failed.\n");
1279 static int pa_cli_command_suspend_sink(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1284 pa_core_assert_ref(c
);
1289 if (!(n
= pa_tokenizer_get(t
, 1))) {
1290 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1294 if (!(m
= pa_tokenizer_get(t
, 2))) {
1295 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1299 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1300 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1304 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1305 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1309 if ((r
= pa_sink_suspend(sink
, suspend
, PA_SUSPEND_USER
)) < 0)
1310 pa_strbuf_printf(buf
, "Failed to resume/suspend sink: %s\n", pa_strerror(r
));
1315 static int pa_cli_command_suspend_source(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1320 pa_core_assert_ref(c
);
1325 if (!(n
= pa_tokenizer_get(t
, 1))) {
1326 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1330 if (!(m
= pa_tokenizer_get(t
, 2))) {
1331 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1335 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1336 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1340 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1341 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1345 if ((r
= pa_source_suspend(source
, suspend
, PA_SUSPEND_USER
)) < 0)
1346 pa_strbuf_printf(buf
, "Failed to resume/suspend source: %s\n", pa_strerror(r
));
1351 static int pa_cli_command_suspend(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1355 pa_core_assert_ref(c
);
1360 if (!(m
= pa_tokenizer_get(t
, 1))) {
1361 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1365 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1366 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1370 if ((r
= pa_sink_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1371 pa_strbuf_printf(buf
, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r
));
1373 if ((r
= pa_source_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1374 pa_strbuf_printf(buf
, "Failed to resume/suspend all sources: %s\n", pa_strerror(r
));
1379 static int pa_cli_command_log_level(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1383 pa_core_assert_ref(c
);
1388 if (!(m
= pa_tokenizer_get(t
, 1))) {
1389 pa_strbuf_puts(buf
, "You need to specify a log level (0..4).\n");
1393 if (pa_atou(m
, &level
) < 0 || level
>= PA_LOG_LEVEL_MAX
) {
1394 pa_strbuf_puts(buf
, "Failed to parse log level.\n");
1398 pa_log_set_level(level
);
1403 static int pa_cli_command_log_meta(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1407 pa_core_assert_ref(c
);
1412 if (!(m
= pa_tokenizer_get(t
, 1))) {
1413 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1417 if ((b
= pa_parse_boolean(m
)) < 0) {
1418 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1422 pa_log_set_flags(PA_LOG_PRINT_META
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1427 static int pa_cli_command_log_time(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1431 pa_core_assert_ref(c
);
1436 if (!(m
= pa_tokenizer_get(t
, 1))) {
1437 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1441 if ((b
= pa_parse_boolean(m
)) < 0) {
1442 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1446 pa_log_set_flags(PA_LOG_PRINT_TIME
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1451 static int pa_cli_command_log_backtrace(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1455 pa_core_assert_ref(c
);
1460 if (!(m
= pa_tokenizer_get(t
, 1))) {
1461 pa_strbuf_puts(buf
, "You need to specify a backtrace level.\n");
1465 if (pa_atou(m
, &nframes
) < 0 || nframes
>= 1000) {
1466 pa_strbuf_puts(buf
, "Failed to parse backtrace level.\n");
1470 pa_log_set_show_backtrace(nframes
);
1475 static int pa_cli_command_card_profile(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1479 pa_core_assert_ref(c
);
1484 if (!(n
= pa_tokenizer_get(t
, 1))) {
1485 pa_strbuf_puts(buf
, "You need to specify a card either by its name or its index.\n");
1489 if (!(p
= pa_tokenizer_get(t
, 2))) {
1490 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1494 if (!(card
= pa_namereg_get(c
, n
, PA_NAMEREG_CARD
))) {
1495 pa_strbuf_puts(buf
, "No card found by this name or index.\n");
1499 if (pa_card_set_profile(card
, p
, TRUE
) < 0) {
1500 pa_strbuf_printf(buf
, "Failed to set card profile to '%s'.\n", p
);
1507 static int pa_cli_command_sink_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1511 pa_core_assert_ref(c
);
1516 if (!(n
= pa_tokenizer_get(t
, 1))) {
1517 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1521 if (!(p
= pa_tokenizer_get(t
, 2))) {
1522 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1526 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1527 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1531 if (pa_sink_set_port(sink
, p
, TRUE
) < 0) {
1532 pa_strbuf_printf(buf
, "Failed to set sink port to '%s'.\n", p
);
1539 static int pa_cli_command_source_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1543 pa_core_assert_ref(c
);
1548 if (!(n
= pa_tokenizer_get(t
, 1))) {
1549 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1553 if (!(p
= pa_tokenizer_get(t
, 2))) {
1554 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1558 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1559 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1563 if (pa_source_set_port(source
, p
, TRUE
) < 0) {
1564 pa_strbuf_printf(buf
, "Failed to set source port to '%s'.\n", p
);
1571 static int pa_cli_command_dump(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1581 pa_core_assert_ref(c
);
1589 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime_r(&now
, txt
));
1591 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime(&now
));
1594 PA_IDXSET_FOREACH(m
, c
->modules
, idx
) {
1596 pa_strbuf_printf(buf
, "load-module %s", m
->name
);
1599 pa_strbuf_printf(buf
, " %s", m
->argument
);
1601 pa_strbuf_puts(buf
, "\n");
1605 PA_IDXSET_FOREACH(sink
, c
->sinks
, idx
) {
1608 pa_strbuf_puts(buf
, "\n");
1612 pa_strbuf_printf(buf
, "set-sink-volume %s 0x%03x\n", sink
->name
, pa_cvolume_max(pa_sink_get_volume(sink
, FALSE
)));
1613 pa_strbuf_printf(buf
, "set-sink-mute %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_mute(sink
, FALSE
)));
1614 pa_strbuf_printf(buf
, "suspend-sink %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_state(sink
) == PA_SINK_SUSPENDED
));
1618 PA_IDXSET_FOREACH(source
, c
->sources
, idx
) {
1621 pa_strbuf_puts(buf
, "\n");
1625 pa_strbuf_printf(buf
, "set-source-volume %s 0x%03x\n", source
->name
, pa_cvolume_max(pa_source_get_volume(source
, FALSE
)));
1626 pa_strbuf_printf(buf
, "set-source-mute %s %s\n", source
->name
, pa_yes_no(pa_source_get_mute(source
, FALSE
)));
1627 pa_strbuf_printf(buf
, "suspend-source %s %s\n", source
->name
, pa_yes_no(pa_source_get_state(source
) == PA_SOURCE_SUSPENDED
));
1631 PA_IDXSET_FOREACH(card
, c
->cards
, idx
) {
1634 pa_strbuf_puts(buf
, "\n");
1638 if (card
->active_profile
)
1639 pa_strbuf_printf(buf
, "set-card-profile %s %s\n", card
->name
, card
->active_profile
->name
);
1643 if ((sink
= pa_namereg_get_default_sink(c
))) {
1645 pa_strbuf_puts(buf
, "\n");
1649 pa_strbuf_printf(buf
, "set-default-sink %s\n", sink
->name
);
1652 if ((source
= pa_namereg_get_default_source(c
))) {
1654 pa_strbuf_puts(buf
, "\n");
1656 pa_strbuf_printf(buf
, "set-default-source %s\n", source
->name
);
1659 pa_strbuf_puts(buf
, "\n### EOF\n");
1664 int pa_cli_command_execute_line_stateful(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
, int *ifstate
) {
1671 cs
= s
+strspn(s
, whitespace
);
1673 if (*cs
== '#' || !*cs
)
1675 else if (*cs
== '.') {
1676 if (!strcmp(cs
, META_ELSE
)) {
1677 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1678 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1680 } else if (*ifstate
== IFSTATE_TRUE
)
1681 *ifstate
= IFSTATE_FALSE
;
1683 *ifstate
= IFSTATE_TRUE
;
1685 } else if (!strcmp(cs
, META_ENDIF
)) {
1686 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1687 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1690 *ifstate
= IFSTATE_NONE
;
1693 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
1695 if (!strcmp(cs
, META_FAIL
))
1697 else if (!strcmp(cs
, META_NOFAIL
))
1701 l
= strcspn(cs
, whitespace
);
1703 if (l
== sizeof(META_INCLUDE
)-1 && !strncmp(cs
, META_INCLUDE
, l
)) {
1705 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
1707 if (stat(filename
, &st
) < 0) {
1708 pa_log_warn("stat('%s'): %s", filename
, pa_cstrerror(errno
));
1712 if (S_ISDIR(st
.st_mode
)) {
1715 if (!(d
= opendir(filename
))) {
1716 pa_log_warn("Failed to read '%s': %s", filename
, pa_cstrerror(errno
));
1721 char **sorted_files
;
1723 pa_bool_t failed
= FALSE
;
1724 pa_dynarray
*files
= pa_dynarray_new();
1726 while ((de
= readdir(d
))) {
1728 size_t flen
= strlen(de
->d_name
);
1733 extn
= &de
->d_name
[flen
-3];
1734 if (strncmp(extn
, ".pa", 3) == 0)
1735 pa_dynarray_append(files
, pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", filename
, de
->d_name
));
1740 count
= pa_dynarray_size(files
);
1741 sorted_files
= pa_xnew(char*, count
);
1742 for (i
= 0; i
< count
; ++i
)
1743 sorted_files
[i
] = pa_dynarray_get(files
, i
);
1744 pa_dynarray_free(files
, NULL
, NULL
);
1746 for (i
= 0; i
< count
; ++i
) {
1747 for (unsigned j
= 0; j
< count
; ++j
) {
1748 if (strcmp(sorted_files
[i
], sorted_files
[j
]) < 0) {
1749 char *tmp
= sorted_files
[i
];
1750 sorted_files
[i
] = sorted_files
[j
];
1751 sorted_files
[j
] = tmp
;
1756 for (i
= 0; i
< count
; ++i
) {
1758 if (pa_cli_command_execute_file(c
, sorted_files
[i
], buf
, fail
) < 0 && *fail
)
1762 pa_xfree(sorted_files
[i
]);
1764 pa_xfree(sorted_files
);
1768 } else if (pa_cli_command_execute_file(c
, filename
, buf
, fail
) < 0 && *fail
) {
1772 } else if (l
== sizeof(META_IFEXISTS
)-1 && !strncmp(cs
, META_IFEXISTS
, l
)) {
1774 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1776 } else if (*ifstate
!= IFSTATE_NONE
) {
1777 pa_strbuf_printf(buf
, "Nested %s commands not supported\n", cs
);
1780 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
1782 /* Search DL_SEARCH_PATH unless the filename is absolute */
1783 if (filename
[0] == PA_PATH_SEP_CHAR
) {
1785 *ifstate
= access(filename
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
1786 pa_log_debug("Checking for existance of '%s': %s", filename
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
1789 const char *paths
, *state
= NULL
;
1792 if (!(paths
= lt_dlgetsearchpath()))
1795 while ((p
= pa_split(paths
, ":", &state
))) {
1798 pathname
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", p
, filename
);
1801 *ifstate
= access(pathname
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
1802 pa_log_debug("Checking for existance of '%s': %s", pathname
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
1806 if (*ifstate
== IFSTATE_TRUE
)
1813 pa_strbuf_printf(buf
, "Invalid meta command: %s\n", cs
);
1814 if (*fail
) return -1;
1818 const struct command
*command
;
1822 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
1825 l
= strcspn(cs
, whitespace
);
1827 for (command
= commands
; command
->name
; command
++)
1828 if (strlen(command
->name
) == l
&& !strncmp(cs
, command
->name
, l
)) {
1830 pa_tokenizer
*t
= pa_tokenizer_new(cs
, command
->args
);
1832 ret
= command
->proc(c
, t
, buf
, fail
);
1833 pa_tokenizer_free(t
);
1836 if (ret
< 0 && *fail
)
1843 pa_strbuf_printf(buf
, "Unknown command: %s\n", cs
);
1852 int pa_cli_command_execute_line(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1853 return pa_cli_command_execute_line_stateful(c
, s
, buf
, fail
, NULL
);
1856 int pa_cli_command_execute_file_stream(pa_core
*c
, FILE *f
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1858 int ifstate
= IFSTATE_NONE
;
1860 pa_bool_t _fail
= TRUE
;
1869 while (fgets(line
, sizeof(line
), f
)) {
1872 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
)
1883 int pa_cli_command_execute_file(pa_core
*c
, const char *fn
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1886 pa_bool_t _fail
= TRUE
;
1895 if (!(f
= pa_fopen_cloexec(fn
, "r"))) {
1896 pa_strbuf_printf(buf
, "open('%s') failed: %s\n", fn
, pa_cstrerror(errno
));
1902 pa_log_debug("Parsing script '%s'", fn
);
1903 ret
= pa_cli_command_execute_file_stream(c
, f
, buf
, fail
);
1912 int pa_cli_command_execute(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1914 int ifstate
= IFSTATE_NONE
;
1915 pa_bool_t _fail
= TRUE
;
1926 size_t l
= strcspn(p
, linebreak
);
1927 char *line
= pa_xstrndup(p
, l
);
1929 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
) {
1936 p
+= strspn(p
, linebreak
);