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 pa_log(_("Time: %0.3f sec; Latency: %0.0f usec. \r"),
578 (float) usec / 1000000,
579 (float) l * (negative?-1.0f:1.0f));
582 /* Someone requested that the latency is shown */
583 static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) {
588 pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL));
591 static void time_event_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) {
592 if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) {
594 if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)))
595 pa_log(_("pa_stream_update_timing_info() failed: %s"), pa_strerror(pa_context_errno(context)));
597 pa_operation_unref(o);
600 pa_context_rttime_restart(context, e, pa_rtclock_now() + TIME_EVENT_USEC);
603 static void help(const char *argv0) {
605 printf(_("%s [options]\n\n"
606 " -h, --help Show this help\n"
607 " --version Show version\n\n"
608 " -r, --record Create a connection for recording\n"
609 " -p, --playback Create a connection for playback\n\n"
610 " -v, --verbose Enable verbose operations\n\n"
611 " -s, --server=SERVER The name of the server to connect to\n"
612 " -d, --device=DEVICE The name of the sink/source to connect to\n"
613 " -n, --client-name=NAME How to call this client on the server\n"
614 " --stream-name=NAME How to call this stream on the server\n"
615 " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n"
616 " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n"
617 " --format=SAMPLEFORMAT The sample type, one of s16le, s16be, u8, float32le,\n"
618 " float32be, ulaw, alaw, s32le, s32be, s24le, s24be,\n"
619 " s24-32le, s24-32be (defaults to s16ne)\n"
620 " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n"
622 " --channel-map=CHANNELMAP Channel map to use instead of the default\n"
623 " --fix-format Take the sample format from the sink the stream is\n"
624 " being connected to.\n"
625 " --fix-rate Take the sampling rate from the sink the stream is\n"
626 " being connected to.\n"
627 " --fix-channels Take the number of channels and the channel map\n"
628 " from the sink the stream is being connected to.\n"
629 " --no-remix Don't upmix or downmix channels.\n"
630 " --no-remap Map channels by index instead of name.\n"
631 " --latency=BYTES Request the specified latency in bytes.\n"
632 " --process-time=BYTES Request the specified process time per request in bytes.\n"
633 " --property=PROPERTY=VALUE Set the specified property to the specified value.\n"
634 " --raw Record/play raw PCM data.\n"
635 " --file-format=FFORMAT Record/play formatted PCM data.\n"
636 " --list-file-formats List available file formats.\n")
658 ARG_LIST_FILE_FORMATS
661 int main(int argc, char *argv[]) {
662 pa_mainloop* m = NULL;
664 char *bn, *server = NULL;
665 pa_time_event *time_event = NULL;
666 const char *filename = NULL;
668 static const struct option long_options[] = {
669 {"record", 0, NULL, 'r'},
670 {"playback", 0, NULL, 'p'},
671 {"device", 1, NULL, 'd'},
672 {"server", 1, NULL, 's'},
673 {"client-name", 1, NULL, 'n'},
674 {"stream-name", 1, NULL, ARG_STREAM_NAME},
675 {"version", 0, NULL, ARG_VERSION},
676 {"help", 0, NULL, 'h'},
677 {"verbose", 0, NULL, 'v'},
678 {"volume", 1, NULL, ARG_VOLUME},
679 {"rate", 1, NULL, ARG_SAMPLERATE},
680 {"format", 1, NULL, ARG_SAMPLEFORMAT},
681 {"channels", 1, NULL, ARG_CHANNELS},
682 {"channel-map", 1, NULL, ARG_CHANNELMAP},
683 {"fix-format", 0, NULL, ARG_FIX_FORMAT},
684 {"fix-rate", 0, NULL, ARG_FIX_RATE},
685 {"fix-channels", 0, NULL, ARG_FIX_CHANNELS},
686 {"no-remap", 0, NULL, ARG_NO_REMAP},
687 {"no-remix", 0, NULL, ARG_NO_REMIX},
688 {"latency", 1, NULL, ARG_LATENCY},
689 {"process-time", 1, NULL, ARG_PROCESS_TIME},
690 {"property", 1, NULL, ARG_PROPERTY},
691 {"raw", 0, NULL, ARG_RAW},
692 {"file-format", 2, NULL, ARG_FILE_FORMAT},
693 {"list-file-formats", 0, NULL, ARG_LIST_FILE_FORMATS},
697 setlocale(LC_ALL, "");
698 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR);
700 bn = pa_path_get_filename(argv[0]);
702 if (strstr(bn, "play")) {
705 } else if (strstr(bn, "record")) {
708 } else if (strstr(bn, "cat")) {
711 } if (strstr(bn, "rec") || strstr(bn, "mon")) {
716 proplist = pa_proplist_new();
718 while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) {
727 printf(_("pacat %s\n"
728 "Compiled with libpulse %s\n"
729 "Linked with libpulse %s\n"),
731 pa_get_headers_version(),
732 pa_get_library_version());
746 device = pa_xstrdup(optarg);
751 server = pa_xstrdup(optarg);
757 if (!(t = pa_locale_to_utf8(optarg)) ||
758 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) {
760 pa_log(_("Invalid client name '%s'"), t ? t : optarg);
769 case ARG_STREAM_NAME: {
771 t = pa_locale_to_utf8(optarg);
773 if (!(t = pa_locale_to_utf8(optarg)) ||
774 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) {
776 pa_log(_("Invalid stream name '%s'"), t ? t : optarg);
790 int v = atoi(optarg);
791 volume = v < 0 ? 0U : (pa_volume_t) v;
792 volume_is_set = TRUE;
797 sample_spec.channels = (uint8_t) atoi(optarg);
798 sample_spec_set = TRUE;
801 case ARG_SAMPLEFORMAT:
802 sample_spec.format = pa_parse_sample_format(optarg);
803 sample_spec_set = TRUE;
807 sample_spec.rate = (uint32_t) atoi(optarg);
808 sample_spec_set = TRUE;
812 if (!pa_channel_map_parse(&channel_map, optarg)) {
813 pa_log(_("Invalid channel map '%s'"), optarg);
817 channel_map_set = TRUE;
820 case ARG_FIX_CHANNELS:
821 flags |= PA_STREAM_FIX_CHANNELS;
825 flags |= PA_STREAM_FIX_RATE;
829 flags |= PA_STREAM_FIX_FORMAT;
833 flags |= PA_STREAM_NO_REMIX_CHANNELS;
837 flags |= PA_STREAM_NO_REMAP_CHANNELS;
841 if (((latency = (size_t) atoi(optarg))) <= 0) {
842 pa_log(_("Invalid latency specification '%s'"), optarg);
847 case ARG_PROCESS_TIME:
848 if (((process_time = (size_t) atoi(optarg))) <= 0) {
849 pa_log(_("Invalid process time specification '%s'"), optarg);
857 if (!(t = pa_locale_to_utf8(optarg)) ||
858 pa_proplist_setp(proplist, t) < 0) {
861 pa_log(_("Invalid property '%s'"), optarg);
873 case ARG_FILE_FORMAT:
877 if ((file_format = pa_sndfile_format_from_string(optarg)) < 0) {
878 pa_log(_("Unknown file format %s."), optarg);
886 case ARG_LIST_FILE_FORMATS:
887 pa_sndfile_dump_formats();
896 if (!pa_sample_spec_valid(&sample_spec)) {
897 pa_log(_("Invalid sample specification"));
901 if (optind+1 == argc) {
904 filename = argv[optind];
906 if ((fd = open(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) {
907 pa_log(_("open(): %s"), strerror(errno));
911 if (dup2(fd, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO) < 0) {
912 pa_log(_("dup2(): %s"), strerror(errno));
918 } else if (optind+1 <= argc) {
919 pa_log(_("Too many arguments."));
927 if (mode == RECORD) {
928 /* This might patch up the sample spec */
929 if (pa_sndfile_write_sample_spec(&sfi, &sample_spec) < 0) {
930 pa_log(_("Failed to generate sample specification for file."));
934 /* Transparently upgrade classic .wav to wavex for multichannel audio */
935 if (file_format <= 0) {
936 if ((sample_spec.channels == 2 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_LEFT &&
937 channel_map.map[1] == PA_CHANNEL_POSITION_RIGHT))) ||
938 (sample_spec.channels == 1 && (!channel_map_set || (channel_map.map[0] == PA_CHANNEL_POSITION_MONO))))
939 file_format = SF_FORMAT_WAV;
941 file_format = SF_FORMAT_WAVEX;
944 sfi.format |= file_format;
947 if (!(sndfile = sf_open_fd(mode == RECORD ? STDOUT_FILENO : STDIN_FILENO,
948 mode == RECORD ? SFM_WRITE : SFM_READ,
950 pa_log(_("Failed to open audio file."));
954 if (mode == PLAYBACK) {
956 pa_log(_("Warning: specified sample specification will be overwritten with specification from file."));
958 if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) {
959 pa_log(_("Failed to determine sample specification from file."));
962 sample_spec_set = TRUE;
964 if (!channel_map_set) {
965 /* Allow the user to overwrite the channel map on the command line */
966 if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) {
967 if (sample_spec.channels > 2)
968 pa_log(_("Warning: Failed to determine channel map from file."));
970 channel_map_set = TRUE;
975 if (!channel_map_set)
976 pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT);
978 if (!pa_channel_map_compatible(&channel_map, &sample_spec)) {
979 pa_log(_("Channel map doesn't match sample specification"));
986 if (mode == PLAYBACK)
987 readf_function = pa_sndfile_readf_function(&sample_spec);
989 if (pa_sndfile_write_channel_map(sndfile, &channel_map) < 0)
990 pa_log(_("Warning: failed to write channel map to file."));
992 writef_function = pa_sndfile_writef_function(&sample_spec);
995 /* Fill in libsndfile prop list data */
996 sfp = pa_proplist_new();
997 pa_sndfile_init_proplist(sndfile, sfp);
998 pa_proplist_update(proplist, PA_UPDATE_MERGE, sfp);
999 pa_proplist_free(sfp);
1003 char tss[PA_SAMPLE_SPEC_SNPRINT_MAX], tcm[PA_CHANNEL_MAP_SNPRINT_MAX];
1005 pa_log(_("Opening a %s stream with sample specification '%s' and channel map '%s'."),
1006 mode == RECORD ? _("recording") : _("playback"),
1007 pa_sample_spec_snprint(tss, sizeof(tss), &sample_spec),
1008 pa_channel_map_snprint(tcm, sizeof(tcm), &channel_map));
1011 /* Fill in client name if none was set */
1012 if (!pa_proplist_contains(proplist, PA_PROP_APPLICATION_NAME)) {
1015 if ((t = pa_locale_to_utf8(bn))) {
1016 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t);
1021 /* Fill in media name if none was set */
1022 if (!pa_proplist_contains(proplist, PA_PROP_MEDIA_NAME)) {
1025 if ((t = filename) ||
1026 (t = pa_proplist_gets(proplist, PA_PROP_APPLICATION_NAME)))
1027 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t);
1030 /* Set up a new main loop */
1031 if (!(m = pa_mainloop_new())) {
1032 pa_log(_("pa_mainloop_new() failed."));
1036 mainloop_api = pa_mainloop_get_api(m);
1038 pa_assert_se(pa_signal_init(mainloop_api) == 0);
1039 pa_signal_new(SIGINT, exit_signal_callback, NULL);
1040 pa_signal_new(SIGTERM, exit_signal_callback, NULL);
1042 pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL);
1044 pa_disable_sigpipe();
1047 if (!(stdio_event = mainloop_api->io_new(mainloop_api,
1048 mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO,
1049 mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT,
1050 mode == PLAYBACK ? stdin_callback : stdout_callback, NULL))) {
1051 pa_log(_("io_new() failed."));
1056 /* Create a new connection context */
1057 if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) {
1058 pa_log(_("pa_context_new() failed."));
1062 pa_context_set_state_callback(context, context_state_callback, NULL);
1064 /* Connect the context */
1065 if (pa_context_connect(context, server, 0, NULL) < 0) {
1066 pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context)));
1071 if (!(time_event = pa_context_rttime_new(context, pa_rtclock_now() + TIME_EVENT_USEC, time_event_callback, NULL))) {
1072 pa_log(_("pa_context_rttime_new() failed."));
1077 /* Run the main loop */
1078 if (pa_mainloop_run(m, &ret) < 0) {
1079 pa_log(_("pa_mainloop_run() failed."));
1085 pa_stream_unref(stream);
1088 pa_context_unref(context);
1091 pa_assert(mainloop_api);
1092 mainloop_api->io_free(stdio_event);
1096 pa_assert(mainloop_api);
1097 mainloop_api->time_free(time_event);
1102 pa_mainloop_free(m);
1114 pa_proplist_free(proplist);