]> code.delx.au - pulseaudio/blob - polyp/cli-command.c
sample cache work
[pulseaudio] / polyp / cli-command.c
1 /* $Id$ */
2
3 /***
4 This file is part of polypaudio.
5
6 polypaudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published
8 by the Free Software Foundation; either version 2 of the License,
9 or (at your option) any later version.
10
11 polypaudio is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with polypaudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19 USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <stdlib.h>
30 #include <errno.h>
31
32 #include "cli-command.h"
33 #include "module.h"
34 #include "sink.h"
35 #include "source.h"
36 #include "client.h"
37 #include "sink-input.h"
38 #include "source-output.h"
39 #include "tokenizer.h"
40 #include "strbuf.h"
41 #include "namereg.h"
42 #include "clitext.h"
43 #include "scache.h"
44 #include "sample-util.h"
45
46 struct command {
47 const char *name;
48 int (*proc) (struct pa_core *c, struct pa_tokenizer*t, struct pa_strbuf *buf, int *fail, int *verbose);
49 const char *help;
50 unsigned args;
51 };
52
53 static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
54 static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
55 static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
56 static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
57 static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
58 static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
59 static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
60 static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
61 static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
62 static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
63 static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
64 static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
65 static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
66 static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
67 static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
68 static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
69 static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
70 static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
71 static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
72 static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
73 static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
74 static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose);
75
76 static const struct command commands[] = {
77 { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
78 { "help", pa_cli_command_help, "Show this help", 1 },
79 { "modules", pa_cli_command_modules, "List loaded modules", 1 },
80 { "sinks", pa_cli_command_sinks, "List loaded sinks", 1 },
81 { "sources", pa_cli_command_sources, "List loaded sources", 1 },
82 { "clients", pa_cli_command_clients, "List loaded clients", 1 },
83 { "sink_inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 },
84 { "source_outputs", pa_cli_command_source_outputs, "List source outputs", 1 },
85 { "stat", pa_cli_command_stat, "Show memory block statistics", 1 },
86 { "info", pa_cli_command_info, "Show comprehensive status", 1 },
87 { "ls", pa_cli_command_info, NULL, 1 },
88 { "list", pa_cli_command_info, NULL, 1 },
89 { "load", pa_cli_command_load, "Load a module (args: name, arguments)", 3},
90 { "unload", pa_cli_command_unload, "Unload a module (args: index)", 2},
91 { "sink_volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3},
92 { "sink_input_volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index|name, volume)", 3},
93 { "sink_default", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2},
94 { "source_default", pa_cli_command_source_default, "Set the default source (args: index|name)", 2},
95 { "kill_client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
96 { "kill_sink_input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
97 { "kill_source_output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
98 { "scache_list", pa_cli_command_scache_list, "List all entries in the sample cache", 2},
99 { "scache_play", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3},
100 { "scache_remove", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2},
101 { NULL, NULL, NULL, 0 }
102 };
103
104 static const char whitespace[] = " \t\n\r";
105 static const char linebreak[] = "\n\r";
106
107 static uint32_t parse_index(const char *n) {
108 long index;
109 char *x;
110 index = strtol(n, &x, 0);
111 if (!x || *x != 0 || index < 0)
112 return (uint32_t) PA_IDXSET_INVALID;
113
114 return (uint32_t) index;
115 }
116
117 static int pa_cli_command_exit(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
118 assert(c && c->mainloop && t);
119 c->mainloop->quit(c->mainloop, 0);
120 return 0;
121 }
122
123 static int pa_cli_command_help(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
124 const struct command*command;
125 assert(c && t && buf);
126
127 pa_strbuf_puts(buf, "Available commands:\n");
128
129 for (command = commands; command->name; command++)
130 if (command->help)
131 pa_strbuf_printf(buf, " %-20s %s\n", command->name, command->help);
132 return 0;
133 }
134
135 static int pa_cli_command_modules(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
136 char *s;
137 assert(c && t);
138 s = pa_module_list_to_string(c);
139 assert(s);
140 pa_strbuf_puts(buf, s);
141 free(s);
142 return 0;
143 }
144
145 static int pa_cli_command_clients(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
146 char *s;
147 assert(c && t);
148 s = pa_client_list_to_string(c);
149 assert(s);
150 pa_strbuf_puts(buf, s);
151 free(s);
152 return 0;
153 }
154
155 static int pa_cli_command_sinks(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
156 char *s;
157 assert(c && t);
158 s = pa_sink_list_to_string(c);
159 assert(s);
160 pa_strbuf_puts(buf, s);
161 free(s);
162 return 0;
163 }
164
165 static int pa_cli_command_sources(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
166 char *s;
167 assert(c && t);
168 s = pa_source_list_to_string(c);
169 assert(s);
170 pa_strbuf_puts(buf, s);
171 free(s);
172 return 0;
173 }
174
175 static int pa_cli_command_sink_inputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
176 char *s;
177 assert(c && t);
178 s = pa_sink_input_list_to_string(c);
179 assert(s);
180 pa_strbuf_puts(buf, s);
181 free(s);
182 return 0;
183 }
184
185 static int pa_cli_command_source_outputs(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
186 char *s;
187 assert(c && t);
188 s = pa_source_output_list_to_string(c);
189 assert(s);
190 pa_strbuf_puts(buf, s);
191 free(s);
192 return 0;
193 }
194
195 static int pa_cli_command_stat(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
196 assert(c && t);
197 pa_strbuf_printf(buf, "Memory blocks allocated: %u, total size: %u bytes.\n", pa_memblock_get_count(), pa_memblock_get_total());
198 return 0;
199 }
200
201 static int pa_cli_command_info(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
202 assert(c && t);
203 pa_cli_command_stat(c, t, buf, fail, verbose);
204 pa_cli_command_modules(c, t, buf, fail, verbose);
205 pa_cli_command_sinks(c, t, buf, fail, verbose);
206 pa_cli_command_sources(c, t, buf, fail, verbose);
207 pa_cli_command_clients(c, t, buf, fail, verbose);
208 pa_cli_command_sink_inputs(c, t, buf, fail, verbose);
209 pa_cli_command_source_outputs(c, t, buf, fail, verbose);
210 pa_cli_command_scache_list(c, t, buf, fail, verbose);
211 return 0;
212 }
213
214 static int pa_cli_command_load(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
215 struct pa_module *m;
216 const char *name;
217 char txt[256];
218 assert(c && t);
219
220 if (!(name = pa_tokenizer_get(t, 1))) {
221 pa_strbuf_puts(buf, "You need to specify the module name and optionally arguments.\n");
222 return -1;
223 }
224
225 if (!(m = pa_module_load(c, name, pa_tokenizer_get(t, 2)))) {
226 pa_strbuf_puts(buf, "Module load failed.\n");
227 return -1;
228 }
229
230 if (*verbose) {
231 snprintf(txt, sizeof(txt), "Module successfully loaded, index: %u.\n", m->index);
232 pa_strbuf_puts(buf, txt);
233 }
234 return 0;
235 }
236
237 static int pa_cli_command_unload(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
238 struct pa_module *m;
239 uint32_t index;
240 const char *i;
241 char *e;
242 assert(c && t);
243
244 if (!(i = pa_tokenizer_get(t, 1))) {
245 pa_strbuf_puts(buf, "You need to specify the module index.\n");
246 return -1;
247 }
248
249 index = (uint32_t) strtoul(i, &e, 10);
250 if (*e || !(m = pa_idxset_get_by_index(c->modules, index))) {
251 pa_strbuf_puts(buf, "Invalid module index.\n");
252 return -1;
253 }
254
255 pa_module_unload_request(c, m);
256 return 0;
257 }
258
259 static int pa_cli_command_sink_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
260 const char *n, *v;
261 char *x = NULL;
262 struct pa_sink *sink;
263 long volume;
264
265 if (!(n = pa_tokenizer_get(t, 1))) {
266 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
267 return -1;
268 }
269
270 if (!(v = pa_tokenizer_get(t, 2))) {
271 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n");
272 return -1;
273 }
274
275 volume = strtol(v, &x, 0);
276 if (!x || *x != 0 || volume < 0) {
277 pa_strbuf_puts(buf, "Failed to parse volume.\n");
278 return -1;
279 }
280
281 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
282 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
283 return -1;
284 }
285
286 sink->volume = (uint32_t) volume;
287 return 0;
288 }
289
290 static int pa_cli_command_sink_input_volume(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
291 const char *n, *v;
292 struct pa_sink_input *si;
293 long volume;
294 uint32_t index;
295 char *x;
296
297 if (!(n = pa_tokenizer_get(t, 1))) {
298 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
299 return -1;
300 }
301
302 if ((index = parse_index(n)) == PA_IDXSET_INVALID) {
303 pa_strbuf_puts(buf, "Failed to parse index.\n");
304 return -1;
305 }
306
307 if (!(v = pa_tokenizer_get(t, 2))) {
308 pa_strbuf_puts(buf, "You need to specify a volume >= 0. (0 is muted, 0x100 is normal volume)\n");
309 return -1;
310 }
311
312 x = NULL;
313 volume = strtol(v, &x, 0);
314 if (!x || *x != 0 || volume < 0) {
315 pa_strbuf_puts(buf, "Failed to parse volume.\n");
316 return -1;
317 }
318
319 if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) index))) {
320 pa_strbuf_puts(buf, "No sink input found with this index.\n");
321 return -1;
322 }
323
324 si->volume = (uint32_t) volume;
325 return 0;
326 }
327
328 static int pa_cli_command_sink_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
329 const char *n;
330 struct pa_sink *sink;
331 assert(c && t);
332
333 if (!(n = pa_tokenizer_get(t, 1))) {
334 pa_strbuf_puts(buf, "You need to specify a sink either by its name or its index.\n");
335 return -1;
336 }
337
338 if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
339 pa_strbuf_puts(buf, "No sink found by this name or index.\n");
340 return -1;
341 }
342
343 c->default_sink_index = sink->index;
344 return 0;
345 }
346
347 static int pa_cli_command_source_default(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
348 const char *n;
349 struct pa_source *source;
350 assert(c && t);
351
352 if (!(n = pa_tokenizer_get(t, 1))) {
353 pa_strbuf_puts(buf, "You need to specify a source either by its name or its index.\n");
354 return -1;
355 }
356
357 if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
358 pa_strbuf_puts(buf, "No source found by this name or index.\n");
359 return -1;
360 }
361
362 c->default_source_index = source->index;
363 return 0;
364 }
365
366 static int pa_cli_command_kill_client(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
367 const char *n;
368 struct pa_client *client;
369 uint32_t index;
370 assert(c && t);
371
372 if (!(n = pa_tokenizer_get(t, 1))) {
373 pa_strbuf_puts(buf, "You need to specify a client by its index.\n");
374 return -1;
375 }
376
377 if ((index = parse_index(n)) == PA_IDXSET_INVALID) {
378 pa_strbuf_puts(buf, "Failed to parse index.\n");
379 return -1;
380 }
381
382 if (!(client = pa_idxset_get_by_index(c->clients, index))) {
383 pa_strbuf_puts(buf, "No client found by this index.\n");
384 return -1;
385 }
386
387 pa_client_kill(client);
388 return 0;
389 }
390
391 static int pa_cli_command_kill_sink_input(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
392 const char *n;
393 struct pa_sink_input *sink_input;
394 uint32_t index;
395 assert(c && t);
396
397 if (!(n = pa_tokenizer_get(t, 1))) {
398 pa_strbuf_puts(buf, "You need to specify a sink input by its index.\n");
399 return -1;
400 }
401
402 if ((index = parse_index(n)) == PA_IDXSET_INVALID) {
403 pa_strbuf_puts(buf, "Failed to parse index.\n");
404 return -1;
405 }
406
407 if (!(sink_input = pa_idxset_get_by_index(c->sink_inputs, index))) {
408 pa_strbuf_puts(buf, "No sink input found by this index.\n");
409 return -1;
410 }
411
412 pa_sink_input_kill(sink_input);
413 return 0;
414 }
415
416 static int pa_cli_command_kill_source_output(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
417 const char *n;
418 struct pa_source_output *source_output;
419 uint32_t index;
420 assert(c && t);
421
422 if (!(n = pa_tokenizer_get(t, 1))) {
423 pa_strbuf_puts(buf, "You need to specify a source output by its index.\n");
424 return -1;
425 }
426
427 if ((index = parse_index(n)) == PA_IDXSET_INVALID) {
428 pa_strbuf_puts(buf, "Failed to parse index.\n");
429 return -1;
430 }
431
432 if (!(source_output = pa_idxset_get_by_index(c->source_outputs, index))) {
433 pa_strbuf_puts(buf, "No source output found by this index.\n");
434 return -1;
435 }
436
437 pa_source_output_kill(source_output);
438 return 0;
439 }
440
441 static int pa_cli_command_scache_list(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
442 char *s;
443 assert(c && t);
444 s = pa_scache_list_to_string(c);
445 assert(s);
446 pa_strbuf_puts(buf, s);
447 free(s);
448 return 0;
449 }
450
451 static int pa_cli_command_scache_play(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
452 const char *n, *sink_name;
453 struct pa_sink *sink;
454 assert(c && t && buf && fail && verbose);
455
456 if (!(n = pa_tokenizer_get(t, 1)) || !(sink_name = pa_tokenizer_get(t, 2))) {
457 pa_strbuf_puts(buf, "You need to specify a sample name and a sink name.\n");
458 return -1;
459 }
460
461 if (!(sink = pa_namereg_get(c, sink_name, PA_NAMEREG_SINK))) {
462 pa_strbuf_puts(buf, "No sink by that name.\n");
463 return -1;
464 }
465
466 if (pa_scache_play_item(c, n, sink, PA_VOLUME_NORM) < 0) {
467 pa_strbuf_puts(buf, "Failed to play sample.\n");
468 return -1;
469 }
470
471 return 0;
472 }
473
474 static int pa_cli_command_scache_remove(struct pa_core *c, struct pa_tokenizer *t, struct pa_strbuf *buf, int *fail, int *verbose) {
475 const char *n;
476 assert(c && t && buf && fail && verbose);
477
478 if (!(n = pa_tokenizer_get(t, 1))) {
479 pa_strbuf_puts(buf, "You need to specify a sample name.\n");
480 return -1;
481 }
482
483 if (pa_scache_remove_item(c, n) < 0) {
484 pa_strbuf_puts(buf, "Failed to remove sample.\n");
485 return -1;
486 }
487
488 return 0;
489 }
490
491 int pa_cli_command_execute_line(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) {
492 const char *cs;
493
494 cs = s+strspn(s, whitespace);
495
496 if (*cs == '#' || !*cs)
497 return 0;
498 else if (*cs == '.') {
499 static const char fail_meta[] = ".fail";
500 static const char nofail_meta[] = ".nofail";
501 static const char verbose_meta[] = ".verbose";
502 static const char noverbose_meta[] = ".noverbose";
503
504 if (!strcmp(cs, verbose_meta))
505 *verbose = 1;
506 else if (!strcmp(cs, noverbose_meta))
507 *verbose = 0;
508 else if (!strcmp(cs, fail_meta))
509 *fail = 1;
510 else if (!strcmp(cs, nofail_meta))
511 *fail = 0;
512 else {
513 size_t l;
514 static const char include_meta[] = ".include";
515 l = strcspn(cs, whitespace);
516
517 if (l == sizeof(include_meta)-1 && !strncmp(cs, include_meta, l)) {
518 const char *filename = cs+l+strspn(cs+l, whitespace);
519
520 if (pa_cli_command_execute_file(c, filename, buf, fail, verbose) < 0)
521 if (*fail) return -1;
522 } else {
523 pa_strbuf_printf(buf, "Invalid meta command: %s\n", cs);
524 if (*fail) return -1;
525 }
526 }
527 } else {
528 const struct command*command;
529 int unknown = 1;
530 size_t l;
531
532 l = strcspn(cs, whitespace);
533
534 for (command = commands; command->name; command++)
535 if (strlen(command->name) == l && !strncmp(cs, command->name, l)) {
536 int ret;
537 struct pa_tokenizer *t = pa_tokenizer_new(cs, command->args);
538 assert(t);
539 ret = command->proc(c, t, buf, fail, verbose);
540 pa_tokenizer_free(t);
541 unknown = 0;
542
543 if (ret < 0 && *fail)
544 return -1;
545
546 break;
547 }
548
549 if (unknown) {
550 pa_strbuf_printf(buf, "Unknown command: %s\n", cs);
551 if (*fail)
552 return -1;
553 }
554 }
555
556 return 0;
557 }
558
559 int pa_cli_command_execute_file(struct pa_core *c, const char *fn, struct pa_strbuf *buf, int *fail, int *verbose) {
560 char line[256];
561 FILE *f = NULL;
562 int ret = -1;
563 assert(c && fn && buf);
564
565 if (!(f = fopen(fn, "r"))) {
566 pa_strbuf_printf(buf, "open('%s') failed: %s\n", fn, strerror(errno));
567 if (!*fail)
568 ret = 0;
569 goto fail;
570 }
571
572 if (*verbose)
573 pa_strbuf_printf(buf, "Executing file: '%s'\n", fn);
574
575 while (fgets(line, sizeof(line), f)) {
576 char *e = line + strcspn(line, linebreak);
577 *e = 0;
578
579 if (pa_cli_command_execute_line(c, line, buf, fail, verbose) < 0 && *fail)
580 goto fail;
581 }
582
583 if (*verbose)
584 pa_strbuf_printf(buf, "Executed file: '%s'\n", fn);
585
586 ret = 0;
587
588 fail:
589 if (f)
590 fclose(f);
591
592 return ret;
593 }
594
595 int pa_cli_command_execute(struct pa_core *c, const char *s, struct pa_strbuf *buf, int *fail, int *verbose) {
596 const char *p;
597 assert(c && s && buf && fail && verbose);
598
599 p = s;
600 while (*p) {
601 size_t l = strcspn(p, linebreak);
602 char *line = strndup(p, l);
603 assert(line);
604
605 if (pa_cli_command_execute_line(c, line, buf, fail, verbose) < 0&& *fail) {
606 free(line);
607 return -1;
608 }
609 free(line);
610
611 p += l;
612 p += strspn(p, linebreak);
613 }
614
615 return 0;
616 }