2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
6 PulseAudio is free software; you can redistribute it and/or modify
7 it under the terms of the GNU Lesser General Public License as published
8 by the Free Software Foundation; either version 2.1 of the License,
9 or (at your option) any later version.
11 PulseAudio 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.
16 You should have received a copy of the GNU Lesser General Public License
17 along with PulseAudio; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
39 #include <pulse/i18n.h>
40 #include <pulse/pulseaudio.h>
42 #include <pulsecore/macro.h>
43 #include <pulsecore/core-util.h>
44 #include <pulsecore/log.h>
45 #include <pulsecore/sndfile-util.h>
47 #define BUFSIZE (16*1024)
49 static pa_context *context = NULL;
50 static pa_mainloop_api *mainloop_api = NULL;
63 sink_input_idx = PA_INVALID_INDEX,
64 source_output_idx = PA_INVALID_INDEX;
66 static uint32_t module_index;
67 static pa_bool_t suspend;
68 static pa_bool_t mute;
69 static pa_volume_t volume;
71 static pa_proplist *proplist = NULL;
73 static SNDFILE *sndfile = NULL;
74 static pa_stream *sample_stream = NULL;
75 static pa_sample_spec sample_spec;
76 static pa_channel_map channel_map;
77 static size_t sample_length = 0;
78 static int actions = 1;
80 static pa_bool_t nl = FALSE;
101 SET_SINK_INPUT_VOLUME,
107 static void quit(int ret) {
108 pa_assert(mainloop_api);
109 mainloop_api->quit(mainloop_api, ret);
112 static void context_drain_complete(pa_context *c, void *userdata) {
113 pa_context_disconnect(c);
116 static void drain(void) {
119 if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
120 pa_context_disconnect(context);
122 pa_operation_unref(o);
125 static void complete_action(void) {
126 pa_assert(actions > 0);
132 static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) {
133 char s[PA_BYTES_SNPRINT_MAX];
135 pa_log(_("Failed to get statistics: %s"), pa_strerror(pa_context_errno(c)));
140 pa_bytes_snprint(s, sizeof(s), i->memblock_total_size);
141 printf(_("Currently in use: %u blocks containing %s bytes total.\n"), i->memblock_total, s);
143 pa_bytes_snprint(s, sizeof(s), i->memblock_allocated_size);
144 printf(_("Allocated during whole lifetime: %u blocks containing %s bytes total.\n"), i->memblock_allocated, s);
146 pa_bytes_snprint(s, sizeof(s), i->scache_size);
147 printf(_("Sample cache size: %s\n"), s);
152 static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) {
153 char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
156 pa_log(_("Failed to get server information: %s"), pa_strerror(pa_context_errno(c)));
161 pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
162 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map);
164 printf(_("User name: %s\n"
167 "Server Version: %s\n"
168 "Default Sample Specification: %s\n"
169 "Default Channel Map: %s\n"
171 "Default Source: %s\n"
179 i->default_sink_name,
180 i->default_source_name,
186 static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
188 static const char *state_table[] = {
189 [1+PA_SINK_INVALID_STATE] = "n/a",
190 [1+PA_SINK_RUNNING] = "RUNNING",
191 [1+PA_SINK_IDLE] = "IDLE",
192 [1+PA_SINK_SUSPENDED] = "SUSPENDED"
196 s[PA_SAMPLE_SPEC_SNPRINT_MAX],
197 cv[PA_CVOLUME_SNPRINT_MAX],
198 cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
199 v[PA_VOLUME_SNPRINT_MAX],
200 vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
201 cm[PA_CHANNEL_MAP_SNPRINT_MAX];
205 pa_log(_("Failed to get sink information: %s"), pa_strerror(pa_context_errno(c)));
221 printf(_("Sink #%u\n"
224 "\tDescription: %s\n"
226 "\tSample Specification: %s\n"
227 "\tChannel Map: %s\n"
228 "\tOwner Module: %u\n"
232 "\tBase Volume: %s%s%s\n"
233 "\tMonitor Source: %s\n"
234 "\tLatency: %0.0f usec, configured %0.0f usec\n"
235 "\tFlags: %s%s%s%s%s%s\n"
236 "\tProperties:\n\t\t%s\n"),
238 state_table[1+i->state],
240 pa_strnull(i->description),
241 pa_strnull(i->driver),
242 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
243 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
246 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
247 i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "",
248 i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
249 pa_cvolume_get_balance(&i->volume, &i->channel_map),
250 pa_volume_snprint(v, sizeof(v), i->base_volume),
251 i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "",
252 i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
253 pa_strnull(i->monitor_source_name),
254 (double) i->latency, (double) i->configured_latency,
255 i->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
256 i->flags & PA_SINK_NETWORK ? "NETWORK " : "",
257 i->flags & PA_SINK_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
258 i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
259 i->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
260 i->flags & PA_SINK_LATENCY ? "LATENCY " : "",
261 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
266 pa_sink_port_info **p;
268 printf(_("\tPorts:\n"));
269 for (p = i->ports; *p; p++)
270 printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description, (*p)->priority);
274 printf(_("\tActive Port: %s\n"),
275 i->active_port->name);
278 static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
280 static const char *state_table[] = {
281 [1+PA_SOURCE_INVALID_STATE] = "n/a",
282 [1+PA_SOURCE_RUNNING] = "RUNNING",
283 [1+PA_SOURCE_IDLE] = "IDLE",
284 [1+PA_SOURCE_SUSPENDED] = "SUSPENDED"
288 s[PA_SAMPLE_SPEC_SNPRINT_MAX],
289 cv[PA_CVOLUME_SNPRINT_MAX],
290 cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
291 v[PA_VOLUME_SNPRINT_MAX],
292 vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
293 cm[PA_CHANNEL_MAP_SNPRINT_MAX];
297 pa_log(_("Failed to get source information: %s"), pa_strerror(pa_context_errno(c)));
313 printf(_("Source #%u\n"
316 "\tDescription: %s\n"
318 "\tSample Specification: %s\n"
319 "\tChannel Map: %s\n"
320 "\tOwner Module: %u\n"
324 "\tBase Volume: %s%s%s\n"
325 "\tMonitor of Sink: %s\n"
326 "\tLatency: %0.0f usec, configured %0.0f usec\n"
327 "\tFlags: %s%s%s%s%s%s\n"
328 "\tProperties:\n\t\t%s\n"),
330 state_table[1+i->state],
332 pa_strnull(i->description),
333 pa_strnull(i->driver),
334 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
335 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
338 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
339 i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "",
340 i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
341 pa_cvolume_get_balance(&i->volume, &i->channel_map),
342 pa_volume_snprint(v, sizeof(v), i->base_volume),
343 i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "",
344 i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
345 i->monitor_of_sink_name ? i->monitor_of_sink_name : _("n/a"),
346 (double) i->latency, (double) i->configured_latency,
347 i->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
348 i->flags & PA_SOURCE_NETWORK ? "NETWORK " : "",
349 i->flags & PA_SOURCE_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
350 i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
351 i->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
352 i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
353 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
358 pa_source_port_info **p;
360 printf(_("\tPorts:\n"));
361 for (p = i->ports; *p; p++)
362 printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description, (*p)->priority);
366 printf(_("\tActive Port: %s\n"),
367 i->active_port->name);
370 static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) {
375 pa_log(_("Failed to get module information: %s"), pa_strerror(pa_context_errno(c)));
391 pa_snprintf(t, sizeof(t), "%u", i->n_used);
393 printf(_("Module #%u\n"
396 "\tUsage counter: %s\n"
397 "\tProperties:\n\t\t%s\n"),
400 i->argument ? i->argument : "",
401 i->n_used != PA_INVALID_INDEX ? t : _("n/a"),
402 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
407 static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) {
412 pa_log(_("Failed to get client information: %s"), pa_strerror(pa_context_errno(c)));
428 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
430 printf(_("Client #%u\n"
432 "\tOwner Module: %s\n"
433 "\tProperties:\n\t\t%s\n"),
435 pa_strnull(i->driver),
436 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
437 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
442 static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_last, void *userdata) {
447 pa_log(_("Failed to get card information: %s"), pa_strerror(pa_context_errno(c)));
463 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
465 printf(_("Card #%u\n"
468 "\tOwner Module: %s\n"
469 "\tProperties:\n\t\t%s\n"),
472 pa_strnull(i->driver),
473 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
474 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
477 pa_card_profile_info *p;
479 printf(_("\tProfiles:\n"));
480 for (p = i->profiles; p->name; p++)
481 printf("\t\t%s: %s (sinks: %u, sources: %u, priority. %u)\n", p->name, p->description, p->n_sinks, p->n_sources, p->priority);
484 if (i->active_profile)
485 printf(_("\tActive Profile: %s\n"),
486 i->active_profile->name);
491 static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
492 char t[32], k[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];
496 pa_log(_("Failed to get sink input information: %s"), pa_strerror(pa_context_errno(c)));
512 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
513 pa_snprintf(k, sizeof(k), "%u", i->client);
515 printf(_("Sink Input #%u\n"
517 "\tOwner Module: %s\n"
520 "\tSample Specification: %s\n"
521 "\tChannel Map: %s\n"
526 "\tBuffer Latency: %0.0f usec\n"
527 "\tSink Latency: %0.0f usec\n"
528 "\tResample method: %s\n"
529 "\tProperties:\n\t\t%s\n"),
531 pa_strnull(i->driver),
532 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
533 i->client != PA_INVALID_INDEX ? k : _("n/a"),
535 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
536 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
538 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
539 pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
540 pa_cvolume_get_balance(&i->volume, &i->channel_map),
541 (double) i->buffer_usec,
542 (double) i->sink_usec,
543 i->resample_method ? i->resample_method : _("n/a"),
544 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
549 static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) {
550 char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
554 pa_log(_("Failed to get source output information: %s"), pa_strerror(pa_context_errno(c)));
571 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
572 pa_snprintf(k, sizeof(k), "%u", i->client);
574 printf(_("Source Output #%u\n"
576 "\tOwner Module: %s\n"
579 "\tSample Specification: %s\n"
580 "\tChannel Map: %s\n"
581 "\tBuffer Latency: %0.0f usec\n"
582 "\tSource Latency: %0.0f usec\n"
583 "\tResample method: %s\n"
584 "\tProperties:\n\t\t%s\n"),
586 pa_strnull(i->driver),
587 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
588 i->client != PA_INVALID_INDEX ? k : _("n/a"),
590 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
591 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
592 (double) i->buffer_usec,
593 (double) i->source_usec,
594 i->resample_method ? i->resample_method : _("n/a"),
595 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
600 static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) {
601 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];
605 pa_log(_("Failed to get sample information: %s"), pa_strerror(pa_context_errno(c)));
621 pa_bytes_snprint(t, sizeof(t), i->bytes);
623 printf(_("Sample #%u\n"
625 "\tSample Specification: %s\n"
626 "\tChannel Map: %s\n"
630 "\tDuration: %0.1fs\n"
634 "\tProperties:\n\t\t%s\n"),
637 pa_sample_spec_valid(&i->sample_spec) ? pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec) : _("n/a"),
638 pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : _("n/a"),
639 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
640 pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
641 pa_cvolume_get_balance(&i->volume, &i->channel_map),
642 (double) i->duration/1000000.0,
645 i->filename ? i->filename : _("n/a"),
646 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
651 static void simple_callback(pa_context *c, int success, void *userdata) {
653 pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
661 static void index_callback(pa_context *c, uint32_t idx, void *userdata) {
662 if (idx == PA_INVALID_INDEX) {
663 pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
673 static void stream_state_callback(pa_stream *s, void *userdata) {
676 switch (pa_stream_get_state(s)) {
677 case PA_STREAM_CREATING:
678 case PA_STREAM_READY:
681 case PA_STREAM_TERMINATED:
685 case PA_STREAM_FAILED:
687 pa_log(_("Failed to upload sample: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
692 static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
695 pa_assert(s && length && sndfile);
697 d = pa_xmalloc(length);
699 pa_assert(sample_length >= length);
700 l = (sf_count_t) (length/pa_frame_size(&sample_spec));
702 if ((sf_readf_float(sndfile, d, l)) != l) {
704 pa_log(_("Premature end of file"));
709 pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE);
711 sample_length -= length;
713 if (sample_length <= 0) {
714 pa_stream_set_write_callback(sample_stream, NULL, NULL);
715 pa_stream_finish_upload(sample_stream);
719 static void context_state_callback(pa_context *c, void *userdata) {
721 switch (pa_context_get_state(c)) {
722 case PA_CONTEXT_CONNECTING:
723 case PA_CONTEXT_AUTHORIZING:
724 case PA_CONTEXT_SETTING_NAME:
727 case PA_CONTEXT_READY:
731 pa_operation_unref(pa_context_stat(c, stat_callback, NULL));
732 pa_operation_unref(pa_context_get_server_info(c, get_server_info_callback, NULL));
736 pa_operation_unref(pa_context_play_sample(c, sample_name, sink_name, PA_VOLUME_NORM, simple_callback, NULL));
740 pa_operation_unref(pa_context_remove_sample(c, sample_name, simple_callback, NULL));
744 sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL);
745 pa_assert(sample_stream);
747 pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL);
748 pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL);
749 pa_stream_connect_upload(sample_stream, sample_length);
753 pa_operation_unref(pa_context_exit_daemon(c, simple_callback, NULL));
758 pa_operation_unref(pa_context_get_module_info_list(c, get_module_info_callback, NULL));
759 pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL));
760 pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL));
761 pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, NULL));
762 pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL));
763 pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL));
764 pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL));
765 pa_operation_unref(pa_context_get_card_info_list(c, get_card_info_callback, NULL));
768 case MOVE_SINK_INPUT:
769 pa_operation_unref(pa_context_move_sink_input_by_name(c, sink_input_idx, sink_name, simple_callback, NULL));
772 case MOVE_SOURCE_OUTPUT:
773 pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL));
777 pa_operation_unref(pa_context_load_module(c, module_name, module_args, index_callback, NULL));
781 pa_operation_unref(pa_context_unload_module(c, module_index, simple_callback, NULL));
786 pa_operation_unref(pa_context_suspend_sink_by_name(c, sink_name, suspend, simple_callback, NULL));
788 pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
793 pa_operation_unref(pa_context_suspend_source_by_name(c, source_name, suspend, simple_callback, NULL));
795 pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
798 case SET_CARD_PROFILE:
799 pa_operation_unref(pa_context_set_card_profile_by_name(c, card_name, profile_name, simple_callback, NULL));
803 pa_operation_unref(pa_context_set_sink_port_by_name(c, sink_name, port_name, simple_callback, NULL));
806 case SET_SOURCE_PORT:
807 pa_operation_unref(pa_context_set_source_port_by_name(c, source_name, port_name, simple_callback, NULL));
811 pa_operation_unref(pa_context_set_sink_mute_by_name(c, sink_name, mute, simple_callback, NULL));
814 case SET_SOURCE_MUTE:
815 pa_operation_unref(pa_context_set_source_mute_by_name(c, source_name, mute, simple_callback, NULL));
818 case SET_SINK_INPUT_MUTE:
819 pa_operation_unref(pa_context_set_sink_input_mute(c, sink_input_idx, mute, simple_callback, NULL));
822 case SET_SINK_VOLUME: {
825 pa_cvolume_set(&v, 1, volume);
826 pa_operation_unref(pa_context_set_sink_volume_by_name(c, sink_name, &v, simple_callback, NULL));
830 case SET_SOURCE_VOLUME: {
833 pa_cvolume_set(&v, 1, volume);
834 pa_operation_unref(pa_context_set_source_volume_by_name(c, source_name, &v, simple_callback, NULL));
838 case SET_SINK_INPUT_VOLUME: {
841 pa_cvolume_set(&v, 1, volume);
842 pa_operation_unref(pa_context_set_sink_input_volume(c, sink_input_idx, &v, simple_callback, NULL));
847 pa_assert_not_reached();
851 case PA_CONTEXT_TERMINATED:
855 case PA_CONTEXT_FAILED:
857 pa_log(_("Connection failure: %s"), pa_strerror(pa_context_errno(c)));
862 static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) {
863 pa_log(_("Got SIGINT, exiting."));
867 static void help(const char *argv0) {
869 printf(_("%s [options] stat\n"
870 "%s [options] list\n"
871 "%s [options] exit\n"
872 "%s [options] upload-sample FILENAME [NAME]\n"
873 "%s [options] play-sample NAME [SINK]\n"
874 "%s [options] remove-sample NAME\n"
875 "%s [options] move-sink-input SINKINPUT SINK\n"
876 "%s [options] move-source-output SOURCEOUTPUT SOURCE\n"
877 "%s [options] load-module NAME [ARGS ...]\n"
878 "%s [options] unload-module MODULE\n"
879 "%s [options] suspend-sink SINK 1|0\n"
880 "%s [options] suspend-source SOURCE 1|0\n"
881 "%s [options] set-card-profile CARD PROFILE\n"
882 "%s [options] set-sink-port SINK PORT\n"
883 "%s [options] set-source-port SOURCE PORT\n"
884 "%s [options] set-sink-volume SINK VOLUME\n"
885 "%s [options] set-source-volume SOURCE VOLUME\n"
886 "%s [options] set-sink-input-volume SINKINPUT VOLUME\n"
887 "%s [options] set-sink-mute SINK 1|0\n"
888 "%s [options] set-source-mute SOURCE 1|0\n"
889 "%s [options] set-sink-input-mute SINKINPUT 1|0\n\n"
890 " -h, --help Show this help\n"
891 " --version Show version\n\n"
892 " -s, --server=SERVER The name of the server to connect to\n"
893 " -n, --client-name=NAME How to call this client on the server\n"),
894 argv0, argv0, argv0, argv0, argv0,
895 argv0, argv0, argv0, argv0, argv0,
896 argv0, argv0, argv0, argv0, argv0,
897 argv0, argv0, argv0, argv0, argv0,
905 int main(int argc, char *argv[]) {
906 pa_mainloop* m = NULL;
908 char *server = NULL, *bn;
910 static const struct option long_options[] = {
911 {"server", 1, NULL, 's'},
912 {"client-name", 1, NULL, 'n'},
913 {"version", 0, NULL, ARG_VERSION},
914 {"help", 0, NULL, 'h'},
918 setlocale(LC_ALL, "");
919 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
921 bn = pa_path_get_filename(argv[0]);
923 proplist = pa_proplist_new();
925 while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) {
933 printf(_("pactl %s\n"
934 "Compiled with libpulse %s\n"
935 "Linked with libpulse %s\n"),
937 pa_get_headers_version(),
938 pa_get_library_version());
944 server = pa_xstrdup(optarg);
950 if (!(t = pa_locale_to_utf8(optarg)) ||
951 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) {
953 pa_log(_("Invalid client name '%s'"), t ? t : optarg);
968 if (pa_streq(argv[optind], "stat"))
970 else if (pa_streq(argv[optind], "exit"))
972 else if (pa_streq(argv[optind], "list"))
974 else if (pa_streq(argv[optind], "upload-sample")) {
976 action = UPLOAD_SAMPLE;
978 if (optind+1 >= argc) {
979 pa_log(_("Please specify a sample file to load"));
984 sample_name = pa_xstrdup(argv[optind+2]);
986 char *f = pa_path_get_filename(argv[optind+1]);
987 sample_name = pa_xstrndup(f, strcspn(f, "."));
991 if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfi))) {
992 pa_log(_("Failed to open sound file."));
996 if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) {
997 pa_log(_("Failed to determine sample specification from file."));
1000 sample_spec.format = PA_SAMPLE_FLOAT32;
1002 if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) {
1003 if (sample_spec.channels > 2)
1004 pa_log(_("Warning: Failed to determine sample specification from file."));
1005 pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
1008 pa_assert(pa_channel_map_compatible(&channel_map, &sample_spec));
1009 sample_length = (size_t) sfi.frames*pa_frame_size(&sample_spec);
1011 } else if (pa_streq(argv[optind], "play-sample")) {
1012 action = PLAY_SAMPLE;
1013 if (argc != optind+2 && argc != optind+3) {
1014 pa_log(_("You have to specify a sample name to play"));
1018 sample_name = pa_xstrdup(argv[optind+1]);
1020 if (optind+2 < argc)
1021 sink_name = pa_xstrdup(argv[optind+2]);
1023 } else if (pa_streq(argv[optind], "remove-sample")) {
1024 action = REMOVE_SAMPLE;
1025 if (argc != optind+2) {
1026 pa_log(_("You have to specify a sample name to remove"));
1030 sample_name = pa_xstrdup(argv[optind+1]);
1032 } else if (pa_streq(argv[optind], "move-sink-input")) {
1033 action = MOVE_SINK_INPUT;
1034 if (argc != optind+3) {
1035 pa_log(_("You have to specify a sink input index and a sink"));
1039 sink_input_idx = (uint32_t) atoi(argv[optind+1]);
1040 sink_name = pa_xstrdup(argv[optind+2]);
1042 } else if (pa_streq(argv[optind], "move-source-output")) {
1043 action = MOVE_SOURCE_OUTPUT;
1044 if (argc != optind+3) {
1045 pa_log(_("You have to specify a source output index and a source"));
1049 source_output_idx = (uint32_t) atoi(argv[optind+1]);
1050 source_name = pa_xstrdup(argv[optind+2]);
1052 } else if (pa_streq(argv[optind], "load-module")) {
1057 action = LOAD_MODULE;
1059 if (argc <= optind+1) {
1060 pa_log(_("You have to specify a module name and arguments."));
1064 module_name = argv[optind+1];
1066 for (i = optind+2; i < argc; i++)
1067 n += strlen(argv[i])+1;
1070 p = module_args = pa_xmalloc(n);
1072 for (i = optind+2; i < argc; i++)
1073 p += sprintf(p, "%s%s", p == module_args ? "" : " ", argv[i]);
1076 } else if (pa_streq(argv[optind], "unload-module")) {
1077 action = UNLOAD_MODULE;
1079 if (argc != optind+2) {
1080 pa_log(_("You have to specify a module index"));
1084 module_index = (uint32_t) atoi(argv[optind+1]);
1086 } else if (pa_streq(argv[optind], "suspend-sink")) {
1087 action = SUSPEND_SINK;
1089 if (argc > optind+3 || optind+1 >= argc) {
1090 pa_log(_("You may not specify more than one sink. You have to specify a boolean value."));
1094 suspend = pa_parse_boolean(argv[argc-1]);
1096 if (argc > optind+2)
1097 sink_name = pa_xstrdup(argv[optind+1]);
1099 } else if (pa_streq(argv[optind], "suspend-source")) {
1100 action = SUSPEND_SOURCE;
1102 if (argc > optind+3 || optind+1 >= argc) {
1103 pa_log(_("You may not specify more than one source. You have to specify a boolean value."));
1107 suspend = pa_parse_boolean(argv[argc-1]);
1109 if (argc > optind+2)
1110 source_name = pa_xstrdup(argv[optind+1]);
1111 } else if (pa_streq(argv[optind], "set-card-profile")) {
1112 action = SET_CARD_PROFILE;
1114 if (argc != optind+3) {
1115 pa_log(_("You have to specify a card name/index and a profile name"));
1119 card_name = pa_xstrdup(argv[optind+1]);
1120 profile_name = pa_xstrdup(argv[optind+2]);
1122 } else if (pa_streq(argv[optind], "set-sink-port")) {
1123 action = SET_SINK_PORT;
1125 if (argc != optind+3) {
1126 pa_log(_("You have to specify a sink name/index and a port name"));
1130 sink_name = pa_xstrdup(argv[optind+1]);
1131 port_name = pa_xstrdup(argv[optind+2]);
1133 } else if (pa_streq(argv[optind], "set-source-port")) {
1134 action = SET_SOURCE_PORT;
1136 if (argc != optind+3) {
1137 pa_log(_("You have to specify a source name/index and a port name"));
1141 source_name = pa_xstrdup(argv[optind+1]);
1142 port_name = pa_xstrdup(argv[optind+2]);
1144 } else if (pa_streq(argv[optind], "set-sink-volume")) {
1146 action = SET_SINK_VOLUME;
1148 if (argc != optind+3) {
1149 pa_log(_("You have to specify a sink name/index and a volume"));
1153 if (pa_atou(argv[optind+2], &v) < 0) {
1154 pa_log(_("Invalid volume specification"));
1158 sink_name = pa_xstrdup(argv[optind+1]);
1159 volume = (pa_volume_t) v;
1161 } else if (pa_streq(argv[optind], "set-source-volume")) {
1163 action = SET_SOURCE_VOLUME;
1165 if (argc != optind+3) {
1166 pa_log(_("You have to specify a source name/index and a volume"));
1170 if (pa_atou(argv[optind+2], &v) < 0) {
1171 pa_log(_("Invalid volume specification"));
1175 source_name = pa_xstrdup(argv[optind+1]);
1176 volume = (pa_volume_t) v;
1178 } else if (pa_streq(argv[optind], "set-sink-input-volume")) {
1180 action = SET_SINK_INPUT_VOLUME;
1182 if (argc != optind+3) {
1183 pa_log(_("You have to specify a sink input index and a volume"));
1187 if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
1188 pa_log(_("Invalid sink input index"));
1192 if (pa_atou(argv[optind+2], &v) < 0) {
1193 pa_log(_("Invalid volume specification"));
1197 volume = (pa_volume_t) v;
1199 } else if (pa_streq(argv[optind], "set-sink-mute")) {
1201 action = SET_SINK_MUTE;
1203 if (argc != optind+3) {
1204 pa_log(_("You have to specify a sink name/index and a mute boolean"));
1208 if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
1209 pa_log(_("Invalid volume specification"));
1213 sink_name = pa_xstrdup(argv[optind+1]);
1216 } else if (pa_streq(argv[optind], "set-source-mute")) {
1218 action = SET_SOURCE_MUTE;
1220 if (argc != optind+3) {
1221 pa_log(_("You have to specify a source name/index and a mute boolean"));
1225 if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
1226 pa_log(_("Invalid volume specification"));
1230 source_name = pa_xstrdup(argv[optind+1]);
1233 } else if (pa_streq(argv[optind], "set-sink-input-mute")) {
1235 action = SET_SINK_INPUT_MUTE;
1237 if (argc != optind+3) {
1238 pa_log(_("You have to specify a sink input index and a mute boolean"));
1242 if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
1243 pa_log(_("Invalid sink input index specification"));
1247 if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
1248 pa_log(_("Invalid volume specification"));
1254 } else if (pa_streq(argv[optind], "help")) {
1261 if (action == NONE) {
1262 pa_log(_("No valid command specified."));
1266 if (!(m = pa_mainloop_new())) {
1267 pa_log(_("pa_mainloop_new() failed."));
1271 mainloop_api = pa_mainloop_get_api(m);
1273 pa_assert_se(pa_signal_init(mainloop_api) == 0);
1274 pa_signal_new(SIGINT, exit_signal_callback, NULL);
1275 pa_signal_new(SIGTERM, exit_signal_callback, NULL);
1276 pa_disable_sigpipe();
1278 if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) {
1279 pa_log(_("pa_context_new() failed."));
1283 pa_context_set_state_callback(context, context_state_callback, NULL);
1284 if (pa_context_connect(context, server, 0, NULL) < 0) {
1285 pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context)));
1289 if (pa_mainloop_run(m, &ret) < 0) {
1290 pa_log(_("pa_mainloop_run() failed."));
1296 pa_stream_unref(sample_stream);
1299 pa_context_unref(context);
1303 pa_mainloop_free(m);
1307 pa_xfree(sample_name);
1308 pa_xfree(sink_name);
1309 pa_xfree(source_name);
1310 pa_xfree(module_args);
1311 pa_xfree(card_name);
1312 pa_xfree(profile_name);
1318 pa_proplist_free(proplist);