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