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