#include <pulsecore/log.h>
#include <pulsecore/sndfile-util.h>
-#define BUFSIZE (16*1024)
-
static pa_context *context = NULL;
static pa_mainloop_api *mainloop_api = NULL;
-static char *device = NULL, *sample_name = NULL, *sink_name = NULL, *source_name = NULL, *module_name = NULL, *module_args = NULL, *card_name = NULL, *profile_name = NULL;
-static uint32_t sink_input_idx = PA_INVALID_INDEX, source_output_idx = PA_INVALID_INDEX;
+static char
+ *sample_name = NULL,
+ *sink_name = NULL,
+ *source_name = NULL,
+ *module_name = NULL,
+ *module_args = NULL,
+ *card_name = NULL,
+ *profile_name = NULL,
+ *port_name = NULL;
+
+static uint32_t
+ sink_input_idx = PA_INVALID_INDEX,
+ source_output_idx = PA_INVALID_INDEX;
+
static uint32_t module_index;
static pa_bool_t suspend;
+static pa_bool_t mute;
+static pa_volume_t volume;
static pa_proplist *proplist = NULL;
static pa_sample_spec sample_spec;
static pa_channel_map channel_map;
static size_t sample_length = 0;
-
static int actions = 1;
static pa_bool_t nl = FALSE;
UNLOAD_MODULE,
SUSPEND_SINK,
SUSPEND_SOURCE,
- SET_CARD_PROFILE
+ SET_CARD_PROFILE,
+ SET_SINK_PORT,
+ SET_SOURCE_PORT,
+ SET_SINK_VOLUME,
+ SET_SOURCE_VOLUME,
+ SET_SINK_INPUT_VOLUME,
+ SET_SINK_MUTE,
+ SET_SOURCE_MUTE,
+ SET_SINK_INPUT_MUTE
} action = NONE;
static void quit(int ret) {
static void drain(void) {
pa_operation *o;
+
if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
pa_context_disconnect(context);
else
}
static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) {
- char s[128];
+ char s[PA_BYTES_SNPRINT_MAX];
if (!i) {
- pa_log(_("Failed to get statistics: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get statistics: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
if (!i) {
- pa_log(_("Failed to get server information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get server information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
+ printf(_("Server String: %s\n"
+ "Library Protocol Version: %u\n"
+ "Server Protocol Version: %u\n"
+ "Is Local: %s\n"
+ "Client Index: %u\n"
+ "Tile Size: %zu\n"),
+ pa_context_get_server(c),
+ pa_context_get_protocol_version(c),
+ pa_context_get_server_protocol_version(c),
+ pa_yes_no(pa_context_is_local(c)),
+ pa_context_get_index(c),
+ pa_context_get_tile_size(c, NULL));
+
pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map);
- printf(_("User name: %s\n"
+ printf(_("User Name: %s\n"
"Host Name: %s\n"
"Server Name: %s\n"
"Server Version: %s\n"
"Default Channel Map: %s\n"
"Default Sink: %s\n"
"Default Source: %s\n"
- "Cookie: %08x\n"),
+ "Cookie: %04x:%04x\n"),
i->user_name,
i->host_name,
i->server_name,
cm,
i->default_sink_name,
i->default_source_name,
- i->cookie);
+ i->cookie >> 16,
+ i->cookie & 0xFFFFU);
complete_action();
}
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get sink information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get sink information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
pa_xfree(pl);
+
+ if (i->ports) {
+ pa_sink_port_info **p;
+
+ printf(_("\tPorts:\n"));
+ for (p = i->ports; *p; p++)
+ printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description, (*p)->priority);
+ }
+
+ if (i->active_port)
+ printf(_("\tActive Port: %s\n"),
+ i->active_port->name);
}
static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get source information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get source information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
pa_xfree(pl);
+
+ if (i->ports) {
+ pa_source_port_info **p;
+
+ printf(_("\tPorts:\n"));
+ for (p = i->ports; *p; p++)
+ printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description, (*p)->priority);
+ }
+
+ if (i->active_port)
+ printf(_("\tActive Port: %s\n"),
+ i->active_port->name);
}
static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) {
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get module information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get module information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get client information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get client information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get card information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get card information: %s"), pa_strerror(pa_context_errno(c)));
complete_action();
return;
}
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get sink input information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get sink input information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get source output information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get source output information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
}
static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) {
- char t[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
+ char t[PA_BYTES_SNPRINT_MAX], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cv[PA_CVOLUME_SNPRINT_MAX], cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
char *pl;
if (is_last < 0) {
- pa_log(_("Failed to get sample information: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failed to get sample information: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
static void simple_callback(pa_context *c, int success, void *userdata) {
if (!success) {
- pa_log(_("Failure: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
static void index_callback(pa_context *c, uint32_t idx, void *userdata) {
if (idx == PA_INVALID_INDEX) {
- pa_log(_("Failure: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
return;
}
case PA_STREAM_FAILED:
default:
- pa_log(_("Failed to upload sample: %s\n"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
+ pa_log(_("Failed to upload sample: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
quit(1);
}
}
if ((sf_readf_float(sndfile, d, l)) != l) {
pa_xfree(d);
- pa_log(_("Premature end of file\n"));
+ pa_log(_("Premature end of file"));
quit(1);
return;
}
break;
case PLAY_SAMPLE:
- pa_operation_unref(pa_context_play_sample(c, sample_name, device, PA_VOLUME_NORM, simple_callback, NULL));
+ pa_operation_unref(pa_context_play_sample(c, sample_name, sink_name, PA_VOLUME_NORM, simple_callback, NULL));
break;
case REMOVE_SAMPLE:
pa_operation_unref(pa_context_set_card_profile_by_name(c, card_name, profile_name, simple_callback, NULL));
break;
+ case SET_SINK_PORT:
+ pa_operation_unref(pa_context_set_sink_port_by_name(c, sink_name, port_name, simple_callback, NULL));
+ break;
+
+ case SET_SOURCE_PORT:
+ pa_operation_unref(pa_context_set_source_port_by_name(c, source_name, port_name, simple_callback, NULL));
+ break;
+
+ case SET_SINK_MUTE:
+ pa_operation_unref(pa_context_set_sink_mute_by_name(c, sink_name, mute, simple_callback, NULL));
+ break;
+
+ case SET_SOURCE_MUTE:
+ pa_operation_unref(pa_context_set_source_mute_by_name(c, source_name, mute, simple_callback, NULL));
+ break;
+
+ case SET_SINK_INPUT_MUTE:
+ pa_operation_unref(pa_context_set_sink_input_mute(c, sink_input_idx, mute, simple_callback, NULL));
+ break;
+
+ case SET_SINK_VOLUME: {
+ pa_cvolume v;
+
+ pa_cvolume_set(&v, 1, volume);
+ pa_operation_unref(pa_context_set_sink_volume_by_name(c, sink_name, &v, simple_callback, NULL));
+ break;
+ }
+
+ case SET_SOURCE_VOLUME: {
+ pa_cvolume v;
+
+ pa_cvolume_set(&v, 1, volume);
+ pa_operation_unref(pa_context_set_source_volume_by_name(c, source_name, &v, simple_callback, NULL));
+ break;
+ }
+
+ case SET_SINK_INPUT_VOLUME: {
+ pa_cvolume v;
+
+ pa_cvolume_set(&v, 1, volume);
+ pa_operation_unref(pa_context_set_sink_input_volume(c, sink_input_idx, &v, simple_callback, NULL));
+ break;
+ }
+
default:
pa_assert_not_reached();
}
case PA_CONTEXT_FAILED:
default:
- pa_log(_("Connection failure: %s\n"), pa_strerror(pa_context_errno(c)));
+ pa_log(_("Connection failure: %s"), pa_strerror(pa_context_errno(c)));
quit(1);
}
}
static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) {
- pa_log(_("Got SIGINT, exiting.\n"));
+ pa_log(_("Got SIGINT, exiting."));
quit(0);
}
"%s [options] upload-sample FILENAME [NAME]\n"
"%s [options] play-sample NAME [SINK]\n"
"%s [options] remove-sample NAME\n"
- "%s [options] move-sink-input ID SINK\n"
- "%s [options] move-source-output ID SOURCE\n"
+ "%s [options] move-sink-input SINKINPUT SINK\n"
+ "%s [options] move-source-output SOURCEOUTPUT SOURCE\n"
"%s [options] load-module NAME [ARGS ...]\n"
- "%s [options] unload-module ID\n"
- "%s [options] suspend-sink [SINK] 1|0\n"
- "%s [options] suspend-source [SOURCE] 1|0\n"
- "%s [options] set-card-profile [CARD] [PROFILE] \n\n"
+ "%s [options] unload-module MODULE\n"
+ "%s [options] suspend-sink SINK 1|0\n"
+ "%s [options] suspend-source SOURCE 1|0\n"
+ "%s [options] set-card-profile CARD PROFILE\n"
+ "%s [options] set-sink-port SINK PORT\n"
+ "%s [options] set-source-port SOURCE PORT\n"
+ "%s [options] set-sink-volume SINK VOLUME\n"
+ "%s [options] set-source-volume SOURCE VOLUME\n"
+ "%s [options] set-sink-input-volume SINKINPUT VOLUME\n"
+ "%s [options] set-sink-mute SINK 1|0\n"
+ "%s [options] set-source-mute SOURCE 1|0\n"
+ "%s [options] set-sink-input-mute SINKINPUT 1|0\n\n"
" -h, --help Show this help\n"
" --version Show version\n\n"
" -s, --server=SERVER The name of the server to connect to\n"
" -n, --client-name=NAME How to call this client on the server\n"),
- argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0, argv0);
+ argv0, argv0, argv0, argv0, argv0,
+ argv0, argv0, argv0, argv0, argv0,
+ argv0, argv0, argv0, argv0, argv0,
+ argv0, argv0, argv0, argv0, argv0,
+ argv0);
}
enum {
int main(int argc, char *argv[]) {
pa_mainloop* m = NULL;
- char tmp[PATH_MAX];
int ret = 1, c;
char *server = NULL, *bn;
if (!(t = pa_locale_to_utf8(optarg)) ||
pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) {
- pa_log(_("Invalid client name '%s'\n"), t ? t : optarg);
+ pa_log(_("Invalid client name '%s'"), t ? t : optarg);
pa_xfree(t);
goto quit;
}
action = UPLOAD_SAMPLE;
if (optind+1 >= argc) {
- pa_log(_("Please specify a sample file to load\n"));
+ pa_log(_("Please specify a sample file to load"));
goto quit;
}
if (optind+2 < argc)
sample_name = pa_xstrdup(argv[optind+2]);
else {
- char *f = strrchr(argv[optind+1], '/');
- size_t n;
- if (f)
- f++;
- else
- f = argv[optind];
-
- n = strcspn(f, ".");
- strncpy(tmp, f, n);
- tmp[n] = 0;
- sample_name = pa_xstrdup(tmp);
+ char *f = pa_path_get_filename(argv[optind+1]);
+ sample_name = pa_xstrndup(f, strcspn(f, "."));
}
pa_zero(sfi);
if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfi))) {
- pa_log(_("Failed to open sound file.\n"));
+ pa_log(_("Failed to open sound file."));
goto quit;
}
if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) {
- pa_log(_("Failed to determine sample specification from file.\n"));
+ pa_log(_("Failed to determine sample specification from file."));
goto quit;
}
sample_spec.format = PA_SAMPLE_FLOAT32;
if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) {
if (sample_spec.channels > 2)
- pa_log(_("Warning: Failed to determine sample specification from file.\n"));
+ pa_log(_("Warning: Failed to determine sample specification from file."));
pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
}
} else if (pa_streq(argv[optind], "play-sample")) {
action = PLAY_SAMPLE;
if (argc != optind+2 && argc != optind+3) {
- pa_log(_("You have to specify a sample name to play\n"));
+ pa_log(_("You have to specify a sample name to play"));
goto quit;
}
sample_name = pa_xstrdup(argv[optind+1]);
if (optind+2 < argc)
- device = pa_xstrdup(argv[optind+2]);
+ sink_name = pa_xstrdup(argv[optind+2]);
} else if (pa_streq(argv[optind], "remove-sample")) {
action = REMOVE_SAMPLE;
if (argc != optind+2) {
- pa_log(_("You have to specify a sample name to remove\n"));
+ pa_log(_("You have to specify a sample name to remove"));
goto quit;
}
} else if (pa_streq(argv[optind], "move-sink-input")) {
action = MOVE_SINK_INPUT;
if (argc != optind+3) {
- pa_log(_("You have to specify a sink input index and a sink\n"));
+ pa_log(_("You have to specify a sink input index and a sink"));
goto quit;
}
} else if (pa_streq(argv[optind], "move-source-output")) {
action = MOVE_SOURCE_OUTPUT;
if (argc != optind+3) {
- pa_log(_("You have to specify a source output index and a source\n"));
+ pa_log(_("You have to specify a source output index and a source"));
goto quit;
}
action = LOAD_MODULE;
if (argc <= optind+1) {
- pa_log(_("You have to specify a module name and arguments.\n"));
+ pa_log(_("You have to specify a module name and arguments."));
goto quit;
}
action = UNLOAD_MODULE;
if (argc != optind+2) {
- pa_log(_("You have to specify a module index\n"));
+ pa_log(_("You have to specify a module index"));
goto quit;
}
action = SUSPEND_SINK;
if (argc > optind+3 || optind+1 >= argc) {
- pa_log(_("You may not specify more than one sink. You have to specify a boolean value.\n"));
+ pa_log(_("You may not specify more than one sink. You have to specify a boolean value."));
goto quit;
}
action = SUSPEND_SOURCE;
if (argc > optind+3 || optind+1 >= argc) {
- pa_log(_("You may not specify more than one source. You have to specify a boolean value.\n"));
+ pa_log(_("You may not specify more than one source. You have to specify a boolean value."));
goto quit;
}
action = SET_CARD_PROFILE;
if (argc != optind+3) {
- pa_log(_("You have to specify a card name/index and a profile name\n"));
+ pa_log(_("You have to specify a card name/index and a profile name"));
goto quit;
}
card_name = pa_xstrdup(argv[optind+1]);
profile_name = pa_xstrdup(argv[optind+2]);
+ } else if (pa_streq(argv[optind], "set-sink-port")) {
+ action = SET_SINK_PORT;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink name/index and a port name"));
+ goto quit;
+ }
+
+ sink_name = pa_xstrdup(argv[optind+1]);
+ port_name = pa_xstrdup(argv[optind+2]);
+
+ } else if (pa_streq(argv[optind], "set-source-port")) {
+ action = SET_SOURCE_PORT;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a source name/index and a port name"));
+ goto quit;
+ }
+
+ source_name = pa_xstrdup(argv[optind+1]);
+ port_name = pa_xstrdup(argv[optind+2]);
+
+ } else if (pa_streq(argv[optind], "set-sink-volume")) {
+ uint32_t v;
+ action = SET_SINK_VOLUME;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink name/index and a volume"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+2], &v) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ sink_name = pa_xstrdup(argv[optind+1]);
+ volume = (pa_volume_t) v;
+
+ } else if (pa_streq(argv[optind], "set-source-volume")) {
+ uint32_t v;
+ action = SET_SOURCE_VOLUME;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a source name/index and a volume"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+2], &v) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ source_name = pa_xstrdup(argv[optind+1]);
+ volume = (pa_volume_t) v;
+
+ } else if (pa_streq(argv[optind], "set-sink-input-volume")) {
+ uint32_t v;
+ action = SET_SINK_INPUT_VOLUME;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink input index and a volume"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
+ pa_log(_("Invalid sink input index"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+2], &v) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ volume = (pa_volume_t) v;
+
+ } else if (pa_streq(argv[optind], "set-sink-mute")) {
+ int b;
+ action = SET_SINK_MUTE;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink name/index and a mute boolean"));
+ goto quit;
+ }
+
+ if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ sink_name = pa_xstrdup(argv[optind+1]);
+ mute = b;
+
+ } else if (pa_streq(argv[optind], "set-source-mute")) {
+ int b;
+ action = SET_SOURCE_MUTE;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a source name/index and a mute boolean"));
+ goto quit;
+ }
+
+ if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ source_name = pa_xstrdup(argv[optind+1]);
+ mute = b;
+
+ } else if (pa_streq(argv[optind], "set-sink-input-mute")) {
+ int b;
+ action = SET_SINK_INPUT_MUTE;
+
+ if (argc != optind+3) {
+ pa_log(_("You have to specify a sink input index and a mute boolean"));
+ goto quit;
+ }
+
+ if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
+ pa_log(_("Invalid sink input index specification"));
+ goto quit;
+ }
+
+ if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
+ pa_log(_("Invalid volume specification"));
+ goto quit;
+ }
+
+ mute = b;
+
} else if (pa_streq(argv[optind], "help")) {
help(bn);
ret = 0;
}
if (action == NONE) {
- pa_log(_("No valid command specified.\n"));
+ pa_log(_("No valid command specified."));
goto quit;
}
if (!(m = pa_mainloop_new())) {
- pa_log(_("pa_mainloop_new() failed.\n"));
+ pa_log(_("pa_mainloop_new() failed."));
goto quit;
}
pa_disable_sigpipe();
if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) {
- pa_log(_("pa_context_new() failed.\n"));
+ pa_log(_("pa_context_new() failed."));
goto quit;
}
}
if (pa_mainloop_run(m, &ret) < 0) {
- pa_log(_("pa_mainloop_run() failed.\n"));
+ pa_log(_("pa_mainloop_run() failed."));
goto quit;
}
}
pa_xfree(server);
- pa_xfree(device);
pa_xfree(sample_name);
pa_xfree(sink_name);
pa_xfree(source_name);