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