#include <ltdl.h>
#include <sys/stat.h>
#include <dirent.h>
+#include <time.h>
#include <pulse/xmalloc.h>
#include <pulse/error.h>
#include <pulsecore/namereg.h>
#include <pulsecore/cli-text.h>
#include <pulsecore/core-scache.h>
-#include <pulsecore/sample-util.h>
#include <pulsecore/sound-file.h>
#include <pulsecore/play-memchunk.h>
#include <pulsecore/sound-file-stream.h>
static int pa_cli_command_card_profile(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
static int pa_cli_command_sink_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
static int pa_cli_command_source_port(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
+static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail);
/* A method table for all available commands */
static const struct command commands[] = {
- { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
{ "help", pa_cli_command_help, "Show this help", 1 },
{ "list-modules", pa_cli_command_modules, "List loaded modules", 1 },
+ { "list-cards", pa_cli_command_cards, "List cards", 1 },
{ "list-sinks", pa_cli_command_sinks, "List loaded sinks", 1 },
{ "list-sources", pa_cli_command_sources, "List loaded sources", 1 },
{ "list-clients", pa_cli_command_clients, "List loaded clients", 1 },
{ "list-sink-inputs", pa_cli_command_sink_inputs, "List sink inputs", 1 },
{ "list-source-outputs", pa_cli_command_source_outputs, "List source outputs", 1 },
- { "list-cards", pa_cli_command_cards, "List cards", 1 },
{ "stat", pa_cli_command_stat, "Show memory block statistics", 1 },
{ "info", pa_cli_command_info, "Show comprehensive status", 1 },
{ "ls", pa_cli_command_info, NULL, 1 },
{ "unload-module", pa_cli_command_unload, "Unload a module (args: index)", 2},
{ "describe-module", pa_cli_command_describe, "Describe a module (arg: name)", 2},
{ "set-sink-volume", pa_cli_command_sink_volume, "Set the volume of a sink (args: index|name, volume)", 3},
- { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3},
{ "set-source-volume", pa_cli_command_source_volume, "Set the volume of a source (args: index|name, volume)", 3},
{ "set-sink-mute", pa_cli_command_sink_mute, "Set the mute switch of a sink (args: index|name, bool)", 3},
- { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3},
{ "set-source-mute", pa_cli_command_source_mute, "Set the mute switch of a source (args: index|name, bool)", 3},
+ { "set-sink-input-volume", pa_cli_command_sink_input_volume, "Set the volume of a sink input (args: index, volume)", 3},
+ { "set-sink-input-mute", pa_cli_command_sink_input_mute, "Set the mute switch of a sink input (args: index, bool)", 3},
+ { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2},
+ { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2},
+ { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index|name, profile-name)", 3},
+ { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index|name, port-name)", 3},
+ { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index|name, port-name)", 3},
+ { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3},
+ { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3},
+ { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2},
+ { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3},
+ { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
{ "update-sink-proplist", pa_cli_command_update_sink_proplist, "Update the properties of a sink (args: index|name, properties)", 3},
{ "update-source-proplist", pa_cli_command_update_source_proplist, "Update the properties of a source (args: index|name, properties)", 3},
{ "update-sink-input-proplist", pa_cli_command_update_sink_input_proplist, "Update the properties of a sink input (args: index, properties)", 3},
{ "update-source-output-proplist", pa_cli_command_update_source_output_proplist, "Update the properties of a source_output (args: index, properties)", 3},
- { "set-default-sink", pa_cli_command_sink_default, "Set the default sink (args: index|name)", 2},
- { "set-default-source", pa_cli_command_source_default, "Set the default source (args: index|name)", 2},
- { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
- { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
- { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
{ "list-samples", pa_cli_command_scache_list, "List all entries in the sample cache", 1},
{ "play-sample", pa_cli_command_scache_play, "Play a sample from the sample cache (args: name, sink|index)", 3},
{ "remove-sample", pa_cli_command_scache_remove, "Remove a sample from the sample cache (args: name)", 2},
{ "load-sample", pa_cli_command_scache_load, "Load a sound file into the sample cache (args: name, filename)", 3},
{ "load-sample-lazy", pa_cli_command_scache_load, "Lazily load a sound file into the sample cache (args: name, filename)", 3},
{ "load-sample-dir-lazy", pa_cli_command_scache_load_dir, "Lazily load all files in a directory into the sample cache (args: pathname)", 2},
- { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3},
- { "dump", pa_cli_command_dump, "Dump daemon configuration", 1},
- { "shared", pa_cli_command_list_shared_props, NULL, 1},
- { "move-sink-input", pa_cli_command_move_sink_input, "Move sink input to another sink (args: index, sink)", 3},
- { "move-source-output", pa_cli_command_move_source_output, "Move source output to another source (args: index, source)", 3},
- { "vacuum", pa_cli_command_vacuum, NULL, 1},
- { "suspend-sink", pa_cli_command_suspend_sink, "Suspend sink (args: index|name, bool)", 3},
- { "suspend-source", pa_cli_command_suspend_source, "Suspend source (args: index|name, bool)", 3},
- { "suspend", pa_cli_command_suspend, "Suspend all sinks and all sources (args: bool)", 2},
- { "set-card-profile", pa_cli_command_card_profile, "Change the profile of a card (args: index, name)", 3},
- { "set-sink-port", pa_cli_command_sink_port, "Change the port of a sink (args: index, name)", 3},
- { "set-source-port", pa_cli_command_source_port, "Change the port of a source (args: index, name)", 3},
+ { "kill-client", pa_cli_command_kill_client, "Kill a client (args: index)", 2},
+ { "kill-sink-input", pa_cli_command_kill_sink_input, "Kill a sink input (args: index)", 2},
+ { "kill-source-output", pa_cli_command_kill_source_output, "Kill a source output (args: index)", 2},
{ "set-log-level", pa_cli_command_log_level, "Change the log level (args: numeric level)", 2},
{ "set-log-meta", pa_cli_command_log_meta, "Show source code location in log messages (args: bool)", 2},
{ "set-log-time", pa_cli_command_log_time, "Show timestamps in log messages (args: bool)", 2},
{ "set-log-backtrace", pa_cli_command_log_backtrace, "Show backtrace in log messages (args: frames)", 2},
+ { "play-file", pa_cli_command_play_file, "Play a sound file (args: filename, sink|index)", 3},
+ { "dump", pa_cli_command_dump, "Dump daemon configuration", 1},
+ { "dump-volumes", pa_cli_command_dump_volumes, "Debug: Show the state of all volumes", 1 },
+ { "shared", pa_cli_command_list_shared_props, "Debug: Show shared properties", 1},
+ { "exit", pa_cli_command_exit, "Terminate the daemon", 1 },
+ { "vacuum", pa_cli_command_vacuum, NULL, 1},
{ NULL, NULL, NULL, 0 }
};
return -1;
}
+ if (!PA_VOLUME_IS_VALID(volume)) {
+ pa_strbuf_puts(buf, "Volume outside permissible range.\n");
+ return -1;
+ }
+
if (!(sink = pa_namereg_get(c, n, PA_NAMEREG_SINK))) {
pa_strbuf_puts(buf, "No sink found by this name or index.\n");
return -1;
return -1;
}
- if (!(si = pa_idxset_get_by_index(c->sink_inputs, (uint32_t) idx))) {
+ if (!PA_VOLUME_IS_VALID(volume)) {
+ pa_strbuf_puts(buf, "Volume outside permissible range.\n");
+ return -1;
+ }
+
+ if (!(si = pa_idxset_get_by_index(c->sink_inputs, idx))) {
pa_strbuf_puts(buf, "No sink input found with this index.\n");
return -1;
}
+ if (!si->volume_writable) {
+ pa_strbuf_puts(buf, "This sink input's volume can't be changed.\n");
+ return -1;
+ }
+
pa_cvolume_set(&cvolume, 1, volume);
pa_sink_input_set_volume(si, &cvolume, TRUE, TRUE);
return 0;
return -1;
}
+ if (!PA_VOLUME_IS_VALID(volume)) {
+ pa_strbuf_puts(buf, "Volume outside permissible range.\n");
+ return -1;
+ }
+
if (!(source = pa_namereg_get(c, n, PA_NAMEREG_SOURCE))) {
pa_strbuf_puts(buf, "No source found by this name or index.\n");
return -1;
}
pa_cvolume_set(&cvolume, 1, volume);
- pa_source_set_volume(source, &cvolume, TRUE);
+ pa_source_set_volume(source, &cvolume, TRUE, TRUE);
return 0;
}
pa_card *card;
pa_bool_t nl;
uint32_t idx;
- char txt[256];
time_t now;
+#ifdef HAVE_CTIME_R
+ char txt[256];
+#endif
pa_core_assert_ref(c);
pa_assert(t);
return 0;
}
+static int pa_cli_command_dump_volumes(pa_core *c, pa_tokenizer *t, pa_strbuf *buf, pa_bool_t *fail) {
+ pa_sink *s;
+ pa_source *so;
+ pa_sink_input *i;
+ pa_source_output *o;
+ uint32_t s_idx, i_idx;
+ char v_str[PA_CVOLUME_SNPRINT_MAX];
+
+ pa_core_assert_ref(c);
+ pa_assert(t);
+ pa_assert(buf);
+ pa_assert(fail);
+
+ PA_IDXSET_FOREACH(s, c->sinks, s_idx) {
+ pa_strbuf_printf(buf, "Sink %d: ", s_idx);
+ pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->reference_volume));
+ pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->real_volume));
+ pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->soft_volume));
+ pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &s->thread_info.current_hw_volume));
+ pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(s->save_volume));
+
+ PA_IDXSET_FOREACH(i, s->inputs, i_idx) {
+ pa_strbuf_printf(buf, "\tInput %d: ", i_idx);
+ pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume));
+ pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->reference_ratio));
+ pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->real_ratio));
+ pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->soft_volume));
+ pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor));
+ pa_strbuf_printf(buf, "volume_factor_sink = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &i->volume_factor_sink));
+ pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(i->save_volume));
+ }
+ }
+
+ PA_IDXSET_FOREACH(so, c->sources, s_idx) {
+ pa_strbuf_printf(buf, "Source %d: ", s_idx);
+ pa_strbuf_printf(buf, "reference = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->reference_volume));
+ pa_strbuf_printf(buf, "real = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->real_volume));
+ pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->soft_volume));
+ pa_strbuf_printf(buf, "current_hw = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &so->thread_info.current_hw_volume));
+ pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(so->save_volume));
+
+ PA_IDXSET_FOREACH(o, so->outputs, i_idx) {
+ pa_strbuf_printf(buf, "\tOutput %d: ", i_idx);
+ pa_strbuf_printf(buf, "volume = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume));
+ pa_strbuf_printf(buf, "reference_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->reference_ratio));
+ pa_strbuf_printf(buf, "real_ratio = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->real_ratio));
+ pa_strbuf_printf(buf, "soft = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->soft_volume));
+ pa_strbuf_printf(buf, "volume_factor = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor));
+ pa_strbuf_printf(buf, "volume_factor_source = %s, ", pa_cvolume_snprint(v_str, sizeof(v_str), &o->volume_factor_source));
+ pa_strbuf_printf(buf, "save = %s\n", pa_yes_no(o->save_volume));
+ }
+ }
+
+ return 0;
+}
+
int pa_cli_command_execute_line_stateful(pa_core *c, const char *s, pa_strbuf *buf, pa_bool_t *fail, int *ifstate) {
const char *cs;
sorted_files = pa_xnew(char*, count);
for (i = 0; i < count; ++i)
sorted_files[i] = pa_dynarray_get(files, i);
- pa_dynarray_free(files, NULL, NULL);
+ pa_dynarray_free(files, NULL);
for (i = 0; i < count; ++i) {
for (unsigned j = 0; j < count; ++j) {
if (filename[0] == PA_PATH_SEP_CHAR) {
*ifstate = access(filename, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
- pa_log_debug("Checking for existance of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
+ pa_log_debug("Checking for existence of '%s': %s", filename, *ifstate == IFSTATE_TRUE ? "success" : "failure");
} else {
const char *paths, *state = NULL;
pa_xfree(p);
*ifstate = access(pathname, F_OK) == 0 ? IFSTATE_TRUE : IFSTATE_FALSE;
- pa_log_debug("Checking for existance of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
+ pa_log_debug("Checking for existence of '%s': %s", pathname, *ifstate == IFSTATE_TRUE ? "success" : "failure");
pa_xfree(pathname);