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