2 This file is part of PulseAudio.
4 Copyright 2004-2006 Lennart Poettering
5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB
7 PulseAudio is free software; you can redistribute it and/or modify
8 it under the terms of the GNU Lesser General Public License as published
9 by the Free Software Foundation; either version 2.1 of the License,
10 or (at your option) any later version.
12 PulseAudio is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with PulseAudio; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
40 #include <pulse/i18n.h>
41 #include <pulse/pulseaudio.h>
42 #include <pulse/rtclock.h>
44 #include <pulsecore/macro.h>
45 #include <pulsecore/core-util.h>
46 #include <pulsecore/log.h>
47 #include <pulsecore/sndfile-util.h>
49 #define TIME_EVENT_USEC 50000
51 #define CLEAR_LINE "\x1B[K"
53 static enum { RECORD, PLAYBACK } mode = PLAYBACK;
55 static pa_context *context = NULL;
56 static pa_stream *stream = NULL;
57 static pa_mainloop_api *mainloop_api = NULL;
59 static void *buffer = NULL;
60 static size_t buffer_length = 0, buffer_index = 0;
62 static pa_io_event* stdio_event = NULL;
64 static pa_proplist *proplist = NULL;
65 static char *device = NULL;
67 static SNDFILE* sndfile = NULL;
69 static pa_bool_t verbose = FALSE;
70 static pa_volume_t volume = PA_VOLUME_NORM;
71 static pa_bool_t volume_is_set = FALSE;
73 static pa_sample_spec sample_spec = {
74 .format = PA_SAMPLE_S16LE,
78 static pa_bool_t sample_spec_set = FALSE;
80 static pa_channel_map channel_map;
81 static pa_bool_t channel_map_set = FALSE;
83 static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames) = NULL;
84 static sf_count_t (*writef_function)(SNDFILE *_sndfile, const void *ptr, sf_count_t frames) = NULL;
86 static pa_stream_flags_t flags = 0;
88 static size_t latency = 0, process_time = 0;
90 static pa_bool_t raw = TRUE;
91 static int file_format = -1;
93 /* A shortcut for terminating the application */
94 static void quit(int ret) {
95 pa_assert(mainloop_api);
96 mainloop_api->quit(mainloop_api, ret);
99 /* Connection draining complete */
100 static void context_drain_complete(pa_context*c, void *userdata) {
101 pa_context_disconnect(c);
104 /* Stream draining complete */
105 static void stream_drain_complete(pa_stream*s, int success, void *userdata) {
108 pa_log(_("Failed to drain stream: %s"), pa_strerror(pa_context_errno(context)));
113 pa_log(_("Playback stream drained."));
115 pa_stream_disconnect(stream);
116 pa_stream_unref(stream);
119 if (!pa_context_drain(context, context_drain_complete, NULL))
120 pa_context_disconnect(context);
123 pa_log(_("Draining connection to server."));
128 static void start_drain(void) {
133 pa_stream_set_write_callback(stream, NULL, NULL);
135 if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) {
136 pa_log(_("pa_stream_drain(): %s"), pa_strerror(pa_context_errno(context)));
141 pa_operation_unref(o);
146 /* Write some data to the stream */
147 static void do_stream_write(size_t length) {
151 if (!buffer || !buffer_length)
155 if (l > buffer_length)
158 if (pa_stream_write(stream, (uint8_t*) buffer + buffer_index, l, NULL, 0, PA_SEEK_RELATIVE) < 0) {
159 pa_log(_("pa_stream_write() failed: %s"), pa_strerror(pa_context_errno(context)));
167 if (!buffer_length) {
170 buffer_index = buffer_length = 0;
174 /* This is called whenever new data may be written to the stream */
175 static void stream_write_callback(pa_stream *s, size_t length, void *userdata) {
177 pa_assert(length > 0);
183 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT);
188 do_stream_write(length);
196 if (pa_stream_begin_write(s, &data, &length) < 0) {
197 pa_log(_("pa_stream_begin_write() failed: %s"), pa_strerror(pa_context_errno(context)));
202 if (readf_function) {
203 size_t k = pa_frame_size(&sample_spec);
205 if ((bytes = readf_function(sndfile, data, (sf_count_t) (length/k))) > 0)
206 bytes *= (sf_count_t) k;
209 bytes = sf_read_raw(sndfile, data, (sf_count_t) length);
212 pa_stream_write(s, data, (size_t) bytes, NULL, 0, PA_SEEK_RELATIVE);
214 pa_stream_cancel_write(s);
216 if (bytes < (sf_count_t) length)
221 /* This is called whenever new data may is available */
222 static void stream_read_callback(pa_stream *s, size_t length, void *userdata) {
225 pa_assert(length > 0);
231 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT);
233 while (pa_stream_readable_size(s) > 0) {
236 if (pa_stream_peek(s, &data, &length) < 0) {
237 pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context)));
243 pa_assert(length > 0);
246 buffer = pa_xrealloc(buffer, buffer_length + length);
247 memcpy((uint8_t*) buffer + buffer_length, data, length);
248 buffer_length += length;
250 buffer = pa_xmalloc(length);
251 memcpy(buffer, data, length);
252 buffer_length = length;
262 while (pa_stream_readable_size(s) > 0) {
266 if (pa_stream_peek(s, &data, &length) < 0) {
267 pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context)));
273 pa_assert(length > 0);
275 if (writef_function) {
276 size_t k = pa_frame_size(&sample_spec);
278 if ((bytes = writef_function(sndfile, data, (sf_count_t) (length/k))) > 0)
279 bytes *= (sf_count_t) k;
282 bytes = sf_write_raw(sndfile, data, (sf_count_t) length);
284 if (bytes < (sf_count_t) length)
292 /* This routine is called whenever the stream state changes */
293 static void stream_state_callback(pa_stream *s, void *userdata) {
296 switch (pa_stream_get_state(s)) {
297 case PA_STREAM_CREATING:
298 case PA_STREAM_TERMINATED:
301 case PA_STREAM_READY:
304 const pa_buffer_attr *a;
305 char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX];
307 pa_log(_("Stream successfully created."));
309 if (!(a = pa_stream_get_buffer_attr(s)))
310 pa_log(_("pa_stream_get_buffer_attr() failed: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
313 if (mode == PLAYBACK)
314 pa_log(_("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u"), a->maxlength, a->tlength, a->prebuf, a->minreq);
316 pa_assert(mode == RECORD);
317 pa_log(_("Buffer metrics: maxlength=%u, fragsize=%u"), a->maxlength, a->fragsize);
321 pa_log(_("Using sample spec '%s', channel map '%s'."),
322 pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)),
323 pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s)));
325 pa_log(_("Connected to device %s (%u, %ssuspended)."),
326 pa_stream_get_device_name(s),
327 pa_stream_get_device_index(s),
328 pa_stream_is_suspended(s) ? "" : "not ");
333 case PA_STREAM_FAILED:
335 pa_log(_("Stream error: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s))));
340 static void stream_suspended_callback(pa_stream *s, void *userdata) {
344 if (pa_stream_is_suspended(s))
345 pa_log(_("Stream device suspended.%s"), CLEAR_LINE);
347 pa_log(_("Stream device resumed.%s"), CLEAR_LINE);
351 static void stream_underflow_callback(pa_stream *s, void *userdata) {
355 pa_log(_("Stream underrun.%s"), CLEAR_LINE);
358 static void stream_overflow_callback(pa_stream *s, void *userdata) {
362 pa_log(_("Stream overrun.%s"), CLEAR_LINE);
365 static void stream_started_callback(pa_stream *s, void *userdata) {
369 pa_log(_("Stream started.%s"), CLEAR_LINE);
372 static void stream_moved_callback(pa_stream *s, void *userdata) {
376 pa_log(_("Stream moved to device %s (%u, %ssuspended).%s"), pa_stream_get_device_name(s), pa_stream_get_device_index(s), pa_stream_is_suspended(s) ? "" : _("not "), CLEAR_LINE);
379 static void stream_buffer_attr_callback(pa_stream *s, void *userdata) {
383 pa_log(_("Stream buffer attributes changed.%s"), CLEAR_LINE);
386 static void stream_event_callback(pa_stream *s, const char *name, pa_proplist *pl, void *userdata) {
393 t = pa_proplist_to_string_sep(pl, ", ");
394 pa_log("Got event '%s', properties '%s'", name, t);
398 /* This is called whenever the context status changes */
399 static void context_state_callback(pa_context *c, void *userdata) {
402 switch (pa_context_get_state(c)) {
403 case PA_CONTEXT_CONNECTING:
404 case PA_CONTEXT_AUTHORIZING:
405 case PA_CONTEXT_SETTING_NAME:
408 case PA_CONTEXT_READY: {
410 pa_buffer_attr buffer_attr;
416 pa_log(_("Connection established.%s"), CLEAR_LINE);
418 if (!(stream = pa_stream_new_with_proplist(c, NULL, &sample_spec, &channel_map, proplist))) {
419 pa_log(_("pa_stream_new() failed: %s"), pa_strerror(pa_context_errno(c)));
423 pa_stream_set_state_callback(stream, stream_state_callback, NULL);
424 pa_stream_set_write_callback(stream, stream_write_callback, NULL);
425 pa_stream_set_read_callback(stream, stream_read_callback, NULL);
426 pa_stream_set_suspended_callback(stream, stream_suspended_callback, NULL);
427 pa_stream_set_moved_callback(stream, stream_moved_callback, NULL);
428 pa_stream_set_underflow_callback(stream, stream_underflow_callback, NULL);
429 pa_stream_set_overflow_callback(stream, stream_overflow_callback, NULL);
430 pa_stream_set_started_callback(stream, stream_started_callback, NULL);
431 pa_stream_set_event_callback(stream, stream_event_callback, NULL);
432 pa_stream_set_buffer_attr_callback(stream, stream_buffer_attr_callback, NULL);
435 memset(&buffer_attr, 0, sizeof(buffer_attr));
436 buffer_attr.tlength = (uint32_t) latency;
437 buffer_attr.minreq = (uint32_t) process_time;
438 buffer_attr.maxlength = (uint32_t) -1;
439 buffer_attr.prebuf = (uint32_t) -1;
440 buffer_attr.fragsize = (uint32_t) latency;
441 flags |= PA_STREAM_ADJUST_LATENCY;
444 if (mode == PLAYBACK) {
446 if ((r = pa_stream_connect_playback(stream, device, latency > 0 ? &buffer_attr : NULL, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL)) < 0) {
447 pa_log(_("pa_stream_connect_playback() failed: %s"), pa_strerror(pa_context_errno(c)));
452 if ((r = pa_stream_connect_record(stream, device, latency > 0 ? &buffer_attr : NULL, flags)) < 0) {
453 pa_log(_("pa_stream_connect_record() failed: %s"), pa_strerror(pa_context_errno(c)));
461 case PA_CONTEXT_TERMINATED:
465 case PA_CONTEXT_FAILED:
467 pa_log(_("Connection failure: %s"), pa_strerror(pa_context_errno(c)));
478 /* New data on STDIN **/
479 static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
483 pa_assert(a == mainloop_api);
485 pa_assert(stdio_event == e);
488 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL);
492 if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || !(l = w = pa_stream_writable_size(stream)))
495 buffer = pa_xmalloc(l);
497 if ((r = read(fd, buffer, l)) <= 0) {
500 pa_log(_("Got EOF."));
505 pa_log(_("read() failed: %s"), strerror(errno));
509 mainloop_api->io_free(stdio_event);
514 buffer_length = (uint32_t) r;
521 /* Some data may be written to STDOUT */
522 static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) {
525 pa_assert(a == mainloop_api);
527 pa_assert(stdio_event == e);
530 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL);
534 pa_assert(buffer_length);
536 if ((r = write(fd, (uint8_t*) buffer+buffer_index, buffer_length)) <= 0) {
537 pa_log(_("write() failed: %s"), strerror(errno));
540 mainloop_api->io_free(stdio_event);
545 buffer_length -= (uint32_t) r;
546 buffer_index += (uint32_t) r;
548 if (!buffer_length) {
551 buffer_length = buffer_index = 0;
555 /* UNIX signal to quit recieved */
556 static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {
558 pa_log(_("Got signal, exiting."));
562 /* Show the current latency */
563 static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) {
570 pa_stream_get_time(s, &usec) < 0 ||
571 pa_stream_get_latency(s, &l, &negative) < 0) {
572 pa_log(_("Failed to get latency: %s"), pa_strerror(pa_context_errno(context)));
577 fprintf(stderr, _("Time: %0.3f sec; Latency: %0.0f usec."),
578 (float) usec / 1000000,
579 (float) l * (negative?-1.0f:1.0f));
580 fprintf(stderr, " \r");
583 /* Someone requested that the latency is shown */
584 static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {
589 pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL));
592 static void time_event_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
593 if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) {
595 if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)))
596 pa_log(_("pa_stream_update_timing_info() failed: %s"), pa_strerror(pa_context_errno(context)));
598 pa_operation_unref(o);
601 pa_context_rttime_restart(context, e, pa_rtclock_now() + TIME_EVENT_USEC);
604 static void help(const char *argv0) {
606 printf(_("%s [options]\n\n"
607 " -h, --help Show this help\n"
608 " --version Show version\n\n"
609 " -r, --record Create a connection for recording\n"
610 " -p, --playback Create a connection for playback\n\n"
611 " -v, --verbose Enable verbose operations\n\n"
612 " -s, --server=SERVER The name of the server to connect to\n"
613 " -d, --device=DEVICE The name of the sink/source to connect to\n"
614 " -n, --client-name=NAME How to call this client on the server\n"
615 " --stream-name=NAME How to call this stream on the server\n"
616 " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n"
617 " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n"
618 " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n"
619 " float32be, ulaw, alaw, s32le, s32be, s24le, s24be,\n"
620 " s24-32le, s24-32be (defaults to s16ne)\n"
621 " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n"
623 " --channel-map=CHANNELMAP Channel map to use instead of the default\n"
624 " --fix-format Take the sample format from the sink the stream is\n"
625 " being connected to.\n"
626 " --fix-rate Take the sampling rate from the sink the stream is\n"
627 " being connected to.\n"
628 " --fix-channels Take the number of channels and the channel map\n"
629 " from the sink the stream is being connected to.\n"
630 " --no-remix Don't upmix or downmix channels.\n"
631 " --no-remap Map channels by index instead of name.\n"
632 " --latency=BYTES Request the specified latency in bytes.\n"
633 " --process-time=BYTES Request the specified process time per request in bytes.\n"
634 " --property=PROPERTY=VALUE Set the specified property to the specified value.\n"
635 " --raw Record/play raw PCM data.\n"
636 " --file-format=FFORMAT Record/play formatted PCM data.\n"
637 " --list-file-formats List available file formats.\n")
659 ARG_LIST_FILE_FORMATS
662 int main(int argc, char *argv[]) {
663 pa_mainloop* m = NULL;
665 char *bn, *server = NULL;
666 pa_time_event *time_event = NULL;
667 const char *filename = NULL;
669 static const struct option long_options[] = {
670 {"record", 0, NULL, 'r'},
671 {"playback", 0, NULL, 'p'},
672 {"device", 1, NULL, 'd'},
673 {"server", 1, NULL, 's'},
674 {"client-name", 1, NULL, 'n'},
675 {"stream-name", 1, NULL, ARG_STREAM_NAME},
676 {"version", 0, NULL, ARG_VERSION},
677 {"help", 0, NULL, 'h'},
678 {"verbose", 0, NULL, 'v'},
679 {"volume", 1, NULL, ARG_VOLUME},
680 {"rate", 1, NULL, ARG_SAMPLERATE},
681 {"format", 1, NULL, ARG_SAMPLEFORMAT},
682 {"channels", 1, NULL, ARG_CHANNELS},
683 {"channel-map", 1, NULL, ARG_CHANNELMAP},
684 {"fix-format", 0, NULL, ARG_FIX_FORMAT},
685 {"fix-rate", 0, NULL, ARG_FIX_RATE},
686 {"fix-channels", 0, NULL, ARG_FIX_CHANNELS},
687 {"no-remap", 0, NULL, ARG_NO_REMAP},
688 {"no-remix", 0, NULL, ARG_NO_REMIX},
689 {"latency", 1, NULL, ARG_LATENCY},
690 {"process-time", 1, NULL, ARG_PROCESS_TIME},
691 {"property", 1, NULL, ARG_PROPERTY},
692 {"raw", 0, NULL, ARG_RAW},
693 {"file-format", 2, NULL, ARG_FILE_FORMAT},
694 {"list-file-formats", 0, NULL, ARG_LIST_FILE_FORMATS},
698 setlocale(LC_ALL, "");
699 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
701 bn = pa_path_get_filename(argv[0]);
703 if (strstr(bn, "play")) {
706 } else if (strstr(bn, "record")) {
709 } else if (strstr(bn, "cat")) {
712 } if (strstr(bn, "rec") || strstr(bn, "mon")) {
717 proplist = pa_proplist_new();
719 while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) {
728 printf(_("pacat %s\n"
729 "Compiled with libpulse %s\n"
730 "Linked with libpulse %s\n"),
732 pa_get_headers_version(),
733 pa_get_library_version());
747 device = pa_xstrdup(optarg);
752 server = pa_xstrdup(optarg);
758 if (!(t = pa_locale_to_utf8(optarg)) ||
759 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) {
761 pa_log(_("Invalid client name '%s'"), t ? t : optarg);
770 case ARG_STREAM_NAME: {
772 t = pa_locale_to_utf8(optarg);
774 if (!(t = pa_locale_to_utf8(optarg)) ||
775 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) {
777 pa_log(_("Invalid stream name '%s'"), t ? t : optarg);
791 int v = atoi(optarg);
792 volume = v < 0 ? 0U : (pa_volume_t) v;
793 volume_is_set = TRUE;
798 sample_spec.channels = (uint8_t) atoi(optarg);
799 sample_spec_set = TRUE;
802 case ARG_SAMPLEFORMAT:
803 sample_spec.format = pa_parse_sample_format(optarg);
804 sample_spec_set = TRUE;
808 sample_spec.rate = (uint32_t) atoi(optarg);
809 sample_spec_set = TRUE;
813 if (!pa_channel_map_parse(&channel_map, optarg)) {
814 pa_log(_("Invalid channel map '%s'"), optarg);
818 channel_map_set = TRUE;
821 case ARG_FIX_CHANNELS:
822 flags |= PA_STREAM_FIX_CHANNELS;
826 flags |= PA_STREAM_FIX_RATE;
830 flags |= PA_STREAM_FIX_FORMAT;
834 flags |= PA_STREAM_NO_REMIX_CHANNELS;
838 flags |= PA_STREAM_NO_REMAP_CHANNELS;
842 if (((latency = (size_t) atoi(optarg))) <= 0) {
843 pa_log(_("Invalid latency specification '%s'"), optarg);
848 case ARG_PROCESS_TIME:
849 if (((process_time = (size_t) atoi(optarg))) <= 0) {
850 pa_log(_("Invalid process time specification '%s'"), optarg);
858 if (!(t = pa_locale_to_utf8(optarg)) ||
859 pa_proplist_setp(proplist, t) < 0) {
862 pa_log(_("Invalid property '%s'"), optarg);
874 case ARG_FILE_FORMAT:
878 if ((file_format = pa_sndfile_format_from_string(optarg)) < 0) {
879 pa_log(_("Unknown file format %s."), optarg);
887 case ARG_LIST_FILE_FORMATS:
888 pa_sndfile_dump_formats();
897 if (!pa_sample_spec_valid(&sample_spec)) {
898 pa_log(_("Invalid sample specification"));
902 if (optind+1 == argc) {
905 filename = argv[optind];
907 if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
908 pa_log(_("open(): %s"), strerror(errno));
912 if (dup2(fd, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO) < 0) {
913 pa_log(_("dup2(): %s"), strerror(errno));
919 } else if (optind+1 <= argc) {
920 pa_log(_("Too many arguments."));
928 if (mode == RECORD) {
929 /* This might patch up the sample spec */
930 if (pa_sndfile_write_sample_spec(&sfi, &sample_spec) < 0) {
931 pa_log(_("Failed to generate sample specification for file."));
935 /* Transparently upgrade classic .wav to wavex for multichannel audio */
936 if (file_format <= 0) {
937 if ((sample_spec.channels == 2 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_LEFT &&
938 channel_map.map[1] == PA_CHANNEL_POSITION_RIGHT))) ||
939 (sample_spec.channels == 1 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_MONO))))
940 file_format = SF_FORMAT_WAV;
942 file_format = SF_FORMAT_WAVEX;
945 sfi.format |= file_format;
948 if (!(sndfile = sf_open_fd(mode == RECORD ? STDOUT_FILENO : STDIN_FILENO,
949 mode == RECORD ? SFM_WRITE : SFM_READ,
951 pa_log(_("Failed to open audio file."));
955 if (mode == PLAYBACK) {
957 pa_log(_("Warning: specified sample specification will be overwritten with specification from file."));
959 if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) {
960 pa_log(_("Failed to determine sample specification from file."));
963 sample_spec_set = TRUE;
965 if (!channel_map_set) {
966 /* Allow the user to overwrite the channel map on the command line */
967 if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) {
968 if (sample_spec.channels > 2)
969 pa_log(_("Warning: Failed to determine channel map from file."));
971 channel_map_set = TRUE;
976 if (!channel_map_set)
977 pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
979 if (!pa_channel_map_compatible(&channel_map, &sample_spec)) {
980 pa_log(_("Channel map doesn't match sample specification"));
987 if (mode == PLAYBACK)
988 readf_function = pa_sndfile_readf_function(&sample_spec);
990 if (pa_sndfile_write_channel_map(sndfile, &channel_map) < 0)
991 pa_log(_("Warning: failed to write channel map to file."));
993 writef_function = pa_sndfile_writef_function(&sample_spec);
996 /* Fill in libsndfile prop list data */
997 sfp = pa_proplist_new();
998 pa_sndfile_init_proplist(sndfile, sfp);
999 pa_proplist_update(proplist, PA_UPDATE_MERGE, sfp);
1000 pa_proplist_free(sfp);
1004 char tss[PA_SAMPLE_SPEC_SNPRINT_MAX], tcm[PA_CHANNEL_MAP_SNPRINT_MAX];
1006 pa_log(_("Opening a %s stream with sample specification '%s' and channel map '%s'."),
1007 mode == RECORD ? _("recording") : _("playback"),
1008 pa_sample_spec_snprint(tss, sizeof(tss), &sample_spec),
1009 pa_channel_map_snprint(tcm, sizeof(tcm), &channel_map));
1012 /* Fill in client name if none was set */
1013 if (!pa_proplist_contains(proplist, PA_PROP_APPLICATION_NAME)) {
1016 if ((t = pa_locale_to_utf8(bn))) {
1017 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t);
1022 /* Fill in media name if none was set */
1023 if (!pa_proplist_contains(proplist, PA_PROP_MEDIA_NAME)) {
1026 if ((t = filename) ||
1027 (t = pa_proplist_gets(proplist, PA_PROP_APPLICATION_NAME)))
1028 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t);
1031 /* Set up a new main loop */
1032 if (!(m = pa_mainloop_new())) {
1033 pa_log(_("pa_mainloop_new() failed."));
1037 mainloop_api = pa_mainloop_get_api(m);
1039 pa_assert_se(pa_signal_init(mainloop_api) == 0);
1040 pa_signal_new(SIGINT, exit_signal_callback, NULL);
1041 pa_signal_new(SIGTERM, exit_signal_callback, NULL);
1043 pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
1045 pa_disable_sigpipe();
1048 if (!(stdio_event = mainloop_api->io_new(mainloop_api,
1049 mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
1050 mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT,
1051 mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) {
1052 pa_log(_("io_new() failed."));
1057 /* Create a new connection context */
1058 if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) {
1059 pa_log(_("pa_context_new() failed."));
1063 pa_context_set_state_callback(context, context_state_callback, NULL);
1065 /* Connect the context */
1066 if (pa_context_connect(context, server, 0, NULL) < 0) {
1067 pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context)));
1072 if (!(time_event = pa_context_rttime_new(context, pa_rtclock_now() + TIME_EVENT_USEC, time_event_callback, NULL))) {
1073 pa_log(_("pa_context_rttime_new() failed."));
1078 /* Run the main loop */
1079 if (pa_mainloop_run(m, &ret) < 0) {
1080 pa_log(_("pa_mainloop_run() failed."));
1086 pa_stream_unref(stream);
1089 pa_context_unref(context);
1092 pa_assert(mainloop_api);
1093 mainloop_api->io_free(stdio_event);
1097 pa_assert(mainloop_api);
1098 mainloop_api->time_free(time_event);
1103 pa_mainloop_free(m);
1115 pa_proplist_free(proplist);