1/*** 2 This file is part of PulseAudio. 3 4 Copyright 2004-2006 Lennart Poettering 5 Copyright 2006 Pierre Ossman <ossman@cendio.se> for Cendio AB 6 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. 11 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. 16 17 You should have received a copy of the GNU Lesser General Public License 18 along with PulseAudio; if not, see <http://www.gnu.org/licenses/>. 19***/ 20 21#ifdef HAVE_CONFIG_H 22#include <config.h> 23#endif 24 25#include <signal.h> 26#include <string.h> 27#include <errno.h> 28#include <unistd.h> 29#include <assert.h> 30#include <stdio.h> 31#include <stdlib.h> 32#include <getopt.h> 33#include <fcntl.h> 34#include <locale.h> 35 36#include <sndfile.h> 37 38#include <pulse/pulseaudio.h> 39#include <pulse/rtclock.h> 40 41#include <pulsecore/core-util.h> 42#include <pulsecore/i18n.h> 43#include <pulsecore/log.h> 44#include <pulsecore/macro.h> 45#include <pulsecore/sndfile-util.h> 46#include <pulsecore/sample-util.h> 47 48#define TIME_EVENT_USEC 50000 49 50#define CLEAR_LINE "\x1B[K" 51 52static enum { RECORD, PLAYBACK } mode = PLAYBACK; 53static const char *purpose = NULL; 54 55static pa_context *context = NULL; 56static pa_stream *stream = NULL; 57static pa_mainloop_api *mainloop_api = NULL; 58 59/* Playback Mode (raw): 60 * 61 * We can only write audio to the PA stream in multiples of the stream's 62 * sample-spec frame size. Meanwhile, the STDIN read(2) system call can return 63 * a length much smaller than the frame-aligned size requested - leading to 64 * invalid writes. This can be reproduced by choosing a starved STDIN backend 65 * (e.g. "pacat /dev/random", "echo 1234 | pacat"), or an incomplete WAV file 66 * in raw non-paplay mode. 67 * 68 * Solve this by writing only frame-aligned sizes, while caching the resulting 69 * trailing partial frames here. This partial frame is then directly written 70 * in the next stream write iteration. Rinse and repeat. 71 */ 72static void *partialframe_buf = NULL; 73static size_t partialframe_len = 0; 74 75/* Recording Mode buffers */ 76static void *buffer = NULL; 77static size_t buffer_length = 0, buffer_index = 0; 78 79static void *silence_buffer = NULL; 80static size_t silence_buffer_length = 0; 81 82static pa_io_event* stdio_event = NULL; 83 84static pa_proplist *proplist = NULL; 85static char *device = NULL; 86 87static SNDFILE* sndfile = NULL; 88 89static bool verbose = false; 90static pa_volume_t volume = PA_VOLUME_NORM; 91static bool volume_is_set = false; 92 93static pa_sample_spec sample_spec = { 94 .format = PA_SAMPLE_S16LE, 95 .rate = 44100, 96 .channels = 2 97}; 98static bool sample_spec_set = false; 99 100static pa_channel_map channel_map; 101static bool channel_map_set = false; 102 103static sf_count_t (*readf_function)(SNDFILE *_sndfile, void *ptr, sf_count_t frames) = NULL; 104static sf_count_t (*writef_function)(SNDFILE *_sndfile, const void *ptr, sf_count_t frames) = NULL; 105 106static pa_stream_flags_t flags = 0; 107 108static size_t latency = 0, process_time = 0; 109static int32_t latency_msec = 0, process_time_msec = 0; 110 111static bool raw = true; 112static int file_format = -1; 113 114static uint32_t monitor_stream = PA_INVALID_INDEX; 115 116static uint32_t cork_requests = 0; 117 118/* A shortcut for terminating the application */ 119static void quit(int ret) { 120 pa_assert(mainloop_api); 121 mainloop_api->quit(mainloop_api, ret); 122} 123 124/* Connection draining complete */ 125static void context_drain_complete(pa_context*c, void *userdata) { 126 pa_context_disconnect(c); 127} 128 129/* Stream draining complete */ 130static void stream_drain_complete(pa_stream*s, int success, void *userdata) { 131 pa_operation *o = NULL; 132 133 if (!success) { 134 pa_log(_("Failed to drain stream: %s"), pa_strerror(pa_context_errno(context))); 135 quit(1); 136 } 137 138 if (verbose) 139 pa_log(_("Playback stream drained.")); 140 141 pa_stream_disconnect(stream); 142 pa_stream_unref(stream); 143 stream = NULL; 144 145 if (!(o = pa_context_drain(context, context_drain_complete, NULL))) 146 pa_context_disconnect(context); 147 else { 148 pa_operation_unref(o); 149 if (verbose) 150 pa_log(_("Draining connection to server.")); 151 } 152} 153 154/* Start draining */ 155static void start_drain(void) { 156 157 if (stream) { 158 pa_operation *o; 159 160 pa_stream_set_write_callback(stream, NULL, NULL); 161 162 if (!(o = pa_stream_drain(stream, stream_drain_complete, NULL))) { 163 pa_log(_("pa_stream_drain(): %s"), pa_strerror(pa_context_errno(context))); 164 quit(1); 165 return; 166 } 167 168 pa_operation_unref(o); 169 } else 170 quit(0); 171} 172 173/* This is called whenever new data may be written to the stream */ 174static void stream_write_callback(pa_stream *s, size_t length, void *userdata) { 175 pa_assert(s); 176 pa_assert(length > 0); 177 178 if (raw) { 179 pa_assert(!sndfile); 180 181 if (stdio_event) 182 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_INPUT); 183 184 } else { 185 sf_count_t bytes; 186 void *data; 187 188 pa_assert(sndfile); 189 190 for (;;) { 191 size_t data_length = length; 192 193 if (pa_stream_begin_write(s, &data, &data_length) < 0) { 194 pa_log(_("pa_stream_begin_write() failed: %s"), pa_strerror(pa_context_errno(context))); 195 quit(1); 196 return; 197 } 198 199 if (readf_function) { 200 size_t k = pa_frame_size(&sample_spec); 201 202 if ((bytes = readf_function(sndfile, data, (sf_count_t) (data_length/k))) > 0) 203 bytes *= (sf_count_t) k; 204 205 } else 206 bytes = sf_read_raw(sndfile, data, (sf_count_t) data_length); 207 208 if (bytes > 0) 209 pa_stream_write(s, data, (size_t) bytes, NULL, 0, PA_SEEK_RELATIVE); 210 else 211 pa_stream_cancel_write(s); 212 213 /* EOF? */ 214 if (bytes < (sf_count_t) data_length) { 215 start_drain(); 216 break; 217 } 218 219 /* Request fulfilled */ 220 if ((size_t) bytes >= length) 221 break; 222 223 length -= bytes; 224 } 225 } 226} 227 228/* This is called whenever new data is available */ 229static void stream_read_callback(pa_stream *s, size_t length, void *userdata) { 230 231 pa_assert(s); 232 pa_assert(length > 0); 233 234 if (raw) { 235 pa_assert(!sndfile); 236 237 if (stdio_event) 238 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_OUTPUT); 239 240 while (pa_stream_readable_size(s) > 0) { 241 const void *data; 242 243 if (pa_stream_peek(s, &data, &length) < 0) { 244 pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); 245 quit(1); 246 return; 247 } 248 249 pa_assert(length > 0); 250 251 /* If there is a hole in the stream, we generate silence, except 252 * if it's a passthrough stream in which case we skip the hole. */ 253 if (data || !(flags & PA_STREAM_PASSTHROUGH)) { 254 buffer = pa_xrealloc(buffer, buffer_index + buffer_length + length); 255 if (data) 256 memcpy((uint8_t *) buffer + buffer_index + buffer_length, data, length); 257 else 258 pa_silence_memory((uint8_t *) buffer + buffer_index + buffer_length, length, &sample_spec); 259 260 buffer_length += length; 261 } 262 263 pa_stream_drop(s); 264 } 265 266 } else { 267 pa_assert(sndfile); 268 269 while (pa_stream_readable_size(s) > 0) { 270 sf_count_t bytes; 271 const void *data; 272 273 if (pa_stream_peek(s, &data, &length) < 0) { 274 pa_log(_("pa_stream_peek() failed: %s"), pa_strerror(pa_context_errno(context))); 275 quit(1); 276 return; 277 } 278 279 pa_assert(length > 0); 280 281 if (!data && (flags & PA_STREAM_PASSTHROUGH)) { 282 pa_stream_drop(s); 283 continue; 284 } 285 286 if (!data && length > silence_buffer_length) { 287 silence_buffer = pa_xrealloc(silence_buffer, length); 288 pa_silence_memory((uint8_t *) silence_buffer + silence_buffer_length, length - silence_buffer_length, &sample_spec); 289 silence_buffer_length = length; 290 } 291 292 if (writef_function) { 293 size_t k = pa_frame_size(&sample_spec); 294 295 if ((bytes = writef_function(sndfile, data ? data : silence_buffer, (sf_count_t) (length/k))) > 0) 296 bytes *= (sf_count_t) k; 297 298 } else 299 bytes = sf_write_raw(sndfile, data ? data : silence_buffer, (sf_count_t) length); 300 301 if (bytes < (sf_count_t) length) 302 quit(1); 303 304 pa_stream_drop(s); 305 } 306 } 307} 308 309/* This routine is called whenever the stream state changes */ 310static void stream_state_callback(pa_stream *s, void *userdata) { 311 pa_assert(s); 312 313 switch (pa_stream_get_state(s)) { 314 case PA_STREAM_CREATING: 315 case PA_STREAM_TERMINATED: 316 break; 317 318 case PA_STREAM_READY: 319 320 if (verbose) { 321 const pa_buffer_attr *a; 322 char cmt[PA_CHANNEL_MAP_SNPRINT_MAX], sst[PA_SAMPLE_SPEC_SNPRINT_MAX]; 323 324 pa_log(_("Stream successfully created.")); 325 326 if (!(a = pa_stream_get_buffer_attr(s))) 327 pa_log(_("pa_stream_get_buffer_attr() failed: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); 328 else { 329 330 if (mode == PLAYBACK) 331 pa_log(_("Buffer metrics: maxlength=%u, tlength=%u, prebuf=%u, minreq=%u"), a->maxlength, a->tlength, a->prebuf, a->minreq); 332 else { 333 pa_assert(mode == RECORD); 334 pa_log(_("Buffer metrics: maxlength=%u, fragsize=%u"), a->maxlength, a->fragsize); 335 } 336 } 337 338 pa_log(_("Using sample spec '%s', channel map '%s'."), 339 pa_sample_spec_snprint(sst, sizeof(sst), pa_stream_get_sample_spec(s)), 340 pa_channel_map_snprint(cmt, sizeof(cmt), pa_stream_get_channel_map(s))); 341 342 pa_log(_("Connected to device %s (index: %u, suspended: %s)."), 343 pa_stream_get_device_name(s), 344 pa_stream_get_device_index(s), 345 pa_yes_no(pa_stream_is_suspended(s))); 346 } 347 348 break; 349 350 case PA_STREAM_FAILED: 351 default: 352 pa_log(_("Stream error: %s"), pa_strerror(pa_context_errno(pa_stream_get_context(s)))); 353 quit(1); 354 } 355} 356 357static void stream_suspended_callback(pa_stream *s, void *userdata) { 358 pa_assert(s); 359 360 if (verbose) { 361 if (pa_stream_is_suspended(s)) 362 pa_log(_("Stream device suspended.%s"), CLEAR_LINE); 363 else 364 pa_log(_("Stream device resumed.%s"), CLEAR_LINE); 365 } 366} 367 368static void stream_underflow_callback(pa_stream *s, void *userdata) { 369 pa_assert(s); 370 371 if (verbose) 372 pa_log(_("Stream underrun.%s"), CLEAR_LINE); 373} 374 375static void stream_overflow_callback(pa_stream *s, void *userdata) { 376 pa_assert(s); 377 378 if (verbose) 379 pa_log(_("Stream overrun.%s"), CLEAR_LINE); 380} 381 382static void stream_started_callback(pa_stream *s, void *userdata) { 383 pa_assert(s); 384 385 if (verbose) 386 pa_log(_("Stream started.%s"), CLEAR_LINE); 387} 388 389static void stream_moved_callback(pa_stream *s, void *userdata) { 390 pa_assert(s); 391 392 if (verbose) 393 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); 394} 395 396static void stream_buffer_attr_callback(pa_stream *s, void *userdata) { 397 pa_assert(s); 398 399 if (verbose) 400 pa_log(_("Stream buffer attributes changed.%s"), CLEAR_LINE); 401} 402 403static void stream_event_callback(pa_stream *s, const char *name, pa_proplist *pl, void *userdata) { 404 char *t; 405 406 pa_assert(s); 407 pa_assert(name); 408 pa_assert(pl); 409 410 t = pa_proplist_to_string_sep(pl, ", "); 411 pa_log("Got event '%s', properties '%s'", name, t); 412 413 if (pa_streq(name, PA_STREAM_EVENT_REQUEST_CORK)) { 414 if (cork_requests == 0) { 415 pa_log(_("Cork request stack is empty: corking stream")); 416 pa_operation_unref(pa_stream_cork(s, 1, NULL, NULL)); 417 } 418 cork_requests++; 419 } else if (pa_streq(name, PA_STREAM_EVENT_REQUEST_UNCORK)) { 420 if (cork_requests == 1) { 421 pa_log(_("Cork request stack is empty: uncorking stream")); 422 pa_operation_unref(pa_stream_cork(s, 0, NULL, NULL)); 423 } 424 if (cork_requests == 0) 425 pa_log(_("Warning: Received more uncork requests than cork requests.")); 426 else 427 cork_requests--; 428 } 429 430 pa_xfree(t); 431} 432 433/* This is called whenever the context status changes */ 434static void context_state_callback(pa_context *c, void *userdata) { 435 pa_assert(c); 436 437 switch (pa_context_get_state(c)) { 438 case PA_CONTEXT_CONNECTING: 439 case PA_CONTEXT_AUTHORIZING: 440 case PA_CONTEXT_SETTING_NAME: 441 break; 442 443 case PA_CONTEXT_READY: { 444 pa_buffer_attr buffer_attr; 445 446 pa_assert(c); 447 pa_assert(!stream); 448 449 if (verbose) 450 pa_log(_("Connection established.%s"), CLEAR_LINE); 451 452 if (!(stream = pa_stream_new_with_proplist(c, NULL, &sample_spec, &channel_map, proplist))) { 453 pa_log(_("pa_stream_new() failed: %s"), pa_strerror(pa_context_errno(c))); 454 goto fail; 455 } 456 457 pa_stream_set_state_callback(stream, stream_state_callback, NULL); 458 pa_stream_set_write_callback(stream, stream_write_callback, NULL); 459 pa_stream_set_read_callback(stream, stream_read_callback, NULL); 460 pa_stream_set_suspended_callback(stream, stream_suspended_callback, NULL); 461 pa_stream_set_moved_callback(stream, stream_moved_callback, NULL); 462 pa_stream_set_underflow_callback(stream, stream_underflow_callback, NULL); 463 pa_stream_set_overflow_callback(stream, stream_overflow_callback, NULL); 464 pa_stream_set_started_callback(stream, stream_started_callback, NULL); 465 pa_stream_set_event_callback(stream, stream_event_callback, NULL); 466 pa_stream_set_buffer_attr_callback(stream, stream_buffer_attr_callback, NULL); 467 468 pa_zero(buffer_attr); 469 buffer_attr.maxlength = (uint32_t) -1; 470 buffer_attr.prebuf = (uint32_t) -1; 471 472 if (latency_msec > 0) { 473 buffer_attr.fragsize = buffer_attr.tlength = pa_usec_to_bytes(latency_msec * PA_USEC_PER_MSEC, &sample_spec); 474 flags |= PA_STREAM_ADJUST_LATENCY; 475 } else if (latency > 0) { 476 buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) latency; 477 flags |= PA_STREAM_ADJUST_LATENCY; 478 } else 479 buffer_attr.fragsize = buffer_attr.tlength = (uint32_t) -1; 480 481 if (process_time_msec > 0) { 482 buffer_attr.minreq = pa_usec_to_bytes(process_time_msec * PA_USEC_PER_MSEC, &sample_spec); 483 } else if (process_time > 0) 484 buffer_attr.minreq = (uint32_t) process_time; 485 else 486 buffer_attr.minreq = (uint32_t) -1; 487 488 if (mode == PLAYBACK) { 489 pa_cvolume cv; 490 if (pa_stream_connect_playback(stream, device, &buffer_attr, flags, volume_is_set ? pa_cvolume_set(&cv, sample_spec.channels, volume) : NULL, NULL) < 0) { 491 pa_log(_("pa_stream_connect_playback() failed: %s"), pa_strerror(pa_context_errno(c))); 492 goto fail; 493 } 494 495 } else { 496 if (monitor_stream != PA_INVALID_INDEX && (pa_stream_set_monitor_stream(stream, monitor_stream) < 0)) { 497 pa_log(_("Failed to set monitor stream: %s"), pa_strerror(pa_context_errno(c))); 498 goto fail; 499 } 500 if (pa_stream_connect_record(stream, device, &buffer_attr, flags) < 0) { 501 pa_log(_("pa_stream_connect_record() failed: %s"), pa_strerror(pa_context_errno(c))); 502 goto fail; 503 } 504 } 505 break; 506 } 507 508 case PA_CONTEXT_TERMINATED: 509 quit(0); 510 break; 511 512 case PA_CONTEXT_FAILED: 513 default: 514 pa_log(_("Connection failure: %s"), pa_strerror(pa_context_errno(c))); 515 goto fail; 516 } 517 518 return; 519 520fail: 521 quit(1); 522 523} 524 525/* New data on STDIN **/ 526static void stdin_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { 527 uint8_t *buf = NULL; 528 size_t writable, towrite, r; 529 530 pa_assert(a == mainloop_api); 531 pa_assert(e); 532 pa_assert(stdio_event == e); 533 534 /* Stream not ready? */ 535 if (!stream || pa_stream_get_state(stream) != PA_STREAM_READY || 536 !(writable = pa_stream_writable_size(stream))) { 537 538 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); 539 return; 540 } 541 542 if (pa_stream_begin_write(stream, (void **)&buf, &writable) < 0) { 543 pa_log(_("pa_stream_begin_write() failed: %s"), pa_strerror(pa_context_errno(context))); 544 quit(1); 545 return; 546 } 547 548 /* Partial frame cached from a previous write iteration? */ 549 if (partialframe_len) { 550 pa_assert(partialframe_len < pa_frame_size(&sample_spec)); 551 memcpy(buf, partialframe_buf, partialframe_len); 552 } 553 554 if ((r = pa_read(fd, buf + partialframe_len, writable - partialframe_len, userdata)) <= 0) { 555 if (r == 0) { 556 if (verbose) 557 pa_log(_("Got EOF.")); 558 559 start_drain(); 560 561 } else { 562 pa_log(_("read() failed: %s"), strerror(errno)); 563 quit(1); 564 } 565 566 mainloop_api->io_free(stdio_event); 567 stdio_event = NULL; 568 return; 569 } 570 r += partialframe_len; 571 572 /* Cache any trailing partial frames for the next write */ 573 towrite = pa_frame_align(r, &sample_spec); 574 partialframe_len = r - towrite; 575 576 if (partialframe_len) 577 memcpy(partialframe_buf, buf + towrite, partialframe_len); 578 579 if (towrite) { 580 if (pa_stream_write(stream, buf, towrite, NULL, 0, PA_SEEK_RELATIVE) < 0) { 581 pa_log(_("pa_stream_write() failed: %s"), pa_strerror(pa_context_errno(context))); 582 quit(1); 583 return; 584 } 585 } else 586 pa_stream_cancel_write(stream); 587} 588 589/* Some data may be written to STDOUT */ 590static void stdout_callback(pa_mainloop_api*a, pa_io_event *e, int fd, pa_io_event_flags_t f, void *userdata) { 591 ssize_t r; 592 593 pa_assert(a == mainloop_api); 594 pa_assert(e); 595 pa_assert(stdio_event == e); 596 597 if (!buffer) { 598 mainloop_api->io_enable(stdio_event, PA_IO_EVENT_NULL); 599 return; 600 } 601 602 pa_assert(buffer_length); 603 604 if ((r = pa_write(fd, (uint8_t*) buffer+buffer_index, buffer_length, userdata)) <= 0) { 605 pa_log(_("write() failed: %s"), strerror(errno)); 606 quit(1); 607 608 mainloop_api->io_free(stdio_event); 609 stdio_event = NULL; 610 return; 611 } 612 613 buffer_length -= (uint32_t) r; 614 buffer_index += (uint32_t) r; 615 616 if (!buffer_length) { 617 pa_xfree(buffer); 618 buffer = NULL; 619 buffer_length = buffer_index = 0; 620 } 621} 622 623/* UNIX signal to quit received */ 624static void exit_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { 625 if (verbose) 626 pa_log(_("Got signal, exiting.")); 627 quit(0); 628} 629 630/* Show the current latency */ 631static void stream_update_timing_callback(pa_stream *s, int success, void *userdata) { 632 pa_usec_t l, usec; 633 int negative = 0; 634 635 pa_assert(s); 636 637 if (!success || 638 pa_stream_get_time(s, &usec) < 0 || 639 pa_stream_get_latency(s, &l, &negative) < 0) { 640 pa_log(_("Failed to get latency: %s"), pa_strerror(pa_context_errno(context))); 641 quit(1); 642 return; 643 } 644 645 fprintf(stderr, _("Time: %0.3f sec; Latency: %0.0f usec."), 646 (float) usec / 1000000, 647 (float) l * (negative?-1.0f:1.0f)); 648 fprintf(stderr, " \r"); 649} 650 651#ifdef SIGUSR1 652/* Someone requested that the latency is shown */ 653static void sigusr1_signal_callback(pa_mainloop_api*m, pa_signal_event *e, int sig, void *userdata) { 654 655 if (!stream) 656 return; 657 658 pa_operation_unref(pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL)); 659} 660#endif 661 662static void time_event_callback(pa_mainloop_api *m, pa_time_event *e, const struct timeval *t, void *userdata) { 663 if (stream && pa_stream_get_state(stream) == PA_STREAM_READY) { 664 pa_operation *o; 665 if (!(o = pa_stream_update_timing_info(stream, stream_update_timing_callback, NULL))) 666 pa_log(_("pa_stream_update_timing_info() failed: %s"), pa_strerror(pa_context_errno(context))); 667 else 668 pa_operation_unref(o); 669 } 670 671 pa_context_rttime_restart(context, e, pa_rtclock_now() + TIME_EVENT_USEC); 672} 673 674static void help(const char *argv0) { 675 676 printf(_("%s [options]\n" 677 "%s\n\n" 678 " -h, --help Show this help\n" 679 " --version Show version\n\n" 680 " -r, --record Create a connection for recording\n" 681 " -p, --playback Create a connection for playback\n\n" 682 " -v, --verbose Enable verbose operations\n\n" 683 " -s, --server=SERVER The name of the server to connect to\n" 684 " -d, --device=DEVICE The name of the sink/source to connect to. The special names @DEFAULT_SINK@, @DEFAULT_SOURCE@ and @DEFAULT_MONITOR@ can be used to specify the default sink, source and monitor respectively.\n" 685 " -n, --client-name=NAME How to call this client on the server\n" 686 " --stream-name=NAME How to call this stream on the server\n" 687 " --volume=VOLUME Specify the initial (linear) volume in range 0...65536\n" 688 " --rate=SAMPLERATE The sample rate in Hz (defaults to 44100)\n" 689 " --format=SAMPLEFORMAT The sample format, see\n" 690 " https://www.freedesktop.org/wiki/Software/PulseAudio/Documentation/User/SupportedAudioFormats/\n" 691 " for possible values (defaults to s16ne)\n" 692 " --channels=CHANNELS The number of channels, 1 for mono, 2 for stereo\n" 693 " (defaults to 2)\n" 694 " --channel-map=CHANNELMAP Channel map to use instead of the default\n" 695 " --fix-format Take the sample format from the sink/source the stream is\n" 696 " being connected to.\n" 697 " --fix-rate Take the sampling rate from the sink/source the stream is\n" 698 " being connected to.\n" 699 " --fix-channels Take the number of channels and the channel map\n" 700 " from the sink/source the stream is being connected to.\n" 701 " --no-remix Don't upmix or downmix channels.\n" 702 " --no-remap Map channels by index instead of name.\n" 703 " --latency=BYTES Request the specified latency in bytes.\n" 704 " --process-time=BYTES Request the specified process time per request in bytes.\n" 705 " --latency-msec=MSEC Request the specified latency in msec.\n" 706 " --process-time-msec=MSEC Request the specified process time per request in msec.\n" 707 " --property=PROPERTY=VALUE Set the specified property to the specified value.\n" 708 " --raw Record/play raw PCM data.\n" 709 " --passthrough Passthrough data.\n" 710 " --file-format[=FFORMAT] Record/play formatted PCM data.\n" 711 " --list-file-formats List available file formats.\n" 712 " --monitor-stream=INDEX Record from the sink input with index INDEX.\n") 713 , argv0, purpose); 714} 715 716enum { 717 ARG_VERSION = 256, 718 ARG_STREAM_NAME, 719 ARG_VOLUME, 720 ARG_SAMPLERATE, 721 ARG_SAMPLEFORMAT, 722 ARG_CHANNELS, 723 ARG_CHANNELMAP, 724 ARG_FIX_FORMAT, 725 ARG_FIX_RATE, 726 ARG_FIX_CHANNELS, 727 ARG_NO_REMAP, 728 ARG_NO_REMIX, 729 ARG_LATENCY, 730 ARG_PROCESS_TIME, 731 ARG_RAW, 732 ARG_PASSTHROUGH, 733 ARG_PROPERTY, 734 ARG_FILE_FORMAT, 735 ARG_LIST_FILE_FORMATS, 736 ARG_LATENCY_MSEC, 737 ARG_PROCESS_TIME_MSEC, 738 ARG_MONITOR_STREAM, 739}; 740 741int main(int argc, char *argv[]) { 742 pa_mainloop* m = NULL; 743 int ret = 1, c; 744 char *bn, *server = NULL; 745 pa_time_event *time_event = NULL; 746 const char *filename = NULL; 747 /* type for pa_read/_write. passed as userdata to the callbacks */ 748 unsigned long type = 0; 749 750 static const struct option long_options[] = { 751 {"record", 0, NULL, 'r'}, 752 {"playback", 0, NULL, 'p'}, 753 {"device", 1, NULL, 'd'}, 754 {"server", 1, NULL, 's'}, 755 {"client-name", 1, NULL, 'n'}, 756 {"stream-name", 1, NULL, ARG_STREAM_NAME}, 757 {"version", 0, NULL, ARG_VERSION}, 758 {"help", 0, NULL, 'h'}, 759 {"verbose", 0, NULL, 'v'}, 760 {"volume", 1, NULL, ARG_VOLUME}, 761 {"rate", 1, NULL, ARG_SAMPLERATE}, 762 {"format", 1, NULL, ARG_SAMPLEFORMAT}, 763 {"channels", 1, NULL, ARG_CHANNELS}, 764 {"channel-map", 1, NULL, ARG_CHANNELMAP}, 765 {"fix-format", 0, NULL, ARG_FIX_FORMAT}, 766 {"fix-rate", 0, NULL, ARG_FIX_RATE}, 767 {"fix-channels", 0, NULL, ARG_FIX_CHANNELS}, 768 {"no-remap", 0, NULL, ARG_NO_REMAP}, 769 {"no-remix", 0, NULL, ARG_NO_REMIX}, 770 {"latency", 1, NULL, ARG_LATENCY}, 771 {"process-time", 1, NULL, ARG_PROCESS_TIME}, 772 {"property", 1, NULL, ARG_PROPERTY}, 773 {"raw", 0, NULL, ARG_RAW}, 774 {"passthrough", 0, NULL, ARG_PASSTHROUGH}, 775 {"file-format", 2, NULL, ARG_FILE_FORMAT}, 776 {"list-file-formats", 0, NULL, ARG_LIST_FILE_FORMATS}, 777 {"latency-msec", 1, NULL, ARG_LATENCY_MSEC}, 778 {"process-time-msec", 1, NULL, ARG_PROCESS_TIME_MSEC}, 779 {"monitor-stream", 1, NULL, ARG_MONITOR_STREAM}, 780 {NULL, 0, NULL, 0} 781 }; 782 783 setlocale(LC_ALL, ""); 784#ifdef ENABLE_NLS 785 bindtextdomain(GETTEXT_PACKAGE, PULSE_LOCALEDIR); 786#endif 787 788 bn = pa_path_get_filename(argv[0]); 789 790 if (strstr(bn, "play")) { 791 mode = PLAYBACK; 792 raw = false; 793 purpose = _("Play back encoded audio files on a PulseAudio sound server."); 794 } else if (strstr(bn, "record")) { 795 mode = RECORD; 796 raw = false; 797 purpose = _("Capture audio data from a PulseAudio sound server and write it to a file."); 798 } else if (strstr(bn, "rec") || strstr(bn, "mon")) { 799 mode = RECORD; 800 raw = true; 801 purpose = _("Capture audio data from a PulseAudio sound server and write it to STDOUT or the specified file."); 802 } else { /* pacat */ 803 mode = PLAYBACK; 804 raw = true; 805 purpose = _("Play back audio data from STDIN or the specified file on a PulseAudio sound server."); 806 } 807 808 proplist = pa_proplist_new(); 809 810 while ((c = getopt_long(argc, argv, "rpd:s:n:hv", long_options, NULL)) != -1) { 811 812 switch (c) { 813 case 'h': 814 help(bn); 815 ret = 0; 816 goto quit; 817 818 case ARG_VERSION: 819 printf(_("pacat %s\n" 820 "Compiled with libpulse %s\n" 821 "Linked with libpulse %s\n"), 822 PACKAGE_VERSION, 823 pa_get_headers_version(), 824 pa_get_library_version()); 825 ret = 0; 826 goto quit; 827 828 case 'r': 829 mode = RECORD; 830 break; 831 832 case 'p': 833 mode = PLAYBACK; 834 break; 835 836 case 'd': 837 pa_xfree(device); 838 device = pa_xstrdup(optarg); 839 break; 840 841 case 's': 842 pa_xfree(server); 843 server = pa_xstrdup(optarg); 844 break; 845 846 case 'n': { 847 char *t; 848 849 if (!(t = pa_locale_to_utf8(optarg)) || 850 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t) < 0) { 851 852 pa_log(_("Invalid client name '%s'"), t ? t : optarg); 853 pa_xfree(t); 854 goto quit; 855 } 856 857 pa_xfree(t); 858 break; 859 } 860 861 case ARG_STREAM_NAME: { 862 char *t; 863 864 if (!(t = pa_locale_to_utf8(optarg)) || 865 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t) < 0) { 866 867 pa_log(_("Invalid stream name '%s'"), t ? t : optarg); 868 pa_xfree(t); 869 goto quit; 870 } 871 872 pa_xfree(t); 873 break; 874 } 875 876 case 'v': 877 verbose = 1; 878 break; 879 880 case ARG_VOLUME: { 881 int v = atoi(optarg); 882 volume = v < 0 ? 0U : (pa_volume_t) v; 883 volume_is_set = true; 884 break; 885 } 886 887 case ARG_CHANNELS: 888 sample_spec.channels = (uint8_t) atoi(optarg); 889 sample_spec_set = true; 890 break; 891 892 case ARG_SAMPLEFORMAT: 893 sample_spec.format = pa_parse_sample_format(optarg); 894 sample_spec_set = true; 895 break; 896 897 case ARG_SAMPLERATE: 898 sample_spec.rate = (uint32_t) atoi(optarg); 899 sample_spec_set = true; 900 break; 901 902 case ARG_CHANNELMAP: 903 if (!pa_channel_map_parse(&channel_map, optarg)) { 904 pa_log(_("Invalid channel map '%s'"), optarg); 905 goto quit; 906 } 907 908 channel_map_set = true; 909 break; 910 911 case ARG_FIX_CHANNELS: 912 flags |= PA_STREAM_FIX_CHANNELS; 913 break; 914 915 case ARG_FIX_RATE: 916 flags |= PA_STREAM_FIX_RATE; 917 break; 918 919 case ARG_FIX_FORMAT: 920 flags |= PA_STREAM_FIX_FORMAT; 921 break; 922 923 case ARG_NO_REMIX: 924 flags |= PA_STREAM_NO_REMIX_CHANNELS; 925 break; 926 927 case ARG_NO_REMAP: 928 flags |= PA_STREAM_NO_REMAP_CHANNELS; 929 break; 930 931 case ARG_LATENCY: 932 if (((latency = (size_t) atoi(optarg))) <= 0) { 933 pa_log(_("Invalid latency specification '%s'"), optarg); 934 goto quit; 935 } 936 break; 937 938 case ARG_PROCESS_TIME: 939 if (((process_time = (size_t) atoi(optarg))) <= 0) { 940 pa_log(_("Invalid process time specification '%s'"), optarg); 941 goto quit; 942 } 943 break; 944 945 case ARG_LATENCY_MSEC: 946 if (((latency_msec = (int32_t) atoi(optarg))) <= 0) { 947 pa_log(_("Invalid latency specification '%s'"), optarg); 948 goto quit; 949 } 950 break; 951 952 case ARG_PROCESS_TIME_MSEC: 953 if (((process_time_msec = (int32_t) atoi(optarg))) <= 0) { 954 pa_log(_("Invalid process time specification '%s'"), optarg); 955 goto quit; 956 } 957 break; 958 959 case ARG_PROPERTY: { 960 char *t; 961 962 if (!(t = pa_locale_to_utf8(optarg)) || 963 pa_proplist_setp(proplist, t) < 0) { 964 965 pa_xfree(t); 966 pa_log(_("Invalid property '%s'"), optarg); 967 goto quit; 968 } 969 970 pa_xfree(t); 971 break; 972 } 973 974 case ARG_RAW: 975 raw = true; 976 break; 977 978 case ARG_PASSTHROUGH: 979 flags |= PA_STREAM_PASSTHROUGH; 980 break; 981 982 case ARG_FILE_FORMAT: 983 if (optarg) { 984 if ((file_format = pa_sndfile_format_from_string(optarg)) < 0) { 985 pa_log(_("Unknown file format %s."), optarg); 986 goto quit; 987 } 988 } 989 990 raw = false; 991 break; 992 993 case ARG_LIST_FILE_FORMATS: 994 pa_sndfile_dump_formats(); 995 ret = 0; 996 goto quit; 997 998 case ARG_MONITOR_STREAM: 999 if (pa_atou(optarg, &monitor_stream) < 0) { 1000 pa_log(_("Failed to parse the argument for --monitor-stream")); 1001 goto quit; 1002 } 1003 break; 1004 1005 default: 1006 goto quit; 1007 } 1008 } 1009 1010 if (!pa_sample_spec_valid(&sample_spec)) { 1011 pa_log(_("Invalid sample specification")); 1012 goto quit; 1013 } 1014 1015 if (optind+1 == argc) { 1016 int fd; 1017 1018 filename = argv[optind]; 1019 1020 if ((fd = pa_open_cloexec(argv[optind], mode == PLAYBACK ? O_RDONLY : O_WRONLY|O_TRUNC|O_CREAT, 0666)) < 0) { 1021 pa_log(_("open(): %s"), strerror(errno)); 1022 goto quit; 1023 } 1024 1025 if (dup2(fd, mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO) < 0) { 1026 pa_log(_("dup2(): %s"), strerror(errno)); 1027 goto quit; 1028 } 1029 1030 pa_close(fd); 1031 1032 } else if (optind+1 <= argc) { 1033 pa_log(_("Too many arguments.")); 1034 goto quit; 1035 } 1036 1037 if (!raw) { 1038 SF_INFO sfi; 1039 pa_zero(sfi); 1040 1041 if (mode == RECORD) { 1042 /* This might patch up the sample spec */ 1043 if (pa_sndfile_write_sample_spec(&sfi, &sample_spec) < 0) { 1044 pa_log(_("Failed to generate sample specification for file.")); 1045 goto quit; 1046 } 1047 1048 if (file_format <= 0) { 1049 char *extension; 1050 if (filename && (extension = strrchr(filename, '.'))) 1051 file_format = pa_sndfile_format_from_string(extension+1); 1052 if (file_format <= 0) 1053 file_format = SF_FORMAT_WAV; 1054 /* Transparently upgrade classic .wav to wavex for multichannel audio */ 1055 if (file_format == SF_FORMAT_WAV && 1056 (sample_spec.channels > 2 || 1057 (channel_map_set && 1058 !(sample_spec.channels == 1 && channel_map.map[0] == PA_CHANNEL_POSITION_MONO) && 1059 !(sample_spec.channels == 2 && channel_map.map[0] == PA_CHANNEL_POSITION_LEFT 1060 && channel_map.map[1] == PA_CHANNEL_POSITION_RIGHT)))) 1061 file_format = SF_FORMAT_WAVEX; 1062 } 1063 1064 sfi.format |= file_format; 1065 1066 /* 1067 * Endianness has been set in pa_sndfile_write_sample_spec(), but 1068 * libsndfile errors out if endianness is set to anything other than 1069 * SF_ENDIAN_FILE for OGG or FLAC. Clear it. 1070 * For OGG, libsndfile accepts only subformat SF_FORMAT_VORBIS. 1071 */ 1072 if (file_format == SF_FORMAT_OGG || file_format == SF_FORMAT_FLAC) 1073 sfi.format = (sfi.format & ~SF_FORMAT_ENDMASK) | SF_ENDIAN_FILE; 1074 if (file_format == SF_FORMAT_OGG) 1075 sfi.format = (sfi.format & ~SF_FORMAT_SUBMASK) | SF_FORMAT_VORBIS; 1076 1077 } 1078 1079 if (!(sndfile = sf_open_fd(mode == RECORD ? STDOUT_FILENO : STDIN_FILENO, 1080 mode == RECORD ? SFM_WRITE : SFM_READ, 1081 &sfi, 0))) { 1082 pa_log(_("Failed to open audio file.")); 1083 goto quit; 1084 } 1085 1086 if (mode == PLAYBACK) { 1087 if (sample_spec_set) 1088 pa_log(_("Warning: specified sample specification will be overwritten with specification from file.")); 1089 1090 if (pa_sndfile_read_sample_spec(sndfile, &sample_spec) < 0) { 1091 pa_log(_("Failed to determine sample specification from file.")); 1092 goto quit; 1093 } 1094 sample_spec_set = true; 1095 1096 if (!channel_map_set) { 1097 /* Allow the user to overwrite the channel map on the command line */ 1098 if (pa_sndfile_read_channel_map(sndfile, &channel_map) < 0) { 1099 if (sample_spec.channels > 2) 1100 pa_log(_("Warning: Failed to determine channel map from file.")); 1101 } else 1102 channel_map_set = true; 1103 } 1104 } 1105 } 1106 1107 if (!channel_map_set) 1108 pa_channel_map_init_extend(&channel_map, sample_spec.channels, PA_CHANNEL_MAP_DEFAULT); 1109 1110 if (!pa_channel_map_compatible(&channel_map, &sample_spec)) { 1111 pa_log(_("Channel map doesn't match sample specification")); 1112 goto quit; 1113 } 1114 1115 if (!raw) { 1116 pa_proplist *sfp; 1117 1118 if (mode == PLAYBACK) 1119 readf_function = pa_sndfile_readf_function(&sample_spec); 1120 else { 1121 if (pa_sndfile_write_channel_map(sndfile, &channel_map) < 0) 1122 pa_log(_("Warning: failed to write channel map to file.")); 1123 1124 writef_function = pa_sndfile_writef_function(&sample_spec); 1125 } 1126 1127 /* Fill in libsndfile prop list data */ 1128 sfp = pa_proplist_new(); 1129 pa_sndfile_init_proplist(sndfile, sfp); 1130 pa_proplist_update(proplist, PA_UPDATE_MERGE, sfp); 1131 pa_proplist_free(sfp); 1132 } 1133 1134 if (verbose) { 1135 char tss[PA_SAMPLE_SPEC_SNPRINT_MAX], tcm[PA_CHANNEL_MAP_SNPRINT_MAX]; 1136 1137 pa_log(_("Opening a %s stream with sample specification '%s' and channel map '%s'."), 1138 mode == RECORD ? _("recording") : _("playback"), 1139 pa_sample_spec_snprint(tss, sizeof(tss), &sample_spec), 1140 pa_channel_map_snprint(tcm, sizeof(tcm), &channel_map)); 1141 } 1142 1143 /* Fill in client name if none was set */ 1144 if (!pa_proplist_contains(proplist, PA_PROP_APPLICATION_NAME)) { 1145 char *t; 1146 1147 if ((t = pa_locale_to_utf8(bn))) { 1148 pa_proplist_sets(proplist, PA_PROP_APPLICATION_NAME, t); 1149 pa_xfree(t); 1150 } 1151 } 1152 1153 /* Fill in media name if none was set */ 1154 if (!pa_proplist_contains(proplist, PA_PROP_MEDIA_NAME)) { 1155 const char *t; 1156 1157 if ((t = filename) || 1158 (t = pa_proplist_gets(proplist, PA_PROP_APPLICATION_NAME))) 1159 pa_proplist_sets(proplist, PA_PROP_MEDIA_NAME, t); 1160 1161 if (!pa_proplist_contains(proplist, PA_PROP_MEDIA_NAME)) { 1162 pa_log(_("Failed to set media name.")); 1163 goto quit; 1164 } 1165 } 1166 1167 if (raw && mode == PLAYBACK) 1168 partialframe_buf = pa_xmalloc(pa_frame_size(&sample_spec)); 1169 1170 /* Set up a new main loop */ 1171 if (!(m = pa_mainloop_new())) { 1172 pa_log(_("pa_mainloop_new() failed.")); 1173 goto quit; 1174 } 1175 1176 mainloop_api = pa_mainloop_get_api(m); 1177 1178 pa_assert_se(pa_signal_init(mainloop_api) == 0); 1179 pa_signal_new(SIGINT, exit_signal_callback, NULL); 1180 pa_signal_new(SIGTERM, exit_signal_callback, NULL); 1181#ifdef SIGUSR1 1182 pa_signal_new(SIGUSR1, sigusr1_signal_callback, NULL); 1183#endif 1184 pa_disable_sigpipe(); 1185 1186 if (raw) { 1187#ifdef OS_IS_WIN32 1188 /* need to turn on binary mode for stdio io. Windows, meh */ 1189 setmode(mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, O_BINARY); 1190#endif 1191 if (!(stdio_event = mainloop_api->io_new(mainloop_api, 1192 mode == PLAYBACK ? STDIN_FILENO : STDOUT_FILENO, 1193 mode == PLAYBACK ? PA_IO_EVENT_INPUT : PA_IO_EVENT_OUTPUT, 1194 mode == PLAYBACK ? stdin_callback : stdout_callback, &type))) { 1195 pa_log(_("io_new() failed.")); 1196 goto quit; 1197 } 1198 } 1199 1200 /* Create a new connection context */ 1201 if (!(context = pa_context_new_with_proplist(mainloop_api, NULL, proplist))) { 1202 pa_log(_("pa_context_new() failed.")); 1203 goto quit; 1204 } 1205 1206 pa_context_set_state_callback(context, context_state_callback, NULL); 1207 1208 /* Connect the context */ 1209 if (pa_context_connect(context, server, 0, NULL) < 0) { 1210 pa_log(_("pa_context_connect() failed: %s"), pa_strerror(pa_context_errno(context))); 1211 goto quit; 1212 } 1213 1214 if (verbose) { 1215 if (!(time_event = pa_context_rttime_new(context, pa_rtclock_now() + TIME_EVENT_USEC, time_event_callback, NULL))) { 1216 pa_log(_("pa_context_rttime_new() failed.")); 1217 goto quit; 1218 } 1219 } 1220 1221 /* Run the main loop */ 1222 if (pa_mainloop_run(m, &ret) < 0) { 1223 pa_log(_("pa_mainloop_run() failed.")); 1224 goto quit; 1225 } 1226 1227quit: 1228 if (stream) 1229 pa_stream_unref(stream); 1230 1231 if (context) 1232 pa_context_unref(context); 1233 1234 if (stdio_event) { 1235 pa_assert(mainloop_api); 1236 mainloop_api->io_free(stdio_event); 1237 } 1238 1239 if (time_event) { 1240 pa_assert(mainloop_api); 1241 mainloop_api->time_free(time_event); 1242 } 1243 1244 if (m) { 1245 pa_signal_done(); 1246 pa_mainloop_free(m); 1247 } 1248 1249 pa_xfree(silence_buffer); 1250 pa_xfree(buffer); 1251 pa_xfree(partialframe_buf); 1252 1253 pa_xfree(server); 1254 pa_xfree(device); 1255 1256 if (sndfile) 1257 sf_close(sndfile); 1258 1259 if (proplist) 1260 pa_proplist_free(proplist); 1261 1262 return ret; 1263} 1264