]> code.delx.au - pulseaudio/blob - src/pulsecore/cli-command.c
cli: Add set-log-target command for pacmd
[pulseaudio] / src / pulsecore / cli-command.c
1 /***
2 This file is part of PulseAudio.
3
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
6
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.
11
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.
16
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
20 USA.
21 ***/
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <string.h>
29 #include <stdlib.h>
30 #include <errno.h>
31 #include <unistd.h>
32 #include <ltdl.h>
33 #include <sys/stat.h>
34 #include <dirent.h>
35 #include <time.h>
36 #include <fcntl.h>
37
38 #include <pulse/xmalloc.h>
39 #include <pulse/error.h>
40
41 #include <pulsecore/module.h>
42 #include <pulsecore/sink.h>
43 #include <pulsecore/source.h>
44 #include <pulsecore/client.h>
45 #include <pulsecore/sink-input.h>
46 #include <pulsecore/source-output.h>
47 #include <pulsecore/tokenizer.h>
48 #include <pulsecore/strbuf.h>
49 #include <pulsecore/namereg.h>
50 #include <pulsecore/cli-text.h>
51 #include <pulsecore/core-scache.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>
60
61 #include "cli-command.h"
62
63 struct command {
64 const char *name;
65 int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, pa_bool_t *fail);
66 const char *help;
67 unsigned args;
68 };
69
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"
76
77 enum {
78 IFSTATE_NONE = -1,
79 IFSTATE_FALSE = 0,
80 IFSTATE_TRUE = 1,
81 };
82
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_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
101 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
102 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
103 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
104 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
105 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
106 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
107 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
108 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
109 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
110 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
111 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
112 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
113 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
114 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
115 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
116 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
117 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
118 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
119 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
120 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
121 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
122 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
123 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
124 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
125 static int pa_cli_command_log_target(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
126 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
127 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
128 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
129 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
130 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
131 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
132 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
133 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
134 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
135 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
136 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
137 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
138
139 /* A method table for all available commands */
140
141 static const struct command commands[] = {
142 { "help", pa_cli_command_help, "Show this help", 1 },
143 { "list-modules", pa_cli_command_modules, "List loaded modules", 1 },
144 { "list-cards", pa_cli_command_cards, "List cards", 1 },
145 { "list-sinks", pa_cli_command_sinks, "List loaded sinks", 1 },
146 { "list-sources", pa_cli_command_sources, "List loaded sources", 1 },
147 { "list-clients", pa_cli_command_clients, "List loaded clients", 1 },
148 { "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 },
149 { "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 },
150 { "stat", pa_cli_command_stat, "Show memory block statistics", 1 },
151 { "info", pa_cli_command_info, "Show comprehensive status", 1 },
152 { "ls", pa_cli_command_info, NULL, 1 },
153 { "list", pa_cli_command_info, NULL, 1 },
154 { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3},
155 { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2},
156 { "describe-module", pa_cli_command_describe, "Describe a module (arg: name)", 2},
157 { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3},
158 { "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3},
159 { "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, bool)", 3},
160 { "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, bool)", 3},
161 { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3},
162 { "set-source-output-volume",pa_cli_command_source_output_volume,"Set the volume of a source output (args: index, volume)", 3},
163 { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3},
164 { "set-source-output-mute", pa_cli_command_source_output_mute, "Set the mute switch of a source output (args: index, bool)", 3},
165 { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2},
166 { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2},
167 { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index|name, profile-name)", 3},
168 { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index|name, port-name)", 3},
169 { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index|name, port-name)", 3},
170 { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3},
171 { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3},
172 { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2},
173 { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3},
174 { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
175 { "update-sink-proplist", pa_cli_command_update_sink_proplist, "Update the properties of a sink (args: index|name, properties)", 3},
176 { "update-source-proplist", pa_cli_command_update_source_proplist, "Update the properties of a source (args: index|name, properties)", 3},
177 { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist, "Update the properties of a sink input (args: index, properties)", 3},
178 { "update-source-output-proplist", pa_cli_command_update_source_output_proplist, "Update the properties of a source output (args: index, properties)", 3},
179 { "list-samples", pa_cli_command_scache_list, "List all entries in the sample cache", 1},
180 { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3},
181 { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2},
182 { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3},
183 { "load-sample-lazy", pa_cli_command_scache_load, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
184 { "load-sample-dir-lazy", pa_cli_command_scache_load_dir, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
185 { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
186 { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
187 { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
188 { "set-log-target", pa_cli_command_log_target, "Change the log target (args: null,auto,syslog,stderr,file:PATH)", 2},
189 { "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2},
190 { "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2},
191 { "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2},
192 { "set-log-backtrace", pa_cli_command_log_backtrace, "Show backtrace in log messages (args: frames)", 2},
193 { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3},
194 { "dump", pa_cli_command_dump, "Dump daemon configuration", 1},
195 { "dump-volumes", pa_cli_command_dump_volumes, "Debug: Show the state of all volumes", 1 },
196 { "shared", pa_cli_command_list_shared_props, "Debug: Show shared properties", 1},
197 { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
198 { "vacuum", pa_cli_command_vacuum, NULL, 1},
199 { NULL, NULL, NULL, 0 }
200 };
201
202 static const char whitespace[] = " \t\n\r";
203 static const char linebreak[] = "\n\r";
204
205 static uint32_t parse_index(const char *n) {
206 uint32_t idx;
207
208 if (pa_atou(n, &idx) < 0)
209 return (uint32_t) PA_IDXSET_INVALID;
210
211 return idx;
212 }
213
214 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
215 pa_core_assert_ref(c);
216 pa_assert(t);
217 pa_assert(buf);
218 pa_assert(fail);
219
220 if (pa_core_exit(c, FALSE, 0) < 0)
221 pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n");
222
223 return 0;
224 }
225
226 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
227 const struct command*command;
228
229 pa_core_assert_ref(c);
230 pa_assert(t);
231 pa_assert(buf);
232 pa_assert(fail);
233
234 pa_strbuf_puts(buf, "Available commands:\n");
235
236 for (command = commands; command->name; command++)
237 if (command->help)
238 pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help);
239 return 0;
240 }
241
242 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
243 char *s;
244
245 pa_core_assert_ref(c);
246 pa_assert(t);
247 pa_assert(buf);
248 pa_assert(fail);
249
250 pa_assert_se(s = pa_module_list_to_string(c));
251 pa_strbuf_puts(buf, s);
252 pa_xfree(s);
253 return 0;
254 }
255
256 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
257 char *s;
258
259 pa_core_assert_ref(c);
260 pa_assert(t);
261 pa_assert(buf);
262 pa_assert(fail);
263
264 pa_assert_se(s = pa_client_list_to_string(c));
265 pa_strbuf_puts(buf, s);
266 pa_xfree(s);
267 return 0;
268 }
269
270 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
271 char *s;
272
273 pa_core_assert_ref(c);
274 pa_assert(t);
275 pa_assert(buf);
276 pa_assert(fail);
277
278 pa_assert_se(s = pa_card_list_to_string(c));
279 pa_strbuf_puts(buf, s);
280 pa_xfree(s);
281 return 0;
282 }
283
284 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
285 char *s;
286
287 pa_core_assert_ref(c);
288 pa_assert(t);
289 pa_assert(buf);
290 pa_assert(fail);
291
292 pa_assert_se(s = pa_sink_list_to_string(c));
293 pa_strbuf_puts(buf, s);
294 pa_xfree(s);
295 return 0;
296 }
297
298 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
299 char *s;
300
301 pa_core_assert_ref(c);
302 pa_assert(t);
303 pa_assert(buf);
304 pa_assert(fail);
305
306 pa_assert_se(s = pa_source_list_to_string(c));
307 pa_strbuf_puts(buf, s);
308 pa_xfree(s);
309 return 0;
310 }
311
312 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
313 char *s;
314
315 pa_core_assert_ref(c);
316 pa_assert(t);
317 pa_assert(buf);
318 pa_assert(fail);
319
320 pa_assert_se(s = pa_sink_input_list_to_string(c));
321 pa_strbuf_puts(buf, s);
322 pa_xfree(s);
323 return 0;
324 }
325
326 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
327 char *s;
328
329 pa_core_assert_ref(c);
330 pa_assert(t);
331 pa_assert(buf);
332 pa_assert(fail);
333
334 pa_assert_se(s = pa_source_output_list_to_string(c));
335 pa_strbuf_puts(buf, s);
336 pa_xfree(s);
337 return 0;
338 }
339
340 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
341 char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
342 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
343 char bytes[PA_BYTES_SNPRINT_MAX];
344 const pa_mempool_stat *mstat;
345 unsigned k;
346 pa_sink *def_sink;
347 pa_source *def_source;
348
349 static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = {
350 [PA_MEMBLOCK_POOL] = "POOL",
351 [PA_MEMBLOCK_POOL_EXTERNAL] = "POOL_EXTERNAL",
352 [PA_MEMBLOCK_APPENDED] = "APPENDED",
353 [PA_MEMBLOCK_USER] = "USER",
354 [PA_MEMBLOCK_FIXED] = "FIXED",
355 [PA_MEMBLOCK_IMPORTED] = "IMPORTED",
356 };
357
358 pa_core_assert_ref(c);
359 pa_assert(t);
360 pa_assert(buf);
361 pa_assert(fail);
362
363 mstat = pa_mempool_get_stat(c->mempool);
364
365 pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
366 (unsigned) pa_atomic_load(&mstat->n_allocated),
367 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->allocated_size)));
368
369 pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
370 (unsigned) pa_atomic_load(&mstat->n_accumulated),
371 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->accumulated_size)));
372
373 pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
374 (unsigned) pa_atomic_load(&mstat->n_imported),
375 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->imported_size)));
376
377 pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
378 (unsigned) pa_atomic_load(&mstat->n_exported),
379 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_atomic_load(&mstat->exported_size)));
380
381 pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
382 pa_bytes_snprint(bytes, sizeof(bytes), (unsigned) pa_scache_total_size(c)));
383
384 pa_strbuf_printf(buf, "Default sample spec: %s\n",
385 pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
386
387 pa_strbuf_printf(buf, "Default channel map: %s\n",
388 pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
389
390 def_sink = pa_namereg_get_default_sink(c);
391 def_source = pa_namereg_get_default_source(c);
392 pa_strbuf_printf(buf, "Default sink name: %s\n"
393 "Default source name: %s\n",
394 def_sink ? def_sink->name : "none",
395 def_source ? def_source->name : "none");
396
397 for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++)
398 pa_strbuf_printf(buf,
399 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
400 type_table[k],
401 (unsigned) pa_atomic_load(&mstat->n_allocated_by_type[k]),
402 (unsigned) pa_atomic_load(&mstat->n_accumulated_by_type[k]));
403
404 return 0;
405 }
406
407 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
408 pa_core_assert_ref(c);
409 pa_assert(t);
410 pa_assert(buf);
411 pa_assert(fail);
412
413 pa_cli_command_stat(c, t, buf, fail);
414 pa_cli_command_modules(c, t, buf, fail);
415 pa_cli_command_sinks(c, t, buf, fail);
416 pa_cli_command_sources(c, t, buf, fail);
417 pa_cli_command_clients(c, t, buf, fail);
418 pa_cli_command_cards(c, t, buf, fail);
419 pa_cli_command_sink_inputs(c, t, buf, fail);
420 pa_cli_command_source_outputs(c, t, buf, fail);
421 pa_cli_command_scache_list(c, t, buf, fail);
422 return 0;
423 }
424
425 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
426 const char *name;
427
428 pa_core_assert_ref(c);
429 pa_assert(t);
430 pa_assert(buf);
431 pa_assert(fail);
432
433 if (!(name = pa_tokenizer_get(t, 1))) {
434 pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
435 return -1;
436 }
437
438 if (!pa_module_load(c, name, pa_tokenizer_get(t, 2))) {
439 pa_strbuf_puts(buf, "Module load failed.\n");
440 return -1;
441 }
442
443 return 0;
444 }
445
446 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
447 pa_module *m;
448 uint32_t idx;
449 const char *i;
450 char *e;
451
452 pa_core_assert_ref(c);
453 pa_assert(t);
454 pa_assert(buf);
455 pa_assert(fail);
456
457 if (!(i = pa_tokenizer_get(t, 1))) {
458 pa_strbuf_puts(buf, "You need to specify the module index.\n");
459 return -1;
460 }
461
462 idx = (uint32_t) strtoul(i, &e, 10);
463 if (*e || !(m = pa_idxset_get_by_index(c->modules, idx))) {
464 pa_strbuf_puts(buf, "Invalid module index.\n");
465 return -1;
466 }
467
468 pa_module_unload_request(m, FALSE);
469 return 0;
470 }
471
472 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
473 const char *name;
474 pa_modinfo *i;
475
476 pa_core_assert_ref(c);
477 pa_assert(t);
478 pa_assert(buf);
479 pa_assert(fail);
480
481 if (!(name = pa_tokenizer_get(t, 1))) {
482 pa_strbuf_puts(buf, "You need to specify the module name.\n");
483 return -1;
484 }
485
486 if ((i = pa_modinfo_get_by_name(name))) {
487
488 pa_strbuf_printf(buf, "Name: %s\n", name);
489
490 if (!i->description && !i->version && !i->author && !i->usage)
491 pa_strbuf_printf(buf, "No module information available\n");
492 else {
493 if (i->version)
494 pa_strbuf_printf(buf, "Version: %s\n", i->version);
495 if (i->description)
496 pa_strbuf_printf(buf, "Description: %s\n", i->description);
497 if (i->author)
498 pa_strbuf_printf(buf, "Author: %s\n", i->author);
499 if (i->usage)
500 pa_strbuf_printf(buf, "Usage: %s\n", i->usage);
501 pa_strbuf_printf(buf, "Load Once: %s\n", pa_yes_no(i->load_once));
502 if (i->deprecated)
503 pa_strbuf_printf(buf, "Warning, deprecated: %s\n", i->deprecated);
504 }
505
506 pa_modinfo_free(i);
507 } else
508 pa_strbuf_puts(buf, "Failed to open module.\n");
509
510 return 0;
511 }
512
513 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
514 const char *n, *v;
515 pa_sink *sink;
516 uint32_t volume;
517 pa_cvolume cvolume;
518
519 pa_core_assert_ref(c);
520 pa_assert(t);
521 pa_assert(buf);
522 pa_assert(fail);
523
524 if (!(n = pa_tokenizer_get(t, 1))) {
525 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
526 return -1;
527 }
528
529 if (!(v = pa_tokenizer_get(t, 2))) {
530 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
531 return -1;
532 }
533
534 if (pa_atou(v, &volume) < 0) {
535 pa_strbuf_puts(buf, "Failed to parse volume.\n");
536 return -1;
537 }
538
539 if (!PA_VOLUME_IS_VALID(volume)) {
540 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
541 return -1;
542 }
543
544 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
545 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
546 return -1;
547 }
548
549 pa_cvolume_set(&cvolume, 1, volume);
550 pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
551 return 0;
552 }
553
554 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
555 const char *n, *v;
556 pa_sink_input *si;
557 pa_volume_t volume;
558 pa_cvolume cvolume;
559 uint32_t idx;
560
561 pa_core_assert_ref(c);
562 pa_assert(t);
563 pa_assert(buf);
564 pa_assert(fail);
565
566 if (!(n = pa_tokenizer_get(t, 1))) {
567 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
568 return -1;
569 }
570
571 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
572 pa_strbuf_puts(buf, "Failed to parse index.\n");
573 return -1;
574 }
575
576 if (!(v = pa_tokenizer_get(t, 2))) {
577 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
578 return -1;
579 }
580
581 if (pa_atou(v, &volume) < 0) {
582 pa_strbuf_puts(buf, "Failed to parse volume.\n");
583 return -1;
584 }
585
586 if (!PA_VOLUME_IS_VALID(volume)) {
587 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
588 return -1;
589 }
590
591 if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) {
592 pa_strbuf_puts(buf, "No sink input found with this index.\n");
593 return -1;
594 }
595
596 if (!si->volume_writable) {
597 pa_strbuf_puts(buf, "This sink input's volume can't be changed.\n");
598 return -1;
599 }
600
601 pa_cvolume_set(&cvolume, 1, volume);
602 pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
603 return 0;
604 }
605
606 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
607 const char *n, *v;
608 pa_source *source;
609 uint32_t volume;
610 pa_cvolume cvolume;
611
612 pa_core_assert_ref(c);
613 pa_assert(t);
614 pa_assert(buf);
615 pa_assert(fail);
616
617 if (!(n = pa_tokenizer_get(t, 1))) {
618 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
619 return -1;
620 }
621
622 if (!(v = pa_tokenizer_get(t, 2))) {
623 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
624 return -1;
625 }
626
627 if (pa_atou(v, &volume) < 0) {
628 pa_strbuf_puts(buf, "Failed to parse volume.\n");
629 return -1;
630 }
631
632 if (!PA_VOLUME_IS_VALID(volume)) {
633 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
634 return -1;
635 }
636
637 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
638 pa_strbuf_puts(buf, "No source found by this name or index.\n");
639 return -1;
640 }
641
642 pa_cvolume_set(&cvolume, 1, volume);
643 pa_source_set_volume(source, &cvolume, TRUE, TRUE);
644 return 0;
645 }
646
647 static int pa_cli_command_source_output_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
648 const char *n, *v;
649 pa_source_output *so;
650 pa_volume_t volume;
651 pa_cvolume cvolume;
652 uint32_t idx;
653
654 pa_core_assert_ref(c);
655 pa_assert(t);
656 pa_assert(buf);
657 pa_assert(fail);
658
659 if (!(n = pa_tokenizer_get(t, 1))) {
660 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
661 return -1;
662 }
663
664 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
665 pa_strbuf_puts(buf, "Failed to parse index.\n");
666 return -1;
667 }
668
669 if (!(v = pa_tokenizer_get(t, 2))) {
670 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
671 return -1;
672 }
673
674 if (pa_atou(v, &volume) < 0) {
675 pa_strbuf_puts(buf, "Failed to parse volume.\n");
676 return -1;
677 }
678
679 if (!PA_VOLUME_IS_VALID(volume)) {
680 pa_strbuf_puts(buf, "Volume outside permissible range.\n");
681 return -1;
682 }
683
684 if (!(so = pa_idxset_get_by_index(c->source_outputs, idx))) {
685 pa_strbuf_puts(buf, "No source output found with this index.\n");
686 return -1;
687 }
688
689 if (!so->volume_writable) {
690 pa_strbuf_puts(buf, "This source output's volume can't be changed.\n");
691 return -1;
692 }
693
694 pa_cvolume_set(&cvolume, 1, volume);
695 pa_source_output_set_volume(so, &cvolume, TRUE, TRUE);
696 return 0;
697 }
698
699 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
700 const char *n, *m;
701 pa_sink *sink;
702 int mute;
703
704 pa_core_assert_ref(c);
705 pa_assert(t);
706 pa_assert(buf);
707 pa_assert(fail);
708
709 if (!(n = pa_tokenizer_get(t, 1))) {
710 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
711 return -1;
712 }
713
714 if (!(m = pa_tokenizer_get(t, 2))) {
715 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
716 return -1;
717 }
718
719 if ((mute = pa_parse_boolean(m)) < 0) {
720 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
721 return -1;
722 }
723
724 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
725 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
726 return -1;
727 }
728
729 pa_sink_set_mute(sink, mute, TRUE);
730 return 0;
731 }
732
733 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
734 const char *n, *m;
735 pa_source *source;
736 int mute;
737
738 pa_core_assert_ref(c);
739 pa_assert(t);
740 pa_assert(buf);
741 pa_assert(fail);
742
743 if (!(n = pa_tokenizer_get(t, 1))) {
744 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
745 return -1;
746 }
747
748 if (!(m = pa_tokenizer_get(t, 2))) {
749 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
750 return -1;
751 }
752
753 if ((mute = pa_parse_boolean(m)) < 0) {
754 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
755 return -1;
756 }
757
758 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
759 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
760 return -1;
761 }
762
763 pa_source_set_mute(source, mute, TRUE);
764 return 0;
765 }
766
767 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
768 const char *n, *s;
769 pa_sink *sink;
770 pa_proplist *p;
771
772 pa_core_assert_ref(c);
773 pa_assert(t);
774 pa_assert(buf);
775 pa_assert(fail);
776
777 if (!(n = pa_tokenizer_get(t, 1))) {
778 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
779 return -1;
780 }
781
782 if (!(s = pa_tokenizer_get(t, 2))) {
783 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
784 return -1;
785 }
786
787 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
788 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
789 return -1;
790 }
791
792 if (!(p = pa_proplist_from_string(s))) {
793 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
794 return -1;
795 }
796
797 pa_sink_update_proplist(sink, PA_UPDATE_REPLACE, p);
798
799 pa_proplist_free(p);
800
801 return 0;
802 }
803
804 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
805 const char *n, *s;
806 pa_source *source;
807 pa_proplist *p;
808
809 pa_core_assert_ref(c);
810 pa_assert(t);
811 pa_assert(buf);
812 pa_assert(fail);
813
814 if (!(n = pa_tokenizer_get(t, 1))) {
815 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
816 return -1;
817 }
818
819 if (!(s = pa_tokenizer_get(t, 2))) {
820 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
821 return -1;
822 }
823
824 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
825 pa_strbuf_puts(buf, "No source found by this name or index.\n");
826 return -1;
827 }
828
829 if (!(p = pa_proplist_from_string(s))) {
830 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
831 return -1;
832 }
833
834 pa_source_update_proplist(source, PA_UPDATE_REPLACE, p);
835
836 pa_proplist_free(p);
837
838 return 0;
839 }
840
841 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
842 const char *n, *s;
843 pa_sink_input *si;
844 uint32_t idx;
845 pa_proplist *p;
846
847 pa_core_assert_ref(c);
848 pa_assert(t);
849 pa_assert(buf);
850 pa_assert(fail);
851
852 if (!(n = pa_tokenizer_get(t, 1))) {
853 pa_strbuf_puts(buf, "You need to specify a sink input either by index.\n");
854 return -1;
855 }
856
857 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
858 pa_strbuf_puts(buf, "Failed to parse index.\n");
859 return -1;
860 }
861
862 if (!(s = pa_tokenizer_get(t, 2))) {
863 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
864 return -1;
865 }
866
867 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
868 pa_strbuf_puts(buf, "No sink input found with this index.\n");
869 return -1;
870 }
871
872 if (!(p = pa_proplist_from_string(s))) {
873 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
874 return -1;
875 }
876
877 pa_sink_input_update_proplist(si, PA_UPDATE_REPLACE, p);
878
879 pa_proplist_free(p);
880
881 return 0;
882 }
883
884 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
885 const char *n, *s;
886 pa_source_output *so;
887 uint32_t idx;
888 pa_proplist *p;
889
890 pa_core_assert_ref(c);
891 pa_assert(t);
892 pa_assert(buf);
893 pa_assert(fail);
894
895 if (!(n = pa_tokenizer_get(t, 1))) {
896 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
897 return -1;
898 }
899
900 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
901 pa_strbuf_puts(buf, "Failed to parse index.\n");
902 return -1;
903 }
904
905 if (!(s = pa_tokenizer_get(t, 2))) {
906 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
907 return -1;
908 }
909
910 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
911 pa_strbuf_puts(buf, "No source output found with this index.\n");
912 return -1;
913 }
914
915 if (!(p = pa_proplist_from_string(s))) {
916 pa_strbuf_puts(buf, "Failed to parse proplist.\n");
917 return -1;
918 }
919
920 pa_source_output_update_proplist(so, PA_UPDATE_REPLACE, p);
921
922 pa_proplist_free(p);
923
924 return 0;
925 }
926
927 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
928 const char *n, *v;
929 pa_sink_input *si;
930 uint32_t idx;
931 int mute;
932
933 pa_core_assert_ref(c);
934 pa_assert(t);
935 pa_assert(buf);
936 pa_assert(fail);
937
938 if (!(n = pa_tokenizer_get(t, 1))) {
939 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
940 return -1;
941 }
942
943 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
944 pa_strbuf_puts(buf, "Failed to parse index.\n");
945 return -1;
946 }
947
948 if (!(v = pa_tokenizer_get(t, 2))) {
949 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
950 return -1;
951 }
952
953 if ((mute = pa_parse_boolean(v)) < 0) {
954 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
955 return -1;
956 }
957
958 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
959 pa_strbuf_puts(buf, "No sink input found with this index.\n");
960 return -1;
961 }
962
963 pa_sink_input_set_mute(si, mute, TRUE);
964 return 0;
965 }
966
967 static int pa_cli_command_source_output_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
968 const char *n, *v;
969 pa_source_output *so;
970 uint32_t idx;
971 int mute;
972
973 pa_core_assert_ref(c);
974 pa_assert(t);
975 pa_assert(buf);
976 pa_assert(fail);
977
978 if (!(n = pa_tokenizer_get(t, 1))) {
979 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
980 return -1;
981 }
982
983 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
984 pa_strbuf_puts(buf, "Failed to parse index.\n");
985 return -1;
986 }
987
988 if (!(v = pa_tokenizer_get(t, 2))) {
989 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
990 return -1;
991 }
992
993 if ((mute = pa_parse_boolean(v)) < 0) {
994 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
995 return -1;
996 }
997
998 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
999 pa_strbuf_puts(buf, "No source output found with this index.\n");
1000 return -1;
1001 }
1002
1003 pa_source_output_set_mute(so, mute, TRUE);
1004 return 0;
1005 }
1006
1007 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1008 const char *n;
1009 pa_sink *s;
1010
1011 pa_core_assert_ref(c);
1012 pa_assert(t);
1013 pa_assert(buf);
1014 pa_assert(fail);
1015
1016 if (!(n = pa_tokenizer_get(t, 1))) {
1017 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1018 return -1;
1019 }
1020
1021 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
1022 pa_namereg_set_default_sink(c, s);
1023 else
1024 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
1025
1026 return 0;
1027 }
1028
1029 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1030 const char *n;
1031 pa_source *s;
1032
1033 pa_core_assert_ref(c);
1034 pa_assert(t);
1035 pa_assert(buf);
1036 pa_assert(fail);
1037
1038 if (!(n = pa_tokenizer_get(t, 1))) {
1039 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1040 return -1;
1041 }
1042
1043 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SOURCE)))
1044 pa_namereg_set_default_source(c, s);
1045 else
1046 pa_strbuf_printf(buf, "Source %s does not exist.\n", n);
1047 return 0;
1048 }
1049
1050 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1051 const char *n;
1052 pa_client *client;
1053 uint32_t idx;
1054
1055 pa_core_assert_ref(c);
1056 pa_assert(t);
1057 pa_assert(buf);
1058 pa_assert(fail);
1059
1060 if (!(n = pa_tokenizer_get(t, 1))) {
1061 pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
1062 return -1;
1063 }
1064
1065 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1066 pa_strbuf_puts(buf, "Failed to parse index.\n");
1067 return -1;
1068 }
1069
1070 if (!(client = pa_idxset_get_by_index(c->clients, idx))) {
1071 pa_strbuf_puts(buf, "No client found by this index.\n");
1072 return -1;
1073 }
1074
1075 pa_client_kill(client);
1076 return 0;
1077 }
1078
1079 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1080 const char *n;
1081 pa_sink_input *sink_input;
1082 uint32_t idx;
1083
1084 pa_core_assert_ref(c);
1085 pa_assert(t);
1086 pa_assert(buf);
1087 pa_assert(fail);
1088
1089 if (!(n = pa_tokenizer_get(t, 1))) {
1090 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1091 return -1;
1092 }
1093
1094 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1095 pa_strbuf_puts(buf, "Failed to parse index.\n");
1096 return -1;
1097 }
1098
1099 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) {
1100 pa_strbuf_puts(buf, "No sink input found by this index.\n");
1101 return -1;
1102 }
1103
1104 pa_sink_input_kill(sink_input);
1105 return 0;
1106 }
1107
1108 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1109 const char *n;
1110 pa_source_output *source_output;
1111 uint32_t idx;
1112
1113 pa_core_assert_ref(c);
1114 pa_assert(t);
1115 pa_assert(buf);
1116 pa_assert(fail);
1117
1118 if (!(n = pa_tokenizer_get(t, 1))) {
1119 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1120 return -1;
1121 }
1122
1123 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1124 pa_strbuf_puts(buf, "Failed to parse index.\n");
1125 return -1;
1126 }
1127
1128 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) {
1129 pa_strbuf_puts(buf, "No source output found by this index.\n");
1130 return -1;
1131 }
1132
1133 pa_source_output_kill(source_output);
1134 return 0;
1135 }
1136
1137 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1138 char *s;
1139
1140 pa_core_assert_ref(c);
1141 pa_assert(t);
1142 pa_assert(buf);
1143 pa_assert(fail);
1144
1145 pa_assert_se(s = pa_scache_list_to_string(c));
1146 pa_strbuf_puts(buf, s);
1147 pa_xfree(s);
1148
1149 return 0;
1150 }
1151
1152 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1153 const char *n, *sink_name;
1154 pa_sink *sink;
1155 uint32_t idx;
1156
1157 pa_core_assert_ref(c);
1158 pa_assert(t);
1159 pa_assert(buf);
1160 pa_assert(fail);
1161
1162 if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1163 pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
1164 return -1;
1165 }
1166
1167 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1168 pa_strbuf_puts(buf, "No sink by that name.\n");
1169 return -1;
1170 }
1171
1172 if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
1173 pa_strbuf_puts(buf, "Failed to play sample.\n");
1174 return -1;
1175 }
1176
1177 pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
1178
1179 return 0;
1180 }
1181
1182 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1183 const char *n;
1184
1185 pa_core_assert_ref(c);
1186 pa_assert(t);
1187 pa_assert(buf);
1188 pa_assert(fail);
1189
1190 if (!(n = pa_tokenizer_get(t, 1))) {
1191 pa_strbuf_puts(buf, "You need to specify a sample name.\n");
1192 return -1;
1193 }
1194
1195 if (pa_scache_remove_item(c, n) < 0) {
1196 pa_strbuf_puts(buf, "Failed to remove sample.\n");
1197 return -1;
1198 }
1199
1200 return 0;
1201 }
1202
1203 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1204 const char *fname, *n;
1205 int r;
1206
1207 pa_core_assert_ref(c);
1208 pa_assert(t);
1209 pa_assert(buf);
1210 pa_assert(fail);
1211
1212 if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
1213 pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
1214 return -1;
1215 }
1216
1217 if (strstr(pa_tokenizer_get(t, 0), "lazy"))
1218 r = pa_scache_add_file_lazy(c, n, fname, NULL);
1219 else
1220 r = pa_scache_add_file(c, n, fname, NULL);
1221
1222 if (r < 0)
1223 pa_strbuf_puts(buf, "Failed to load sound file.\n");
1224
1225 return 0;
1226 }
1227
1228 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1229 const char *pname;
1230
1231 pa_core_assert_ref(c);
1232 pa_assert(t);
1233 pa_assert(buf);
1234 pa_assert(fail);
1235
1236 if (!(pname = pa_tokenizer_get(t, 1))) {
1237 pa_strbuf_puts(buf, "You need to specify a path name.\n");
1238 return -1;
1239 }
1240
1241 if (pa_scache_add_directory_lazy(c, pname) < 0) {
1242 pa_strbuf_puts(buf, "Failed to load directory.\n");
1243 return -1;
1244 }
1245
1246 return 0;
1247 }
1248
1249 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1250 const char *fname, *sink_name;
1251 pa_sink *sink;
1252
1253 pa_core_assert_ref(c);
1254 pa_assert(t);
1255 pa_assert(buf);
1256 pa_assert(fail);
1257
1258 if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1259 pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
1260 return -1;
1261 }
1262
1263 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1264 pa_strbuf_puts(buf, "No sink by that name.\n");
1265 return -1;
1266 }
1267
1268
1269 return pa_play_file(sink, fname, NULL);
1270 }
1271
1272 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1273 pa_core_assert_ref(c);
1274 pa_assert(t);
1275 pa_assert(buf);
1276 pa_assert(fail);
1277
1278 pa_shared_dump(c, buf);
1279 return 0;
1280 }
1281
1282 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1283 pa_core_assert_ref(c);
1284 pa_assert(t);
1285 pa_assert(buf);
1286 pa_assert(fail);
1287
1288 pa_mempool_vacuum(c->mempool);
1289
1290 return 0;
1291 }
1292
1293 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1294 const char *n, *k;
1295 pa_sink_input *si;
1296 pa_sink *sink;
1297 uint32_t idx;
1298
1299 pa_core_assert_ref(c);
1300 pa_assert(t);
1301 pa_assert(buf);
1302 pa_assert(fail);
1303
1304 if (!(n = pa_tokenizer_get(t, 1))) {
1305 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1306 return -1;
1307 }
1308
1309 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1310 pa_strbuf_puts(buf, "Failed to parse index.\n");
1311 return -1;
1312 }
1313
1314 if (!(k = pa_tokenizer_get(t, 2))) {
1315 pa_strbuf_puts(buf, "You need to specify a sink.\n");
1316 return -1;
1317 }
1318
1319 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
1320 pa_strbuf_puts(buf, "No sink input found with this index.\n");
1321 return -1;
1322 }
1323
1324 if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK))) {
1325 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1326 return -1;
1327 }
1328
1329 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
1330 pa_strbuf_puts(buf, "Moved failed.\n");
1331 return -1;
1332 }
1333 return 0;
1334 }
1335
1336 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1337 const char *n, *k;
1338 pa_source_output *so;
1339 pa_source *source;
1340 uint32_t idx;
1341
1342 pa_core_assert_ref(c);
1343 pa_assert(t);
1344 pa_assert(buf);
1345 pa_assert(fail);
1346
1347 if (!(n = pa_tokenizer_get(t, 1))) {
1348 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1349 return -1;
1350 }
1351
1352 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1353 pa_strbuf_puts(buf, "Failed to parse index.\n");
1354 return -1;
1355 }
1356
1357 if (!(k = pa_tokenizer_get(t, 2))) {
1358 pa_strbuf_puts(buf, "You need to specify a source.\n");
1359 return -1;
1360 }
1361
1362 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1363 pa_strbuf_puts(buf, "No source output found with this index.\n");
1364 return -1;
1365 }
1366
1367 if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE))) {
1368 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1369 return -1;
1370 }
1371
1372 if (pa_source_output_move_to(so, source, TRUE) < 0) {
1373 pa_strbuf_puts(buf, "Moved failed.\n");
1374 return -1;
1375 }
1376 return 0;
1377 }
1378
1379 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1380 const char *n, *m;
1381 pa_sink *sink;
1382 int suspend, r;
1383
1384 pa_core_assert_ref(c);
1385 pa_assert(t);
1386 pa_assert(buf);
1387 pa_assert(fail);
1388
1389 if (!(n = pa_tokenizer_get(t, 1))) {
1390 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1391 return -1;
1392 }
1393
1394 if (!(m = pa_tokenizer_get(t, 2))) {
1395 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1396 return -1;
1397 }
1398
1399 if ((suspend = pa_parse_boolean(m)) < 0) {
1400 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1401 return -1;
1402 }
1403
1404 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1405 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1406 return -1;
1407 }
1408
1409 if ((r = pa_sink_suspend(sink, suspend, PA_SUSPEND_USER)) < 0)
1410 pa_strbuf_printf(buf, "Failed to resume/suspend sink: %s\n", pa_strerror(r));
1411
1412 return 0;
1413 }
1414
1415 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1416 const char *n, *m;
1417 pa_source *source;
1418 int suspend, r;
1419
1420 pa_core_assert_ref(c);
1421 pa_assert(t);
1422 pa_assert(buf);
1423 pa_assert(fail);
1424
1425 if (!(n = pa_tokenizer_get(t, 1))) {
1426 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1427 return -1;
1428 }
1429
1430 if (!(m = pa_tokenizer_get(t, 2))) {
1431 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1432 return -1;
1433 }
1434
1435 if ((suspend = pa_parse_boolean(m)) < 0) {
1436 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1437 return -1;
1438 }
1439
1440 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1441 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1442 return -1;
1443 }
1444
1445 if ((r = pa_source_suspend(source, suspend, PA_SUSPEND_USER)) < 0)
1446 pa_strbuf_printf(buf, "Failed to resume/suspend source: %s\n", pa_strerror(r));
1447
1448 return 0;
1449 }
1450
1451 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1452 const char *m;
1453 int suspend, r;
1454
1455 pa_core_assert_ref(c);
1456 pa_assert(t);
1457 pa_assert(buf);
1458 pa_assert(fail);
1459
1460 if (!(m = pa_tokenizer_get(t, 1))) {
1461 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1462 return -1;
1463 }
1464
1465 if ((suspend = pa_parse_boolean(m)) < 0) {
1466 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1467 return -1;
1468 }
1469
1470 if ((r = pa_sink_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1471 pa_strbuf_printf(buf, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r));
1472
1473 if ((r = pa_source_suspend_all(c, suspend, PA_SUSPEND_USER)) < 0)
1474 pa_strbuf_printf(buf, "Failed to resume/suspend all sources: %s\n", pa_strerror(r));
1475
1476 return 0;
1477 }
1478
1479 static int pa_cli_command_log_target(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1480 const char *m;
1481
1482 pa_core_assert_ref(c);
1483 pa_assert(t);
1484 pa_assert(buf);
1485 pa_assert(fail);
1486
1487 if (!(m = pa_tokenizer_get(t, 1))) {
1488 pa_strbuf_puts(buf, "You need to specify a log target (null,auto,syslog,stderr,file:PATH).\n");
1489 return -1;
1490 }
1491
1492 if (pa_streq(m, "null"))
1493 pa_log_set_target(PA_LOG_NULL);
1494 else if (pa_streq(m, "syslog"))
1495 pa_log_set_target(PA_LOG_SYSLOG);
1496 else if (pa_streq(m, "stderr") || pa_streq(m, "auto")) {
1497 /* 'auto' is actually the effect with 'stderr' */
1498 pa_log_set_target(PA_LOG_STDERR);
1499 } else if (pa_startswith(m, "file:")) {
1500 const char *file_path = m + 5;
1501 int log_fd;
1502
1503 /* Open target file with user rights */
1504 if ((log_fd = open(file_path, O_RDWR|O_TRUNC|O_CREAT, S_IRUSR | S_IWUSR)) >= 0) {
1505 pa_log_set_target(PA_LOG_FD);
1506 pa_log_set_fd(log_fd);
1507 } else {
1508 pa_strbuf_printf(buf, "Failed to open target file %s, error : %s\n", file_path, pa_cstrerror(errno));
1509 return -1;
1510 }
1511 } else {
1512 pa_strbuf_puts(buf, "You need to specify a log target (null,auto,syslog,stderr,file:PATH).\n");
1513 return -1;
1514 }
1515
1516 return 0;
1517 }
1518
1519 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1520 const char *m;
1521 uint32_t level;
1522
1523 pa_core_assert_ref(c);
1524 pa_assert(t);
1525 pa_assert(buf);
1526 pa_assert(fail);
1527
1528 if (!(m = pa_tokenizer_get(t, 1))) {
1529 pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n");
1530 return -1;
1531 }
1532
1533 if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) {
1534 pa_strbuf_puts(buf, "Failed to parse log level.\n");
1535 return -1;
1536 }
1537
1538 pa_log_set_level(level);
1539
1540 return 0;
1541 }
1542
1543 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1544 const char *m;
1545 pa_bool_t b;
1546
1547 pa_core_assert_ref(c);
1548 pa_assert(t);
1549 pa_assert(buf);
1550 pa_assert(fail);
1551
1552 if (!(m = pa_tokenizer_get(t, 1))) {
1553 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1554 return -1;
1555 }
1556
1557 if ((b = pa_parse_boolean(m)) < 0) {
1558 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1559 return -1;
1560 }
1561
1562 pa_log_set_flags(PA_LOG_PRINT_META, b ? PA_LOG_SET : PA_LOG_UNSET);
1563
1564 return 0;
1565 }
1566
1567 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1568 const char *m;
1569 pa_bool_t b;
1570
1571 pa_core_assert_ref(c);
1572 pa_assert(t);
1573 pa_assert(buf);
1574 pa_assert(fail);
1575
1576 if (!(m = pa_tokenizer_get(t, 1))) {
1577 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1578 return -1;
1579 }
1580
1581 if ((b = pa_parse_boolean(m)) < 0) {
1582 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1583 return -1;
1584 }
1585
1586 pa_log_set_flags(PA_LOG_PRINT_TIME, b ? PA_LOG_SET : PA_LOG_UNSET);
1587
1588 return 0;
1589 }
1590
1591 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1592 const char *m;
1593 uint32_t nframes;
1594
1595 pa_core_assert_ref(c);
1596 pa_assert(t);
1597 pa_assert(buf);
1598 pa_assert(fail);
1599
1600 if (!(m = pa_tokenizer_get(t, 1))) {
1601 pa_strbuf_puts(buf, "You need to specify a backtrace level.\n");
1602 return -1;
1603 }
1604
1605 if (pa_atou(m, &nframes) < 0 || nframes >= 1000) {
1606 pa_strbuf_puts(buf, "Failed to parse backtrace level.\n");
1607 return -1;
1608 }
1609
1610 pa_log_set_show_backtrace(nframes);
1611
1612 return 0;
1613 }
1614
1615 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1616 const char *n, *p;
1617 pa_card *card;
1618
1619 pa_core_assert_ref(c);
1620 pa_assert(t);
1621 pa_assert(buf);
1622 pa_assert(fail);
1623
1624 if (!(n = pa_tokenizer_get(t, 1))) {
1625 pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1626 return -1;
1627 }
1628
1629 if (!(p = pa_tokenizer_get(t, 2))) {
1630 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1631 return -1;
1632 }
1633
1634 if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1635 pa_strbuf_puts(buf, "No card found by this name or index.\n");
1636 return -1;
1637 }
1638
1639 if (pa_card_set_profile(card, p, TRUE) < 0) {
1640 pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
1641 return -1;
1642 }
1643
1644 return 0;
1645 }
1646
1647 static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1648 const char *n, *p;
1649 pa_sink *sink;
1650
1651 pa_core_assert_ref(c);
1652 pa_assert(t);
1653 pa_assert(buf);
1654 pa_assert(fail);
1655
1656 if (!(n = pa_tokenizer_get(t, 1))) {
1657 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1658 return -1;
1659 }
1660
1661 if (!(p = pa_tokenizer_get(t, 2))) {
1662 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1663 return -1;
1664 }
1665
1666 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1667 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1668 return -1;
1669 }
1670
1671 if (pa_sink_set_port(sink, p, TRUE) < 0) {
1672 pa_strbuf_printf(buf, "Failed to set sink port to '%s'.\n", p);
1673 return -1;
1674 }
1675
1676 return 0;
1677 }
1678
1679 static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1680 const char *n, *p;
1681 pa_source *source;
1682
1683 pa_core_assert_ref(c);
1684 pa_assert(t);
1685 pa_assert(buf);
1686 pa_assert(fail);
1687
1688 if (!(n = pa_tokenizer_get(t, 1))) {
1689 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1690 return -1;
1691 }
1692
1693 if (!(p = pa_tokenizer_get(t, 2))) {
1694 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1695 return -1;
1696 }
1697
1698 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1699 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1700 return -1;
1701 }
1702
1703 if (pa_source_set_port(source, p, TRUE) < 0) {
1704 pa_strbuf_printf(buf, "Failed to set source port to '%s'.\n", p);
1705 return -1;
1706 }
1707
1708 return 0;
1709 }
1710
1711 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1712 pa_module *m;
1713 pa_sink *sink;
1714 pa_source *source;
1715 pa_card *card;
1716 pa_bool_t nl;
1717 uint32_t idx;
1718 time_t now;
1719 #ifdef HAVE_CTIME_R
1720 char txt[256];
1721 #endif
1722
1723 pa_core_assert_ref(c);
1724 pa_assert(t);
1725 pa_assert(buf);
1726 pa_assert(fail);
1727
1728 time(&now);
1729
1730 #ifdef HAVE_CTIME_R
1731 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
1732 #else
1733 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
1734 #endif
1735
1736 PA_IDXSET_FOREACH(m, c->modules, idx) {
1737
1738 pa_strbuf_printf(buf, "load-module %s", m->name);
1739
1740 if (m->argument)
1741 pa_strbuf_printf(buf, " %s", m->argument);
1742
1743 pa_strbuf_puts(buf, "\n");
1744 }
1745
1746 nl = FALSE;
1747 PA_IDXSET_FOREACH(sink, c->sinks, idx) {
1748
1749 if (!nl) {
1750 pa_strbuf_puts(buf, "\n");
1751 nl = TRUE;
1752 }
1753
1754 pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_max(pa_sink_get_volume(sink, FALSE)));
1755 pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
1756 pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
1757 }
1758
1759 nl = FALSE;
1760 PA_IDXSET_FOREACH(source, c->sources, idx) {
1761
1762 if (!nl) {
1763 pa_strbuf_puts(buf, "\n");
1764 nl = TRUE;
1765 }
1766
1767 pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_max(pa_source_get_volume(source, FALSE)));
1768 pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
1769 pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
1770 }
1771
1772 nl = FALSE;
1773 PA_IDXSET_FOREACH(card, c->cards, idx) {
1774
1775 if (!nl) {
1776 pa_strbuf_puts(buf, "\n");
1777 nl = TRUE;
1778 }
1779
1780 if (card->active_profile)
1781 pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
1782 }
1783
1784 nl = FALSE;
1785 if ((sink = pa_namereg_get_default_sink(c))) {
1786 if (!nl) {
1787 pa_strbuf_puts(buf, "\n");
1788 nl = TRUE;
1789 }
1790
1791 pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
1792 }
1793
1794 if ((source = pa_namereg_get_default_source(c))) {
1795 if (!nl)
1796 pa_strbuf_puts(buf, "\n");
1797
1798 pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
1799 }
1800
1801 pa_strbuf_puts(buf, "\n### EOF\n");
1802
1803 return 0;
1804 }
1805
1806 static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1807 pa_sink *s;
1808 pa_source *so;
1809 pa_sink_input *i;
1810 pa_source_output *o;
1811 uint32_t s_idx, i_idx;
1812 char v_str[PA_CVOLUME_SNPRINT_MAX];
1813
1814 pa_core_assert_ref(c);
1815 pa_assert(t);
1816 pa_assert(buf);
1817 pa_assert(fail);
1818
1819 PA_IDXSET_FOREACH(s, c->sinks, s_idx) {
1820 pa_strbuf_printf(buf, "Sink %d: ", s_idx);
1821 pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->reference_volume));
1822 pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->real_volume));
1823 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->soft_volume));
1824 pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->thread_info.current_hw_volume));
1825 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(s->save_volume));
1826
1827 PA_IDXSET_FOREACH(i, s->inputs, i_idx) {
1828 pa_strbuf_printf(buf, "\tInput %d: ", i_idx);
1829 pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume));
1830 pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->reference_ratio));
1831 pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->real_ratio));
1832 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->soft_volume));
1833 pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor));
1834 pa_strbuf_printf(buf, "volume_factor_sink = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor_sink));
1835 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(i->save_volume));
1836 }
1837 }
1838
1839 PA_IDXSET_FOREACH(so, c->sources, s_idx) {
1840 pa_strbuf_printf(buf, "Source %d: ", s_idx);
1841 pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->reference_volume));
1842 pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->real_volume));
1843 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->soft_volume));
1844 pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->thread_info.current_hw_volume));
1845 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(so->save_volume));
1846
1847 PA_IDXSET_FOREACH(o, so->outputs, i_idx) {
1848 pa_strbuf_printf(buf, "\tOutput %d: ", i_idx);
1849 pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume));
1850 pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->reference_ratio));
1851 pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->real_ratio));
1852 pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->soft_volume));
1853 pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor));
1854 pa_strbuf_printf(buf, "volume_factor_source = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor_source));
1855 pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(o->save_volume));
1856 }
1857 }
1858
1859 return 0;
1860 }
1861
1862 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) {
1863 const char *cs;
1864
1865 pa_assert(c);
1866 pa_assert(s);
1867 pa_assert(buf);
1868
1869 cs = s+strspn(s, whitespace);
1870
1871 if (*cs == '#' || !*cs)
1872 return 0;
1873 else if (*cs == '.') {
1874 if (!strcmp(cs, META_ELSE)) {
1875 if (!ifstate || *ifstate == IFSTATE_NONE) {
1876 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1877 return -1;
1878 } else if (*ifstate == IFSTATE_TRUE)
1879 *ifstate = IFSTATE_FALSE;
1880 else
1881 *ifstate = IFSTATE_TRUE;
1882 return 0;
1883 } else if (!strcmp(cs, META_ENDIF)) {
1884 if (!ifstate || *ifstate == IFSTATE_NONE) {
1885 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1886 return -1;
1887 } else
1888 *ifstate = IFSTATE_NONE;
1889 return 0;
1890 }
1891 if (ifstate && *ifstate == IFSTATE_FALSE)
1892 return 0;
1893 if (!strcmp(cs, META_FAIL))
1894 *fail = TRUE;
1895 else if (!strcmp(cs, META_NOFAIL))
1896 *fail = FALSE;
1897 else {
1898 size_t l;
1899 l = strcspn(cs, whitespace);
1900
1901 if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
1902 struct stat st;
1903 const char *filename = cs+l+strspn(cs+l, whitespace);
1904
1905 if (stat(filename, &st) < 0) {
1906 pa_log_warn("stat('%s'): %s", filename, pa_cstrerror(errno));
1907 if (*fail)
1908 return -1;
1909 } else {
1910 if (S_ISDIR(st.st_mode)) {
1911 DIR *d;
1912
1913 if (!(d = opendir(filename))) {
1914 pa_log_warn("Failed to read '%s': %s", filename, pa_cstrerror(errno));
1915 if (*fail)
1916 return -1;
1917 } else {
1918 unsigned i, count;
1919 char **sorted_files;
1920 struct dirent *de;
1921 pa_bool_t failed = FALSE;
1922 pa_dynarray *files = pa_dynarray_new();
1923
1924 while ((de = readdir(d))) {
1925 char *extn;
1926 size_t flen = strlen(de->d_name);
1927
1928 if (flen < 4)
1929 continue;
1930
1931 extn = &de->d_name[flen-3];
1932 if (strncmp(extn, ".pa", 3) == 0)
1933 pa_dynarray_append(files, pa_sprintf_malloc("%s" PA_PATH_SEP "%s", filename, de->d_name));
1934 }
1935
1936 closedir(d);
1937
1938 count = pa_dynarray_size(files);
1939 sorted_files = pa_xnew(char*, count);
1940 for (i = 0; i < count; ++i)
1941 sorted_files[i] = pa_dynarray_get(files, i);
1942 pa_dynarray_free(files, NULL);
1943
1944 for (i = 0; i < count; ++i) {
1945 for (unsigned j = 0; j < count; ++j) {
1946 if (strcmp(sorted_files[i], sorted_files[j]) < 0) {
1947 char *tmp = sorted_files[i];
1948 sorted_files[i] = sorted_files[j];
1949 sorted_files[j] = tmp;
1950 }
1951 }
1952 }
1953
1954 for (i = 0; i < count; ++i) {
1955 if (!failed) {
1956 if (pa_cli_command_execute_file(c, sorted_files[i], buf, fail) < 0 && *fail)
1957 failed = TRUE;
1958 }
1959
1960 pa_xfree(sorted_files[i]);
1961 }
1962 pa_xfree(sorted_files);
1963 if (failed)
1964 return -1;
1965 }
1966 } else if (pa_cli_command_execute_file(c, filename, buf, fail) < 0 && *fail) {
1967 return -1;
1968 }
1969 }
1970 } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
1971 if (!ifstate) {
1972 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1973 return -1;
1974 } else if (*ifstate != IFSTATE_NONE) {
1975 pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs);
1976 return -1;
1977 } else {
1978 const char *filename = cs+l+strspn(cs+l, whitespace);
1979
1980 /* Search DL_SEARCH_PATH unless the filename is absolute */
1981 if (filename[0] == PA_PATH_SEP_CHAR) {
1982
1983 *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1984 pa_log_debug("Checking for existence of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1985
1986 } else {
1987 const char *paths, *state = NULL;
1988 char *p;
1989
1990 if (!(paths = lt_dlgetsearchpath()))
1991 return -1;
1992
1993 while ((p = pa_split(paths, ":", &state))) {
1994 char *pathname;
1995
1996 pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
1997 pa_xfree(p);
1998
1999 *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
2000 pa_log_debug("Checking for existence of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
2001
2002 pa_xfree(pathname);
2003
2004 if (*ifstate == IFSTATE_TRUE)
2005 break;
2006 }
2007 }
2008
2009 }
2010 } else {
2011 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
2012 if (*fail) return -1;
2013 }
2014 }
2015 } else {
2016 const struct command*command;
2017 int unknown = 1;
2018 size_t l;
2019
2020 if (ifstate && *ifstate == IFSTATE_FALSE)
2021 return 0;
2022
2023 l = strcspn(cs, whitespace);
2024
2025 for (command = commands; command->name; command++)
2026 if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
2027 int ret;
2028 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
2029 pa_assert(t);
2030 ret = command->proc(c, t, buf, fail);
2031 pa_tokenizer_free(t);
2032 unknown = 0;
2033
2034 if (ret < 0 && *fail)
2035 return -1;
2036
2037 break;
2038 }
2039
2040 if (unknown) {
2041 pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
2042 if (*fail)
2043 return -1;
2044 }
2045 }
2046
2047 return 0;
2048 }
2049
2050 int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
2051 return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
2052 }
2053
2054 int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
2055 char line[2048];
2056 int ifstate = IFSTATE_NONE;
2057 int ret = -1;
2058 pa_bool_t _fail = TRUE;
2059
2060 pa_assert(c);
2061 pa_assert(f);
2062 pa_assert(buf);
2063
2064 if (!fail)
2065 fail = &_fail;
2066
2067 while (fgets(line, sizeof(line), f)) {
2068 pa_strip_nl(line);
2069
2070 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
2071 goto fail;
2072 }
2073
2074 ret = 0;
2075
2076 fail:
2077
2078 return ret;
2079 }
2080
2081 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
2082 FILE *f = NULL;
2083 int ret = -1;
2084 pa_bool_t _fail = TRUE;
2085
2086 pa_assert(c);
2087 pa_assert(fn);
2088 pa_assert(buf);
2089
2090 if (!fail)
2091 fail = &_fail;
2092
2093 if (!(f = pa_fopen_cloexec(fn, "r"))) {
2094 pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
2095 if (!*fail)
2096 ret = 0;
2097 goto fail;
2098 }
2099
2100 pa_log_debug("Parsing script '%s'", fn);
2101 ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
2102
2103 fail:
2104 if (f)
2105 fclose(f);
2106
2107 return ret;
2108 }
2109
2110 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
2111 const char *p;
2112 int ifstate = IFSTATE_NONE;
2113 pa_bool_t _fail = TRUE;
2114
2115 pa_assert(c);
2116 pa_assert(s);
2117 pa_assert(buf);
2118
2119 if (!fail)
2120 fail = &_fail;
2121
2122 p = s;
2123 while (*p) {
2124 size_t l = strcspn(p, linebreak);
2125 char *line = pa_xstrndup(p, l);
2126
2127 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) {
2128 pa_xfree(line);
2129 return -1;
2130 }
2131 pa_xfree(line);
2132
2133 p += l;
2134 p += strspn(p, linebreak);
2135 }
2136
2137 return 0;
2138 }