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