2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
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.
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.
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
39 #include <pulse/xmalloc.h>
40 #include <pulse/error.h>
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>
62 #include "cli-command.h"
66 int (*proc
) (pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
);
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"
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
);
141 /* A method table for all available commands */
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 }
205 static const char whitespace
[] = " \t\n\r";
206 static const char linebreak
[] = "\n\r";
208 static uint32_t parse_index(const char *n
) {
211 if (pa_atou(n
, &idx
) < 0)
212 return (uint32_t) PA_IDXSET_INVALID
;
217 static int pa_cli_command_exit(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
218 pa_core_assert_ref(c
);
223 if (pa_core_exit(c
, FALSE
, 0) < 0)
224 pa_strbuf_puts(buf
, "Not allowed to terminate daemon.\n");
229 static int pa_cli_command_help(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
230 const struct command
*command
;
232 pa_core_assert_ref(c
);
237 pa_strbuf_puts(buf
, "Available commands:\n");
239 for (command
= commands
; command
->name
; command
++)
241 pa_strbuf_printf(buf
, " %-25s %s\n", command
->name
, command
->help
);
245 static int pa_cli_command_modules(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
248 pa_core_assert_ref(c
);
253 pa_assert_se(s
= pa_module_list_to_string(c
));
254 pa_strbuf_puts(buf
, s
);
259 static int pa_cli_command_clients(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
262 pa_core_assert_ref(c
);
267 pa_assert_se(s
= pa_client_list_to_string(c
));
268 pa_strbuf_puts(buf
, s
);
273 static int pa_cli_command_cards(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
276 pa_core_assert_ref(c
);
281 pa_assert_se(s
= pa_card_list_to_string(c
));
282 pa_strbuf_puts(buf
, s
);
287 static int pa_cli_command_sinks(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
290 pa_core_assert_ref(c
);
295 pa_assert_se(s
= pa_sink_list_to_string(c
));
296 pa_strbuf_puts(buf
, s
);
301 static int pa_cli_command_sources(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
304 pa_core_assert_ref(c
);
309 pa_assert_se(s
= pa_source_list_to_string(c
));
310 pa_strbuf_puts(buf
, s
);
315 static int pa_cli_command_sink_inputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
318 pa_core_assert_ref(c
);
323 pa_assert_se(s
= pa_sink_input_list_to_string(c
));
324 pa_strbuf_puts(buf
, s
);
329 static int pa_cli_command_source_outputs(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
332 pa_core_assert_ref(c
);
337 pa_assert_se(s
= pa_source_output_list_to_string(c
));
338 pa_strbuf_puts(buf
, s
);
343 static int pa_cli_command_stat(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
344 char ss
[PA_SAMPLE_SPEC_SNPRINT_MAX
];
345 char cm
[PA_CHANNEL_MAP_SNPRINT_MAX
];
346 char bytes
[PA_BYTES_SNPRINT_MAX
];
347 const pa_mempool_stat
*mstat
;
350 pa_source
*def_source
;
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",
361 pa_core_assert_ref(c
);
366 mstat
= pa_mempool_get_stat(c
->mempool
);
368 pa_strbuf_printf(buf
, "Memory blocks currently allocated: %u, size: %s.\n",
369 (unsigned) pa_atomic_load(&mstat
->n_allocated
),
370 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->allocated_size
)));
372 pa_strbuf_printf(buf
, "Memory blocks allocated during the whole lifetime: %u, size: %s.\n",
373 (unsigned) pa_atomic_load(&mstat
->n_accumulated
),
374 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->accumulated_size
)));
376 pa_strbuf_printf(buf
, "Memory blocks imported from other processes: %u, size: %s.\n",
377 (unsigned) pa_atomic_load(&mstat
->n_imported
),
378 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->imported_size
)));
380 pa_strbuf_printf(buf
, "Memory blocks exported to other processes: %u, size: %s.\n",
381 (unsigned) pa_atomic_load(&mstat
->n_exported
),
382 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_atomic_load(&mstat
->exported_size
)));
384 pa_strbuf_printf(buf
, "Total sample cache size: %s.\n",
385 pa_bytes_snprint(bytes
, sizeof(bytes
), (unsigned) pa_scache_total_size(c
)));
387 pa_strbuf_printf(buf
, "Default sample spec: %s\n",
388 pa_sample_spec_snprint(ss
, sizeof(ss
), &c
->default_sample_spec
));
390 pa_strbuf_printf(buf
, "Default channel map: %s\n",
391 pa_channel_map_snprint(cm
, sizeof(cm
), &c
->default_channel_map
));
393 def_sink
= pa_namereg_get_default_sink(c
);
394 def_source
= pa_namereg_get_default_source(c
);
395 pa_strbuf_printf(buf
, "Default sink name: %s\n"
396 "Default source name: %s\n",
397 def_sink
? def_sink
->name
: "none",
398 def_source
? def_source
->name
: "none");
400 for (k
= 0; k
< PA_MEMBLOCK_TYPE_MAX
; k
++)
401 pa_strbuf_printf(buf
,
402 "Memory blocks of type %s: %u allocated/%u accumulated.\n",
404 (unsigned) pa_atomic_load(&mstat
->n_allocated_by_type
[k
]),
405 (unsigned) pa_atomic_load(&mstat
->n_accumulated_by_type
[k
]));
410 static int pa_cli_command_info(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
411 pa_core_assert_ref(c
);
416 pa_cli_command_stat(c
, t
, buf
, fail
);
417 pa_cli_command_modules(c
, t
, buf
, fail
);
418 pa_cli_command_sinks(c
, t
, buf
, fail
);
419 pa_cli_command_sources(c
, t
, buf
, fail
);
420 pa_cli_command_clients(c
, t
, buf
, fail
);
421 pa_cli_command_cards(c
, t
, buf
, fail
);
422 pa_cli_command_sink_inputs(c
, t
, buf
, fail
);
423 pa_cli_command_source_outputs(c
, t
, buf
, fail
);
424 pa_cli_command_scache_list(c
, t
, buf
, fail
);
428 static int pa_cli_command_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
431 pa_core_assert_ref(c
);
436 if (!(name
= pa_tokenizer_get(t
, 1))) {
437 pa_strbuf_puts(buf
, "You need to specify the module name and optionally arguments.\n");
441 if (!pa_module_load(c
, name
, pa_tokenizer_get(t
, 2))) {
442 pa_strbuf_puts(buf
, "Module load failed.\n");
449 static int pa_cli_command_unload(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
453 pa_bool_t unloaded
= FALSE
;
455 pa_core_assert_ref(c
);
460 if (!(i
= pa_tokenizer_get(t
, 1))) {
461 pa_strbuf_puts(buf
, "You need to specify the module index or name.\n");
465 if (pa_atou(i
, &idx
) >= 0) {
466 if (!(m
= pa_idxset_get_by_index(c
->modules
, idx
))) {
467 pa_strbuf_puts(buf
, "Invalid module index.\n");
471 pa_module_unload_request(m
, FALSE
);
474 PA_IDXSET_FOREACH(m
, c
->modules
, idx
)
475 if (pa_streq(i
, m
->name
)) {
477 pa_module_unload_request(m
, FALSE
);
480 if (unloaded
== FALSE
) {
481 pa_strbuf_printf(buf
, "Module %s not loaded.\n", i
);
489 static int pa_cli_command_describe(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
493 pa_core_assert_ref(c
);
498 if (!(name
= pa_tokenizer_get(t
, 1))) {
499 pa_strbuf_puts(buf
, "You need to specify the module name.\n");
503 if ((i
= pa_modinfo_get_by_name(name
))) {
505 pa_strbuf_printf(buf
, "Name: %s\n", name
);
507 if (!i
->description
&& !i
->version
&& !i
->author
&& !i
->usage
)
508 pa_strbuf_printf(buf
, "No module information available\n");
511 pa_strbuf_printf(buf
, "Version: %s\n", i
->version
);
513 pa_strbuf_printf(buf
, "Description: %s\n", i
->description
);
515 pa_strbuf_printf(buf
, "Author: %s\n", i
->author
);
517 pa_strbuf_printf(buf
, "Usage: %s\n", i
->usage
);
518 pa_strbuf_printf(buf
, "Load Once: %s\n", pa_yes_no(i
->load_once
));
520 pa_strbuf_printf(buf
, "Warning, deprecated: %s\n", i
->deprecated
);
525 pa_strbuf_puts(buf
, "Failed to open module.\n");
530 static int pa_cli_command_sink_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
536 pa_core_assert_ref(c
);
541 if (!(n
= pa_tokenizer_get(t
, 1))) {
542 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
546 if (!(v
= pa_tokenizer_get(t
, 2))) {
547 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
551 if (pa_atou(v
, &volume
) < 0) {
552 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
556 if (!PA_VOLUME_IS_VALID(volume
)) {
557 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
561 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
562 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
566 pa_cvolume_set(&cvolume
, 1, volume
);
567 pa_sink_set_volume(sink
, &cvolume
, TRUE
, TRUE
);
571 static int pa_cli_command_sink_input_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
578 pa_core_assert_ref(c
);
583 if (!(n
= pa_tokenizer_get(t
, 1))) {
584 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
588 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
589 pa_strbuf_puts(buf
, "Failed to parse index.\n");
593 if (!(v
= pa_tokenizer_get(t
, 2))) {
594 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
598 if (pa_atou(v
, &volume
) < 0) {
599 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
603 if (!PA_VOLUME_IS_VALID(volume
)) {
604 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
608 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
609 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
613 if (!si
->volume_writable
) {
614 pa_strbuf_puts(buf
, "This sink input's volume can't be changed.\n");
618 pa_cvolume_set(&cvolume
, 1, volume
);
619 pa_sink_input_set_volume(si
, &cvolume
, TRUE
, TRUE
);
623 static int pa_cli_command_source_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
629 pa_core_assert_ref(c
);
634 if (!(n
= pa_tokenizer_get(t
, 1))) {
635 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
639 if (!(v
= pa_tokenizer_get(t
, 2))) {
640 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
644 if (pa_atou(v
, &volume
) < 0) {
645 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
649 if (!PA_VOLUME_IS_VALID(volume
)) {
650 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
654 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
655 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
659 pa_cvolume_set(&cvolume
, 1, volume
);
660 pa_source_set_volume(source
, &cvolume
, TRUE
, TRUE
);
664 static int pa_cli_command_source_output_volume(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
666 pa_source_output
*so
;
671 pa_core_assert_ref(c
);
676 if (!(n
= pa_tokenizer_get(t
, 1))) {
677 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
681 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
682 pa_strbuf_puts(buf
, "Failed to parse index.\n");
686 if (!(v
= pa_tokenizer_get(t
, 2))) {
687 pa_strbuf_puts(buf
, "You need to specify a volume >= 0. (0 is muted, 0x10000 is normal volume)\n");
691 if (pa_atou(v
, &volume
) < 0) {
692 pa_strbuf_puts(buf
, "Failed to parse volume.\n");
696 if (!PA_VOLUME_IS_VALID(volume
)) {
697 pa_strbuf_puts(buf
, "Volume outside permissible range.\n");
701 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, idx
))) {
702 pa_strbuf_puts(buf
, "No source output found with this index.\n");
706 if (!so
->volume_writable
) {
707 pa_strbuf_puts(buf
, "This source output's volume can't be changed.\n");
711 pa_cvolume_set(&cvolume
, 1, volume
);
712 pa_source_output_set_volume(so
, &cvolume
, TRUE
, TRUE
);
716 static int pa_cli_command_sink_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
721 pa_core_assert_ref(c
);
726 if (!(n
= pa_tokenizer_get(t
, 1))) {
727 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
731 if (!(m
= pa_tokenizer_get(t
, 2))) {
732 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
736 if ((mute
= pa_parse_boolean(m
)) < 0) {
737 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
741 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
742 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
746 pa_sink_set_mute(sink
, mute
, TRUE
);
750 static int pa_cli_command_source_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
755 pa_core_assert_ref(c
);
760 if (!(n
= pa_tokenizer_get(t
, 1))) {
761 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
765 if (!(m
= pa_tokenizer_get(t
, 2))) {
766 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
770 if ((mute
= pa_parse_boolean(m
)) < 0) {
771 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
775 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
776 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
780 pa_source_set_mute(source
, mute
, TRUE
);
784 static int pa_cli_command_update_sink_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
789 pa_core_assert_ref(c
);
794 if (!(n
= pa_tokenizer_get(t
, 1))) {
795 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
799 if (!(s
= pa_tokenizer_get(t
, 2))) {
800 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
804 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
805 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
809 if (!(p
= pa_proplist_from_string(s
))) {
810 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
814 pa_sink_update_proplist(sink
, PA_UPDATE_REPLACE
, p
);
821 static int pa_cli_command_update_source_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
826 pa_core_assert_ref(c
);
831 if (!(n
= pa_tokenizer_get(t
, 1))) {
832 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
836 if (!(s
= pa_tokenizer_get(t
, 2))) {
837 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
841 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
842 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
846 if (!(p
= pa_proplist_from_string(s
))) {
847 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
851 pa_source_update_proplist(source
, PA_UPDATE_REPLACE
, p
);
858 static int pa_cli_command_update_sink_input_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
864 pa_core_assert_ref(c
);
869 if (!(n
= pa_tokenizer_get(t
, 1))) {
870 pa_strbuf_puts(buf
, "You need to specify a sink input either by index.\n");
874 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
875 pa_strbuf_puts(buf
, "Failed to parse index.\n");
879 if (!(s
= pa_tokenizer_get(t
, 2))) {
880 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
884 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
885 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
889 if (!(p
= pa_proplist_from_string(s
))) {
890 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
894 pa_sink_input_update_proplist(si
, PA_UPDATE_REPLACE
, p
);
901 static int pa_cli_command_update_source_output_proplist(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
903 pa_source_output
*so
;
907 pa_core_assert_ref(c
);
912 if (!(n
= pa_tokenizer_get(t
, 1))) {
913 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
917 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
918 pa_strbuf_puts(buf
, "Failed to parse index.\n");
922 if (!(s
= pa_tokenizer_get(t
, 2))) {
923 pa_strbuf_puts(buf
, "You need to specify a \"key=value\" argument.\n");
927 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
928 pa_strbuf_puts(buf
, "No source output found with this index.\n");
932 if (!(p
= pa_proplist_from_string(s
))) {
933 pa_strbuf_puts(buf
, "Failed to parse proplist.\n");
937 pa_source_output_update_proplist(so
, PA_UPDATE_REPLACE
, p
);
944 static int pa_cli_command_sink_input_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
950 pa_core_assert_ref(c
);
955 if (!(n
= pa_tokenizer_get(t
, 1))) {
956 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
960 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
961 pa_strbuf_puts(buf
, "Failed to parse index.\n");
965 if (!(v
= pa_tokenizer_get(t
, 2))) {
966 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
970 if ((mute
= pa_parse_boolean(v
)) < 0) {
971 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
975 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
976 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
980 pa_sink_input_set_mute(si
, mute
, TRUE
);
984 static int pa_cli_command_source_output_mute(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
986 pa_source_output
*so
;
990 pa_core_assert_ref(c
);
995 if (!(n
= pa_tokenizer_get(t
, 1))) {
996 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1000 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1001 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1005 if (!(v
= pa_tokenizer_get(t
, 2))) {
1006 pa_strbuf_puts(buf
, "You need to specify a mute switch setting (0/1).\n");
1010 if ((mute
= pa_parse_boolean(v
)) < 0) {
1011 pa_strbuf_puts(buf
, "Failed to parse mute switch.\n");
1015 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
1016 pa_strbuf_puts(buf
, "No source output found with this index.\n");
1020 pa_source_output_set_mute(so
, mute
, TRUE
);
1024 static int pa_cli_command_sink_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1028 pa_core_assert_ref(c
);
1033 if (!(n
= pa_tokenizer_get(t
, 1))) {
1034 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1038 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
)))
1039 pa_namereg_set_default_sink(c
, s
);
1041 pa_strbuf_printf(buf
, "Sink %s does not exist.\n", n
);
1046 static int pa_cli_command_source_default(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1050 pa_core_assert_ref(c
);
1055 if (!(n
= pa_tokenizer_get(t
, 1))) {
1056 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1060 if ((s
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
)))
1061 pa_namereg_set_default_source(c
, s
);
1063 pa_strbuf_printf(buf
, "Source %s does not exist.\n", n
);
1067 static int pa_cli_command_kill_client(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1072 pa_core_assert_ref(c
);
1077 if (!(n
= pa_tokenizer_get(t
, 1))) {
1078 pa_strbuf_puts(buf
, "You need to specify a client by its index.\n");
1082 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1083 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1087 if (!(client
= pa_idxset_get_by_index(c
->clients
, idx
))) {
1088 pa_strbuf_puts(buf
, "No client found by this index.\n");
1092 pa_client_kill(client
);
1096 static int pa_cli_command_kill_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1098 pa_sink_input
*sink_input
;
1101 pa_core_assert_ref(c
);
1106 if (!(n
= pa_tokenizer_get(t
, 1))) {
1107 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
1111 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1112 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1116 if (!(sink_input
= pa_idxset_get_by_index(c
->sink_inputs
, idx
))) {
1117 pa_strbuf_puts(buf
, "No sink input found by this index.\n");
1121 pa_sink_input_kill(sink_input
);
1125 static int pa_cli_command_kill_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1127 pa_source_output
*source_output
;
1130 pa_core_assert_ref(c
);
1135 if (!(n
= pa_tokenizer_get(t
, 1))) {
1136 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1140 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1141 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1145 if (!(source_output
= pa_idxset_get_by_index(c
->source_outputs
, idx
))) {
1146 pa_strbuf_puts(buf
, "No source output found by this index.\n");
1150 pa_source_output_kill(source_output
);
1154 static int pa_cli_command_scache_list(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1157 pa_core_assert_ref(c
);
1162 pa_assert_se(s
= pa_scache_list_to_string(c
));
1163 pa_strbuf_puts(buf
, s
);
1169 static int pa_cli_command_scache_play(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1170 const char *n
, *sink_name
;
1174 pa_core_assert_ref(c
);
1179 if (!(n
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1180 pa_strbuf_puts(buf
, "You need to specify a sample name and a sink name.\n");
1184 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1185 pa_strbuf_puts(buf
, "No sink by that name.\n");
1189 if (pa_scache_play_item(c
, n
, sink
, PA_VOLUME_NORM
, NULL
, &idx
) < 0) {
1190 pa_strbuf_puts(buf
, "Failed to play sample.\n");
1194 pa_strbuf_printf(buf
, "Playing on sink input #%i\n", idx
);
1199 static int pa_cli_command_scache_remove(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1202 pa_core_assert_ref(c
);
1207 if (!(n
= pa_tokenizer_get(t
, 1))) {
1208 pa_strbuf_puts(buf
, "You need to specify a sample name.\n");
1212 if (pa_scache_remove_item(c
, n
) < 0) {
1213 pa_strbuf_puts(buf
, "Failed to remove sample.\n");
1220 static int pa_cli_command_scache_load(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1221 const char *fname
, *n
;
1224 pa_core_assert_ref(c
);
1229 if (!(fname
= pa_tokenizer_get(t
, 2)) || !(n
= pa_tokenizer_get(t
, 1))) {
1230 pa_strbuf_puts(buf
, "You need to specify a file name and a sample name.\n");
1234 if (strstr(pa_tokenizer_get(t
, 0), "lazy"))
1235 r
= pa_scache_add_file_lazy(c
, n
, fname
, NULL
);
1237 r
= pa_scache_add_file(c
, n
, fname
, NULL
);
1240 pa_strbuf_puts(buf
, "Failed to load sound file.\n");
1245 static int pa_cli_command_scache_load_dir(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1248 pa_core_assert_ref(c
);
1253 if (!(pname
= pa_tokenizer_get(t
, 1))) {
1254 pa_strbuf_puts(buf
, "You need to specify a path name.\n");
1258 if (pa_scache_add_directory_lazy(c
, pname
) < 0) {
1259 pa_strbuf_puts(buf
, "Failed to load directory.\n");
1266 static int pa_cli_command_play_file(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1267 const char *fname
, *sink_name
;
1270 pa_core_assert_ref(c
);
1275 if (!(fname
= pa_tokenizer_get(t
, 1)) || !(sink_name
= pa_tokenizer_get(t
, 2))) {
1276 pa_strbuf_puts(buf
, "You need to specify a file name and a sink name.\n");
1280 if (!(sink
= pa_namereg_get(c
, sink_name
, PA_NAMEREG_SINK
))) {
1281 pa_strbuf_puts(buf
, "No sink by that name.\n");
1286 return pa_play_file(sink
, fname
, NULL
);
1289 static int pa_cli_command_list_shared_props(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1290 pa_core_assert_ref(c
);
1295 pa_shared_dump(c
, buf
);
1299 static int pa_cli_command_vacuum(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1300 pa_core_assert_ref(c
);
1305 pa_mempool_vacuum(c
->mempool
);
1310 static int pa_cli_command_move_sink_input(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1316 pa_core_assert_ref(c
);
1321 if (!(n
= pa_tokenizer_get(t
, 1))) {
1322 pa_strbuf_puts(buf
, "You need to specify a sink input by its index.\n");
1326 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1327 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1331 if (!(k
= pa_tokenizer_get(t
, 2))) {
1332 pa_strbuf_puts(buf
, "You need to specify a sink.\n");
1336 if (!(si
= pa_idxset_get_by_index(c
->sink_inputs
, (uint32_t) idx
))) {
1337 pa_strbuf_puts(buf
, "No sink input found with this index.\n");
1341 if (!(sink
= pa_namereg_get(c
, k
, PA_NAMEREG_SINK
))) {
1342 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1346 if (pa_sink_input_move_to(si
, sink
, TRUE
) < 0) {
1347 pa_strbuf_puts(buf
, "Moved failed.\n");
1353 static int pa_cli_command_move_source_output(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1355 pa_source_output
*so
;
1359 pa_core_assert_ref(c
);
1364 if (!(n
= pa_tokenizer_get(t
, 1))) {
1365 pa_strbuf_puts(buf
, "You need to specify a source output by its index.\n");
1369 if ((idx
= parse_index(n
)) == PA_IDXSET_INVALID
) {
1370 pa_strbuf_puts(buf
, "Failed to parse index.\n");
1374 if (!(k
= pa_tokenizer_get(t
, 2))) {
1375 pa_strbuf_puts(buf
, "You need to specify a source.\n");
1379 if (!(so
= pa_idxset_get_by_index(c
->source_outputs
, (uint32_t) idx
))) {
1380 pa_strbuf_puts(buf
, "No source output found with this index.\n");
1384 if (!(source
= pa_namereg_get(c
, k
, PA_NAMEREG_SOURCE
))) {
1385 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1389 if (pa_source_output_move_to(so
, source
, TRUE
) < 0) {
1390 pa_strbuf_puts(buf
, "Moved failed.\n");
1396 static int pa_cli_command_suspend_sink(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1401 pa_core_assert_ref(c
);
1406 if (!(n
= pa_tokenizer_get(t
, 1))) {
1407 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1411 if (!(m
= pa_tokenizer_get(t
, 2))) {
1412 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1416 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1417 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1421 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1422 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1426 pa_log_debug("%s of sink %s requested via CLI.", suspend
? "Suspending" : "Resuming", sink
->name
);
1428 if ((r
= pa_sink_suspend(sink
, suspend
, PA_SUSPEND_USER
)) < 0)
1429 pa_strbuf_printf(buf
, "Failed to resume/suspend sink: %s\n", pa_strerror(r
));
1434 static int pa_cli_command_suspend_source(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1439 pa_core_assert_ref(c
);
1444 if (!(n
= pa_tokenizer_get(t
, 1))) {
1445 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1449 if (!(m
= pa_tokenizer_get(t
, 2))) {
1450 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1454 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1455 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1459 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1460 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1464 pa_log_debug("%s of source %s requested via CLI.", suspend
? "Suspending" : "Resuming", source
->name
);
1466 if ((r
= pa_source_suspend(source
, suspend
, PA_SUSPEND_USER
)) < 0)
1467 pa_strbuf_printf(buf
, "Failed to resume/suspend source: %s\n", pa_strerror(r
));
1472 static int pa_cli_command_suspend(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1476 pa_core_assert_ref(c
);
1481 if (!(m
= pa_tokenizer_get(t
, 1))) {
1482 pa_strbuf_puts(buf
, "You need to specify a suspend switch setting (0/1).\n");
1486 if ((suspend
= pa_parse_boolean(m
)) < 0) {
1487 pa_strbuf_puts(buf
, "Failed to parse suspend switch.\n");
1491 pa_log_debug("%s of all sinks and sources requested via CLI.", suspend
? "Suspending" : "Resuming");
1493 if ((r
= pa_sink_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1494 pa_strbuf_printf(buf
, "Failed to resume/suspend all sinks: %s\n", pa_strerror(r
));
1496 if ((r
= pa_source_suspend_all(c
, suspend
, PA_SUSPEND_USER
)) < 0)
1497 pa_strbuf_printf(buf
, "Failed to resume/suspend all sources: %s\n", pa_strerror(r
));
1502 static int pa_cli_command_log_target(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1505 pa_core_assert_ref(c
);
1510 if (!(m
= pa_tokenizer_get(t
, 1))) {
1511 pa_strbuf_puts(buf
, "You need to specify a log target (null,auto,syslog,stderr,file:PATH).\n");
1515 if (pa_streq(m
, "null"))
1516 pa_log_set_target(PA_LOG_NULL
);
1517 else if (pa_streq(m
, "syslog"))
1518 pa_log_set_target(PA_LOG_SYSLOG
);
1519 else if (pa_streq(m
, "stderr") || pa_streq(m
, "auto")) {
1520 /* 'auto' is actually the effect with 'stderr' */
1521 pa_log_set_target(PA_LOG_STDERR
);
1522 } else if (pa_startswith(m
, "file:")) {
1523 const char *file_path
= m
+ 5;
1526 /* Open target file with user rights */
1527 if ((log_fd
= open(file_path
, O_RDWR
|O_TRUNC
|O_CREAT
, S_IRUSR
| S_IWUSR
)) >= 0) {
1528 pa_log_set_target(PA_LOG_FD
);
1529 pa_log_set_fd(log_fd
);
1531 pa_strbuf_printf(buf
, "Failed to open target file %s, error : %s\n", file_path
, pa_cstrerror(errno
));
1535 pa_strbuf_puts(buf
, "You need to specify a log target (null,auto,syslog,stderr,file:PATH).\n");
1542 static int pa_cli_command_log_level(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1546 pa_core_assert_ref(c
);
1551 if (!(m
= pa_tokenizer_get(t
, 1))) {
1552 pa_strbuf_puts(buf
, "You need to specify a log level (0..4).\n");
1556 if (pa_atou(m
, &level
) < 0 || level
>= PA_LOG_LEVEL_MAX
) {
1557 pa_strbuf_puts(buf
, "Failed to parse log level.\n");
1561 pa_log_set_level(level
);
1566 static int pa_cli_command_log_meta(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1570 pa_core_assert_ref(c
);
1575 if (!(m
= pa_tokenizer_get(t
, 1))) {
1576 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1580 if ((b
= pa_parse_boolean(m
)) < 0) {
1581 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1585 pa_log_set_flags(PA_LOG_PRINT_META
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1590 static int pa_cli_command_log_time(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1594 pa_core_assert_ref(c
);
1599 if (!(m
= pa_tokenizer_get(t
, 1))) {
1600 pa_strbuf_puts(buf
, "You need to specify a boolean.\n");
1604 if ((b
= pa_parse_boolean(m
)) < 0) {
1605 pa_strbuf_puts(buf
, "Failed to parse log meta switch.\n");
1609 pa_log_set_flags(PA_LOG_PRINT_TIME
, b
? PA_LOG_SET
: PA_LOG_UNSET
);
1614 static int pa_cli_command_log_backtrace(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1618 pa_core_assert_ref(c
);
1623 if (!(m
= pa_tokenizer_get(t
, 1))) {
1624 pa_strbuf_puts(buf
, "You need to specify a backtrace level.\n");
1628 if (pa_atou(m
, &nframes
) < 0 || nframes
>= 1000) {
1629 pa_strbuf_puts(buf
, "Failed to parse backtrace level.\n");
1633 pa_log_set_show_backtrace(nframes
);
1638 static int pa_cli_command_card_profile(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1642 pa_core_assert_ref(c
);
1647 if (!(n
= pa_tokenizer_get(t
, 1))) {
1648 pa_strbuf_puts(buf
, "You need to specify a card either by its name or its index.\n");
1652 if (!(p
= pa_tokenizer_get(t
, 2))) {
1653 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1657 if (!(card
= pa_namereg_get(c
, n
, PA_NAMEREG_CARD
))) {
1658 pa_strbuf_puts(buf
, "No card found by this name or index.\n");
1662 if (pa_card_set_profile(card
, p
, TRUE
) < 0) {
1663 pa_strbuf_printf(buf
, "Failed to set card profile to '%s'.\n", p
);
1670 static int pa_cli_command_sink_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1674 pa_core_assert_ref(c
);
1679 if (!(n
= pa_tokenizer_get(t
, 1))) {
1680 pa_strbuf_puts(buf
, "You need to specify a sink either by its name or its index.\n");
1684 if (!(p
= pa_tokenizer_get(t
, 2))) {
1685 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1689 if (!(sink
= pa_namereg_get(c
, n
, PA_NAMEREG_SINK
))) {
1690 pa_strbuf_puts(buf
, "No sink found by this name or index.\n");
1694 if (pa_sink_set_port(sink
, p
, TRUE
) < 0) {
1695 pa_strbuf_printf(buf
, "Failed to set sink port to '%s'.\n", p
);
1702 static int pa_cli_command_source_port(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1706 pa_core_assert_ref(c
);
1711 if (!(n
= pa_tokenizer_get(t
, 1))) {
1712 pa_strbuf_puts(buf
, "You need to specify a source either by its name or its index.\n");
1716 if (!(p
= pa_tokenizer_get(t
, 2))) {
1717 pa_strbuf_puts(buf
, "You need to specify a profile by its name.\n");
1721 if (!(source
= pa_namereg_get(c
, n
, PA_NAMEREG_SOURCE
))) {
1722 pa_strbuf_puts(buf
, "No source found by this name or index.\n");
1726 if (pa_source_set_port(source
, p
, TRUE
) < 0) {
1727 pa_strbuf_printf(buf
, "Failed to set source port to '%s'.\n", p
);
1734 static int pa_cli_command_port_offset(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1735 const char *n
, *p
, *l
;
1736 pa_device_port
*port
;
1740 pa_core_assert_ref(c
);
1745 if (!(n
= pa_tokenizer_get(t
, 1))) {
1746 pa_strbuf_puts(buf
, "You need to specify a card either by its name or its index.\n");
1750 if (!(p
= pa_tokenizer_get(t
, 2))) {
1751 pa_strbuf_puts(buf
, "You need to specify a port by its name.\n");
1755 if (!(l
= pa_tokenizer_get(t
, 3))) {
1756 pa_strbuf_puts(buf
, "You need to specify a latency offset.\n");
1760 if (pa_atoi(l
, &offset
) < 0) {
1761 pa_strbuf_puts(buf
, "Failed to parse the latency offset.\n");
1765 if (!(card
= pa_namereg_get(c
, n
, PA_NAMEREG_CARD
))) {
1766 pa_strbuf_puts(buf
, "No card found by this name or index.\n");
1770 if (!(port
= pa_hashmap_get(card
->ports
, p
))) {
1771 pa_strbuf_puts(buf
, "No port found by this name.\n");
1775 pa_device_port_set_latency_offset(port
, offset
);
1780 static int pa_cli_command_dump(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1792 pa_core_assert_ref(c
);
1800 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime_r(&now
, txt
));
1802 pa_strbuf_printf(buf
, "### Configuration dump generated at %s\n", ctime(&now
));
1805 PA_IDXSET_FOREACH(m
, c
->modules
, idx
) {
1807 pa_strbuf_printf(buf
, "load-module %s", m
->name
);
1810 pa_strbuf_printf(buf
, " %s", m
->argument
);
1812 pa_strbuf_puts(buf
, "\n");
1816 PA_IDXSET_FOREACH(sink
, c
->sinks
, idx
) {
1819 pa_strbuf_puts(buf
, "\n");
1823 pa_strbuf_printf(buf
, "set-sink-volume %s 0x%03x\n", sink
->name
, pa_cvolume_max(pa_sink_get_volume(sink
, FALSE
)));
1824 pa_strbuf_printf(buf
, "set-sink-mute %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_mute(sink
, FALSE
)));
1825 pa_strbuf_printf(buf
, "suspend-sink %s %s\n", sink
->name
, pa_yes_no(pa_sink_get_state(sink
) == PA_SINK_SUSPENDED
));
1829 PA_IDXSET_FOREACH(source
, c
->sources
, idx
) {
1832 pa_strbuf_puts(buf
, "\n");
1836 pa_strbuf_printf(buf
, "set-source-volume %s 0x%03x\n", source
->name
, pa_cvolume_max(pa_source_get_volume(source
, FALSE
)));
1837 pa_strbuf_printf(buf
, "set-source-mute %s %s\n", source
->name
, pa_yes_no(pa_source_get_mute(source
, FALSE
)));
1838 pa_strbuf_printf(buf
, "suspend-source %s %s\n", source
->name
, pa_yes_no(pa_source_get_state(source
) == PA_SOURCE_SUSPENDED
));
1842 PA_IDXSET_FOREACH(card
, c
->cards
, idx
) {
1845 pa_strbuf_puts(buf
, "\n");
1849 pa_strbuf_printf(buf
, "set-card-profile %s %s\n", card
->name
, card
->active_profile
->name
);
1853 if ((sink
= pa_namereg_get_default_sink(c
))) {
1855 pa_strbuf_puts(buf
, "\n");
1859 pa_strbuf_printf(buf
, "set-default-sink %s\n", sink
->name
);
1862 if ((source
= pa_namereg_get_default_source(c
))) {
1864 pa_strbuf_puts(buf
, "\n");
1866 pa_strbuf_printf(buf
, "set-default-source %s\n", source
->name
);
1869 pa_strbuf_puts(buf
, "\n### EOF\n");
1874 static int pa_cli_command_dump_volumes(pa_core
*c
, pa_tokenizer
*t
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
1878 pa_source_output
*o
;
1879 uint32_t s_idx
, i_idx
;
1880 char v_str
[PA_CVOLUME_SNPRINT_MAX
];
1882 pa_core_assert_ref(c
);
1887 PA_IDXSET_FOREACH(s
, c
->sinks
, s_idx
) {
1888 pa_strbuf_printf(buf
, "Sink %d: ", s_idx
);
1889 pa_strbuf_printf(buf
, "reference = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->reference_volume
));
1890 pa_strbuf_printf(buf
, "real = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->real_volume
));
1891 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->soft_volume
));
1892 pa_strbuf_printf(buf
, "current_hw = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &s
->thread_info
.current_hw_volume
));
1893 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(s
->save_volume
));
1895 PA_IDXSET_FOREACH(i
, s
->inputs
, i_idx
) {
1896 pa_strbuf_printf(buf
, "\tInput %d: ", i_idx
);
1897 pa_strbuf_printf(buf
, "volume = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->volume
));
1898 pa_strbuf_printf(buf
, "reference_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->reference_ratio
));
1899 pa_strbuf_printf(buf
, "real_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->real_ratio
));
1900 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->soft_volume
));
1901 pa_strbuf_printf(buf
, "volume_factor = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->volume_factor
));
1902 pa_strbuf_printf(buf
, "volume_factor_sink = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &i
->volume_factor_sink
));
1903 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(i
->save_volume
));
1907 PA_IDXSET_FOREACH(so
, c
->sources
, s_idx
) {
1908 pa_strbuf_printf(buf
, "Source %d: ", s_idx
);
1909 pa_strbuf_printf(buf
, "reference = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->reference_volume
));
1910 pa_strbuf_printf(buf
, "real = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->real_volume
));
1911 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->soft_volume
));
1912 pa_strbuf_printf(buf
, "current_hw = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &so
->thread_info
.current_hw_volume
));
1913 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(so
->save_volume
));
1915 PA_IDXSET_FOREACH(o
, so
->outputs
, i_idx
) {
1916 pa_strbuf_printf(buf
, "\tOutput %d: ", i_idx
);
1917 pa_strbuf_printf(buf
, "volume = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->volume
));
1918 pa_strbuf_printf(buf
, "reference_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->reference_ratio
));
1919 pa_strbuf_printf(buf
, "real_ratio = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->real_ratio
));
1920 pa_strbuf_printf(buf
, "soft = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->soft_volume
));
1921 pa_strbuf_printf(buf
, "volume_factor = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->volume_factor
));
1922 pa_strbuf_printf(buf
, "volume_factor_source = %s, ", pa_cvolume_snprint(v_str
, sizeof(v_str
), &o
->volume_factor_source
));
1923 pa_strbuf_printf(buf
, "save = %s\n", pa_yes_no(o
->save_volume
));
1930 int pa_cli_command_execute_line_stateful(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
, int *ifstate
) {
1937 cs
= s
+strspn(s
, whitespace
);
1939 if (*cs
== '#' || !*cs
)
1941 else if (*cs
== '.') {
1942 if (!strcmp(cs
, META_ELSE
)) {
1943 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1944 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1946 } else if (*ifstate
== IFSTATE_TRUE
)
1947 *ifstate
= IFSTATE_FALSE
;
1949 *ifstate
= IFSTATE_TRUE
;
1951 } else if (!strcmp(cs
, META_ENDIF
)) {
1952 if (!ifstate
|| *ifstate
== IFSTATE_NONE
) {
1953 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
1956 *ifstate
= IFSTATE_NONE
;
1959 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
1961 if (!strcmp(cs
, META_FAIL
))
1963 else if (!strcmp(cs
, META_NOFAIL
))
1967 l
= strcspn(cs
, whitespace
);
1969 if (l
== sizeof(META_INCLUDE
)-1 && !strncmp(cs
, META_INCLUDE
, l
)) {
1971 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
1973 if (stat(filename
, &st
) < 0) {
1974 pa_log_warn("stat('%s'): %s", filename
, pa_cstrerror(errno
));
1978 if (S_ISDIR(st
.st_mode
)) {
1981 if (!(d
= opendir(filename
))) {
1982 pa_log_warn("Failed to read '%s': %s", filename
, pa_cstrerror(errno
));
1987 char **sorted_files
;
1989 pa_bool_t failed
= FALSE
;
1990 pa_dynarray
*files
= pa_dynarray_new();
1992 while ((de
= readdir(d
))) {
1994 size_t flen
= strlen(de
->d_name
);
1999 extn
= &de
->d_name
[flen
-3];
2000 if (strncmp(extn
, ".pa", 3) == 0)
2001 pa_dynarray_append(files
, pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", filename
, de
->d_name
));
2006 count
= pa_dynarray_size(files
);
2007 sorted_files
= pa_xnew(char*, count
);
2008 for (i
= 0; i
< count
; ++i
)
2009 sorted_files
[i
] = pa_dynarray_get(files
, i
);
2010 pa_dynarray_free(files
, NULL
);
2012 for (i
= 0; i
< count
; ++i
) {
2013 for (unsigned j
= 0; j
< count
; ++j
) {
2014 if (strcmp(sorted_files
[i
], sorted_files
[j
]) < 0) {
2015 char *tmp
= sorted_files
[i
];
2016 sorted_files
[i
] = sorted_files
[j
];
2017 sorted_files
[j
] = tmp
;
2022 for (i
= 0; i
< count
; ++i
) {
2024 if (pa_cli_command_execute_file(c
, sorted_files
[i
], buf
, fail
) < 0 && *fail
)
2028 pa_xfree(sorted_files
[i
]);
2030 pa_xfree(sorted_files
);
2034 } else if (pa_cli_command_execute_file(c
, filename
, buf
, fail
) < 0 && *fail
) {
2038 } else if (l
== sizeof(META_IFEXISTS
)-1 && !strncmp(cs
, META_IFEXISTS
, l
)) {
2040 pa_strbuf_printf(buf
, "Meta command %s is not valid in this context\n", cs
);
2042 } else if (*ifstate
!= IFSTATE_NONE
) {
2043 pa_strbuf_printf(buf
, "Nested %s commands not supported\n", cs
);
2046 const char *filename
= cs
+l
+strspn(cs
+l
, whitespace
);
2048 /* Search DL_SEARCH_PATH unless the filename is absolute */
2049 if (filename
[0] == PA_PATH_SEP_CHAR
) {
2051 *ifstate
= access(filename
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
2052 pa_log_debug("Checking for existence of '%s': %s", filename
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
2055 const char *paths
, *state
= NULL
;
2058 if (!(paths
= lt_dlgetsearchpath()))
2061 while ((p
= pa_split(paths
, ":", &state
))) {
2064 pathname
= pa_sprintf_malloc("%s" PA_PATH_SEP
"%s", p
, filename
);
2066 *ifstate
= access(pathname
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
2067 pa_log_debug("Checking for existence of '%s': %s", pathname
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
2069 if (PA_UNLIKELY(pa_run_from_build_tree())) {
2070 /* If run from the build tree, search in <path>/.libs as well */
2071 char *ltpathname
= pa_sprintf_malloc("%s" PA_PATH_SEP
".libs" PA_PATH_SEP
"%s", p
, filename
);
2073 *ifstate
= access(ltpathname
, F_OK
) == 0 ? IFSTATE_TRUE
: IFSTATE_FALSE
;
2074 pa_log_debug("Checking for existence of '%s': %s", ltpathname
, *ifstate
== IFSTATE_TRUE
? "success" : "failure");
2076 pa_xfree(ltpathname
);
2082 if (*ifstate
== IFSTATE_TRUE
)
2089 pa_strbuf_printf(buf
, "Invalid meta command: %s\n", cs
);
2090 if (*fail
) return -1;
2094 const struct command
*command
;
2098 if (ifstate
&& *ifstate
== IFSTATE_FALSE
)
2101 l
= strcspn(cs
, whitespace
);
2103 for (command
= commands
; command
->name
; command
++)
2104 if (strlen(command
->name
) == l
&& !strncmp(cs
, command
->name
, l
)) {
2106 pa_tokenizer
*t
= pa_tokenizer_new(cs
, command
->args
);
2108 ret
= command
->proc(c
, t
, buf
, fail
);
2109 pa_tokenizer_free(t
);
2112 if (ret
< 0 && *fail
)
2119 pa_strbuf_printf(buf
, "Unknown command: %s\n", cs
);
2128 int pa_cli_command_execute_line(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
2129 return pa_cli_command_execute_line_stateful(c
, s
, buf
, fail
, NULL
);
2132 int pa_cli_command_execute_file_stream(pa_core
*c
, FILE *f
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
2134 int ifstate
= IFSTATE_NONE
;
2136 pa_bool_t _fail
= TRUE
;
2145 while (fgets(line
, sizeof(line
), f
)) {
2148 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
)
2159 int pa_cli_command_execute_file(pa_core
*c
, const char *fn
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
2162 pa_bool_t _fail
= TRUE
;
2171 if (!(f
= pa_fopen_cloexec(fn
, "r"))) {
2172 pa_strbuf_printf(buf
, "open('%s') failed: %s\n", fn
, pa_cstrerror(errno
));
2178 pa_log_debug("Parsing script '%s'", fn
);
2179 ret
= pa_cli_command_execute_file_stream(c
, f
, buf
, fail
);
2188 int pa_cli_command_execute(pa_core
*c
, const char *s
, pa_strbuf
*buf
, pa_bool_t
*fail
) {
2190 int ifstate
= IFSTATE_NONE
;
2191 pa_bool_t _fail
= TRUE
;
2202 size_t l
= strcspn(p
, linebreak
);
2203 char *line
= pa_xstrndup(p
, l
);
2205 if (pa_cli_command_execute_line_stateful(c
, line
, buf
, fail
, &ifstate
) < 0 && *fail
) {
2212 p
+= strspn(p
, linebreak
);