]> code.delx.au - pulseaudio/blob - src/pulsecore/cli-command.c
Merge commit 'coling/lgpl21'
[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
34 #include <pulse/xmalloc.h>
35
36 #include <pulsecore/module.h>
37 #include <pulsecore/sink.h>
38 #include <pulsecore/source.h>
39 #include <pulsecore/client.h>
40 #include <pulsecore/sink-input.h>
41 #include <pulsecore/source-output.h>
42 #include <pulsecore/tokenizer.h>
43 #include <pulsecore/strbuf.h>
44 #include <pulsecore/namereg.h>
45 #include <pulsecore/cli-text.h>
46 #include <pulsecore/core-scache.h>
47 #include <pulsecore/sample-util.h>
48 #include <pulsecore/sound-file.h>
49 #include <pulsecore/play-memchunk.h>
50 #include <pulsecore/sound-file-stream.h>
51 #include <pulsecore/shared.h>
52 #include <pulsecore/core-util.h>
53 #include <pulsecore/core-error.h>
54 #include <pulsecore/modinfo.h>
55
56 #include "cli-command.h"
57
58 struct command {
59 const char *name;
60 int (*proc) (pa_core *c, pa_tokenizer*t, pa_strbuf *buf, pa_bool_t *fail);
61 const char *help;
62 unsigned args;
63 };
64
65 #define META_INCLUDE ".include"
66 #define META_FAIL ".fail"
67 #define META_NOFAIL ".nofail"
68 #define META_IFEXISTS ".ifexists"
69 #define META_ELSE ".else"
70 #define META_ENDIF ".endif"
71
72 enum {
73 IFSTATE_NONE = -1,
74 IFSTATE_FALSE = 0,
75 IFSTATE_TRUE = 1,
76 };
77
78 /* Prototypes for all available commands */
79 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
80 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
81 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
82 static int pa_cli_command_clients(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
83 static int pa_cli_command_cards(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
84 static int pa_cli_command_sinks(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
85 static int pa_cli_command_sources(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
86 static int pa_cli_command_sink_inputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
87 static int pa_cli_command_source_outputs(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
88 static int pa_cli_command_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
89 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
90 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
91 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
92 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
93 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
94 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
95 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
96 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
97 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
98 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
99 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
100 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
101 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
102 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
103 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
104 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
105 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
106 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
107 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
108 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
109 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
110 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
111 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
112 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
113 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
114 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
115 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
116 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
117 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
118 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
119 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
120 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
121 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
122 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
123 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
124 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
125 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
126 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
127
128 /* A method table for all available commands */
129
130 static const struct command commands[] = {
131 { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
132 { "help", pa_cli_command_help, "Show this help", 1 },
133 { "list-modules", pa_cli_command_modules, "List loaded modules", 1 },
134 { "list-sinks", pa_cli_command_sinks, "List loaded sinks", 1 },
135 { "list-sources", pa_cli_command_sources, "List loaded sources", 1 },
136 { "list-clients", pa_cli_command_clients, "List loaded clients", 1 },
137 { "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 },
138 { "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 },
139 { "list-cards", pa_cli_command_cards, "List cards", 1 },
140 { "stat", pa_cli_command_stat, "Show memory block statistics", 1 },
141 { "info", pa_cli_command_info, "Show comprehensive status", 1 },
142 { "ls", pa_cli_command_info, NULL, 1 },
143 { "list", pa_cli_command_info, NULL, 1 },
144 { "load-module", pa_cli_command_load, "Load a module (args: name, arguments)", 3},
145 { "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2},
146 { "describe-module", pa_cli_command_describe, "Describe a module (arg: name)", 2},
147 { "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3},
148 { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3},
149 { "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3},
150 { "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, bool)", 3},
151 { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3},
152 { "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, bool)", 3},
153 { "update-sink-proplist", pa_cli_command_update_sink_proplist, "Update the properties of a sink (args: index|name, properties)", 3},
154 { "update-source-proplist", pa_cli_command_update_source_proplist, "Update the properties of a source (args: index|name, properties)", 3},
155 { "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist, "Update the properties of a sink input (args: index, properties)", 3},
156 { "update-source-output-proplist", pa_cli_command_update_source_output_proplist, "Update the properties of a source_output (args: index, properties)", 3},
157 { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2},
158 { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2},
159 { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
160 { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
161 { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
162 { "list-samples", pa_cli_command_scache_list, "List all entries in the sample cache", 1},
163 { "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3},
164 { "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2},
165 { "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3},
166 { "load-sample-lazy", pa_cli_command_scache_load, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
167 { "load-sample-dir-lazy", pa_cli_command_scache_load_dir, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
168 { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3},
169 { "dump", pa_cli_command_dump, "Dump daemon configuration", 1},
170 { "shared", pa_cli_command_list_shared_props, NULL, 1},
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 { "vacuum", pa_cli_command_vacuum, NULL, 1},
174 { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3},
175 { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3},
176 { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2},
177 { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (aargs: index, name)", 3},
178 { "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2},
179 { "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2},
180 { "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2},
181 { "set-log-backtrace", pa_cli_command_log_backtrace, "Show bakctrace in log messages (args: frames)", 2},
182 { NULL, NULL, NULL, 0 }
183 };
184
185 static const char whitespace[] = " \t\n\r";
186 static const char linebreak[] = "\n\r";
187
188 static uint32_t parse_index(const char *n) {
189 uint32_t idx;
190
191 if (pa_atou(n, &idx) < 0)
192 return (uint32_t) PA_IDXSET_INVALID;
193
194 return idx;
195 }
196
197 static int pa_cli_command_exit(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
198 pa_core_assert_ref(c);
199 pa_assert(t);
200 pa_assert(buf);
201 pa_assert(fail);
202
203 if (pa_core_exit(c, FALSE, 0) < 0)
204 pa_strbuf_puts(buf, "Not allowed to terminate daemon.\n");
205
206 return 0;
207 }
208
209 static int pa_cli_command_help(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
210 const struct command*command;
211
212 pa_core_assert_ref(c);
213 pa_assert(t);
214 pa_assert(buf);
215 pa_assert(fail);
216
217 pa_strbuf_puts(buf, "Available commands:\n");
218
219 for (command = commands; command->name; command++)
220 if (command->help)
221 pa_strbuf_printf(buf, " %-25s %s\n", command->name, command->help);
222 return 0;
223 }
224
225 static int pa_cli_command_modules(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
226 char *s;
227
228 pa_core_assert_ref(c);
229 pa_assert(t);
230 pa_assert(buf);
231 pa_assert(fail);
232
233 pa_assert_se(s = pa_module_list_to_string(c));
234 pa_strbuf_puts(buf, s);
235 pa_xfree(s);
236 return 0;
237 }
238
239 static int pa_cli_command_clients(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_client_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_cards(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_card_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_sinks(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_sink_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_sources(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_source_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_sink_inputs(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_sink_input_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_source_outputs(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_source_output_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_stat(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
324 char ss[PA_SAMPLE_SPEC_SNPRINT_MAX];
325 char cm[PA_CHANNEL_MAP_SNPRINT_MAX];
326 char s[256];
327 const pa_mempool_stat *stat;
328 unsigned k;
329 pa_sink *def_sink;
330 pa_source *def_source;
331
332 static const char* const type_table[PA_MEMBLOCK_TYPE_MAX] = {
333 [PA_MEMBLOCK_POOL] = "POOL",
334 [PA_MEMBLOCK_POOL_EXTERNAL] = "POOL_EXTERNAL",
335 [PA_MEMBLOCK_APPENDED] = "APPENDED",
336 [PA_MEMBLOCK_USER] = "USER",
337 [PA_MEMBLOCK_FIXED] = "FIXED",
338 [PA_MEMBLOCK_IMPORTED] = "IMPORTED",
339 };
340
341 pa_core_assert_ref(c);
342 pa_assert(t);
343 pa_assert(buf);
344 pa_assert(fail);
345
346 stat = pa_mempool_get_stat(c->mempool);
347
348 pa_strbuf_printf(buf, "Memory blocks currently allocated: %u, size: %s.\n",
349 (unsigned) pa_atomic_load(&stat->n_allocated),
350 pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->allocated_size)));
351
352 pa_strbuf_printf(buf, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
353 (unsigned) pa_atomic_load(&stat->n_accumulated),
354 pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->accumulated_size)));
355
356 pa_strbuf_printf(buf, "Memory blocks imported from other processes: %u, size: %s.\n",
357 (unsigned) pa_atomic_load(&stat->n_imported),
358 pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->imported_size)));
359
360 pa_strbuf_printf(buf, "Memory blocks exported to other processes: %u, size: %s.\n",
361 (unsigned) pa_atomic_load(&stat->n_exported),
362 pa_bytes_snprint(s, sizeof(s), (unsigned) pa_atomic_load(&stat->exported_size)));
363
364 pa_strbuf_printf(buf, "Total sample cache size: %s.\n",
365 pa_bytes_snprint(s, sizeof(s), (unsigned) pa_scache_total_size(c)));
366
367 pa_strbuf_printf(buf, "Default sample spec: %s\n",
368 pa_sample_spec_snprint(ss, sizeof(ss), &c->default_sample_spec));
369
370 pa_strbuf_printf(buf, "Default channel map: %s\n",
371 pa_channel_map_snprint(cm, sizeof(cm), &c->default_channel_map));
372
373 def_sink = pa_namereg_get_default_sink(c);
374 def_source = pa_namereg_get_default_source(c);
375 pa_strbuf_printf(buf, "Default sink name: %s\n"
376 "Default source name: %s\n",
377 def_sink ? def_sink->name : "none",
378 def_source ? def_source->name : "none");
379
380 for (k = 0; k < PA_MEMBLOCK_TYPE_MAX; k++)
381 pa_strbuf_printf(buf,
382 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
383 type_table[k],
384 (unsigned) pa_atomic_load(&stat->n_allocated_by_type[k]),
385 (unsigned) pa_atomic_load(&stat->n_accumulated_by_type[k]));
386
387 return 0;
388 }
389
390 static int pa_cli_command_info(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
391 pa_core_assert_ref(c);
392 pa_assert(t);
393 pa_assert(buf);
394 pa_assert(fail);
395
396 pa_cli_command_stat(c, t, buf, fail);
397 pa_cli_command_modules(c, t, buf, fail);
398 pa_cli_command_sinks(c, t, buf, fail);
399 pa_cli_command_sources(c, t, buf, fail);
400 pa_cli_command_clients(c, t, buf, fail);
401 pa_cli_command_cards(c, t, buf, fail);
402 pa_cli_command_sink_inputs(c, t, buf, fail);
403 pa_cli_command_source_outputs(c, t, buf, fail);
404 pa_cli_command_scache_list(c, t, buf, fail);
405 return 0;
406 }
407
408 static int pa_cli_command_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
409 const char *name;
410
411 pa_core_assert_ref(c);
412 pa_assert(t);
413 pa_assert(buf);
414 pa_assert(fail);
415
416 if (!(name = pa_tokenizer_get(t, 1))) {
417 pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
418 return -1;
419 }
420
421 if (!pa_module_load(c, name, pa_tokenizer_get(t, 2))) {
422 pa_strbuf_puts(buf, "Module load failed.\n");
423 return -1;
424 }
425
426 return 0;
427 }
428
429 static int pa_cli_command_unload(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
430 pa_module *m;
431 uint32_t idx;
432 const char *i;
433 char *e;
434
435 pa_core_assert_ref(c);
436 pa_assert(t);
437 pa_assert(buf);
438 pa_assert(fail);
439
440 if (!(i = pa_tokenizer_get(t, 1))) {
441 pa_strbuf_puts(buf, "You need to specify the module index.\n");
442 return -1;
443 }
444
445 idx = (uint32_t) strtoul(i, &e, 10);
446 if (*e || !(m = pa_idxset_get_by_index(c->modules, idx))) {
447 pa_strbuf_puts(buf, "Invalid module index.\n");
448 return -1;
449 }
450
451 pa_module_unload_request(m, FALSE);
452 return 0;
453 }
454
455 static int pa_cli_command_describe(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
456 const char *name;
457 pa_modinfo *i;
458
459 pa_core_assert_ref(c);
460 pa_assert(t);
461 pa_assert(buf);
462 pa_assert(fail);
463
464 if (!(name = pa_tokenizer_get(t, 1))) {
465 pa_strbuf_puts(buf, "You need to specify the module name.\n");
466 return -1;
467 }
468
469 if ((i = pa_modinfo_get_by_name(name))) {
470
471 pa_strbuf_printf(buf, "Name: %s\n", name);
472
473 if (!i->description && !i->version && !i->author && !i->usage)
474 pa_strbuf_printf(buf, "No module information available\n");
475 else {
476 if (i->version)
477 pa_strbuf_printf(buf, "Version: %s\n", i->version);
478 if (i->description)
479 pa_strbuf_printf(buf, "Description: %s\n", i->description);
480 if (i->author)
481 pa_strbuf_printf(buf, "Author: %s\n", i->author);
482 if (i->usage)
483 pa_strbuf_printf(buf, "Usage: %s\n", i->usage);
484 pa_strbuf_printf(buf, "Load Once: %s\n", pa_yes_no(i->load_once));
485 }
486
487 pa_modinfo_free(i);
488 } else
489 pa_strbuf_puts(buf, "Failed to open module.\n");
490
491 return 0;
492 }
493
494 static int pa_cli_command_sink_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
495 const char *n, *v;
496 pa_sink *sink;
497 uint32_t volume;
498 pa_cvolume cvolume;
499
500 pa_core_assert_ref(c);
501 pa_assert(t);
502 pa_assert(buf);
503 pa_assert(fail);
504
505 if (!(n = pa_tokenizer_get(t, 1))) {
506 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
507 return -1;
508 }
509
510 if (!(v = pa_tokenizer_get(t, 2))) {
511 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
512 return -1;
513 }
514
515 if (pa_atou(v, &volume) < 0) {
516 pa_strbuf_puts(buf, "Failed to parse volume.\n");
517 return -1;
518 }
519
520 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
521 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
522 return -1;
523 }
524
525 pa_cvolume_set(&cvolume, sink->sample_spec.channels, volume);
526 pa_sink_set_volume(sink, &cvolume, TRUE, TRUE);
527 return 0;
528 }
529
530 static int pa_cli_command_sink_input_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
531 const char *n, *v;
532 pa_sink_input *si;
533 pa_volume_t volume;
534 pa_cvolume cvolume;
535 uint32_t idx;
536
537 pa_core_assert_ref(c);
538 pa_assert(t);
539 pa_assert(buf);
540 pa_assert(fail);
541
542 if (!(n = pa_tokenizer_get(t, 1))) {
543 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
544 return -1;
545 }
546
547 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
548 pa_strbuf_puts(buf, "Failed to parse index.\n");
549 return -1;
550 }
551
552 if (!(v = pa_tokenizer_get(t, 2))) {
553 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
554 return -1;
555 }
556
557 if (pa_atou(v, &volume) < 0) {
558 pa_strbuf_puts(buf, "Failed to parse volume.\n");
559 return -1;
560 }
561
562 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
563 pa_strbuf_puts(buf, "No sink input found with this index.\n");
564 return -1;
565 }
566
567 pa_cvolume_set(&cvolume, si->sample_spec.channels, volume);
568 pa_sink_input_set_volume(si, &cvolume, TRUE);
569 return 0;
570 }
571
572 static int pa_cli_command_source_volume(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
573 const char *n, *v;
574 pa_source *source;
575 uint32_t volume;
576 pa_cvolume cvolume;
577
578 pa_core_assert_ref(c);
579 pa_assert(t);
580 pa_assert(buf);
581 pa_assert(fail);
582
583 if (!(n = pa_tokenizer_get(t, 1))) {
584 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
585 return -1;
586 }
587
588 if (!(v = pa_tokenizer_get(t, 2))) {
589 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
590 return -1;
591 }
592
593 if (pa_atou(v, &volume) < 0) {
594 pa_strbuf_puts(buf, "Failed to parse volume.\n");
595 return -1;
596 }
597
598 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
599 pa_strbuf_puts(buf, "No source found by this name or index.\n");
600 return -1;
601 }
602
603 pa_cvolume_set(&cvolume, source->sample_spec.channels, volume);
604 pa_source_set_volume(source, &cvolume);
605 return 0;
606 }
607
608 static int pa_cli_command_sink_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
609 const char *n, *m;
610 pa_sink *sink;
611 int mute;
612
613 pa_core_assert_ref(c);
614 pa_assert(t);
615 pa_assert(buf);
616 pa_assert(fail);
617
618 if (!(n = pa_tokenizer_get(t, 1))) {
619 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
620 return -1;
621 }
622
623 if (!(m = pa_tokenizer_get(t, 2))) {
624 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
625 return -1;
626 }
627
628 if ((mute = pa_parse_boolean(m)) < 0) {
629 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
630 return -1;
631 }
632
633 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
634 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
635 return -1;
636 }
637
638 pa_sink_set_mute(sink, mute);
639 return 0;
640 }
641
642 static int pa_cli_command_source_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
643 const char *n, *m;
644 pa_source *source;
645 int mute;
646
647 pa_core_assert_ref(c);
648 pa_assert(t);
649 pa_assert(buf);
650 pa_assert(fail);
651
652 if (!(n = pa_tokenizer_get(t, 1))) {
653 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
654 return -1;
655 }
656
657 if (!(m = pa_tokenizer_get(t, 2))) {
658 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
659 return -1;
660 }
661
662 if ((mute = pa_parse_boolean(m)) < 0) {
663 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
664 return -1;
665 }
666
667 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
668 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
669 return -1;
670 }
671
672 pa_source_set_mute(source, mute);
673 return 0;
674 }
675
676 static int pa_cli_command_update_sink_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
677 const char *n, *s;
678 pa_sink *sink;
679 pa_proplist *p;
680
681 pa_core_assert_ref(c);
682 pa_assert(t);
683 pa_assert(buf);
684 pa_assert(fail);
685
686 if (!(n = pa_tokenizer_get(t, 1))) {
687 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
688 return -1;
689 }
690
691 if (!(s = pa_tokenizer_get(t, 2))) {
692 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
693 return -1;
694 }
695
696 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
697 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
698 return -1;
699 }
700
701 p = pa_proplist_from_string(s);
702
703 pa_sink_update_proplist(sink, PA_UPDATE_REPLACE, p);
704
705 pa_proplist_free(p);
706
707 return 0;
708 }
709
710 static int pa_cli_command_update_source_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
711 const char *n, *s;
712 pa_source *source;
713 pa_proplist *p;
714
715 pa_core_assert_ref(c);
716 pa_assert(t);
717 pa_assert(buf);
718 pa_assert(fail);
719
720 if (!(n = pa_tokenizer_get(t, 1))) {
721 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
722 return -1;
723 }
724
725 if (!(s = pa_tokenizer_get(t, 2))) {
726 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
727 return -1;
728 }
729
730 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
731 pa_strbuf_puts(buf, "No source found by this name or index.\n");
732 return -1;
733 }
734
735 p = pa_proplist_from_string(s);
736
737 pa_source_update_proplist(source, PA_UPDATE_REPLACE, p);
738
739 pa_proplist_free(p);
740
741 return 0;
742 }
743
744 static int pa_cli_command_update_sink_input_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
745 const char *n, *s;
746 pa_sink_input *si;
747 uint32_t idx;
748 pa_proplist *p;
749
750 pa_core_assert_ref(c);
751 pa_assert(t);
752 pa_assert(buf);
753 pa_assert(fail);
754
755 if (!(n = pa_tokenizer_get(t, 1))) {
756 pa_strbuf_puts(buf, "You need to specify a sink input either by index.\n");
757 return -1;
758 }
759
760 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
761 pa_strbuf_puts(buf, "Failed to parse index.\n");
762 return -1;
763 }
764
765 if (!(s = pa_tokenizer_get(t, 2))) {
766 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
767 return -1;
768 }
769
770 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
771 pa_strbuf_puts(buf, "No sink input found with this index.\n");
772 return -1;
773 }
774
775 p = pa_proplist_from_string(s);
776
777 pa_sink_input_update_proplist(si, PA_UPDATE_REPLACE, p);
778
779 pa_proplist_free(p);
780
781 return 0;
782 }
783
784 static int pa_cli_command_update_source_output_proplist(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
785 const char *n, *s;
786 pa_source_output *so;
787 uint32_t idx;
788 pa_proplist *p;
789
790 pa_core_assert_ref(c);
791 pa_assert(t);
792 pa_assert(buf);
793 pa_assert(fail);
794
795 if (!(n = pa_tokenizer_get(t, 1))) {
796 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
797 return -1;
798 }
799
800 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
801 pa_strbuf_puts(buf, "Failed to parse index.\n");
802 return -1;
803 }
804
805 if (!(s = pa_tokenizer_get(t, 2))) {
806 pa_strbuf_puts(buf, "You need to specify a \"key=value\" argument.\n");
807 return -1;
808 }
809
810 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
811 pa_strbuf_puts(buf, "No source output found with this index.\n");
812 return -1;
813 }
814
815 p = pa_proplist_from_string(s);
816
817 pa_source_output_update_proplist(so, PA_UPDATE_REPLACE, p);
818
819 pa_proplist_free(p);
820
821 return 0;
822 }
823
824 static int pa_cli_command_sink_input_mute(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
825 const char *n, *v;
826 pa_sink_input *si;
827 uint32_t idx;
828 int mute;
829
830 pa_core_assert_ref(c);
831 pa_assert(t);
832 pa_assert(buf);
833 pa_assert(fail);
834
835 if (!(n = pa_tokenizer_get(t, 1))) {
836 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
837 return -1;
838 }
839
840 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
841 pa_strbuf_puts(buf, "Failed to parse index.\n");
842 return -1;
843 }
844
845 if (!(v = pa_tokenizer_get(t, 2))) {
846 pa_strbuf_puts(buf, "You need to specify a mute switch setting (0/1).\n");
847 return -1;
848 }
849
850 if ((mute = pa_parse_boolean(v)) < 0) {
851 pa_strbuf_puts(buf, "Failed to parse mute switch.\n");
852 return -1;
853 }
854
855 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
856 pa_strbuf_puts(buf, "No sink input found with this index.\n");
857 return -1;
858 }
859
860 pa_sink_input_set_mute(si, mute, TRUE);
861 return 0;
862 }
863
864 static int pa_cli_command_sink_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
865 const char *n;
866 pa_sink *s;
867
868 pa_core_assert_ref(c);
869 pa_assert(t);
870 pa_assert(buf);
871 pa_assert(fail);
872
873 if (!(n = pa_tokenizer_get(t, 1))) {
874 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
875 return -1;
876 }
877
878 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SINK)))
879 pa_namereg_set_default_sink(c, s);
880 else
881 pa_strbuf_printf(buf, "Sink %s does not exist.\n", n);
882
883 return 0;
884 }
885
886 static int pa_cli_command_source_default(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
887 const char *n;
888 pa_source *s;
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 either by its name or its index.\n");
897 return -1;
898 }
899
900 if ((s = pa_namereg_get(c, n, PA_NAMEREG_SOURCE)))
901 pa_namereg_set_default_source(c, s);
902 else
903 pa_strbuf_printf(buf, "Source %s does not exist.\n", n);
904 return 0;
905 }
906
907 static int pa_cli_command_kill_client(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
908 const char *n;
909 pa_client *client;
910 uint32_t idx;
911
912 pa_core_assert_ref(c);
913 pa_assert(t);
914 pa_assert(buf);
915 pa_assert(fail);
916
917 if (!(n = pa_tokenizer_get(t, 1))) {
918 pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
919 return -1;
920 }
921
922 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
923 pa_strbuf_puts(buf, "Failed to parse index.\n");
924 return -1;
925 }
926
927 if (!(client = pa_idxset_get_by_index(c->clients, idx))) {
928 pa_strbuf_puts(buf, "No client found by this index.\n");
929 return -1;
930 }
931
932 pa_client_kill(client);
933 return 0;
934 }
935
936 static int pa_cli_command_kill_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
937 const char *n;
938 pa_sink_input *sink_input;
939 uint32_t idx;
940
941 pa_core_assert_ref(c);
942 pa_assert(t);
943 pa_assert(buf);
944 pa_assert(fail);
945
946 if (!(n = pa_tokenizer_get(t, 1))) {
947 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
948 return -1;
949 }
950
951 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
952 pa_strbuf_puts(buf, "Failed to parse index.\n");
953 return -1;
954 }
955
956 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, idx))) {
957 pa_strbuf_puts(buf, "No sink input found by this index.\n");
958 return -1;
959 }
960
961 pa_sink_input_kill(sink_input);
962 return 0;
963 }
964
965 static int pa_cli_command_kill_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
966 const char *n;
967 pa_source_output *source_output;
968 uint32_t idx;
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 (!(source_output = pa_idxset_get_by_index(c->source_outputs, idx))) {
986 pa_strbuf_puts(buf, "No source output found by this index.\n");
987 return -1;
988 }
989
990 pa_source_output_kill(source_output);
991 return 0;
992 }
993
994 static int pa_cli_command_scache_list(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
995 char *s;
996
997 pa_core_assert_ref(c);
998 pa_assert(t);
999 pa_assert(buf);
1000 pa_assert(fail);
1001
1002 pa_assert_se(s = pa_scache_list_to_string(c));
1003 pa_strbuf_puts(buf, s);
1004 pa_xfree(s);
1005
1006 return 0;
1007 }
1008
1009 static int pa_cli_command_scache_play(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1010 const char *n, *sink_name;
1011 pa_sink *sink;
1012 uint32_t idx;
1013
1014 pa_core_assert_ref(c);
1015 pa_assert(t);
1016 pa_assert(buf);
1017 pa_assert(fail);
1018
1019 if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1020 pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
1021 return -1;
1022 }
1023
1024 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1025 pa_strbuf_puts(buf, "No sink by that name.\n");
1026 return -1;
1027 }
1028
1029 if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM, NULL, &idx) < 0) {
1030 pa_strbuf_puts(buf, "Failed to play sample.\n");
1031 return -1;
1032 }
1033
1034 pa_strbuf_printf(buf, "Playing on sink input #%i\n", idx);
1035
1036 return 0;
1037 }
1038
1039 static int pa_cli_command_scache_remove(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1040 const char *n;
1041
1042 pa_core_assert_ref(c);
1043 pa_assert(t);
1044 pa_assert(buf);
1045 pa_assert(fail);
1046
1047 if (!(n = pa_tokenizer_get(t, 1))) {
1048 pa_strbuf_puts(buf, "You need to specify a sample name.\n");
1049 return -1;
1050 }
1051
1052 if (pa_scache_remove_item(c, n) < 0) {
1053 pa_strbuf_puts(buf, "Failed to remove sample.\n");
1054 return -1;
1055 }
1056
1057 return 0;
1058 }
1059
1060 static int pa_cli_command_scache_load(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1061 const char *fname, *n;
1062 int r;
1063
1064 pa_core_assert_ref(c);
1065 pa_assert(t);
1066 pa_assert(buf);
1067 pa_assert(fail);
1068
1069 if (!(fname = pa_tokenizer_get(t, 2)) || !(n = pa_tokenizer_get(t, 1))) {
1070 pa_strbuf_puts(buf, "You need to specify a file name and a sample name.\n");
1071 return -1;
1072 }
1073
1074 if (strstr(pa_tokenizer_get(t, 0), "lazy"))
1075 r = pa_scache_add_file_lazy(c, n, fname, NULL);
1076 else
1077 r = pa_scache_add_file(c, n, fname, NULL);
1078
1079 if (r < 0)
1080 pa_strbuf_puts(buf, "Failed to load sound file.\n");
1081
1082 return 0;
1083 }
1084
1085 static int pa_cli_command_scache_load_dir(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1086 const char *pname;
1087
1088 pa_core_assert_ref(c);
1089 pa_assert(t);
1090 pa_assert(buf);
1091 pa_assert(fail);
1092
1093 if (!(pname = pa_tokenizer_get(t, 1))) {
1094 pa_strbuf_puts(buf, "You need to specify a path name.\n");
1095 return -1;
1096 }
1097
1098 if (pa_scache_add_directory_lazy(c, pname) < 0) {
1099 pa_strbuf_puts(buf, "Failed to load directory.\n");
1100 return -1;
1101 }
1102
1103 return 0;
1104 }
1105
1106 static int pa_cli_command_play_file(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1107 const char *fname, *sink_name;
1108 pa_sink *sink;
1109
1110 pa_core_assert_ref(c);
1111 pa_assert(t);
1112 pa_assert(buf);
1113 pa_assert(fail);
1114
1115 if (!(fname = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
1116 pa_strbuf_puts(buf, "You need to specify a file name and a sink name.\n");
1117 return -1;
1118 }
1119
1120 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
1121 pa_strbuf_puts(buf, "No sink by that name.\n");
1122 return -1;
1123 }
1124
1125
1126 return pa_play_file(sink, fname, NULL);
1127 }
1128
1129 static int pa_cli_command_list_shared_props(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1130 pa_core_assert_ref(c);
1131 pa_assert(t);
1132 pa_assert(buf);
1133 pa_assert(fail);
1134
1135 pa_shared_dump(c, buf);
1136 return 0;
1137 }
1138
1139 static int pa_cli_command_vacuum(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1140 pa_core_assert_ref(c);
1141 pa_assert(t);
1142 pa_assert(buf);
1143 pa_assert(fail);
1144
1145 pa_mempool_vacuum(c->mempool);
1146
1147 return 0;
1148 }
1149
1150 static int pa_cli_command_move_sink_input(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1151 const char *n, *k;
1152 pa_sink_input *si;
1153 pa_sink *sink;
1154 uint32_t idx;
1155
1156 pa_core_assert_ref(c);
1157 pa_assert(t);
1158 pa_assert(buf);
1159 pa_assert(fail);
1160
1161 if (!(n = pa_tokenizer_get(t, 1))) {
1162 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
1163 return -1;
1164 }
1165
1166 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1167 pa_strbuf_puts(buf, "Failed to parse index.\n");
1168 return -1;
1169 }
1170
1171 if (!(k = pa_tokenizer_get(t, 2))) {
1172 pa_strbuf_puts(buf, "You need to specify a sink.\n");
1173 return -1;
1174 }
1175
1176 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
1177 pa_strbuf_puts(buf, "No sink input found with this index.\n");
1178 return -1;
1179 }
1180
1181 if (!(sink = pa_namereg_get(c, k, PA_NAMEREG_SINK))) {
1182 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1183 return -1;
1184 }
1185
1186 if (pa_sink_input_move_to(si, sink, TRUE) < 0) {
1187 pa_strbuf_puts(buf, "Moved failed.\n");
1188 return -1;
1189 }
1190 return 0;
1191 }
1192
1193 static int pa_cli_command_move_source_output(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1194 const char *n, *k;
1195 pa_source_output *so;
1196 pa_source *source;
1197 uint32_t idx;
1198
1199 pa_core_assert_ref(c);
1200 pa_assert(t);
1201 pa_assert(buf);
1202 pa_assert(fail);
1203
1204 if (!(n = pa_tokenizer_get(t, 1))) {
1205 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
1206 return -1;
1207 }
1208
1209 if ((idx = parse_index(n)) == PA_IDXSET_INVALID) {
1210 pa_strbuf_puts(buf, "Failed to parse index.\n");
1211 return -1;
1212 }
1213
1214 if (!(k = pa_tokenizer_get(t, 2))) {
1215 pa_strbuf_puts(buf, "You need to specify a source.\n");
1216 return -1;
1217 }
1218
1219 if (!(so = pa_idxset_get_by_index(c->source_outputs, (uint32_t) idx))) {
1220 pa_strbuf_puts(buf, "No source output found with this index.\n");
1221 return -1;
1222 }
1223
1224 if (!(source = pa_namereg_get(c, k, PA_NAMEREG_SOURCE))) {
1225 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1226 return -1;
1227 }
1228
1229 if (pa_source_output_move_to(so, source, TRUE) < 0) {
1230 pa_strbuf_puts(buf, "Moved failed.\n");
1231 return -1;
1232 }
1233 return 0;
1234 }
1235
1236 static int pa_cli_command_suspend_sink(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1237 const char *n, *m;
1238 pa_sink *sink;
1239 int suspend;
1240
1241 pa_core_assert_ref(c);
1242 pa_assert(t);
1243 pa_assert(buf);
1244 pa_assert(fail);
1245
1246 if (!(n = pa_tokenizer_get(t, 1))) {
1247 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
1248 return -1;
1249 }
1250
1251 if (!(m = pa_tokenizer_get(t, 2))) {
1252 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1253 return -1;
1254 }
1255
1256 if ((suspend = pa_parse_boolean(m)) < 0) {
1257 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1258 return -1;
1259 }
1260
1261 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
1262 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
1263 return -1;
1264 }
1265
1266 pa_sink_suspend(sink, suspend);
1267 return 0;
1268 }
1269
1270 static int pa_cli_command_suspend_source(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1271 const char *n, *m;
1272 pa_source *source;
1273 int suspend;
1274
1275 pa_core_assert_ref(c);
1276 pa_assert(t);
1277 pa_assert(buf);
1278 pa_assert(fail);
1279
1280 if (!(n = pa_tokenizer_get(t, 1))) {
1281 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
1282 return -1;
1283 }
1284
1285 if (!(m = pa_tokenizer_get(t, 2))) {
1286 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1287 return -1;
1288 }
1289
1290 if ((suspend = pa_parse_boolean(m)) < 0) {
1291 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1292 return -1;
1293 }
1294
1295 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
1296 pa_strbuf_puts(buf, "No source found by this name or index.\n");
1297 return -1;
1298 }
1299
1300 pa_source_suspend(source, suspend);
1301 return 0;
1302 }
1303
1304 static int pa_cli_command_suspend(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1305 const char *m;
1306 int suspend;
1307 int ret;
1308
1309 pa_core_assert_ref(c);
1310 pa_assert(t);
1311 pa_assert(buf);
1312 pa_assert(fail);
1313
1314 if (!(m = pa_tokenizer_get(t, 1))) {
1315 pa_strbuf_puts(buf, "You need to specify a suspend switch setting (0/1).\n");
1316 return -1;
1317 }
1318
1319 if ((suspend = pa_parse_boolean(m)) < 0) {
1320 pa_strbuf_puts(buf, "Failed to parse suspend switch.\n");
1321 return -1;
1322 }
1323
1324 ret = - (pa_sink_suspend_all(c, suspend) < 0);
1325 if (pa_source_suspend_all(c, suspend) < 0)
1326 ret = -1;
1327
1328 if (ret < 0)
1329 pa_strbuf_puts(buf, "Failed to resume/suspend all sinks/sources.\n");
1330
1331 return 0;
1332 }
1333
1334 static int pa_cli_command_log_level(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1335 const char *m;
1336 uint32_t level;
1337
1338 pa_core_assert_ref(c);
1339 pa_assert(t);
1340 pa_assert(buf);
1341 pa_assert(fail);
1342
1343 if (!(m = pa_tokenizer_get(t, 1))) {
1344 pa_strbuf_puts(buf, "You need to specify a log level (0..4).\n");
1345 return -1;
1346 }
1347
1348 if (pa_atou(m, &level) < 0 || level >= PA_LOG_LEVEL_MAX) {
1349 pa_strbuf_puts(buf, "Failed to parse log level.\n");
1350 return -1;
1351 }
1352
1353 pa_log_set_level(level);
1354
1355 return 0;
1356 }
1357
1358 static int pa_cli_command_log_meta(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1359 const char *m;
1360 pa_bool_t b;
1361
1362 pa_core_assert_ref(c);
1363 pa_assert(t);
1364 pa_assert(buf);
1365 pa_assert(fail);
1366
1367 if (!(m = pa_tokenizer_get(t, 1))) {
1368 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1369 return -1;
1370 }
1371
1372 if ((b = pa_parse_boolean(m)) < 0) {
1373 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1374 return -1;
1375 }
1376
1377 pa_log_set_flags(PA_LOG_PRINT_META, b ? PA_LOG_SET : PA_LOG_UNSET);
1378
1379 return 0;
1380 }
1381
1382 static int pa_cli_command_log_time(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1383 const char *m;
1384 pa_bool_t b;
1385
1386 pa_core_assert_ref(c);
1387 pa_assert(t);
1388 pa_assert(buf);
1389 pa_assert(fail);
1390
1391 if (!(m = pa_tokenizer_get(t, 1))) {
1392 pa_strbuf_puts(buf, "You need to specify a boolean.\n");
1393 return -1;
1394 }
1395
1396 if ((b = pa_parse_boolean(m)) < 0) {
1397 pa_strbuf_puts(buf, "Failed to parse log meta switch.\n");
1398 return -1;
1399 }
1400
1401 pa_log_set_flags(PA_LOG_PRINT_TIME, b ? PA_LOG_SET : PA_LOG_UNSET);
1402
1403 return 0;
1404 }
1405
1406 static int pa_cli_command_log_backtrace(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1407 const char *m;
1408 uint32_t nframes;
1409
1410 pa_core_assert_ref(c);
1411 pa_assert(t);
1412 pa_assert(buf);
1413 pa_assert(fail);
1414
1415 if (!(m = pa_tokenizer_get(t, 1))) {
1416 pa_strbuf_puts(buf, "You need to specify a backtrace level.\n");
1417 return -1;
1418 }
1419
1420 if (pa_atou(m, &nframes) < 0 || nframes >= 1000) {
1421 pa_strbuf_puts(buf, "Failed to parse backtrace level.\n");
1422 return -1;
1423 }
1424
1425 pa_log_set_show_backtrace(nframes);
1426
1427 return 0;
1428 }
1429
1430 static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1431 const char *n, *p;
1432 pa_card *card;
1433
1434 pa_core_assert_ref(c);
1435 pa_assert(t);
1436 pa_assert(buf);
1437 pa_assert(fail);
1438
1439 if (!(n = pa_tokenizer_get(t, 1))) {
1440 pa_strbuf_puts(buf, "You need to specify a card either by its name or its index.\n");
1441 return -1;
1442 }
1443
1444 if (!(p = pa_tokenizer_get(t, 2))) {
1445 pa_strbuf_puts(buf, "You need to specify a profile by its name.\n");
1446 return -1;
1447 }
1448
1449 if (!(card = pa_namereg_get(c, n, PA_NAMEREG_CARD))) {
1450 pa_strbuf_puts(buf, "No card found by this name or index.\n");
1451 return -1;
1452 }
1453
1454 if (pa_card_set_profile(card, p) < 0) {
1455 pa_strbuf_printf(buf, "Failed to set card profile to '%s'.\n", p);
1456 return -1;
1457 }
1458
1459 return 0;
1460 }
1461
1462 static int pa_cli_command_dump(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
1463 pa_module *m;
1464 pa_sink *sink;
1465 pa_source *source;
1466 pa_card *card;
1467 int nl;
1468 uint32_t idx;
1469 char txt[256];
1470 time_t now;
1471
1472 pa_core_assert_ref(c);
1473 pa_assert(t);
1474 pa_assert(buf);
1475 pa_assert(fail);
1476
1477 time(&now);
1478
1479 #ifdef HAVE_CTIME_R
1480 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime_r(&now, txt));
1481 #else
1482 pa_strbuf_printf(buf, "### Configuration dump generated at %s\n", ctime(&now));
1483 #endif
1484
1485 for (m = pa_idxset_first(c->modules, &idx); m; m = pa_idxset_next(c->modules, &idx)) {
1486
1487 pa_strbuf_printf(buf, "load-module %s", m->name);
1488
1489 if (m->argument)
1490 pa_strbuf_printf(buf, " %s", m->argument);
1491
1492 pa_strbuf_puts(buf, "\n");
1493 }
1494
1495 nl = 0;
1496
1497 for (sink = pa_idxset_first(c->sinks, &idx); sink; sink = pa_idxset_next(c->sinks, &idx)) {
1498
1499 if (!nl) {
1500 pa_strbuf_puts(buf, "\n");
1501 nl = 1;
1502 }
1503
1504 pa_strbuf_printf(buf, "set-sink-volume %s 0x%03x\n", sink->name, pa_cvolume_avg(pa_sink_get_volume(sink, FALSE)));
1505 pa_strbuf_printf(buf, "set-sink-mute %s %s\n", sink->name, pa_yes_no(pa_sink_get_mute(sink, FALSE)));
1506 pa_strbuf_printf(buf, "suspend-sink %s %s\n", sink->name, pa_yes_no(pa_sink_get_state(sink) == PA_SINK_SUSPENDED));
1507 }
1508
1509 for (source = pa_idxset_first(c->sources, &idx); source; source = pa_idxset_next(c->sources, &idx)) {
1510
1511 if (!nl) {
1512 pa_strbuf_puts(buf, "\n");
1513 nl = 1;
1514 }
1515
1516 pa_strbuf_printf(buf, "set-source-volume %s 0x%03x\n", source->name, pa_cvolume_avg(pa_source_get_volume(source, FALSE)));
1517 pa_strbuf_printf(buf, "set-source-mute %s %s\n", source->name, pa_yes_no(pa_source_get_mute(source, FALSE)));
1518 pa_strbuf_printf(buf, "suspend-source %s %s\n", source->name, pa_yes_no(pa_source_get_state(source) == PA_SOURCE_SUSPENDED));
1519 }
1520
1521 for (card = pa_idxset_first(c->cards, &idx); card; card = pa_idxset_next(c->cards, &idx)) {
1522
1523 if (!nl) {
1524 pa_strbuf_puts(buf, "\n");
1525 nl = 1;
1526 }
1527
1528 if (card->active_profile)
1529 pa_strbuf_printf(buf, "set-card-profile %s %s\n", card->name, card->active_profile->name);
1530 }
1531
1532 nl = 0;
1533
1534 if ((sink = pa_namereg_get_default_sink(c))) {
1535 if (!nl) {
1536 pa_strbuf_puts(buf, "\n");
1537 nl = 1;
1538 }
1539 pa_strbuf_printf(buf, "set-default-sink %s\n", sink->name);
1540 }
1541
1542 if ((source = pa_namereg_get_default_source(c))) {
1543 if (!nl) {
1544 pa_strbuf_puts(buf, "\n");
1545 nl = 1;
1546 }
1547 pa_strbuf_printf(buf, "set-default-source %s\n", source->name);
1548 }
1549
1550 pa_strbuf_puts(buf, "\n### EOF\n");
1551
1552 return 0;
1553 }
1554
1555 int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) {
1556 const char *cs;
1557
1558 pa_assert(c);
1559 pa_assert(s);
1560 pa_assert(buf);
1561
1562 cs = s+strspn(s, whitespace);
1563
1564 if (*cs == '#' || !*cs)
1565 return 0;
1566 else if (*cs == '.') {
1567 if (!strcmp(cs, META_ELSE)) {
1568 if (!ifstate || *ifstate == IFSTATE_NONE) {
1569 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1570 return -1;
1571 } else if (*ifstate == IFSTATE_TRUE)
1572 *ifstate = IFSTATE_FALSE;
1573 else
1574 *ifstate = IFSTATE_TRUE;
1575 return 0;
1576 } else if (!strcmp(cs, META_ENDIF)) {
1577 if (!ifstate || *ifstate == IFSTATE_NONE) {
1578 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1579 return -1;
1580 } else
1581 *ifstate = IFSTATE_NONE;
1582 return 0;
1583 }
1584 if (ifstate && *ifstate == IFSTATE_FALSE)
1585 return 0;
1586 if (!strcmp(cs, META_FAIL))
1587 *fail = TRUE;
1588 else if (!strcmp(cs, META_NOFAIL))
1589 *fail = FALSE;
1590 else {
1591 size_t l;
1592 l = strcspn(cs, whitespace);
1593
1594 if (l == sizeof(META_INCLUDE)-1 && !strncmp(cs, META_INCLUDE, l)) {
1595 const char *filename = cs+l+strspn(cs+l, whitespace);
1596 if (pa_cli_command_execute_file(c, filename, buf, fail) < 0)
1597 if (*fail)
1598 return -1;
1599 } else if (l == sizeof(META_IFEXISTS)-1 && !strncmp(cs, META_IFEXISTS, l)) {
1600 if (!ifstate) {
1601 pa_strbuf_printf(buf, "Meta command %s is not valid in this context\n", cs);
1602 return -1;
1603 } else if (*ifstate != IFSTATE_NONE) {
1604 pa_strbuf_printf(buf, "Nested %s commands not supported\n", cs);
1605 return -1;
1606 } else {
1607 const char *filename = cs+l+strspn(cs+l, whitespace);
1608
1609 /* Search DL_SEARCH_PATH unless the filename is absolute */
1610 if (filename[0] == PA_PATH_SEP_CHAR) {
1611
1612 *ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1613 pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1614
1615 } else {
1616 const char *paths, *state = NULL;
1617 char *p;
1618
1619 if (!(paths = lt_dlgetsearchpath()))
1620 return -1;
1621
1622 while ((p = pa_split(paths, ":", &state))) {
1623 char *pathname;
1624
1625 pathname = pa_sprintf_malloc("%s" PA_PATH_SEP "%s", p, filename);
1626 pa_xfree(p);
1627
1628 *ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
1629 pa_log_debug("Checking for existance of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
1630
1631 pa_xfree(pathname);
1632
1633 if (*ifstate == IFSTATE_TRUE)
1634 break;
1635 }
1636 }
1637
1638 }
1639 } else {
1640 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
1641 if (*fail) return -1;
1642 }
1643 }
1644 } else {
1645 const struct command*command;
1646 int unknown = 1;
1647 size_t l;
1648
1649 if (ifstate && *ifstate == IFSTATE_FALSE)
1650 return 0;
1651
1652 l = strcspn(cs, whitespace);
1653
1654 for (command = commands; command->name; command++)
1655 if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
1656 int ret;
1657 pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
1658 pa_assert(t);
1659 ret = command->proc(c, t, buf, fail);
1660 pa_tokenizer_free(t);
1661 unknown = 0;
1662
1663 if (ret < 0 && *fail)
1664 return -1;
1665
1666 break;
1667 }
1668
1669 if (unknown) {
1670 pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
1671 if (*fail)
1672 return -1;
1673 }
1674 }
1675
1676 return 0;
1677 }
1678
1679 int pa_cli_command_execute_line(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
1680 return pa_cli_command_execute_line_stateful(c, s, buf, fail, NULL);
1681 }
1682
1683 int pa_cli_command_execute_file_stream(pa_core *c, FILE *f, pa_strbuf *buf, pa_bool_t *fail) {
1684 char line[1024];
1685 int ifstate = IFSTATE_NONE;
1686 int ret = -1;
1687 pa_bool_t _fail = TRUE;
1688
1689 pa_assert(c);
1690 pa_assert(f);
1691 pa_assert(buf);
1692
1693 if (!fail)
1694 fail = &_fail;
1695
1696 while (fgets(line, sizeof(line), f)) {
1697 pa_strip_nl(line);
1698
1699 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail)
1700 goto fail;
1701 }
1702
1703 ret = 0;
1704
1705 fail:
1706
1707 return ret;
1708 }
1709
1710 int pa_cli_command_execute_file(pa_core *c, const char *fn, pa_strbuf *buf, pa_bool_t *fail) {
1711 FILE *f = NULL;
1712 int ret = -1;
1713 pa_bool_t _fail = TRUE;
1714
1715 pa_assert(c);
1716 pa_assert(fn);
1717 pa_assert(buf);
1718
1719 if (!fail)
1720 fail = &_fail;
1721
1722 if (!(f = fopen(fn, "r"))) {
1723 pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, pa_cstrerror(errno));
1724 if (!*fail)
1725 ret = 0;
1726 goto fail;
1727 }
1728
1729 ret = pa_cli_command_execute_file_stream(c, f, buf, fail);
1730
1731 ret = 0;
1732
1733 fail:
1734 if (f)
1735 fclose(f);
1736
1737 return ret;
1738 }
1739
1740 int pa_cli_command_execute(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail) {
1741 const char *p;
1742 int ifstate = IFSTATE_NONE;
1743 pa_bool_t _fail = TRUE;
1744
1745 pa_assert(c);
1746 pa_assert(s);
1747 pa_assert(buf);
1748
1749 if (!fail)
1750 fail = &_fail;
1751
1752 p = s;
1753 while (*p) {
1754 size_t l = strcspn(p, linebreak);
1755 char *line = pa_xstrndup(p, l);
1756
1757 if (pa_cli_command_execute_line_stateful(c, line, buf, fail, &ifstate) < 0 && *fail) {
1758 pa_xfree(line);
1759 return -1;
1760 }
1761 pa_xfree(line);
1762
1763 p += l;
1764 p += strspn(p, linebreak);
1765 }
1766
1767 return 0;
1768 }