l10n: Updates to Russian (ru) translation
[pulseaudio-mirror.git] / src / utils / pactl.c
blobcae96f293fa00eef3fff572995e354ef7dbf9f78
1 /***
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
19 USA.
20 ***/
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
26 #include <signal.h>
27 #include <string.h>
28 #include <errno.h>
29 #include <unistd.h>
30 #include <assert.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <limits.h>
34 #include <getopt.h>
35 #include <locale.h>
37 #include <sndfile.h>
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 static pa_context *context = NULL;
48 static pa_mainloop_api *mainloop_api = NULL;
50 static char
51 *sample_name = NULL,
52 *sink_name = NULL,
53 *source_name = NULL,
54 *module_name = NULL,
55 *module_args = NULL,
56 *card_name = NULL,
57 *profile_name = NULL,
58 *port_name = NULL;
60 static uint32_t
61 sink_input_idx = PA_INVALID_INDEX,
62 source_output_idx = PA_INVALID_INDEX;
64 static uint32_t module_index;
65 static pa_bool_t suspend;
66 static pa_bool_t mute;
67 static pa_volume_t volume;
69 static pa_proplist *proplist = NULL;
71 static SNDFILE *sndfile = NULL;
72 static pa_stream *sample_stream = NULL;
73 static pa_sample_spec sample_spec;
74 static pa_channel_map channel_map;
75 static size_t sample_length = 0;
76 static int actions = 1;
78 static pa_bool_t nl = FALSE;
80 static enum {
81 NONE,
82 EXIT,
83 STAT,
84 UPLOAD_SAMPLE,
85 PLAY_SAMPLE,
86 REMOVE_SAMPLE,
87 LIST,
88 MOVE_SINK_INPUT,
89 MOVE_SOURCE_OUTPUT,
90 LOAD_MODULE,
91 UNLOAD_MODULE,
92 SUSPEND_SINK,
93 SUSPEND_SOURCE,
94 SET_CARD_PROFILE,
95 SET_SINK_PORT,
96 SET_SOURCE_PORT,
97 SET_SINK_VOLUME,
98 SET_SOURCE_VOLUME,
99 SET_SINK_INPUT_VOLUME,
100 SET_SINK_MUTE,
101 SET_SOURCE_MUTE,
102 SET_SINK_INPUT_MUTE,
103 SUBSCRIBE
104 } action = NONE;
106 static void quit(int ret) {
107 pa_assert(mainloop_api);
108 mainloop_api->quit(mainloop_api, ret);
111 static void context_drain_complete(pa_context *c, void *userdata) {
112 pa_context_disconnect(c);
115 static void drain(void) {
116 pa_operation *o;
118 if (!(o = pa_context_drain(context, context_drain_complete, NULL)))
119 pa_context_disconnect(context);
120 else
121 pa_operation_unref(o);
124 static void complete_action(void) {
125 pa_assert(actions > 0);
127 if (!(--actions))
128 drain();
131 static void stat_callback(pa_context *c, const pa_stat_info *i, void *userdata) {
132 char s[PA_BYTES_SNPRINT_MAX];
133 if (!i) {
134 pa_log(_("Failed to get statistics: %s"), pa_strerror(pa_context_errno(c)));
135 quit(1);
136 return;
139 pa_bytes_snprint(s, sizeof(s), i->memblock_total_size);
140 printf(_("Currently in use: %u blocks containing %s bytes total.\n"), i->memblock_total, s);
142 pa_bytes_snprint(s, sizeof(s), i->memblock_allocated_size);
143 printf(_("Allocated during whole lifetime: %u blocks containing %s bytes total.\n"), i->memblock_allocated, s);
145 pa_bytes_snprint(s, sizeof(s), i->scache_size);
146 printf(_("Sample cache size: %s\n"), s);
148 complete_action();
151 static void get_server_info_callback(pa_context *c, const pa_server_info *i, void *useerdata) {
152 char ss[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
154 if (!i) {
155 pa_log(_("Failed to get server information: %s"), pa_strerror(pa_context_errno(c)));
156 quit(1);
157 return;
160 printf(_("Server String: %s\n"
161 "Library Protocol Version: %u\n"
162 "Server Protocol Version: %u\n"
163 "Is Local: %s\n"
164 "Client Index: %u\n"
165 "Tile Size: %zu\n"),
166 pa_context_get_server(c),
167 pa_context_get_protocol_version(c),
168 pa_context_get_server_protocol_version(c),
169 pa_yes_no(pa_context_is_local(c)),
170 pa_context_get_index(c),
171 pa_context_get_tile_size(c, NULL));
173 pa_sample_spec_snprint(ss, sizeof(ss), &i->sample_spec);
174 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map);
176 printf(_("User Name: %s\n"
177 "Host Name: %s\n"
178 "Server Name: %s\n"
179 "Server Version: %s\n"
180 "Default Sample Specification: %s\n"
181 "Default Channel Map: %s\n"
182 "Default Sink: %s\n"
183 "Default Source: %s\n"
184 "Cookie: %04x:%04x\n"),
185 i->user_name,
186 i->host_name,
187 i->server_name,
188 i->server_version,
191 i->default_sink_name,
192 i->default_source_name,
193 i->cookie >> 16,
194 i->cookie & 0xFFFFU);
196 complete_action();
199 static void get_sink_info_callback(pa_context *c, const pa_sink_info *i, int is_last, void *userdata) {
201 static const char *state_table[] = {
202 [1+PA_SINK_INVALID_STATE] = "n/a",
203 [1+PA_SINK_RUNNING] = "RUNNING",
204 [1+PA_SINK_IDLE] = "IDLE",
205 [1+PA_SINK_SUSPENDED] = "SUSPENDED"
208 char
209 s[PA_SAMPLE_SPEC_SNPRINT_MAX],
210 cv[PA_CVOLUME_SNPRINT_MAX],
211 cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
212 v[PA_VOLUME_SNPRINT_MAX],
213 vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
214 cm[PA_CHANNEL_MAP_SNPRINT_MAX];
215 char *pl;
217 if (is_last < 0) {
218 pa_log(_("Failed to get sink information: %s"), pa_strerror(pa_context_errno(c)));
219 quit(1);
220 return;
223 if (is_last) {
224 complete_action();
225 return;
228 pa_assert(i);
230 if (nl)
231 printf("\n");
232 nl = TRUE;
234 printf(_("Sink #%u\n"
235 "\tState: %s\n"
236 "\tName: %s\n"
237 "\tDescription: %s\n"
238 "\tDriver: %s\n"
239 "\tSample Specification: %s\n"
240 "\tChannel Map: %s\n"
241 "\tOwner Module: %u\n"
242 "\tMute: %s\n"
243 "\tVolume: %s%s%s\n"
244 "\t balance %0.2f\n"
245 "\tBase Volume: %s%s%s\n"
246 "\tMonitor Source: %s\n"
247 "\tLatency: %0.0f usec, configured %0.0f usec\n"
248 "\tFlags: %s%s%s%s%s%s\n"
249 "\tProperties:\n\t\t%s\n"),
250 i->index,
251 state_table[1+i->state],
252 i->name,
253 pa_strnull(i->description),
254 pa_strnull(i->driver),
255 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
256 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
257 i->owner_module,
258 pa_yes_no(i->mute),
259 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
260 i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "",
261 i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
262 pa_cvolume_get_balance(&i->volume, &i->channel_map),
263 pa_volume_snprint(v, sizeof(v), i->base_volume),
264 i->flags & PA_SINK_DECIBEL_VOLUME ? "\n\t " : "",
265 i->flags & PA_SINK_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
266 pa_strnull(i->monitor_source_name),
267 (double) i->latency, (double) i->configured_latency,
268 i->flags & PA_SINK_HARDWARE ? "HARDWARE " : "",
269 i->flags & PA_SINK_NETWORK ? "NETWORK " : "",
270 i->flags & PA_SINK_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
271 i->flags & PA_SINK_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
272 i->flags & PA_SINK_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
273 i->flags & PA_SINK_LATENCY ? "LATENCY " : "",
274 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
276 pa_xfree(pl);
278 if (i->ports) {
279 pa_sink_port_info **p;
281 printf(_("\tPorts:\n"));
282 for (p = i->ports; *p; p++)
283 printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description, (*p)->priority);
286 if (i->active_port)
287 printf(_("\tActive Port: %s\n"),
288 i->active_port->name);
291 static void get_source_info_callback(pa_context *c, const pa_source_info *i, int is_last, void *userdata) {
293 static const char *state_table[] = {
294 [1+PA_SOURCE_INVALID_STATE] = "n/a",
295 [1+PA_SOURCE_RUNNING] = "RUNNING",
296 [1+PA_SOURCE_IDLE] = "IDLE",
297 [1+PA_SOURCE_SUSPENDED] = "SUSPENDED"
300 char
301 s[PA_SAMPLE_SPEC_SNPRINT_MAX],
302 cv[PA_CVOLUME_SNPRINT_MAX],
303 cvdb[PA_SW_CVOLUME_SNPRINT_DB_MAX],
304 v[PA_VOLUME_SNPRINT_MAX],
305 vdb[PA_SW_VOLUME_SNPRINT_DB_MAX],
306 cm[PA_CHANNEL_MAP_SNPRINT_MAX];
307 char *pl;
309 if (is_last < 0) {
310 pa_log(_("Failed to get source information: %s"), pa_strerror(pa_context_errno(c)));
311 quit(1);
312 return;
315 if (is_last) {
316 complete_action();
317 return;
320 pa_assert(i);
322 if (nl)
323 printf("\n");
324 nl = TRUE;
326 printf(_("Source #%u\n"
327 "\tState: %s\n"
328 "\tName: %s\n"
329 "\tDescription: %s\n"
330 "\tDriver: %s\n"
331 "\tSample Specification: %s\n"
332 "\tChannel Map: %s\n"
333 "\tOwner Module: %u\n"
334 "\tMute: %s\n"
335 "\tVolume: %s%s%s\n"
336 "\t balance %0.2f\n"
337 "\tBase Volume: %s%s%s\n"
338 "\tMonitor of Sink: %s\n"
339 "\tLatency: %0.0f usec, configured %0.0f usec\n"
340 "\tFlags: %s%s%s%s%s%s\n"
341 "\tProperties:\n\t\t%s\n"),
342 i->index,
343 state_table[1+i->state],
344 i->name,
345 pa_strnull(i->description),
346 pa_strnull(i->driver),
347 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
348 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
349 i->owner_module,
350 pa_yes_no(i->mute),
351 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
352 i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "",
353 i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume) : "",
354 pa_cvolume_get_balance(&i->volume, &i->channel_map),
355 pa_volume_snprint(v, sizeof(v), i->base_volume),
356 i->flags & PA_SOURCE_DECIBEL_VOLUME ? "\n\t " : "",
357 i->flags & PA_SOURCE_DECIBEL_VOLUME ? pa_sw_volume_snprint_dB(vdb, sizeof(vdb), i->base_volume) : "",
358 i->monitor_of_sink_name ? i->monitor_of_sink_name : _("n/a"),
359 (double) i->latency, (double) i->configured_latency,
360 i->flags & PA_SOURCE_HARDWARE ? "HARDWARE " : "",
361 i->flags & PA_SOURCE_NETWORK ? "NETWORK " : "",
362 i->flags & PA_SOURCE_HW_MUTE_CTRL ? "HW_MUTE_CTRL " : "",
363 i->flags & PA_SOURCE_HW_VOLUME_CTRL ? "HW_VOLUME_CTRL " : "",
364 i->flags & PA_SOURCE_DECIBEL_VOLUME ? "DECIBEL_VOLUME " : "",
365 i->flags & PA_SOURCE_LATENCY ? "LATENCY " : "",
366 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
368 pa_xfree(pl);
370 if (i->ports) {
371 pa_source_port_info **p;
373 printf(_("\tPorts:\n"));
374 for (p = i->ports; *p; p++)
375 printf("\t\t%s: %s (priority. %u)\n", (*p)->name, (*p)->description, (*p)->priority);
378 if (i->active_port)
379 printf(_("\tActive Port: %s\n"),
380 i->active_port->name);
383 static void get_module_info_callback(pa_context *c, const pa_module_info *i, int is_last, void *userdata) {
384 char t[32];
385 char *pl;
387 if (is_last < 0) {
388 pa_log(_("Failed to get module information: %s"), pa_strerror(pa_context_errno(c)));
389 quit(1);
390 return;
393 if (is_last) {
394 complete_action();
395 return;
398 pa_assert(i);
400 if (nl)
401 printf("\n");
402 nl = TRUE;
404 pa_snprintf(t, sizeof(t), "%u", i->n_used);
406 printf(_("Module #%u\n"
407 "\tName: %s\n"
408 "\tArgument: %s\n"
409 "\tUsage counter: %s\n"
410 "\tProperties:\n\t\t%s\n"),
411 i->index,
412 i->name,
413 i->argument ? i->argument : "",
414 i->n_used != PA_INVALID_INDEX ? t : _("n/a"),
415 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
417 pa_xfree(pl);
420 static void get_client_info_callback(pa_context *c, const pa_client_info *i, int is_last, void *userdata) {
421 char t[32];
422 char *pl;
424 if (is_last < 0) {
425 pa_log(_("Failed to get client information: %s"), pa_strerror(pa_context_errno(c)));
426 quit(1);
427 return;
430 if (is_last) {
431 complete_action();
432 return;
435 pa_assert(i);
437 if (nl)
438 printf("\n");
439 nl = TRUE;
441 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
443 printf(_("Client #%u\n"
444 "\tDriver: %s\n"
445 "\tOwner Module: %s\n"
446 "\tProperties:\n\t\t%s\n"),
447 i->index,
448 pa_strnull(i->driver),
449 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
450 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
452 pa_xfree(pl);
455 static void get_card_info_callback(pa_context *c, const pa_card_info *i, int is_last, void *userdata) {
456 char t[32];
457 char *pl;
459 if (is_last < 0) {
460 pa_log(_("Failed to get card information: %s"), pa_strerror(pa_context_errno(c)));
461 complete_action();
462 return;
465 if (is_last) {
466 complete_action();
467 return;
470 pa_assert(i);
472 if (nl)
473 printf("\n");
474 nl = TRUE;
476 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
478 printf(_("Card #%u\n"
479 "\tName: %s\n"
480 "\tDriver: %s\n"
481 "\tOwner Module: %s\n"
482 "\tProperties:\n\t\t%s\n"),
483 i->index,
484 i->name,
485 pa_strnull(i->driver),
486 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
487 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
489 if (i->profiles) {
490 pa_card_profile_info *p;
492 printf(_("\tProfiles:\n"));
493 for (p = i->profiles; p->name; p++)
494 printf("\t\t%s: %s (sinks: %u, sources: %u, priority. %u)\n", p->name, p->description, p->n_sinks, p->n_sources, p->priority);
497 if (i->active_profile)
498 printf(_("\tActive Profile: %s\n"),
499 i->active_profile->name);
501 pa_xfree(pl);
504 static void get_sink_input_info_callback(pa_context *c, const pa_sink_input_info *i, int is_last, void *userdata) {
505 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];
506 char *pl;
508 if (is_last < 0) {
509 pa_log(_("Failed to get sink input information: %s"), pa_strerror(pa_context_errno(c)));
510 quit(1);
511 return;
514 if (is_last) {
515 complete_action();
516 return;
519 pa_assert(i);
521 if (nl)
522 printf("\n");
523 nl = TRUE;
525 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
526 pa_snprintf(k, sizeof(k), "%u", i->client);
528 printf(_("Sink Input #%u\n"
529 "\tDriver: %s\n"
530 "\tOwner Module: %s\n"
531 "\tClient: %s\n"
532 "\tSink: %u\n"
533 "\tSample Specification: %s\n"
534 "\tChannel Map: %s\n"
535 "\tMute: %s\n"
536 "\tVolume: %s\n"
537 "\t %s\n"
538 "\t balance %0.2f\n"
539 "\tBuffer Latency: %0.0f usec\n"
540 "\tSink Latency: %0.0f usec\n"
541 "\tResample method: %s\n"
542 "\tProperties:\n\t\t%s\n"),
543 i->index,
544 pa_strnull(i->driver),
545 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
546 i->client != PA_INVALID_INDEX ? k : _("n/a"),
547 i->sink,
548 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
549 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
550 pa_yes_no(i->mute),
551 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
552 pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
553 pa_cvolume_get_balance(&i->volume, &i->channel_map),
554 (double) i->buffer_usec,
555 (double) i->sink_usec,
556 i->resample_method ? i->resample_method : _("n/a"),
557 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
559 pa_xfree(pl);
562 static void get_source_output_info_callback(pa_context *c, const pa_source_output_info *i, int is_last, void *userdata) {
563 char t[32], k[32], s[PA_SAMPLE_SPEC_SNPRINT_MAX], cm[PA_CHANNEL_MAP_SNPRINT_MAX];
564 char *pl;
566 if (is_last < 0) {
567 pa_log(_("Failed to get source output information: %s"), pa_strerror(pa_context_errno(c)));
568 quit(1);
569 return;
572 if (is_last) {
573 complete_action();
574 return;
577 pa_assert(i);
579 if (nl)
580 printf("\n");
581 nl = TRUE;
584 pa_snprintf(t, sizeof(t), "%u", i->owner_module);
585 pa_snprintf(k, sizeof(k), "%u", i->client);
587 printf(_("Source Output #%u\n"
588 "\tDriver: %s\n"
589 "\tOwner Module: %s\n"
590 "\tClient: %s\n"
591 "\tSource: %u\n"
592 "\tSample Specification: %s\n"
593 "\tChannel Map: %s\n"
594 "\tBuffer Latency: %0.0f usec\n"
595 "\tSource Latency: %0.0f usec\n"
596 "\tResample method: %s\n"
597 "\tProperties:\n\t\t%s\n"),
598 i->index,
599 pa_strnull(i->driver),
600 i->owner_module != PA_INVALID_INDEX ? t : _("n/a"),
601 i->client != PA_INVALID_INDEX ? k : _("n/a"),
602 i->source,
603 pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec),
604 pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map),
605 (double) i->buffer_usec,
606 (double) i->source_usec,
607 i->resample_method ? i->resample_method : _("n/a"),
608 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
610 pa_xfree(pl);
613 static void get_sample_info_callback(pa_context *c, const pa_sample_info *i, int is_last, void *userdata) {
614 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];
615 char *pl;
617 if (is_last < 0) {
618 pa_log(_("Failed to get sample information: %s"), pa_strerror(pa_context_errno(c)));
619 quit(1);
620 return;
623 if (is_last) {
624 complete_action();
625 return;
628 pa_assert(i);
630 if (nl)
631 printf("\n");
632 nl = TRUE;
634 pa_bytes_snprint(t, sizeof(t), i->bytes);
636 printf(_("Sample #%u\n"
637 "\tName: %s\n"
638 "\tSample Specification: %s\n"
639 "\tChannel Map: %s\n"
640 "\tVolume: %s\n"
641 "\t %s\n"
642 "\t balance %0.2f\n"
643 "\tDuration: %0.1fs\n"
644 "\tSize: %s\n"
645 "\tLazy: %s\n"
646 "\tFilename: %s\n"
647 "\tProperties:\n\t\t%s\n"),
648 i->index,
649 i->name,
650 pa_sample_spec_valid(&i->sample_spec) ? pa_sample_spec_snprint(s, sizeof(s), &i->sample_spec) : _("n/a"),
651 pa_sample_spec_valid(&i->sample_spec) ? pa_channel_map_snprint(cm, sizeof(cm), &i->channel_map) : _("n/a"),
652 pa_cvolume_snprint(cv, sizeof(cv), &i->volume),
653 pa_sw_cvolume_snprint_dB(cvdb, sizeof(cvdb), &i->volume),
654 pa_cvolume_get_balance(&i->volume, &i->channel_map),
655 (double) i->duration/1000000.0,
657 pa_yes_no(i->lazy),
658 i->filename ? i->filename : _("n/a"),
659 pl = pa_proplist_to_string_sep(i->proplist, "\n\t\t"));
661 pa_xfree(pl);
664 static void simple_callback(pa_context *c, int success, void *userdata) {
665 if (!success) {
666 pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
667 quit(1);
668 return;
671 complete_action();
674 static void index_callback(pa_context *c, uint32_t idx, void *userdata) {
675 if (idx == PA_INVALID_INDEX) {
676 pa_log(_("Failure: %s"), pa_strerror(pa_context_errno(c)));
677 quit(1);
678 return;
681 printf("%u\n", idx);
683 complete_action();
686 static void stream_state_callback(pa_stream *s, void *userdata) {
687 pa_assert(s);
689 switch (pa_stream_get_state(s)) {
690 case PA_STREAM_CREATING:
691 case PA_STREAM_READY:
692 break;
694 case PA_STREAM_TERMINATED:
695 drain();
696 break;
698 case PA_STREAM_FAILED:
699 default:
700 pa_log(_("Failed to upload sample: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
701 quit(1);
705 static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
706 sf_count_t l;
707 float *d;
708 pa_assert(s && length && sndfile);
710 d = pa_xmalloc(length);
712 pa_assert(sample_length >= length);
713 l = (sf_count_t) (length/pa_frame_size(&sample_spec));
715 if ((sf_readf_float(sndfile, d, l)) != l) {
716 pa_xfree(d);
717 pa_log(_("Premature end of file"));
718 quit(1);
719 return;
722 pa_stream_write(s, d, length, pa_xfree, 0, PA_SEEK_RELATIVE);
724 sample_length -= length;
726 if (sample_length <= 0) {
727 pa_stream_set_write_callback(sample_stream, NULL, NULL);
728 pa_stream_finish_upload(sample_stream);
732 static const char *subscription_event_type_to_string(pa_subscription_event_type_t t) {
734 switch (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK) {
736 case PA_SUBSCRIPTION_EVENT_NEW:
737 return _("new");
739 case PA_SUBSCRIPTION_EVENT_CHANGE:
740 return _("change");
742 case PA_SUBSCRIPTION_EVENT_REMOVE:
743 return _("remove");
746 return _("unknown");
749 static const char *subscription_event_facility_to_string(pa_subscription_event_type_t t) {
751 switch (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK) {
753 case PA_SUBSCRIPTION_EVENT_SINK:
754 return _("sink");
756 case PA_SUBSCRIPTION_EVENT_SOURCE:
757 return _("source");
759 case PA_SUBSCRIPTION_EVENT_SINK_INPUT:
760 return _("sink-input");
762 case PA_SUBSCRIPTION_EVENT_SOURCE_OUTPUT:
763 return _("source-output");
765 case PA_SUBSCRIPTION_EVENT_MODULE:
766 return _("module");
768 case PA_SUBSCRIPTION_EVENT_CLIENT:
769 return _("client");
771 case PA_SUBSCRIPTION_EVENT_SAMPLE_CACHE:
772 return _("sample-cache");
774 case PA_SUBSCRIPTION_EVENT_SERVER:
775 return _("server");
777 case PA_SUBSCRIPTION_EVENT_CARD:
778 return _("server");
781 return _("unknown");
784 static void context_subscribe_callback(pa_context *c, pa_subscription_event_type_t t, uint32_t idx, void *userdata) {
785 pa_assert(c);
787 printf(_("Event '%s' on %s #%u\n"),
788 subscription_event_type_to_string(t),
789 subscription_event_facility_to_string(t),
790 idx);
793 static void context_state_callback(pa_context *c, void *userdata) {
794 pa_assert(c);
795 switch (pa_context_get_state(c)) {
796 case PA_CONTEXT_CONNECTING:
797 case PA_CONTEXT_AUTHORIZING:
798 case PA_CONTEXT_SETTING_NAME:
799 break;
801 case PA_CONTEXT_READY:
802 switch (action) {
803 case STAT:
804 actions = 2;
805 pa_operation_unref(pa_context_stat(c, stat_callback, NULL));
806 pa_operation_unref(pa_context_get_server_info(c, get_server_info_callback, NULL));
807 break;
809 case PLAY_SAMPLE:
810 pa_operation_unref(pa_context_play_sample(c, sample_name, sink_name, PA_VOLUME_NORM, simple_callback, NULL));
811 break;
813 case REMOVE_SAMPLE:
814 pa_operation_unref(pa_context_remove_sample(c, sample_name, simple_callback, NULL));
815 break;
817 case UPLOAD_SAMPLE:
818 sample_stream = pa_stream_new(c, sample_name, &sample_spec, NULL);
819 pa_assert(sample_stream);
821 pa_stream_set_state_callback(sample_stream, stream_state_callback, NULL);
822 pa_stream_set_write_callback(sample_stream, stream_write_callback, NULL);
823 pa_stream_connect_upload(sample_stream, sample_length);
824 break;
826 case EXIT:
827 pa_operation_unref(pa_context_exit_daemon(c, simple_callback, NULL));
828 break;
830 case LIST:
831 actions = 8;
832 pa_operation_unref(pa_context_get_module_info_list(c, get_module_info_callback, NULL));
833 pa_operation_unref(pa_context_get_sink_info_list(c, get_sink_info_callback, NULL));
834 pa_operation_unref(pa_context_get_source_info_list(c, get_source_info_callback, NULL));
835 pa_operation_unref(pa_context_get_sink_input_info_list(c, get_sink_input_info_callback, NULL));
836 pa_operation_unref(pa_context_get_source_output_info_list(c, get_source_output_info_callback, NULL));
837 pa_operation_unref(pa_context_get_client_info_list(c, get_client_info_callback, NULL));
838 pa_operation_unref(pa_context_get_sample_info_list(c, get_sample_info_callback, NULL));
839 pa_operation_unref(pa_context_get_card_info_list(c, get_card_info_callback, NULL));
840 break;
842 case MOVE_SINK_INPUT:
843 pa_operation_unref(pa_context_move_sink_input_by_name(c, sink_input_idx, sink_name, simple_callback, NULL));
844 break;
846 case MOVE_SOURCE_OUTPUT:
847 pa_operation_unref(pa_context_move_source_output_by_name(c, source_output_idx, source_name, simple_callback, NULL));
848 break;
850 case LOAD_MODULE:
851 pa_operation_unref(pa_context_load_module(c, module_name, module_args, index_callback, NULL));
852 break;
854 case UNLOAD_MODULE:
855 pa_operation_unref(pa_context_unload_module(c, module_index, simple_callback, NULL));
856 break;
858 case SUSPEND_SINK:
859 if (sink_name)
860 pa_operation_unref(pa_context_suspend_sink_by_name(c, sink_name, suspend, simple_callback, NULL));
861 else
862 pa_operation_unref(pa_context_suspend_sink_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
863 break;
865 case SUSPEND_SOURCE:
866 if (source_name)
867 pa_operation_unref(pa_context_suspend_source_by_name(c, source_name, suspend, simple_callback, NULL));
868 else
869 pa_operation_unref(pa_context_suspend_source_by_index(c, PA_INVALID_INDEX, suspend, simple_callback, NULL));
870 break;
872 case SET_CARD_PROFILE:
873 pa_operation_unref(pa_context_set_card_profile_by_name(c, card_name, profile_name, simple_callback, NULL));
874 break;
876 case SET_SINK_PORT:
877 pa_operation_unref(pa_context_set_sink_port_by_name(c, sink_name, port_name, simple_callback, NULL));
878 break;
880 case SET_SOURCE_PORT:
881 pa_operation_unref(pa_context_set_source_port_by_name(c, source_name, port_name, simple_callback, NULL));
882 break;
884 case SET_SINK_MUTE:
885 pa_operation_unref(pa_context_set_sink_mute_by_name(c, sink_name, mute, simple_callback, NULL));
886 break;
888 case SET_SOURCE_MUTE:
889 pa_operation_unref(pa_context_set_source_mute_by_name(c, source_name, mute, simple_callback, NULL));
890 break;
892 case SET_SINK_INPUT_MUTE:
893 pa_operation_unref(pa_context_set_sink_input_mute(c, sink_input_idx, mute, simple_callback, NULL));
894 break;
896 case SET_SINK_VOLUME: {
897 pa_cvolume v;
899 pa_cvolume_set(&v, 1, volume);
900 pa_operation_unref(pa_context_set_sink_volume_by_name(c, sink_name, &v, simple_callback, NULL));
901 break;
904 case SET_SOURCE_VOLUME: {
905 pa_cvolume v;
907 pa_cvolume_set(&v, 1, volume);
908 pa_operation_unref(pa_context_set_source_volume_by_name(c, source_name, &v, simple_callback, NULL));
909 break;
912 case SET_SINK_INPUT_VOLUME: {
913 pa_cvolume v;
915 pa_cvolume_set(&v, 1, volume);
916 pa_operation_unref(pa_context_set_sink_input_volume(c, sink_input_idx, &v, simple_callback, NULL));
917 break;
920 case SUBSCRIBE:
921 pa_context_set_subscribe_callback(c, context_subscribe_callback, NULL);
923 pa_operation_unref(pa_context_subscribe(
925 PA_SUBSCRIPTION_MASK_SINK|
926 PA_SUBSCRIPTION_MASK_SOURCE|
927 PA_SUBSCRIPTION_MASK_SINK_INPUT|
928 PA_SUBSCRIPTION_MASK_SOURCE_OUTPUT|
929 PA_SUBSCRIPTION_MASK_MODULE|
930 PA_SUBSCRIPTION_MASK_CLIENT|
931 PA_SUBSCRIPTION_MASK_SAMPLE_CACHE|
932 PA_SUBSCRIPTION_MASK_SERVER|
933 PA_SUBSCRIPTION_MASK_CARD,
934 NULL,
935 NULL));
936 break;
938 default:
939 pa_assert_not_reached();
941 break;
943 case PA_CONTEXT_TERMINATED:
944 quit(0);
945 break;
947 case PA_CONTEXT_FAILED:
948 default:
949 pa_log(_("Connection failure: %s"), pa_strerror(pa_context_errno(c)));
950 quit(1);
954 static void exit_signal_callback(pa_mainloop_api *m, pa_signal_event *e, int sig, void *userdata) {
955 pa_log(_("Got SIGINT, exiting."));
956 quit(0);
959 static void help(const char *argv0) {
961 printf(_("%s [options] stat\n"
962 "%s [options] list\n"
963 "%s [options] exit\n"
964 "%s [options] upload-sample FILENAME [NAME]\n"
965 "%s [options] play-sample NAME [SINK]\n"
966 "%s [options] remove-sample NAME\n"
967 "%s [options] move-sink-input SINKINPUT SINK\n"
968 "%s [options] move-source-output SOURCEOUTPUT SOURCE\n"
969 "%s [options] load-module NAME [ARGS ...]\n"
970 "%s [options] unload-module MODULE\n"
971 "%s [options] suspend-sink SINK 1|0\n"
972 "%s [options] suspend-source SOURCE 1|0\n"
973 "%s [options] set-card-profile CARD PROFILE\n"
974 "%s [options] set-sink-port SINK PORT\n"
975 "%s [options] set-source-port SOURCE PORT\n"
976 "%s [options] set-sink-volume SINK VOLUME\n"
977 "%s [options] set-source-volume SOURCE VOLUME\n"
978 "%s [options] set-sink-input-volume SINKINPUT VOLUME\n"
979 "%s [options] set-sink-mute SINK 1|0\n"
980 "%s [options] set-source-mute SOURCE 1|0\n"
981 "%s [options] set-sink-input-mute SINKINPUT 1|0\n"
982 "%s [options] subscribe\n\n"
983 " -h, --help Show this help\n"
984 " --version Show version\n\n"
985 " -s, --server=SERVER The name of the server to connect to\n"
986 " -n, --client-name=NAME How to call this client on the server\n"),
987 argv0, argv0, argv0, argv0, argv0,
988 argv0, argv0, argv0, argv0, argv0,
989 argv0, argv0, argv0, argv0, argv0,
990 argv0, argv0, argv0, argv0, argv0,
991 argv0, argv0);
994 enum {
995 ARG_VERSION = 256
998 int main(int argc, char *argv[]) {
999 pa_mainloop* m = NULL;
1000 int ret = 1, c;
1001 char *server = NULL, *bn;
1003 static const struct option long_options[] = {
1004 {"server", 1, NULL, 's'},
1005 {"client-name", 1, NULL, 'n'},
1006 {"version", 0, NULL, ARG_VERSION},
1007 {"help", 0, NULL, 'h'},
1008 {NULL, 0, NULL, 0}
1011 setlocale(LC_ALL, "");
1012 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
1014 bn = pa_path_get_filename(argv[0]);
1016 proplist = pa_proplist_new();
1018 while ((c = getopt_long(argc, argv, "s:n:h", long_options, NULL)) != -1) {
1019 switch (c) {
1020 case 'h' :
1021 help(bn);
1022 ret = 0;
1023 goto quit;
1025 case ARG_VERSION:
1026 printf(_("pactl %s\n"
1027 "Compiled with libpulse %s\n"
1028 "Linked with libpulse %s\n"),
1029 PACKAGE_VERSION,
1030 pa_get_headers_version(),
1031 pa_get_library_version());
1032 ret = 0;
1033 goto quit;
1035 case 's':
1036 pa_xfree(server);
1037 server = pa_xstrdup(optarg);
1038 break;
1040 case 'n': {
1041 char *t;
1043 if (!(t = pa_locale_to_utf8(optarg)) ||
1044 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) {
1046 pa_log(_("Invalid client name '%s'"), t ? t : optarg);
1047 pa_xfree(t);
1048 goto quit;
1051 pa_xfree(t);
1052 break;
1055 default:
1056 goto quit;
1060 if (optind < argc) {
1061 if (pa_streq(argv[optind], "stat"))
1062 action = STAT;
1063 else if (pa_streq(argv[optind], "exit"))
1064 action = EXIT;
1065 else if (pa_streq(argv[optind], "list"))
1066 action = LIST;
1067 else if (pa_streq(argv[optind], "upload-sample")) {
1068 struct SF_INFO sfi;
1069 action = UPLOAD_SAMPLE;
1071 if (optind+1 >= argc) {
1072 pa_log(_("Please specify a sample file to load"));
1073 goto quit;
1076 if (optind+2 < argc)
1077 sample_name = pa_xstrdup(argv[optind+2]);
1078 else {
1079 char *f = pa_path_get_filename(argv[optind+1]);
1080 sample_name = pa_xstrndup(f, strcspn(f, "."));
1083 pa_zero(sfi);
1084 if (!(sndfile = sf_open(argv[optind+1], SFM_READ, &sfi))) {
1085 pa_log(_("Failed to open sound file."));
1086 goto quit;
1089 if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) {
1090 pa_log(_("Failed to determine sample specification from file."));
1091 goto quit;
1093 sample_spec.format = PA_SAMPLE_FLOAT32;
1095 if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) {
1096 if (sample_spec.channels > 2)
1097 pa_log(_("Warning: Failed to determine sample specification from file."));
1098 pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
1101 pa_assert(pa_channel_map_compatible(&channel_map, &sample_spec));
1102 sample_length = (size_t) sfi.frames*pa_frame_size(&sample_spec);
1104 } else if (pa_streq(argv[optind], "play-sample")) {
1105 action = PLAY_SAMPLE;
1106 if (argc != optind+2 && argc != optind+3) {
1107 pa_log(_("You have to specify a sample name to play"));
1108 goto quit;
1111 sample_name = pa_xstrdup(argv[optind+1]);
1113 if (optind+2 < argc)
1114 sink_name = pa_xstrdup(argv[optind+2]);
1116 } else if (pa_streq(argv[optind], "remove-sample")) {
1117 action = REMOVE_SAMPLE;
1118 if (argc != optind+2) {
1119 pa_log(_("You have to specify a sample name to remove"));
1120 goto quit;
1123 sample_name = pa_xstrdup(argv[optind+1]);
1125 } else if (pa_streq(argv[optind], "move-sink-input")) {
1126 action = MOVE_SINK_INPUT;
1127 if (argc != optind+3) {
1128 pa_log(_("You have to specify a sink input index and a sink"));
1129 goto quit;
1132 sink_input_idx = (uint32_t) atoi(argv[optind+1]);
1133 sink_name = pa_xstrdup(argv[optind+2]);
1135 } else if (pa_streq(argv[optind], "move-source-output")) {
1136 action = MOVE_SOURCE_OUTPUT;
1137 if (argc != optind+3) {
1138 pa_log(_("You have to specify a source output index and a source"));
1139 goto quit;
1142 source_output_idx = (uint32_t) atoi(argv[optind+1]);
1143 source_name = pa_xstrdup(argv[optind+2]);
1145 } else if (pa_streq(argv[optind], "load-module")) {
1146 int i;
1147 size_t n = 0;
1148 char *p;
1150 action = LOAD_MODULE;
1152 if (argc <= optind+1) {
1153 pa_log(_("You have to specify a module name and arguments."));
1154 goto quit;
1157 module_name = argv[optind+1];
1159 for (i = optind+2; i < argc; i++)
1160 n += strlen(argv[i])+1;
1162 if (n > 0) {
1163 p = module_args = pa_xmalloc(n);
1165 for (i = optind+2; i < argc; i++)
1166 p += sprintf(p, "%s%s", p == module_args ? "" : " ", argv[i]);
1169 } else if (pa_streq(argv[optind], "unload-module")) {
1170 action = UNLOAD_MODULE;
1172 if (argc != optind+2) {
1173 pa_log(_("You have to specify a module index"));
1174 goto quit;
1177 module_index = (uint32_t) atoi(argv[optind+1]);
1179 } else if (pa_streq(argv[optind], "suspend-sink")) {
1180 action = SUSPEND_SINK;
1182 if (argc > optind+3 || optind+1 >= argc) {
1183 pa_log(_("You may not specify more than one sink. You have to specify a boolean value."));
1184 goto quit;
1187 suspend = pa_parse_boolean(argv[argc-1]);
1189 if (argc > optind+2)
1190 sink_name = pa_xstrdup(argv[optind+1]);
1192 } else if (pa_streq(argv[optind], "suspend-source")) {
1193 action = SUSPEND_SOURCE;
1195 if (argc > optind+3 || optind+1 >= argc) {
1196 pa_log(_("You may not specify more than one source. You have to specify a boolean value."));
1197 goto quit;
1200 suspend = pa_parse_boolean(argv[argc-1]);
1202 if (argc > optind+2)
1203 source_name = pa_xstrdup(argv[optind+1]);
1204 } else if (pa_streq(argv[optind], "set-card-profile")) {
1205 action = SET_CARD_PROFILE;
1207 if (argc != optind+3) {
1208 pa_log(_("You have to specify a card name/index and a profile name"));
1209 goto quit;
1212 card_name = pa_xstrdup(argv[optind+1]);
1213 profile_name = pa_xstrdup(argv[optind+2]);
1215 } else if (pa_streq(argv[optind], "set-sink-port")) {
1216 action = SET_SINK_PORT;
1218 if (argc != optind+3) {
1219 pa_log(_("You have to specify a sink name/index and a port name"));
1220 goto quit;
1223 sink_name = pa_xstrdup(argv[optind+1]);
1224 port_name = pa_xstrdup(argv[optind+2]);
1226 } else if (pa_streq(argv[optind], "set-source-port")) {
1227 action = SET_SOURCE_PORT;
1229 if (argc != optind+3) {
1230 pa_log(_("You have to specify a source name/index and a port name"));
1231 goto quit;
1234 source_name = pa_xstrdup(argv[optind+1]);
1235 port_name = pa_xstrdup(argv[optind+2]);
1237 } else if (pa_streq(argv[optind], "set-sink-volume")) {
1238 uint32_t v;
1239 action = SET_SINK_VOLUME;
1241 if (argc != optind+3) {
1242 pa_log(_("You have to specify a sink name/index and a volume"));
1243 goto quit;
1246 if (pa_atou(argv[optind+2], &v) < 0) {
1247 pa_log(_("Invalid volume specification"));
1248 goto quit;
1251 sink_name = pa_xstrdup(argv[optind+1]);
1252 volume = (pa_volume_t) v;
1254 } else if (pa_streq(argv[optind], "set-source-volume")) {
1255 uint32_t v;
1256 action = SET_SOURCE_VOLUME;
1258 if (argc != optind+3) {
1259 pa_log(_("You have to specify a source name/index and a volume"));
1260 goto quit;
1263 if (pa_atou(argv[optind+2], &v) < 0) {
1264 pa_log(_("Invalid volume specification"));
1265 goto quit;
1268 source_name = pa_xstrdup(argv[optind+1]);
1269 volume = (pa_volume_t) v;
1271 } else if (pa_streq(argv[optind], "set-sink-input-volume")) {
1272 uint32_t v;
1273 action = SET_SINK_INPUT_VOLUME;
1275 if (argc != optind+3) {
1276 pa_log(_("You have to specify a sink input index and a volume"));
1277 goto quit;
1280 if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
1281 pa_log(_("Invalid sink input index"));
1282 goto quit;
1285 if (pa_atou(argv[optind+2], &v) < 0) {
1286 pa_log(_("Invalid volume specification"));
1287 goto quit;
1290 volume = (pa_volume_t) v;
1292 } else if (pa_streq(argv[optind], "set-sink-mute")) {
1293 int b;
1294 action = SET_SINK_MUTE;
1296 if (argc != optind+3) {
1297 pa_log(_("You have to specify a sink name/index and a mute boolean"));
1298 goto quit;
1301 if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
1302 pa_log(_("Invalid volume specification"));
1303 goto quit;
1306 sink_name = pa_xstrdup(argv[optind+1]);
1307 mute = b;
1309 } else if (pa_streq(argv[optind], "set-source-mute")) {
1310 int b;
1311 action = SET_SOURCE_MUTE;
1313 if (argc != optind+3) {
1314 pa_log(_("You have to specify a source name/index and a mute boolean"));
1315 goto quit;
1318 if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
1319 pa_log(_("Invalid volume specification"));
1320 goto quit;
1323 source_name = pa_xstrdup(argv[optind+1]);
1324 mute = b;
1326 } else if (pa_streq(argv[optind], "set-sink-input-mute")) {
1327 int b;
1328 action = SET_SINK_INPUT_MUTE;
1330 if (argc != optind+3) {
1331 pa_log(_("You have to specify a sink input index and a mute boolean"));
1332 goto quit;
1335 if (pa_atou(argv[optind+1], &sink_input_idx) < 0) {
1336 pa_log(_("Invalid sink input index specification"));
1337 goto quit;
1340 if ((b = pa_parse_boolean(argv[optind+2])) < 0) {
1341 pa_log(_("Invalid volume specification"));
1342 goto quit;
1345 mute = b;
1347 } else if (pa_streq(argv[optind], "subscribe"))
1349 action = SUBSCRIBE;
1351 else if (pa_streq(argv[optind], "help")) {
1352 help(bn);
1353 ret = 0;
1354 goto quit;
1358 if (action == NONE) {
1359 pa_log(_("No valid command specified."));
1360 goto quit;
1363 if (!(m = pa_mainloop_new())) {
1364 pa_log(_("pa_mainloop_new() failed."));
1365 goto quit;
1368 mainloop_api = pa_mainloop_get_api(m);
1370 pa_assert_se(pa_signal_init(mainloop_api) == 0);
1371 pa_signal_new(SIGINT, exit_signal_callback, NULL);
1372 pa_signal_new(SIGTERM, exit_signal_callback, NULL);
1373 pa_disable_sigpipe();
1375 if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) {
1376 pa_log(_("pa_context_new() failed."));
1377 goto quit;
1380 pa_context_set_state_callback(context, context_state_callback, NULL);
1381 if (pa_context_connect(context, server, 0, NULL) < 0) {
1382 pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context)));
1383 goto quit;
1386 if (pa_mainloop_run(m, &ret) < 0) {
1387 pa_log(_("pa_mainloop_run() failed."));
1388 goto quit;
1391 quit:
1392 if (sample_stream)
1393 pa_stream_unref(sample_stream);
1395 if (context)
1396 pa_context_unref(context);
1398 if (m) {
1399 pa_signal_done();
1400 pa_mainloop_free(m);
1403 pa_xfree(server);
1404 pa_xfree(sample_name);
1405 pa_xfree(sink_name);
1406 pa_xfree(source_name);
1407 pa_xfree(module_args);
1408 pa_xfree(card_name);
1409 pa_xfree(profile_name);
1411 if (sndfile)
1412 sf_close(sndfile);
1414 if (proplist)
1415 pa_proplist_free(proplist);
1417 return ret;