1 /*
2 * aplay.c - plays and records
3 *
4 * CREATIVE LABS CHANNEL-files
5 * Microsoft WAVE-files
6 * SPARC AUDIO .AU-files
7 * Raw Data
8 *
9 * Copyright (c) by Jaroslav Kysela <perex@perex.cz>
10 * Based on vplay program by Michael Beck
11 *
12 *
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 2 of the License, or
16 * (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
26 *
27 */
28
29 #define _GNU_SOURCE
30 #include "aconfig.h"
31 #include <stdio.h>
32 #include <malloc.h>
33 #include <unistd.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <getopt.h>
37 #include <fcntl.h>
38 #include <ctype.h>
39 #include <errno.h>
40 #include <limits.h>
41 #include <time.h>
42 #include <locale.h>
43 #include <alsa/asoundlib.h>
44 #include <assert.h>
45 #include <termios.h>
46 #include <signal.h>
47 #include <poll.h>
48 #include <sys/uio.h>
49 #include <sys/time.h>
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #include "gettext.h"
53 #include "formats.h"
54 #include "version.h"
55
56 #define ABS(a) (a) < 0 ? -(a) : (a)
57
58 #ifdef SND_CHMAP_API_VERSION
59 #define CONFIG_SUPPORT_CHMAP 1
60 #endif
61
62 #ifndef LLONG_MAX
63 #define LLONG_MAX 9223372036854775807LL
64 #endif
65
66 #ifndef le16toh
67 #include <asm/byteorder.h>
68 #define le16toh(x) __le16_to_cpu(x)
69 #define be16toh(x) __be16_to_cpu(x)
70 #define le32toh(x) __le32_to_cpu(x)
71 #define be32toh(x) __be32_to_cpu(x)
72 #endif
73
74 #ifndef _LARGEFILE64_SOURCE
75 /* assume modern system */
76 typedef off_t off64_t;
77 #define lseek64 lseek
78 #endif
79
80 #define DEFAULT_FORMAT SND_PCM_FORMAT_U8
81 #define DEFAULT_SPEED 8000
82
83 #define FORMAT_DEFAULT -1
84 #define FORMAT_RAW 0
85 #define FORMAT_VOC 1
86 #define FORMAT_WAVE 2
87 #define FORMAT_AU 3
88
89 /* global data */
90
91 static snd_pcm_sframes_t (*readi_func)(snd_pcm_t *handle, void *buffer, snd_pcm_uframes_t size);
92 static snd_pcm_sframes_t (*writei_func)(snd_pcm_t *handle, const void *buffer, snd_pcm_uframes_t size);
93 static snd_pcm_sframes_t (*readn_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
94 static snd_pcm_sframes_t (*writen_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
95
96 enum {
97 VUMETER_NONE,
98 VUMETER_MONO,
99 VUMETER_STEREO
100 };
101
102 static char *command;
103 static snd_pcm_t *handle;
104 static struct {
105 snd_pcm_format_t format;
106 unsigned int channels;
107 unsigned int rate;
108 } hwparams, rhwparams;
109 static int timelimit = 0;
110 static int sampleslimit = 0;
111 static int quiet_mode = 0;
112 static int file_type = FORMAT_DEFAULT;
113 static int open_mode = 0;
114 static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
115 static int mmap_flag = 0;
116 static int interleaved = 1;
117 static int nonblock = 0;
118 static volatile sig_atomic_t in_aborting = 0;
119 static u_char *audiobuf = NULL;
120 static snd_pcm_uframes_t chunk_size = 0;
121 static unsigned period_time = 0;
122 static unsigned buffer_time = 0;
123 static snd_pcm_uframes_t period_frames = 0;
124 static snd_pcm_uframes_t buffer_frames = 0;
125 static int avail_min = -1;
126 static int start_delay = 0;
127 static int stop_delay = 0;
128 static int monotonic = 0;
129 static int interactive = 0;
130 static int can_pause = 0;
131 static int fatal_errors = 0;
132 static int verbose = 0;
133 static int vumeter = VUMETER_NONE;
134 static int buffer_pos = 0;
135 static size_t significant_bits_per_sample, bits_per_sample, bits_per_frame;
136 static size_t chunk_bytes;
137 static int test_position = 0;
138 static int test_coef = 8;
139 static int test_nowait = 0;
140 static snd_output_t *log;
141 static long long max_file_size = 0;
142 static int max_file_time = 0;
143 static int use_strftime = 0;
144 volatile static int recycle_capture_file = 0;
145 static long term_c_lflag = -1;
146 static int dump_hw_params = 0;
147
148 static int fd = -1;
149 static off64_t pbrec_count = LLONG_MAX, fdcount;
150 static int vocmajor, vocminor;
151
152 static char *pidfile_name = NULL;
153 FILE *pidf = NULL;
154 static int pidfile_written = 0;
155
156 #ifdef CONFIG_SUPPORT_CHMAP
157 static snd_pcm_chmap_t *channel_map = NULL; /* chmap to override */
158 static unsigned int *hw_map = NULL; /* chmap to follow */
159 #endif
160
161 /* needed prototypes */
162
163 static void done_stdin(void);
164
165 static void playback(char *filename);
166 static void capture(char *filename);
167 static void playbackv(char **filenames, unsigned int count);
168 static void capturev(char **filenames, unsigned int count);
169
170 static void begin_voc(int fd, size_t count);
171 static void end_voc(int fd);
172 static void begin_wave(int fd, size_t count);
173 static void end_wave(int fd);
174 static void begin_au(int fd, size_t count);
175 static void end_au(int fd);
176
177 static void suspend(void);
178
179 static const struct fmt_capture {
180 void (*start) (int fd, size_t count);
181 void (*end) (int fd);
182 char *what;
183 long long max_filesize;
184 } fmt_rec_table[] = {
185 { NULL, NULL, N_("raw data"), LLONG_MAX },
186 { begin_voc, end_voc, N_("VOC"), 16000000LL },
187 /* FIXME: can WAV handle exactly 2GB or less than it? */
188 { begin_wave, end_wave, N_("WAVE"), 2147483648LL },
189 { begin_au, end_au, N_("Sparc Audio"), LLONG_MAX }
190 };
191
192 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
193 #define error(...) do {\
194 fprintf(stderr, "%s: %s:%d: ", command, __func__, __LINE__); \
195 fprintf(stderr, __VA_ARGS__); \
196 putc('\n', stderr); \
197 } while (0)
198 #else
199 #define error(args...) do {\
200 fprintf(stderr, "%s: %s:%d: ", command, __func__, __LINE__); \
201 fprintf(stderr, ##args); \
202 putc('\n', stderr); \
203 } while (0)
204 #endif
205
usage(char * command)206 static void usage(char *command)
207 {
208 snd_pcm_format_t k;
209 printf(
210 _("Usage: %s [OPTION]... [FILE]...\n"
211 "\n"
212 "-h, --help help\n"
213 " --version print current version\n"
214 "-l, --list-devices list all soundcards and digital audio devices\n"
215 "-L, --list-pcms list device names\n"
216 "-D, --device=NAME select PCM by name\n"
217 "-q, --quiet quiet mode\n"
218 "-t, --file-type TYPE file type (voc, wav, raw or au)\n"
219 "-c, --channels=# channels\n"
220 "-f, --format=FORMAT sample format (case insensitive)\n"
221 "-r, --rate=# sample rate\n"
222 "-d, --duration=# interrupt after # seconds\n"
223 "-s, --samples=# interrupt after # samples per channel\n"
224 "-M, --mmap mmap stream\n"
225 "-N, --nonblock nonblocking mode\n"
226 "-F, --period-time=# distance between interrupts is # microseconds\n"
227 "-B, --buffer-time=# buffer duration is # microseconds\n"
228 " --period-size=# distance between interrupts is # frames\n"
229 " --buffer-size=# buffer duration is # frames\n"
230 "-A, --avail-min=# min available space for wakeup is # microseconds\n"
231 "-R, --start-delay=# delay for automatic PCM start is # microseconds \n"
232 " (relative to buffer size if <= 0)\n"
233 "-T, --stop-delay=# delay for automatic PCM stop is # microseconds from xrun\n"
234 "-v, --verbose show PCM structure and setup (accumulative)\n"
235 "-V, --vumeter=TYPE enable VU meter (TYPE: mono or stereo)\n"
236 "-I, --separate-channels one file for each channel\n"
237 "-i, --interactive allow interactive operation from stdin\n"
238 "-m, --chmap=ch1,ch2,.. Give the channel map to override or follow\n"
239 " --disable-resample disable automatic rate resample\n"
240 " --disable-channels disable automatic channel conversions\n"
241 " --disable-format disable automatic format conversions\n"
242 " --disable-softvol disable software volume control (softvol)\n"
243 " --test-position test ring buffer position\n"
244 " --test-coef=# test coefficient for ring buffer position (default 8)\n"
245 " expression for validation is: coef * (buffer_size / 2)\n"
246 " --test-nowait do not wait for ring buffer - eats whole CPU\n"
247 " --max-file-time=# start another output file when the old file has recorded\n"
248 " for this many seconds\n"
249 " --process-id-file write the process ID here\n"
250 " --use-strftime apply the strftime facility to the output file name\n"
251 " --dump-hw-params dump hw_params of the device\n"
252 " --fatal-errors treat all errors as fatal\n"
253 )
254 , command);
255 printf(_("Recognized sample formats are:"));
256 for (k = 0; k <= SND_PCM_FORMAT_LAST; ++k) {
257 const char *s = snd_pcm_format_name(k);
258 if (s)
259 printf(" %s", s);
260 }
261 printf(_("\nSome of these may not be available on selected hardware\n"));
262 printf(_("The available format shortcuts are:\n"));
263 printf(_("-f cd (16 bit little endian, 44100, stereo)\n"));
264 printf(_("-f cdr (16 bit big endian, 44100, stereo)\n"));
265 printf(_("-f dat (16 bit little endian, 48000, stereo)\n"));
266 }
267
device_list(void)268 static void device_list(void)
269 {
270 snd_ctl_t *handle;
271 int card, err, dev, idx;
272 snd_ctl_card_info_t *info;
273 snd_pcm_info_t *pcminfo;
274 snd_ctl_card_info_alloca(&info);
275 snd_pcm_info_alloca(&pcminfo);
276
277 card = -1;
278 if (snd_card_next(&card) < 0 || card < 0) {
279 error(_("no soundcards found..."));
280 return;
281 }
282 printf(_("**** List of %s Hardware Devices ****\n"),
283 snd_pcm_stream_name(stream));
284 while (card >= 0) {
285 char name[32];
286 sprintf(name, "hw:%d", card);
287 if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
288 error("control open (%i): %s", card, snd_strerror(err));
289 goto next_card;
290 }
291 if ((err = snd_ctl_card_info(handle, info)) < 0) {
292 error("control hardware info (%i): %s", card, snd_strerror(err));
293 snd_ctl_close(handle);
294 goto next_card;
295 }
296 dev = -1;
297 while (1) {
298 unsigned int count;
299 if (snd_ctl_pcm_next_device(handle, &dev)<0)
300 error("snd_ctl_pcm_next_device");
301 if (dev < 0)
302 break;
303 snd_pcm_info_set_device(pcminfo, dev);
304 snd_pcm_info_set_subdevice(pcminfo, 0);
305 snd_pcm_info_set_stream(pcminfo, stream);
306 if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
307 if (err != -ENOENT)
308 error("control digital audio info (%i): %s", card, snd_strerror(err));
309 continue;
310 }
311 printf(_("card %i: %s [%s], device %i: %s [%s]\n"),
312 card, snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_name(info),
313 dev,
314 snd_pcm_info_get_id(pcminfo),
315 snd_pcm_info_get_name(pcminfo));
316 count = snd_pcm_info_get_subdevices_count(pcminfo);
317 printf( _(" Subdevices: %i/%i\n"),
318 snd_pcm_info_get_subdevices_avail(pcminfo), count);
319 for (idx = 0; idx < (int)count; idx++) {
320 snd_pcm_info_set_subdevice(pcminfo, idx);
321 if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
322 error("control digital audio playback info (%i): %s", card, snd_strerror(err));
323 } else {
324 printf(_(" Subdevice #%i: %s\n"),
325 idx, snd_pcm_info_get_subdevice_name(pcminfo));
326 }
327 }
328 }
329 snd_ctl_close(handle);
330 next_card:
331 if (snd_card_next(&card) < 0) {
332 error("snd_card_next");
333 break;
334 }
335 }
336 }
337
pcm_list(void)338 static void pcm_list(void)
339 {
340 void **hints, **n;
341 char *name, *descr, *descr1, *io;
342 const char *filter;
343
344 if (snd_device_name_hint(-1, "pcm", &hints) < 0)
345 return;
346 n = hints;
347 filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";
348 while (*n != NULL) {
349 name = snd_device_name_get_hint(*n, "NAME");
350 descr = snd_device_name_get_hint(*n, "DESC");
351 io = snd_device_name_get_hint(*n, "IOID");
352 if (io != NULL && strcmp(io, filter) != 0)
353 goto __end;
354 printf("%s\n", name);
355 if ((descr1 = descr) != NULL) {
356 printf(" ");
357 while (*descr1) {
358 if (*descr1 == '\n')
359 printf("\n ");
360 else
361 putchar(*descr1);
362 descr1++;
363 }
364 putchar('\n');
365 }
366 __end:
367 if (name != NULL)
368 free(name);
369 if (descr != NULL)
370 free(descr);
371 if (io != NULL)
372 free(io);
373 n++;
374 }
375 snd_device_name_free_hint(hints);
376 }
377
version(void)378 static void version(void)
379 {
380 printf("%s: version " SND_UTIL_VERSION_STR " by Jaroslav Kysela <perex@perex.cz>\n", command);
381 }
382
383 /*
384 * Subroutine to clean up before exit.
385 */
prg_exit(int code)386 static void prg_exit(int code)
387 {
388 done_stdin();
389 if (handle)
390 snd_pcm_close(handle);
391 if (pidfile_written)
392 remove (pidfile_name);
393 exit(code);
394 }
395
signal_handler(int sig)396 static void signal_handler(int sig)
397 {
398 if (in_aborting)
399 return;
400
401 in_aborting = 1;
402 if (verbose==2)
403 putchar('\n');
404 if (!quiet_mode)
405 fprintf(stderr, _("Aborted by signal %s...\n"), strsignal(sig));
406 if (handle)
407 snd_pcm_abort(handle);
408 if (sig == SIGABRT) {
409 /* do not call snd_pcm_close() and abort immediately */
410 handle = NULL;
411 prg_exit(EXIT_FAILURE);
412 }
413 signal(sig, SIG_DFL);
414 }
415
416 /* call on SIGUSR1 signal. */
signal_handler_recycle(int sig)417 static void signal_handler_recycle (int sig)
418 {
419 /* flag the capture loop to start a new output file */
420 recycle_capture_file = 1;
421 }
422
423 enum {
424 OPT_VERSION = 1,
425 OPT_PERIOD_SIZE,
426 OPT_BUFFER_SIZE,
427 OPT_DISABLE_RESAMPLE,
428 OPT_DISABLE_CHANNELS,
429 OPT_DISABLE_FORMAT,
430 OPT_DISABLE_SOFTVOL,
431 OPT_TEST_POSITION,
432 OPT_TEST_COEF,
433 OPT_TEST_NOWAIT,
434 OPT_MAX_FILE_TIME,
435 OPT_PROCESS_ID_FILE,
436 OPT_USE_STRFTIME,
437 OPT_DUMP_HWPARAMS,
438 OPT_FATAL_ERRORS,
439 };
440
441 /*
442 * make sure we write all bytes or return an error
443 */
xwrite(int fd,const void * buf,size_t count)444 static ssize_t xwrite(int fd, const void *buf, size_t count)
445 {
446 ssize_t written;
447 size_t offset = 0;
448
449 while (offset < count) {
450 written = write(fd, (char *)buf + offset, count - offset);
451 if (written <= 0)
452 return written;
453
454 offset += written;
455 };
456
457 return offset;
458 }
459
parse_long(const char * str,int * err)460 static long parse_long(const char *str, int *err)
461 {
462 long val;
463 char *endptr;
464
465 errno = 0;
466 val = strtol(str, &endptr, 0);
467
468 if (errno != 0 || *endptr != '\0')
469 *err = -1;
470 else
471 *err = 0;
472
473 return val;
474 }
475
main(int argc,char * argv[])476 int main(int argc, char *argv[])
477 {
478 int duration_or_sample = 0;
479 int option_index;
480 static const char short_options[] = "hnlLD:qt:c:f:r:d:s:MNF:A:R:T:B:vV:IPCi"
481 #ifdef CONFIG_SUPPORT_CHMAP
482 "m:"
483 #endif
484 ;
485 static const struct option long_options[] = {
486 {"help", 0, 0, 'h'},
487 {"version", 0, 0, OPT_VERSION},
488 {"list-devnames", 0, 0, 'n'},
489 {"list-devices", 0, 0, 'l'},
490 {"list-pcms", 0, 0, 'L'},
491 {"device", 1, 0, 'D'},
492 {"quiet", 0, 0, 'q'},
493 {"file-type", 1, 0, 't'},
494 {"channels", 1, 0, 'c'},
495 {"format", 1, 0, 'f'},
496 {"rate", 1, 0, 'r'},
497 {"duration", 1, 0 ,'d'},
498 {"samples", 1, 0, 's'},
499 {"mmap", 0, 0, 'M'},
500 {"nonblock", 0, 0, 'N'},
501 {"period-time", 1, 0, 'F'},
502 {"period-size", 1, 0, OPT_PERIOD_SIZE},
503 {"avail-min", 1, 0, 'A'},
504 {"start-delay", 1, 0, 'R'},
505 {"stop-delay", 1, 0, 'T'},
506 {"buffer-time", 1, 0, 'B'},
507 {"buffer-size", 1, 0, OPT_BUFFER_SIZE},
508 {"verbose", 0, 0, 'v'},
509 {"vumeter", 1, 0, 'V'},
510 {"separate-channels", 0, 0, 'I'},
511 {"playback", 0, 0, 'P'},
512 {"capture", 0, 0, 'C'},
513 {"disable-resample", 0, 0, OPT_DISABLE_RESAMPLE},
514 {"disable-channels", 0, 0, OPT_DISABLE_CHANNELS},
515 {"disable-format", 0, 0, OPT_DISABLE_FORMAT},
516 {"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},
517 {"test-position", 0, 0, OPT_TEST_POSITION},
518 {"test-coef", 1, 0, OPT_TEST_COEF},
519 {"test-nowait", 0, 0, OPT_TEST_NOWAIT},
520 {"max-file-time", 1, 0, OPT_MAX_FILE_TIME},
521 {"process-id-file", 1, 0, OPT_PROCESS_ID_FILE},
522 {"use-strftime", 0, 0, OPT_USE_STRFTIME},
523 {"interactive", 0, 0, 'i'},
524 {"dump-hw-params", 0, 0, OPT_DUMP_HWPARAMS},
525 {"fatal-errors", 0, 0, OPT_FATAL_ERRORS},
526 #ifdef CONFIG_SUPPORT_CHMAP
527 {"chmap", 1, 0, 'm'},
528 #endif
529 {0, 0, 0, 0}
530 };
531 char *pcm_name = "default";
532 int tmp, err, c;
533 int do_device_list = 0, do_pcm_list = 0;
534 snd_pcm_info_t *info;
535 FILE *direction;
536
537 #ifdef ENABLE_NLS
538 setlocale(LC_ALL, "");
539 textdomain(PACKAGE);
540 #endif
541
542 snd_pcm_info_alloca(&info);
543
544 err = snd_output_stdio_attach(&log, stderr, 0);
545 assert(err >= 0);
546
547 command = argv[0];
548 file_type = FORMAT_DEFAULT;
549 if (strstr(argv[0], "arecord")) {
550 stream = SND_PCM_STREAM_CAPTURE;
551 file_type = FORMAT_WAVE;
552 command = "arecord";
553 start_delay = 1;
554 direction = stdout;
555 } else if (strstr(argv[0], "aplay")) {
556 stream = SND_PCM_STREAM_PLAYBACK;
557 command = "aplay";
558 direction = stdin;
559 } else {
560 error(_("command should be named either arecord or aplay"));
561 return 1;
562 }
563
564 if (isatty(fileno(direction)) && (argc == 1)) {
565 usage(command);
566 return 1;
567 }
568
569 chunk_size = -1;
570 rhwparams.format = DEFAULT_FORMAT;
571 rhwparams.rate = DEFAULT_SPEED;
572 rhwparams.channels = 1;
573
574 while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) {
575 switch (c) {
576 case 'h':
577 usage(command);
578 return 0;
579 case OPT_VERSION:
580 version();
581 return 0;
582 case 'l':
583 do_device_list = 1;
584 break;
585 case 'L':
586 do_pcm_list = 1;
587 break;
588 case 'D':
589 pcm_name = optarg;
590 break;
591 case 'q':
592 quiet_mode = 1;
593 break;
594 case 't':
595 if (strcasecmp(optarg, "raw") == 0)
596 file_type = FORMAT_RAW;
597 else if (strcasecmp(optarg, "voc") == 0)
598 file_type = FORMAT_VOC;
599 else if (strcasecmp(optarg, "wav") == 0)
600 file_type = FORMAT_WAVE;
601 else if (strcasecmp(optarg, "au") == 0 || strcasecmp(optarg, "sparc") == 0)
602 file_type = FORMAT_AU;
603 else {
604 error(_("unrecognized file format %s"), optarg);
605 return 1;
606 }
607 break;
608 case 'c':
609 rhwparams.channels = parse_long(optarg, &err);
610 if (err < 0) {
611 error(_("invalid channels argument '%s'"), optarg);
612 return 1;
613 }
614 if (rhwparams.channels < 1 || rhwparams.channels > 256) {
615 error(_("value %i for channels is invalid"), rhwparams.channels);
616 return 1;
617 }
618 break;
619 case 'f':
620 if (strcasecmp(optarg, "cd") == 0 || strcasecmp(optarg, "cdr") == 0) {
621 if (strcasecmp(optarg, "cdr") == 0)
622 rhwparams.format = SND_PCM_FORMAT_S16_BE;
623 else
624 rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
625 rhwparams.rate = 44100;
626 rhwparams.channels = 2;
627 } else if (strcasecmp(optarg, "dat") == 0) {
628 rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
629 rhwparams.rate = 48000;
630 rhwparams.channels = 2;
631 } else {
632 rhwparams.format = snd_pcm_format_value(optarg);
633 if (rhwparams.format == SND_PCM_FORMAT_UNKNOWN) {
634 error(_("wrong extended format '%s'"), optarg);
635 prg_exit(EXIT_FAILURE);
636 }
637 }
638 break;
639 case 'r':
640 tmp = parse_long(optarg, &err);
641 if (err < 0) {
642 error(_("invalid rate argument '%s'"), optarg);
643 return 1;
644 }
645 if (tmp < 1000)
646 tmp *= 1000;
647 rhwparams.rate = tmp;
648 if (tmp < 2000 || tmp > 768000) {
649 error(_("bad speed value %i"), tmp);
650 return 1;
651 }
652 break;
653 case 'd':
654 if (duration_or_sample) {
655 error(_("duration and samples arguments cannot be used together"));
656 return 1;
657 }
658 timelimit = parse_long(optarg, &err);
659 if (err < 0) {
660 error(_("invalid duration argument '%s'"), optarg);
661 return 1;
662 }
663 duration_or_sample = 1;
664 break;
665 case 's':
666 if (duration_or_sample) {
667 error(_("samples and duration arguments cannot be used together"));
668 return 1;
669 }
670 sampleslimit = parse_long(optarg, &err);
671 if (err < 0) {
672 error(_("invalid samples argument '%s'"), optarg);
673 return 1;
674 }
675 duration_or_sample = 1;
676 break;
677 case 'N':
678 nonblock = 1;
679 open_mode |= SND_PCM_NONBLOCK;
680 break;
681 case 'F':
682 period_time = parse_long(optarg, &err);
683 if (err < 0) {
684 error(_("invalid period time argument '%s'"), optarg);
685 return 1;
686 }
687 break;
688 case 'B':
689 buffer_time = parse_long(optarg, &err);
690 if (err < 0) {
691 error(_("invalid buffer time argument '%s'"), optarg);
692 return 1;
693 }
694 break;
695 case OPT_PERIOD_SIZE:
696 period_frames = parse_long(optarg, &err);
697 if (err < 0) {
698 error(_("invalid period size argument '%s'"), optarg);
699 return 1;
700 }
701 break;
702 case OPT_BUFFER_SIZE:
703 buffer_frames = parse_long(optarg, &err);
704 if (err < 0) {
705 error(_("invalid buffer size argument '%s'"), optarg);
706 return 1;
707 }
708 break;
709 case 'A':
710 avail_min = parse_long(optarg, &err);
711 if (err < 0) {
712 error(_("invalid min available space argument '%s'"), optarg);
713 return 1;
714 }
715 break;
716 case 'R':
717 start_delay = parse_long(optarg, &err);
718 if (err < 0) {
719 error(_("invalid start delay argument '%s'"), optarg);
720 return 1;
721 }
722 break;
723 case 'T':
724 stop_delay = parse_long(optarg, &err);
725 if (err < 0) {
726 error(_("invalid stop delay argument '%s'"), optarg);
727 return 1;
728 }
729 break;
730 case 'v':
731 verbose++;
732 if (verbose > 1 && !vumeter)
733 vumeter = VUMETER_MONO;
734 break;
735 case 'V':
736 if (*optarg == 's')
737 vumeter = VUMETER_STEREO;
738 else if (*optarg == 'm')
739 vumeter = VUMETER_MONO;
740 else
741 vumeter = VUMETER_NONE;
742 break;
743 case 'M':
744 mmap_flag = 1;
745 break;
746 case 'I':
747 interleaved = 0;
748 break;
749 case 'P':
750 stream = SND_PCM_STREAM_PLAYBACK;
751 command = "aplay";
752 break;
753 case 'C':
754 stream = SND_PCM_STREAM_CAPTURE;
755 command = "arecord";
756 start_delay = 1;
757 if (file_type == FORMAT_DEFAULT)
758 file_type = FORMAT_WAVE;
759 break;
760 case 'i':
761 interactive = 1;
762 break;
763 case OPT_DISABLE_RESAMPLE:
764 open_mode |= SND_PCM_NO_AUTO_RESAMPLE;
765 break;
766 case OPT_DISABLE_CHANNELS:
767 open_mode |= SND_PCM_NO_AUTO_CHANNELS;
768 break;
769 case OPT_DISABLE_FORMAT:
770 open_mode |= SND_PCM_NO_AUTO_FORMAT;
771 break;
772 case OPT_DISABLE_SOFTVOL:
773 open_mode |= SND_PCM_NO_SOFTVOL;
774 break;
775 case OPT_TEST_POSITION:
776 test_position = 1;
777 break;
778 case OPT_TEST_COEF:
779 test_coef = parse_long(optarg, &err);
780 if (err < 0) {
781 error(_("invalid test coef argument '%s'"), optarg);
782 return 1;
783 }
784 if (test_coef < 1)
785 test_coef = 1;
786 break;
787 case OPT_TEST_NOWAIT:
788 test_nowait = 1;
789 break;
790 case OPT_MAX_FILE_TIME:
791 max_file_time = parse_long(optarg, &err);
792 if (err < 0) {
793 error(_("invalid max file time argument '%s'"), optarg);
794 return 1;
795 }
796 break;
797 case OPT_PROCESS_ID_FILE:
798 pidfile_name = optarg;
799 break;
800 case OPT_USE_STRFTIME:
801 use_strftime = 1;
802 break;
803 case OPT_DUMP_HWPARAMS:
804 dump_hw_params = 1;
805 break;
806 case OPT_FATAL_ERRORS:
807 fatal_errors = 1;
808 break;
809 #ifdef CONFIG_SUPPORT_CHMAP
810 case 'm':
811 channel_map = snd_pcm_chmap_parse_string(optarg);
812 if (!channel_map) {
813 fprintf(stderr, _("Unable to parse channel map string: %s\n"), optarg);
814 return 1;
815 }
816 break;
817 #endif
818 default:
819 fprintf(stderr, _("Try `%s --help' for more information.\n"), command);
820 return 1;
821 }
822 }
823
824 if (do_device_list) {
825 if (do_pcm_list) pcm_list();
826 device_list();
827 goto __end;
828 } else if (do_pcm_list) {
829 pcm_list();
830 goto __end;
831 }
832
833 err = snd_pcm_open(&handle, pcm_name, stream, open_mode);
834 if (err < 0) {
835 error(_("audio open error: %s"), snd_strerror(err));
836 return 1;
837 }
838
839 if ((err = snd_pcm_info(handle, info)) < 0) {
840 error(_("info error: %s"), snd_strerror(err));
841 return 1;
842 }
843
844 if (nonblock) {
845 err = snd_pcm_nonblock(handle, 1);
846 if (err < 0) {
847 error(_("nonblock setting error: %s"), snd_strerror(err));
848 return 1;
849 }
850 }
851
852 chunk_size = 1024;
853 hwparams = rhwparams;
854
855 audiobuf = (u_char *)malloc(1024);
856 if (audiobuf == NULL) {
857 error(_("not enough memory"));
858 return 1;
859 }
860
861 if (mmap_flag) {
862 writei_func = snd_pcm_mmap_writei;
863 readi_func = snd_pcm_mmap_readi;
864 writen_func = snd_pcm_mmap_writen;
865 readn_func = snd_pcm_mmap_readn;
866 } else {
867 writei_func = snd_pcm_writei;
868 readi_func = snd_pcm_readi;
869 writen_func = snd_pcm_writen;
870 readn_func = snd_pcm_readn;
871 }
872
873 if (pidfile_name) {
874 errno = 0;
875 pidf = fopen (pidfile_name, "w");
876 if (pidf) {
877 (void)fprintf (pidf, "%d\n", getpid());
878 fclose(pidf);
879 pidfile_written = 1;
880 } else {
881 error(_("Cannot create process ID file %s: %s"),
882 pidfile_name, strerror (errno));
883 return 1;
884 }
885 }
886
887 signal(SIGINT, signal_handler);
888 signal(SIGTERM, signal_handler);
889 signal(SIGABRT, signal_handler);
890 signal(SIGUSR1, signal_handler_recycle);
891 if (interleaved) {
892 if (optind > argc - 1) {
893 if (stream == SND_PCM_STREAM_PLAYBACK)
894 playback(NULL);
895 else
896 capture(NULL);
897 } else {
898 while (optind <= argc - 1) {
899 if (stream == SND_PCM_STREAM_PLAYBACK)
900 playback(argv[optind++]);
901 else
902 capture(argv[optind++]);
903 }
904 }
905 } else {
906 if (stream == SND_PCM_STREAM_PLAYBACK)
907 playbackv(&argv[optind], argc - optind);
908 else
909 capturev(&argv[optind], argc - optind);
910 }
911 if (verbose==2)
912 putchar('\n');
913 snd_pcm_close(handle);
914 handle = NULL;
915 free(audiobuf);
916 __end:
917 snd_output_close(log);
918 snd_config_update_free_global();
919 prg_exit(EXIT_SUCCESS);
920 /* avoid warning */
921 return EXIT_SUCCESS;
922 }
923
924 /*
925 * Safe read (for pipes)
926 */
927
safe_read(int fd,void * buf,size_t count)928 static ssize_t safe_read(int fd, void *buf, size_t count)
929 {
930 ssize_t result = 0, res;
931
932 while (count > 0 && !in_aborting) {
933 if ((res = read(fd, buf, count)) == 0)
934 break;
935 if (res < 0)
936 return result > 0 ? result : res;
937 count -= res;
938 result += res;
939 buf = (char *)buf + res;
940 }
941 return result;
942 }
943
944 /*
945 * Test, if it is a .VOC file and return >=0 if ok (this is the length of rest)
946 * < 0 if not
947 */
test_vocfile(void * buffer)948 static int test_vocfile(void *buffer)
949 {
950 VocHeader *vp = buffer;
951
952 if (!memcmp(vp->magic, VOC_MAGIC_STRING, 20)) {
953 vocminor = LE_SHORT(vp->version) & 0xFF;
954 vocmajor = LE_SHORT(vp->version) / 256;
955 if (LE_SHORT(vp->version) != (0x1233 - LE_SHORT(vp->coded_ver)))
956 return -2; /* coded version mismatch */
957 return LE_SHORT(vp->headerlen) - sizeof(VocHeader); /* 0 mostly */
958 }
959 return -1; /* magic string fail */
960 }
961
962 /*
963 * helper for test_wavefile
964 */
965
test_wavefile_read(int fd,u_char * buffer,size_t * size,size_t reqsize,int line)966 static size_t test_wavefile_read(int fd, u_char *buffer, size_t *size, size_t reqsize, int line)
967 {
968 if (*size >= reqsize)
969 return *size;
970 if ((size_t)safe_read(fd, buffer + *size, reqsize - *size) != reqsize - *size) {
971 error(_("read error (called from line %i)"), line);
972 prg_exit(EXIT_FAILURE);
973 }
974 return *size = reqsize;
975 }
976
977 #define check_wavefile_space(buffer, len, blimit) \
978 if (len > blimit) { \
979 blimit = len; \
980 if ((buffer = realloc(buffer, blimit)) == NULL) { \
981 error(_("not enough memory")); \
982 prg_exit(EXIT_FAILURE); \
983 } \
984 }
985
986 /*
987 * test, if it's a .WAV file, > 0 if ok (and set the speed, stereo etc.)
988 * == 0 if not
989 * Value returned is bytes to be discarded.
990 */
test_wavefile(int fd,u_char * _buffer,size_t size)991 static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
992 {
993 WaveHeader *h = (WaveHeader *)_buffer;
994 u_char *buffer = NULL;
995 size_t blimit = 0;
996 WaveFmtBody *f;
997 WaveChunkHeader *c;
998 u_int type, len;
999 unsigned short format, channels;
1000 int big_endian, native_format;
1001
1002 if (size < sizeof(WaveHeader))
1003 return -1;
1004 if (h->magic == WAV_RIFF)
1005 big_endian = 0;
1006 else if (h->magic == WAV_RIFX)
1007 big_endian = 1;
1008 else
1009 return -1;
1010 if (h->type != WAV_WAVE)
1011 return -1;
1012
1013 if (size > sizeof(WaveHeader)) {
1014 check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);
1015 memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));
1016 }
1017 size -= sizeof(WaveHeader);
1018 while (1) {
1019 check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
1020 test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
1021 c = (WaveChunkHeader*)buffer;
1022 type = c->type;
1023 len = TO_CPU_INT(c->length, big_endian);
1024 len += len % 2;
1025 if (size > sizeof(WaveChunkHeader))
1026 memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
1027 size -= sizeof(WaveChunkHeader);
1028 if (type == WAV_FMT)
1029 break;
1030 check_wavefile_space(buffer, len, blimit);
1031 test_wavefile_read(fd, buffer, &size, len, __LINE__);
1032 if (size > len)
1033 memmove(buffer, buffer + len, size - len);
1034 size -= len;
1035 }
1036
1037 if (len < sizeof(WaveFmtBody)) {
1038 error(_("unknown length of 'fmt ' chunk (read %u, should be %u at least)"),
1039 len, (u_int)sizeof(WaveFmtBody));
1040 prg_exit(EXIT_FAILURE);
1041 }
1042 check_wavefile_space(buffer, len, blimit);
1043 test_wavefile_read(fd, buffer, &size, len, __LINE__);
1044 f = (WaveFmtBody*) buffer;
1045 format = TO_CPU_SHORT(f->format, big_endian);
1046 if (format == WAV_FMT_EXTENSIBLE) {
1047 WaveFmtExtensibleBody *fe = (WaveFmtExtensibleBody*)buffer;
1048 if (len < sizeof(WaveFmtExtensibleBody)) {
1049 error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),
1050 len, (u_int)sizeof(WaveFmtExtensibleBody));
1051 prg_exit(EXIT_FAILURE);
1052 }
1053 if (memcmp(fe->guid_tag, WAV_GUID_TAG, 14) != 0) {
1054 error(_("wrong format tag in extensible 'fmt ' chunk"));
1055 prg_exit(EXIT_FAILURE);
1056 }
1057 format = TO_CPU_SHORT(fe->guid_format, big_endian);
1058 }
1059 if (format != WAV_FMT_PCM &&
1060 format != WAV_FMT_IEEE_FLOAT) {
1061 error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), format);
1062 prg_exit(EXIT_FAILURE);
1063 }
1064 channels = TO_CPU_SHORT(f->channels, big_endian);
1065 if (channels < 1) {
1066 error(_("can't play WAVE-files with %d tracks"), channels);
1067 prg_exit(EXIT_FAILURE);
1068 }
1069 hwparams.channels = channels;
1070 switch (TO_CPU_SHORT(f->bit_p_spl, big_endian)) {
1071 case 8:
1072 if (hwparams.format != DEFAULT_FORMAT &&
1073 hwparams.format != SND_PCM_FORMAT_U8)
1074 fprintf(stderr, _("Warning: format is changed to U8\n"));
1075 hwparams.format = SND_PCM_FORMAT_U8;
1076 break;
1077 case 16:
1078 if (big_endian)
1079 native_format = SND_PCM_FORMAT_S16_BE;
1080 else
1081 native_format = SND_PCM_FORMAT_S16_LE;
1082 if (hwparams.format != DEFAULT_FORMAT &&
1083 hwparams.format != native_format)
1084 fprintf(stderr, _("Warning: format is changed to %s\n"),
1085 snd_pcm_format_name(native_format));
1086 hwparams.format = native_format;
1087 break;
1088 case 24:
1089 switch (TO_CPU_SHORT(f->byte_p_spl, big_endian) / hwparams.channels) {
1090 case 3:
1091 if (big_endian)
1092 native_format = SND_PCM_FORMAT_S24_3BE;
1093 else
1094 native_format = SND_PCM_FORMAT_S24_3LE;
1095 if (hwparams.format != DEFAULT_FORMAT &&
1096 hwparams.format != native_format)
1097 fprintf(stderr, _("Warning: format is changed to %s\n"),
1098 snd_pcm_format_name(native_format));
1099 hwparams.format = native_format;
1100 break;
1101 case 4:
1102 if (big_endian)
1103 native_format = SND_PCM_FORMAT_S24_BE;
1104 else
1105 native_format = SND_PCM_FORMAT_S24_LE;
1106 if (hwparams.format != DEFAULT_FORMAT &&
1107 hwparams.format != native_format)
1108 fprintf(stderr, _("Warning: format is changed to %s\n"),
1109 snd_pcm_format_name(native_format));
1110 hwparams.format = native_format;
1111 break;
1112 default:
1113 error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),
1114 TO_CPU_SHORT(f->bit_p_spl, big_endian),
1115 TO_CPU_SHORT(f->byte_p_spl, big_endian),
1116 hwparams.channels);
1117 prg_exit(EXIT_FAILURE);
1118 }
1119 break;
1120 case 32:
1121 if (format == WAV_FMT_PCM) {
1122 if (big_endian)
1123 native_format = SND_PCM_FORMAT_S32_BE;
1124 else
1125 native_format = SND_PCM_FORMAT_S32_LE;
1126 hwparams.format = native_format;
1127 } else if (format == WAV_FMT_IEEE_FLOAT) {
1128 if (big_endian)
1129 native_format = SND_PCM_FORMAT_FLOAT_BE;
1130 else
1131 native_format = SND_PCM_FORMAT_FLOAT_LE;
1132 hwparams.format = native_format;
1133 }
1134 break;
1135 default:
1136 error(_(" can't play WAVE-files with sample %d bits wide"),
1137 TO_CPU_SHORT(f->bit_p_spl, big_endian));
1138 prg_exit(EXIT_FAILURE);
1139 }
1140 hwparams.rate = TO_CPU_INT(f->sample_fq, big_endian);
1141
1142 if (size > len)
1143 memmove(buffer, buffer + len, size - len);
1144 size -= len;
1145
1146 while (1) {
1147 u_int type, len;
1148
1149 check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
1150 test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
1151 c = (WaveChunkHeader*)buffer;
1152 type = c->type;
1153 len = TO_CPU_INT(c->length, big_endian);
1154 if (size > sizeof(WaveChunkHeader))
1155 memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
1156 size -= sizeof(WaveChunkHeader);
1157 if (type == WAV_DATA) {
1158 if (len < pbrec_count && len < 0x7ffffffe)
1159 pbrec_count = len;
1160 if (size > 0)
1161 memcpy(_buffer, buffer, size);
1162 free(buffer);
1163 return size;
1164 }
1165 len += len % 2;
1166 check_wavefile_space(buffer, len, blimit);
1167 test_wavefile_read(fd, buffer, &size, len, __LINE__);
1168 if (size > len)
1169 memmove(buffer, buffer + len, size - len);
1170 size -= len;
1171 }
1172
1173 /* shouldn't be reached */
1174 return -1;
1175 }
1176
1177 /*
1178
1179 */
1180
test_au(int fd,void * buffer)1181 static int test_au(int fd, void *buffer)
1182 {
1183 AuHeader *ap = buffer;
1184
1185 if (ap->magic != AU_MAGIC)
1186 return -1;
1187 if (BE_INT(ap->hdr_size) > 128 || BE_INT(ap->hdr_size) < 24)
1188 return -1;
1189 pbrec_count = BE_INT(ap->data_size);
1190 switch (BE_INT(ap->encoding)) {
1191 case AU_FMT_ULAW:
1192 if (hwparams.format != DEFAULT_FORMAT &&
1193 hwparams.format != SND_PCM_FORMAT_MU_LAW)
1194 fprintf(stderr, _("Warning: format is changed to MU_LAW\n"));
1195 hwparams.format = SND_PCM_FORMAT_MU_LAW;
1196 break;
1197 case AU_FMT_LIN8:
1198 if (hwparams.format != DEFAULT_FORMAT &&
1199 hwparams.format != SND_PCM_FORMAT_U8)
1200 fprintf(stderr, _("Warning: format is changed to U8\n"));
1201 hwparams.format = SND_PCM_FORMAT_U8;
1202 break;
1203 case AU_FMT_LIN16:
1204 if (hwparams.format != DEFAULT_FORMAT &&
1205 hwparams.format != SND_PCM_FORMAT_S16_BE)
1206 fprintf(stderr, _("Warning: format is changed to S16_BE\n"));
1207 hwparams.format = SND_PCM_FORMAT_S16_BE;
1208 break;
1209 default:
1210 return -1;
1211 }
1212 hwparams.rate = BE_INT(ap->sample_rate);
1213 if (hwparams.rate < 2000 || hwparams.rate > 256000)
1214 return -1;
1215 hwparams.channels = BE_INT(ap->channels);
1216 if (hwparams.channels < 1 || hwparams.channels > 256)
1217 return -1;
1218 if ((size_t)safe_read(fd, (char *)buffer + sizeof(AuHeader), BE_INT(ap->hdr_size) - sizeof(AuHeader)) != BE_INT(ap->hdr_size) - sizeof(AuHeader)) {
1219 error(_("read error"));
1220 prg_exit(EXIT_FAILURE);
1221 }
1222 return 0;
1223 }
1224
show_available_sample_formats(snd_pcm_hw_params_t * params)1225 static void show_available_sample_formats(snd_pcm_hw_params_t* params)
1226 {
1227 snd_pcm_format_t format;
1228
1229 fprintf(stderr, "Available formats:\n");
1230 for (format = 0; format <= SND_PCM_FORMAT_LAST; format++) {
1231 if (snd_pcm_hw_params_test_format(handle, params, format) == 0)
1232 fprintf(stderr, "- %s\n", snd_pcm_format_name(format));
1233 }
1234 }
1235
1236 #ifdef CONFIG_SUPPORT_CHMAP
setup_chmap(void)1237 static int setup_chmap(void)
1238 {
1239 snd_pcm_chmap_t *chmap = channel_map;
1240 char mapped[hwparams.channels];
1241 snd_pcm_chmap_t *hw_chmap;
1242 unsigned int ch, i;
1243 int err;
1244
1245 if (!chmap)
1246 return 0;
1247
1248 if (chmap->channels != hwparams.channels) {
1249 error(_("Channel numbers don't match between hw_params and channel map"));
1250 return -1;
1251 }
1252 err = snd_pcm_set_chmap(handle, chmap);
1253 if (!err)
1254 return 0;
1255
1256 hw_chmap = snd_pcm_get_chmap(handle);
1257 if (!hw_chmap) {
1258 fprintf(stderr, _("Warning: unable to get channel map\n"));
1259 return 0;
1260 }
1261
1262 if (hw_chmap->channels == chmap->channels &&
1263 !memcmp(hw_chmap, chmap, 4 * (chmap->channels + 1))) {
1264 /* maps are identical, so no need to convert */
1265 free(hw_chmap);
1266 return 0;
1267 }
1268
1269 hw_map = calloc(hwparams.channels, sizeof(int));
1270 if (!hw_map) {
1271 error(_("not enough memory"));
1272 free(hw_chmap);
1273 return -1;
1274 }
1275
1276 memset(mapped, 0, sizeof(mapped));
1277 for (ch = 0; ch < hw_chmap->channels; ch++) {
1278 if (chmap->pos[ch] == hw_chmap->pos[ch]) {
1279 mapped[ch] = 1;
1280 hw_map[ch] = ch;
1281 continue;
1282 }
1283 for (i = 0; i < hw_chmap->channels; i++) {
1284 if (!mapped[i] && chmap->pos[ch] == hw_chmap->pos[i]) {
1285 mapped[i] = 1;
1286 hw_map[ch] = i;
1287 break;
1288 }
1289 }
1290 if (i >= hw_chmap->channels) {
1291 char buf[256];
1292 error(_("Channel %d doesn't match with hw_parmas"), ch);
1293 snd_pcm_chmap_print(hw_chmap, sizeof(buf), buf);
1294 fprintf(stderr, "hardware chmap = %s\n", buf);
1295 free(hw_chmap);
1296 return -1;
1297 }
1298 }
1299 free(hw_chmap);
1300 return 0;
1301 }
1302 #else
1303 #define setup_chmap() 0
1304 #endif
1305
set_params(void)1306 static void set_params(void)
1307 {
1308 snd_pcm_hw_params_t *params;
1309 snd_pcm_sw_params_t *swparams;
1310 snd_pcm_uframes_t buffer_size;
1311 int err;
1312 size_t n;
1313 unsigned int rate;
1314 snd_pcm_uframes_t start_threshold, stop_threshold;
1315 snd_pcm_hw_params_alloca(¶ms);
1316 snd_pcm_sw_params_alloca(&swparams);
1317 err = snd_pcm_hw_params_any(handle, params);
1318 if (err < 0) {
1319 error(_("Broken configuration for this PCM: no configurations available"));
1320 prg_exit(EXIT_FAILURE);
1321 }
1322 if (dump_hw_params) {
1323 fprintf(stderr, _("HW Params of device \"%s\":\n"),
1324 snd_pcm_name(handle));
1325 fprintf(stderr, "--------------------\n");
1326 snd_pcm_hw_params_dump(params, log);
1327 fprintf(stderr, "--------------------\n");
1328 }
1329 if (mmap_flag) {
1330 snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
1331 snd_pcm_access_mask_none(mask);
1332 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
1333 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
1334 snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
1335 err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
1336 } else if (interleaved)
1337 err = snd_pcm_hw_params_set_access(handle, params,
1338 SND_PCM_ACCESS_RW_INTERLEAVED);
1339 else
1340 err = snd_pcm_hw_params_set_access(handle, params,
1341 SND_PCM_ACCESS_RW_NONINTERLEAVED);
1342 if (err < 0) {
1343 error(_("Access type not available"));
1344 prg_exit(EXIT_FAILURE);
1345 }
1346 err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
1347 if (err < 0) {
1348 error(_("Sample format non available"));
1349 show_available_sample_formats(params);
1350 prg_exit(EXIT_FAILURE);
1351 }
1352 err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
1353 if (err < 0) {
1354 error(_("Channels count non available"));
1355 prg_exit(EXIT_FAILURE);
1356 }
1357
1358 #if 0
1359 err = snd_pcm_hw_params_set_periods_min(handle, params, 2);
1360 assert(err >= 0);
1361 #endif
1362 rate = hwparams.rate;
1363 err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);
1364 assert(err >= 0);
1365 if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) {
1366 if (!quiet_mode) {
1367 char plugex[64];
1368 const char *pcmname = snd_pcm_name(handle);
1369 fprintf(stderr, _("Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"), rate, hwparams.rate);
1370 if (! pcmname || strchr(snd_pcm_name(handle), ':'))
1371 *plugex = 0;
1372 else
1373 snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",
1374 snd_pcm_name(handle));
1375 fprintf(stderr, _(" please, try the plug plugin %s\n"),
1376 plugex);
1377 }
1378 }
1379 rate = hwparams.rate;
1380 if (buffer_time == 0 && buffer_frames == 0) {
1381 err = snd_pcm_hw_params_get_buffer_time_max(params,
1382 &buffer_time, 0);
1383 assert(err >= 0);
1384 if (buffer_time > 500000)
1385 buffer_time = 500000;
1386 }
1387 if (period_time == 0 && period_frames == 0) {
1388 if (buffer_time > 0)
1389 period_time = buffer_time / 4;
1390 else
1391 period_frames = buffer_frames / 4;
1392 }
1393 if (period_time > 0)
1394 err = snd_pcm_hw_params_set_period_time_near(handle, params,
1395 &period_time, 0);
1396 else
1397 err = snd_pcm_hw_params_set_period_size_near(handle, params,
1398 &period_frames, 0);
1399 assert(err >= 0);
1400 if (buffer_time > 0) {
1401 err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
1402 &buffer_time, 0);
1403 } else {
1404 err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
1405 &buffer_frames);
1406 }
1407 assert(err >= 0);
1408 monotonic = snd_pcm_hw_params_is_monotonic(params);
1409 can_pause = snd_pcm_hw_params_can_pause(params);
1410 err = snd_pcm_hw_params(handle, params);
1411 if (err < 0) {
1412 error(_("Unable to install hw params:"));
1413 snd_pcm_hw_params_dump(params, log);
1414 prg_exit(EXIT_FAILURE);
1415 }
1416 snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
1417 snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
1418 if (chunk_size == buffer_size) {
1419 error(_("Can't use period equal to buffer size (%lu == %lu)"),
1420 chunk_size, buffer_size);
1421 prg_exit(EXIT_FAILURE);
1422 }
1423 err = snd_pcm_sw_params_current(handle, swparams);
1424 if (err < 0) {
1425 error(_("Unable to get current sw params."));
1426 prg_exit(EXIT_FAILURE);
1427 }
1428 if (avail_min < 0)
1429 n = chunk_size;
1430 else
1431 n = (double) rate * avail_min / 1000000;
1432 err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
1433
1434 /* round up to closest transfer boundary */
1435 n = buffer_size;
1436 if (start_delay <= 0) {
1437 start_threshold = n + (double) rate * start_delay / 1000000;
1438 } else
1439 start_threshold = (double) rate * start_delay / 1000000;
1440 if (start_threshold < 1)
1441 start_threshold = 1;
1442 if (start_threshold > n)
1443 start_threshold = n;
1444 err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
1445 assert(err >= 0);
1446 if (stop_delay <= 0)
1447 stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
1448 else
1449 stop_threshold = (double) rate * stop_delay / 1000000;
1450 err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
1451 assert(err >= 0);
1452
1453 if (snd_pcm_sw_params(handle, swparams) < 0) {
1454 error(_("unable to install sw params:"));
1455 snd_pcm_sw_params_dump(swparams, log);
1456 prg_exit(EXIT_FAILURE);
1457 }
1458
1459 if (setup_chmap())
1460 prg_exit(EXIT_FAILURE);
1461
1462 if (verbose)
1463 snd_pcm_dump(handle, log);
1464
1465 bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
1466 significant_bits_per_sample = snd_pcm_format_width(hwparams.format);
1467 bits_per_frame = bits_per_sample * hwparams.channels;
1468 chunk_bytes = chunk_size * bits_per_frame / 8;
1469 audiobuf = realloc(audiobuf, chunk_bytes);
1470 if (audiobuf == NULL) {
1471 error(_("not enough memory"));
1472 prg_exit(EXIT_FAILURE);
1473 }
1474 // fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);
1475
1476 /* stereo VU-meter isn't always available... */
1477 if (vumeter == VUMETER_STEREO) {
1478 if (hwparams.channels != 2 || !interleaved || verbose > 2)
1479 vumeter = VUMETER_MONO;
1480 }
1481
1482 /* show mmap buffer arragment */
1483 if (mmap_flag && verbose) {
1484 const snd_pcm_channel_area_t *areas;
1485 snd_pcm_uframes_t offset, size = chunk_size;
1486 int i;
1487 err = snd_pcm_mmap_begin(handle, &areas, &offset, &size);
1488 if (err < 0) {
1489 error(_("snd_pcm_mmap_begin problem: %s"), snd_strerror(err));
1490 prg_exit(EXIT_FAILURE);
1491 }
1492 for (i = 0; i < hwparams.channels; i++)
1493 fprintf(stderr, "mmap_area[%i] = %p,%u,%u (%u)\n", i, areas[i].addr, areas[i].first, areas[i].step, snd_pcm_format_physical_width(hwparams.format));
1494 /* not required, but for sure */
1495 snd_pcm_mmap_commit(handle, offset, 0);
1496 }
1497
1498 buffer_frames = buffer_size; /* for position test */
1499 }
1500
init_stdin(void)1501 static void init_stdin(void)
1502 {
1503 struct termios term;
1504 long flags;
1505
1506 if (!interactive)
1507 return;
1508 if (!isatty(fileno(stdin))) {
1509 interactive = 0;
1510 return;
1511 }
1512 tcgetattr(fileno(stdin), &term);
1513 term_c_lflag = term.c_lflag;
1514 if (fd == fileno(stdin))
1515 return;
1516 flags = fcntl(fileno(stdin), F_GETFL);
1517 if (flags < 0 || fcntl(fileno(stdin), F_SETFL, flags|O_NONBLOCK) < 0)
1518 fprintf(stderr, _("stdin O_NONBLOCK flag setup failed\n"));
1519 term.c_lflag &= ~ICANON;
1520 tcsetattr(fileno(stdin), TCSANOW, &term);
1521 }
1522
done_stdin(void)1523 static void done_stdin(void)
1524 {
1525 struct termios term;
1526
1527 if (!interactive)
1528 return;
1529 if (fd == fileno(stdin) || term_c_lflag == -1)
1530 return;
1531 tcgetattr(fileno(stdin), &term);
1532 term.c_lflag = term_c_lflag;
1533 tcsetattr(fileno(stdin), TCSANOW, &term);
1534 }
1535
do_pause(void)1536 static void do_pause(void)
1537 {
1538 int err;
1539 unsigned char b;
1540
1541 if (!can_pause) {
1542 fprintf(stderr, _("\rPAUSE command ignored (no hw support)\n"));
1543 return;
1544 }
1545 if (snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED)
1546 suspend();
1547
1548 err = snd_pcm_pause(handle, 1);
1549 if (err < 0) {
1550 error(_("pause push error: %s"), snd_strerror(err));
1551 return;
1552 }
1553 while (1) {
1554 while (read(fileno(stdin), &b, 1) != 1);
1555 if (b == ' ' || b == '\r') {
1556 while (read(fileno(stdin), &b, 1) == 1);
1557 if (snd_pcm_state(handle) == SND_PCM_STATE_SUSPENDED)
1558 suspend();
1559 err = snd_pcm_pause(handle, 0);
1560 if (err < 0)
1561 error(_("pause release error: %s"), snd_strerror(err));
1562 return;
1563 }
1564 }
1565 }
1566
check_stdin(void)1567 static void check_stdin(void)
1568 {
1569 unsigned char b;
1570
1571 if (!interactive)
1572 return;
1573 if (fd != fileno(stdin)) {
1574 while (read(fileno(stdin), &b, 1) == 1) {
1575 if (b == ' ' || b == '\r') {
1576 while (read(fileno(stdin), &b, 1) == 1);
1577 fprintf(stderr, _("\r=== PAUSE === "));
1578 fflush(stderr);
1579 do_pause();
1580 fprintf(stderr, " \r");
1581 fflush(stderr);
1582 }
1583 }
1584 }
1585 }
1586
1587 #ifndef timersub
1588 #define timersub(a, b, result) \
1589 do { \
1590 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
1591 (result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
1592 if ((result)->tv_usec < 0) { \
1593 --(result)->tv_sec; \
1594 (result)->tv_usec += 1000000; \
1595 } \
1596 } while (0)
1597 #endif
1598
1599 #ifndef timermsub
1600 #define timermsub(a, b, result) \
1601 do { \
1602 (result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
1603 (result)->tv_nsec = (a)->tv_nsec - (b)->tv_nsec; \
1604 if ((result)->tv_nsec < 0) { \
1605 --(result)->tv_sec; \
1606 (result)->tv_nsec += 1000000000L; \
1607 } \
1608 } while (0)
1609 #endif
1610
1611 /* I/O error handler */
xrun(void)1612 static void xrun(void)
1613 {
1614 snd_pcm_status_t *status;
1615 int res;
1616
1617 snd_pcm_status_alloca(&status);
1618 if ((res = snd_pcm_status(handle, status))<0) {
1619 error(_("status error: %s"), snd_strerror(res));
1620 prg_exit(EXIT_FAILURE);
1621 }
1622 if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
1623 if (fatal_errors) {
1624 error(_("fatal %s: %s"),
1625 stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
1626 snd_strerror(res));
1627 prg_exit(EXIT_FAILURE);
1628 }
1629 if (monotonic) {
1630 #ifdef HAVE_CLOCK_GETTIME
1631 struct timespec now, diff, tstamp;
1632 clock_gettime(CLOCK_MONOTONIC, &now);
1633 snd_pcm_status_get_trigger_htstamp(status, &tstamp);
1634 timermsub(&now, &tstamp, &diff);
1635 fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
1636 stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
1637 diff.tv_sec * 1000 + diff.tv_nsec / 1000000.0);
1638 #else
1639 fprintf(stderr, "%s !!!\n", _("underrun"));
1640 #endif
1641 } else {
1642 struct timeval now, diff, tstamp;
1643 gettimeofday(&now, 0);
1644 snd_pcm_status_get_trigger_tstamp(status, &tstamp);
1645 timersub(&now, &tstamp, &diff);
1646 fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
1647 stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
1648 diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
1649 }
1650 if (verbose) {
1651 fprintf(stderr, _("Status:\n"));
1652 snd_pcm_status_dump(status, log);
1653 }
1654 if ((res = snd_pcm_prepare(handle))<0) {
1655 error(_("xrun: prepare error: %s"), snd_strerror(res));
1656 prg_exit(EXIT_FAILURE);
1657 }
1658 return; /* ok, data should be accepted again */
1659 } if (snd_pcm_status_get_state(status) == SND_PCM_STATE_DRAINING) {
1660 if (verbose) {
1661 fprintf(stderr, _("Status(DRAINING):\n"));
1662 snd_pcm_status_dump(status, log);
1663 }
1664 if (stream == SND_PCM_STREAM_CAPTURE) {
1665 fprintf(stderr, _("capture stream format change? attempting recover...\n"));
1666 if ((res = snd_pcm_prepare(handle))<0) {
1667 error(_("xrun(DRAINING): prepare error: %s"), snd_strerror(res));
1668 prg_exit(EXIT_FAILURE);
1669 }
1670 return;
1671 }
1672 }
1673 if (verbose) {
1674 fprintf(stderr, _("Status(R/W):\n"));
1675 snd_pcm_status_dump(status, log);
1676 }
1677 error(_("read/write error, state = %s"), snd_pcm_state_name(snd_pcm_status_get_state(status)));
1678 prg_exit(EXIT_FAILURE);
1679 }
1680
1681 /* I/O suspend handler */
suspend(void)1682 static void suspend(void)
1683 {
1684 int res;
1685
1686 if (!quiet_mode) {
1687 fprintf(stderr, _("Suspended. Trying resume. ")); fflush(stderr);
1688 }
1689 while ((res = snd_pcm_resume(handle)) == -EAGAIN)
1690 sleep(1); /* wait until suspend flag is released */
1691 if (res < 0) {
1692 if (!quiet_mode) {
1693 fprintf(stderr, _("Failed. Restarting stream. ")); fflush(stderr);
1694 }
1695 if ((res = snd_pcm_prepare(handle)) < 0) {
1696 error(_("suspend: prepare error: %s"), snd_strerror(res));
1697 prg_exit(EXIT_FAILURE);
1698 }
1699 }
1700 if (!quiet_mode)
1701 fprintf(stderr, _("Done.\n"));
1702 }
1703
print_vu_meter_mono(int perc,int maxperc)1704 static void print_vu_meter_mono(int perc, int maxperc)
1705 {
1706 const int bar_length = 50;
1707 char line[80];
1708 int val;
1709
1710 for (val = 0; val <= perc * bar_length / 100 && val < bar_length; val++)
1711 line[val] = '#';
1712 for (; val <= maxperc * bar_length / 100 && val < bar_length; val++)
1713 line[val] = ' ';
1714 line[val] = '+';
1715 for (++val; val <= bar_length; val++)
1716 line[val] = ' ';
1717 if (maxperc > 99)
1718 sprintf(line + val, "| MAX");
1719 else
1720 sprintf(line + val, "| %02i%%", maxperc);
1721 fputs(line, stderr);
1722 if (perc > 100)
1723 fprintf(stderr, _(" !clip "));
1724 }
1725
print_vu_meter_stereo(int * perc,int * maxperc)1726 static void print_vu_meter_stereo(int *perc, int *maxperc)
1727 {
1728 const int bar_length = 35;
1729 char line[80];
1730 int c;
1731
1732 memset(line, ' ', sizeof(line) - 1);
1733 line[bar_length + 3] = '|';
1734
1735 for (c = 0; c < 2; c++) {
1736 int p = perc[c] * bar_length / 100;
1737 char tmp[4];
1738 if (p > bar_length)
1739 p = bar_length;
1740 if (c)
1741 memset(line + bar_length + 6 + 1, '#', p);
1742 else
1743 memset(line + bar_length - p - 1, '#', p);
1744 p = maxperc[c] * bar_length / 100;
1745 if (p > bar_length)
1746 p = bar_length;
1747 if (c)
1748 line[bar_length + 6 + 1 + p] = '+';
1749 else
1750 line[bar_length - p - 1] = '+';
1751 if (ABS(maxperc[c]) > 99)
1752 sprintf(tmp, "MAX");
1753 else
1754 sprintf(tmp, "%02d%%", maxperc[c]);
1755 if (c)
1756 memcpy(line + bar_length + 3 + 1, tmp, 3);
1757 else
1758 memcpy(line + bar_length, tmp, 3);
1759 }
1760 line[bar_length * 2 + 6 + 2] = 0;
1761 fputs(line, stderr);
1762 }
1763
print_vu_meter(signed int * perc,signed int * maxperc)1764 static void print_vu_meter(signed int *perc, signed int *maxperc)
1765 {
1766 if (vumeter == VUMETER_STEREO)
1767 print_vu_meter_stereo(perc, maxperc);
1768 else
1769 print_vu_meter_mono(*perc, *maxperc);
1770 }
1771
1772 /* peak handler */
compute_max_peak(u_char * data,size_t count)1773 static void compute_max_peak(u_char *data, size_t count)
1774 {
1775 signed int val, max, perc[2], max_peak[2];
1776 static int run = 0;
1777 size_t ocount = count;
1778 int format_little_endian = snd_pcm_format_little_endian(hwparams.format);
1779 int ichans, c;
1780
1781 if (vumeter == VUMETER_STEREO)
1782 ichans = 2;
1783 else
1784 ichans = 1;
1785
1786 memset(max_peak, 0, sizeof(max_peak));
1787 switch (bits_per_sample) {
1788 case 8: {
1789 signed char *valp = (signed char *)data;
1790 signed char mask = snd_pcm_format_silence(hwparams.format);
1791 c = 0;
1792 while (count-- > 0) {
1793 val = *valp++ ^ mask;
1794 val = abs(val);
1795 if (max_peak[c] < val)
1796 max_peak[c] = val;
1797 if (vumeter == VUMETER_STEREO)
1798 c = !c;
1799 }
1800 break;
1801 }
1802 case 16: {
1803 signed short *valp = (signed short *)data;
1804 signed short mask = snd_pcm_format_silence_16(hwparams.format);
1805 signed short sval;
1806
1807 count /= 2;
1808 c = 0;
1809 while (count-- > 0) {
1810 if (format_little_endian)
1811 sval = le16toh(*valp);
1812 else
1813 sval = be16toh(*valp);
1814 sval = abs(sval) ^ mask;
1815 if (max_peak[c] < sval)
1816 max_peak[c] = sval;
1817 valp++;
1818 if (vumeter == VUMETER_STEREO)
1819 c = !c;
1820 }
1821 break;
1822 }
1823 case 24: {
1824 unsigned char *valp = data;
1825 signed int mask = snd_pcm_format_silence_32(hwparams.format);
1826
1827 count /= 3;
1828 c = 0;
1829 while (count-- > 0) {
1830 if (format_little_endian) {
1831 val = valp[0] | (valp[1]<<8) | (valp[2]<<16);
1832 } else {
1833 val = (valp[0]<<16) | (valp[1]<<8) | valp[2];
1834 }
1835 /* Correct signed bit in 32-bit value */
1836 if (val & (1<<(bits_per_sample-1))) {
1837 val |= 0xff<<24; /* Negate upper bits too */
1838 }
1839 val = abs(val) ^ mask;
1840 if (max_peak[c] < val)
1841 max_peak[c] = val;
1842 valp += 3;
1843 if (vumeter == VUMETER_STEREO)
1844 c = !c;
1845 }
1846 break;
1847 }
1848 case 32: {
1849 signed int *valp = (signed int *)data;
1850 signed int mask = snd_pcm_format_silence_32(hwparams.format);
1851
1852 count /= 4;
1853 c = 0;
1854 while (count-- > 0) {
1855 if (format_little_endian)
1856 val = le32toh(*valp);
1857 else
1858 val = be32toh(*valp);
1859 val = abs(val) ^ mask;
1860 if (max_peak[c] < val)
1861 max_peak[c] = val;
1862 valp++;
1863 if (vumeter == VUMETER_STEREO)
1864 c = !c;
1865 }
1866 break;
1867 }
1868 default:
1869 if (run == 0) {
1870 fprintf(stderr, _("Unsupported bit size %d.\n"), (int)bits_per_sample);
1871 run = 1;
1872 }
1873 return;
1874 }
1875 max = 1 << (significant_bits_per_sample-1);
1876 if (max <= 0)
1877 max = 0x7fffffff;
1878
1879 for (c = 0; c < ichans; c++) {
1880 if (bits_per_sample > 16)
1881 perc[c] = max_peak[c] / (max / 100);
1882 else
1883 perc[c] = max_peak[c] * 100 / max;
1884 }
1885
1886 if (interleaved && verbose <= 2) {
1887 static int maxperc[2];
1888 static time_t t=0;
1889 const time_t tt=time(NULL);
1890 if(tt>t) {
1891 t=tt;
1892 maxperc[0] = 0;
1893 maxperc[1] = 0;
1894 }
1895 for (c = 0; c < ichans; c++)
1896 if (perc[c] > maxperc[c])
1897 maxperc[c] = perc[c];
1898
1899 putc('\r', stderr);
1900 print_vu_meter(perc, maxperc);
1901 fflush(stderr);
1902 }
1903 else if(verbose==3) {
1904 fprintf(stderr, _("Max peak (%li samples): 0x%08x "), (long)ocount, max_peak[0]);
1905 for (val = 0; val < 20; val++)
1906 if (val <= perc[0] / 5)
1907 putc('#', stderr);
1908 else
1909 putc(' ', stderr);
1910 fprintf(stderr, " %i%%\n", perc[0]);
1911 fflush(stderr);
1912 }
1913 }
1914
do_test_position(void)1915 static void do_test_position(void)
1916 {
1917 static long counter = 0;
1918 static time_t tmr = -1;
1919 time_t now;
1920 static float availsum, delaysum, samples;
1921 static snd_pcm_sframes_t maxavail, maxdelay;
1922 static snd_pcm_sframes_t minavail, mindelay;
1923 static snd_pcm_sframes_t badavail = 0, baddelay = 0;
1924 snd_pcm_sframes_t outofrange;
1925 snd_pcm_sframes_t avail, delay;
1926 int err;
1927
1928 err = snd_pcm_avail_delay(handle, &avail, &delay);
1929 if (err < 0)
1930 return;
1931 outofrange = (test_coef * (snd_pcm_sframes_t)buffer_frames) / 2;
1932 if (avail > outofrange || avail < -outofrange ||
1933 delay > outofrange || delay < -outofrange) {
1934 badavail = avail; baddelay = delay;
1935 availsum = delaysum = samples = 0;
1936 maxavail = maxdelay = 0;
1937 minavail = mindelay = buffer_frames * 16;
1938 fprintf(stderr, _("Suspicious buffer position (%li total): "
1939 "avail = %li, delay = %li, buffer = %li\n"),
1940 ++counter, (long)avail, (long)delay, (long)buffer_frames);
1941 } else if (verbose) {
1942 time(&now);
1943 if (tmr == (time_t) -1) {
1944 tmr = now;
1945 availsum = delaysum = samples = 0;
1946 maxavail = maxdelay = 0;
1947 minavail = mindelay = buffer_frames * 16;
1948 }
1949 if (avail > maxavail)
1950 maxavail = avail;
1951 if (delay > maxdelay)
1952 maxdelay = delay;
1953 if (avail < minavail)
1954 minavail = avail;
1955 if (delay < mindelay)
1956 mindelay = delay;
1957 availsum += avail;
1958 delaysum += delay;
1959 samples++;
1960 if (avail != 0 && now != tmr) {
1961 fprintf(stderr, "BUFPOS: avg%li/%li "
1962 "min%li/%li max%li/%li (%li) (%li:%li/%li)\n",
1963 (long)(availsum / samples),
1964 (long)(delaysum / samples),
1965 (long)minavail, (long)mindelay,
1966 (long)maxavail, (long)maxdelay,
1967 (long)buffer_frames,
1968 counter, badavail, baddelay);
1969 tmr = now;
1970 }
1971 }
1972 }
1973
1974 /*
1975 */
1976 #ifdef CONFIG_SUPPORT_CHMAP
remap_data(u_char * data,size_t count)1977 static u_char *remap_data(u_char *data, size_t count)
1978 {
1979 static u_char *tmp, *src, *dst;
1980 static size_t tmp_size;
1981 size_t sample_bytes = bits_per_sample / 8;
1982 size_t step = bits_per_frame / 8;
1983 size_t chunk_bytes;
1984 unsigned int ch, i;
1985
1986 if (!hw_map)
1987 return data;
1988
1989 chunk_bytes = count * bits_per_frame / 8;
1990 if (tmp_size < chunk_bytes) {
1991 free(tmp);
1992 tmp = malloc(chunk_bytes);
1993 if (!tmp) {
1994 error(_("not enough memory"));
1995 exit(1);
1996 }
1997 tmp_size = count;
1998 }
1999
2000 src = data;
2001 dst = tmp;
2002 for (i = 0; i < count; i++) {
2003 for (ch = 0; ch < hwparams.channels; ch++) {
2004 memcpy(dst, src + sample_bytes * hw_map[ch],
2005 sample_bytes);
2006 dst += sample_bytes;
2007 }
2008 src += step;
2009 }
2010 return tmp;
2011 }
2012
remap_datav(u_char ** data,size_t count)2013 static u_char **remap_datav(u_char **data, size_t count)
2014 {
2015 static u_char **tmp;
2016 unsigned int ch;
2017
2018 if (!hw_map)
2019 return data;
2020
2021 if (!tmp) {
2022 tmp = malloc(sizeof(*tmp) * hwparams.channels);
2023 if (!tmp) {
2024 error(_("not enough memory"));
2025 exit(1);
2026 }
2027 for (ch = 0; ch < hwparams.channels; ch++)
2028 tmp[ch] = data[hw_map[ch]];
2029 }
2030 return tmp;
2031 }
2032 #else
2033 #define remap_data(data, count) (data)
2034 #define remap_datav(data, count) (data)
2035 #endif
2036
2037 /*
2038 * write function
2039 */
2040
pcm_write(u_char * data,size_t count)2041 static ssize_t pcm_write(u_char *data, size_t count)
2042 {
2043 ssize_t r;
2044 ssize_t result = 0;
2045
2046 if (count < chunk_size) {
2047 snd_pcm_format_set_silence(hwparams.format, data + count * bits_per_frame / 8, (chunk_size - count) * hwparams.channels);
2048 count = chunk_size;
2049 }
2050 data = remap_data(data, count);
2051 while (count > 0 && !in_aborting) {
2052 if (test_position)
2053 do_test_position();
2054 check_stdin();
2055 r = writei_func(handle, data, count);
2056 if (test_position)
2057 do_test_position();
2058 if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
2059 if (!test_nowait)
2060 snd_pcm_wait(handle, 100);
2061 } else if (r == -EPIPE) {
2062 xrun();
2063 } else if (r == -ESTRPIPE) {
2064 suspend();
2065 } else if (r < 0) {
2066 error(_("write error: %s"), snd_strerror(r));
2067 prg_exit(EXIT_FAILURE);
2068 }
2069 if (r > 0) {
2070 if (vumeter)
2071 compute_max_peak(data, r * hwparams.channels);
2072 result += r;
2073 count -= r;
2074 data += r * bits_per_frame / 8;
2075 }
2076 }
2077 return result;
2078 }
2079
pcm_writev(u_char ** data,unsigned int channels,size_t count)2080 static ssize_t pcm_writev(u_char **data, unsigned int channels, size_t count)
2081 {
2082 ssize_t r;
2083 size_t result = 0;
2084
2085 if (count != chunk_size) {
2086 unsigned int channel;
2087 size_t offset = count;
2088 size_t remaining = chunk_size - count;
2089 for (channel = 0; channel < channels; channel++)
2090 snd_pcm_format_set_silence(hwparams.format, data[channel] + offset * bits_per_sample / 8, remaining);
2091 count = chunk_size;
2092 }
2093 data = remap_datav(data, count);
2094 while (count > 0 && !in_aborting) {
2095 unsigned int channel;
2096 void *bufs[channels];
2097 size_t offset = result;
2098 for (channel = 0; channel < channels; channel++)
2099 bufs[channel] = data[channel] + offset * bits_per_sample / 8;
2100 if (test_position)
2101 do_test_position();
2102 check_stdin();
2103 r = writen_func(handle, bufs, count);
2104 if (test_position)
2105 do_test_position();
2106 if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
2107 if (!test_nowait)
2108 snd_pcm_wait(handle, 100);
2109 } else if (r == -EPIPE) {
2110 xrun();
2111 } else if (r == -ESTRPIPE) {
2112 suspend();
2113 } else if (r < 0) {
2114 error(_("writev error: %s"), snd_strerror(r));
2115 prg_exit(EXIT_FAILURE);
2116 }
2117 if (r > 0) {
2118 if (vumeter) {
2119 for (channel = 0; channel < channels; channel++)
2120 compute_max_peak(data[channel], r);
2121 }
2122 result += r;
2123 count -= r;
2124 }
2125 }
2126 return result;
2127 }
2128
2129 /*
2130 * read function
2131 */
2132
pcm_read(u_char * data,size_t rcount)2133 static ssize_t pcm_read(u_char *data, size_t rcount)
2134 {
2135 ssize_t r;
2136 size_t result = 0;
2137 size_t count = rcount;
2138
2139 if (count != chunk_size) {
2140 count = chunk_size;
2141 }
2142
2143 while (count > 0 && !in_aborting) {
2144 if (test_position)
2145 do_test_position();
2146 check_stdin();
2147 r = readi_func(handle, data, count);
2148 if (test_position)
2149 do_test_position();
2150 if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
2151 if (!test_nowait)
2152 snd_pcm_wait(handle, 100);
2153 } else if (r == -EPIPE) {
2154 xrun();
2155 } else if (r == -ESTRPIPE) {
2156 suspend();
2157 } else if (r < 0) {
2158 error(_("read error: %s"), snd_strerror(r));
2159 prg_exit(EXIT_FAILURE);
2160 }
2161 if (r > 0) {
2162 if (vumeter)
2163 compute_max_peak(data, r * hwparams.channels);
2164 result += r;
2165 count -= r;
2166 data += r * bits_per_frame / 8;
2167 }
2168 }
2169 return rcount;
2170 }
2171
pcm_readv(u_char ** data,unsigned int channels,size_t rcount)2172 static ssize_t pcm_readv(u_char **data, unsigned int channels, size_t rcount)
2173 {
2174 ssize_t r;
2175 size_t result = 0;
2176 size_t count = rcount;
2177
2178 if (count != chunk_size) {
2179 count = chunk_size;
2180 }
2181
2182 while (count > 0 && !in_aborting) {
2183 unsigned int channel;
2184 void *bufs[channels];
2185 size_t offset = result;
2186 for (channel = 0; channel < channels; channel++)
2187 bufs[channel] = data[channel] + offset * bits_per_sample / 8;
2188 if (test_position)
2189 do_test_position();
2190 check_stdin();
2191 r = readn_func(handle, bufs, count);
2192 if (test_position)
2193 do_test_position();
2194 if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
2195 if (!test_nowait)
2196 snd_pcm_wait(handle, 100);
2197 } else if (r == -EPIPE) {
2198 xrun();
2199 } else if (r == -ESTRPIPE) {
2200 suspend();
2201 } else if (r < 0) {
2202 error(_("readv error: %s"), snd_strerror(r));
2203 prg_exit(EXIT_FAILURE);
2204 }
2205 if (r > 0) {
2206 if (vumeter) {
2207 for (channel = 0; channel < channels; channel++)
2208 compute_max_peak(data[channel], r);
2209 }
2210 result += r;
2211 count -= r;
2212 }
2213 }
2214 return rcount;
2215 }
2216
2217 /*
2218 * ok, let's play a .voc file
2219 */
2220
voc_pcm_write(u_char * data,size_t count)2221 static ssize_t voc_pcm_write(u_char *data, size_t count)
2222 {
2223 ssize_t result = count, r;
2224 size_t size;
2225
2226 while (count > 0 && !in_aborting) {
2227 size = count;
2228 if (size > chunk_bytes - buffer_pos)
2229 size = chunk_bytes - buffer_pos;
2230 memcpy(audiobuf + buffer_pos, data, size);
2231 data += size;
2232 count -= size;
2233 buffer_pos += size;
2234 if ((size_t)buffer_pos == chunk_bytes) {
2235 if ((size_t)(r = pcm_write(audiobuf, chunk_size)) != chunk_size)
2236 return r;
2237 buffer_pos = 0;
2238 }
2239 }
2240 return result;
2241 }
2242
voc_write_silence(unsigned x)2243 static void voc_write_silence(unsigned x)
2244 {
2245 unsigned l;
2246 u_char *buf;
2247
2248 buf = (u_char *) malloc(chunk_bytes);
2249 if (buf == NULL) {
2250 error(_("can't allocate buffer for silence"));
2251 return; /* not fatal error */
2252 }
2253 snd_pcm_format_set_silence(hwparams.format, buf, chunk_size * hwparams.channels);
2254 while (x > 0 && !in_aborting) {
2255 l = x;
2256 if (l > chunk_size)
2257 l = chunk_size;
2258 if (voc_pcm_write(buf, l) != (ssize_t)l) {
2259 error(_("write error"));
2260 prg_exit(EXIT_FAILURE);
2261 }
2262 x -= l;
2263 }
2264 free(buf);
2265 }
2266
voc_pcm_flush(void)2267 static void voc_pcm_flush(void)
2268 {
2269 if (buffer_pos > 0) {
2270 size_t b;
2271 if (snd_pcm_format_set_silence(hwparams.format, audiobuf + buffer_pos, chunk_bytes - buffer_pos * 8 / bits_per_sample) < 0)
2272 fprintf(stderr, _("voc_pcm_flush - silence error"));
2273 b = chunk_size;
2274 if (pcm_write(audiobuf, b) != (ssize_t)b)
2275 error(_("voc_pcm_flush error"));
2276 }
2277 snd_pcm_nonblock(handle, 0);
2278 snd_pcm_drain(handle);
2279 snd_pcm_nonblock(handle, nonblock);
2280 }
2281
voc_play(int fd,int ofs,char * name)2282 static void voc_play(int fd, int ofs, char *name)
2283 {
2284 int l;
2285 VocBlockType *bp;
2286 VocVoiceData *vd;
2287 VocExtBlock *eb;
2288 size_t nextblock, in_buffer;
2289 u_char *data, *buf;
2290 char was_extended = 0, output = 0;
2291 u_short *sp, repeat = 0;
2292 off64_t filepos = 0;
2293
2294 #define COUNT(x) nextblock -= x; in_buffer -= x; data += x
2295 #define COUNT1(x) in_buffer -= x; data += x
2296
2297 data = buf = (u_char *)malloc(64 * 1024);
2298 buffer_pos = 0;
2299 if (data == NULL) {
2300 error(_("malloc error"));
2301 prg_exit(EXIT_FAILURE);
2302 }
2303 if (!quiet_mode) {
2304 fprintf(stderr, _("Playing Creative Labs Channel file '%s'...\n"), name);
2305 }
2306 /* first we waste the rest of header, ugly but we don't need seek */
2307 while (ofs > (ssize_t)chunk_bytes) {
2308 if ((size_t)safe_read(fd, buf, chunk_bytes) != chunk_bytes) {
2309 error(_("read error"));
2310 prg_exit(EXIT_FAILURE);
2311 }
2312 ofs -= chunk_bytes;
2313 }
2314 if (ofs) {
2315 if (safe_read(fd, buf, ofs) != ofs) {
2316 error(_("read error"));
2317 prg_exit(EXIT_FAILURE);
2318 }
2319 }
2320 hwparams.format = DEFAULT_FORMAT;
2321 hwparams.channels = 1;
2322 hwparams.rate = DEFAULT_SPEED;
2323 set_params();
2324
2325 in_buffer = nextblock = 0;
2326 while (!in_aborting) {
2327 Fill_the_buffer: /* need this for repeat */
2328 if (in_buffer < 32) {
2329 /* move the rest of buffer to pos 0 and fill the buf up */
2330 if (in_buffer)
2331 memcpy(buf, data, in_buffer);
2332 data = buf;
2333 if ((l = safe_read(fd, buf + in_buffer, chunk_bytes - in_buffer)) > 0)
2334 in_buffer += l;
2335 else if (!in_buffer) {
2336 /* the file is truncated, so simulate 'Terminator'
2337 and reduce the datablock for safe landing */
2338 nextblock = buf[0] = 0;
2339 if (l == -1) {
2340 perror(name);
2341 prg_exit(EXIT_FAILURE);
2342 }
2343 }
2344 }
2345 while (!nextblock) { /* this is a new block */
2346 if (in_buffer < sizeof(VocBlockType))
2347 goto __end;
2348 bp = (VocBlockType *) data;
2349 COUNT1(sizeof(VocBlockType));
2350 nextblock = VOC_DATALEN(bp);
2351 if (output && !quiet_mode)
2352 fprintf(stderr, "\n"); /* write /n after ASCII-out */
2353 output = 0;
2354 switch (bp->type) {
2355 case 0:
2356 #if 0
2357 d_printf("Terminator\n");
2358 #endif
2359 return; /* VOC-file stop */
2360 case 1:
2361 vd = (VocVoiceData *) data;
2362 COUNT1(sizeof(VocVoiceData));
2363 /* we need a SYNC, before we can set new SPEED, STEREO ... */
2364
2365 if (!was_extended) {
2366 hwparams.rate = (int) (vd->tc);
2367 hwparams.rate = 1000000 / (256 - hwparams.rate);
2368 #if 0
2369 d_printf("Channel data %d Hz\n", dsp_speed);
2370 #endif
2371 if (vd->pack) { /* /dev/dsp can't it */
2372 error(_("can't play packed .voc files"));
2373 return;
2374 }
2375 if (hwparams.channels == 2) /* if we are in Stereo-Mode, switch back */
2376 hwparams.channels = 1;
2377 } else { /* there was extended block */
2378 hwparams.channels = 2;
2379 was_extended = 0;
2380 }
2381 set_params();
2382 break;
2383 case 2: /* nothing to do, pure data */
2384 #if 0
2385 d_printf("Channel continuation\n");
2386 #endif
2387 break;
2388 case 3: /* a silence block, no data, only a count */
2389 sp = (u_short *) data;
2390 COUNT1(sizeof(u_short));
2391 hwparams.rate = (int) (*data);
2392 COUNT1(1);
2393 hwparams.rate = 1000000 / (256 - hwparams.rate);
2394 set_params();
2395 #if 0
2396 {
2397 size_t silence;
2398 silence = (((size_t) * sp) * 1000) / hwparams.rate;
2399 d_printf("Silence for %d ms\n", (int) silence);
2400 }
2401 #endif
2402 voc_write_silence(*sp);
2403 break;
2404 case 4: /* a marker for syncronisation, no effect */
2405 sp = (u_short *) data;
2406 COUNT1(sizeof(u_short));
2407 #if 0
2408 d_printf("Marker %d\n", *sp);
2409 #endif
2410 break;
2411 case 5: /* ASCII text, we copy to stderr */
2412 output = 1;
2413 #if 0
2414 d_printf("ASCII - text :\n");
2415 #endif
2416 break;
2417 case 6: /* repeat marker, says repeatcount */
2418 /* my specs don't say it: maybe this can be recursive, but
2419 I don't think somebody use it */
2420 repeat = *(u_short *) data;
2421 COUNT1(sizeof(u_short));
2422 #if 0
2423 d_printf("Repeat loop %d times\n", repeat);
2424 #endif
2425 if (filepos >= 0) { /* if < 0, one seek fails, why test another */
2426 if ((filepos = lseek64(fd, 0, 1)) < 0) {
2427 error(_("can't play loops; %s isn't seekable\n"), name);
2428 repeat = 0;
2429 } else {
2430 filepos -= in_buffer; /* set filepos after repeat */
2431 }
2432 } else {
2433 repeat = 0;
2434 }
2435 break;
2436 case 7: /* ok, lets repeat that be rewinding tape */
2437 if (repeat) {
2438 if (repeat != 0xFFFF) {
2439 #if 0
2440 d_printf("Repeat loop %d\n", repeat);
2441 #endif
2442 --repeat;
2443 }
2444 #if 0
2445 else
2446 d_printf("Neverending loop\n");
2447 #endif
2448 lseek64(fd, filepos, 0);
2449 in_buffer = 0; /* clear the buffer */
2450 goto Fill_the_buffer;
2451 }
2452 #if 0
2453 else
2454 d_printf("End repeat loop\n");
2455 #endif
2456 break;
2457 case 8: /* the extension to play Stereo, I have SB 1.0 :-( */
2458 was_extended = 1;
2459 eb = (VocExtBlock *) data;
2460 COUNT1(sizeof(VocExtBlock));
2461 hwparams.rate = (int) (eb->tc);
2462 hwparams.rate = 256000000L / (65536 - hwparams.rate);
2463 hwparams.channels = eb->mode == VOC_MODE_STEREO ? 2 : 1;
2464 if (hwparams.channels == 2)
2465 hwparams.rate = hwparams.rate >> 1;
2466 if (eb->pack) { /* /dev/dsp can't it */
2467 error(_("can't play packed .voc files"));
2468 return;
2469 }
2470 #if 0
2471 d_printf("Extended block %s %d Hz\n",
2472 (eb->mode ? "Stereo" : "Mono"), dsp_speed);
2473 #endif
2474 break;
2475 default:
2476 error(_("unknown blocktype %d. terminate."), bp->type);
2477 return;
2478 } /* switch (bp->type) */
2479 } /* while (! nextblock) */
2480 /* put nextblock data bytes to dsp */
2481 l = in_buffer;
2482 if (nextblock < (size_t)l)
2483 l = nextblock;
2484 if (l) {
2485 if (output && !quiet_mode) {
2486 if (xwrite(2, data, l) != l) { /* to stderr */
2487 error(_("write error"));
2488 prg_exit(EXIT_FAILURE);
2489 }
2490 } else {
2491 if (voc_pcm_write(data, l) != l) {
2492 error(_("write error"));
2493 prg_exit(EXIT_FAILURE);
2494 }
2495 }
2496 COUNT(l);
2497 }
2498 } /* while(1) */
2499 __end:
2500 voc_pcm_flush();
2501 free(buf);
2502 }
2503 /* that was a big one, perhaps somebody split it :-) */
2504
2505 /* setting the globals for playing raw data */
init_raw_data(void)2506 static void init_raw_data(void)
2507 {
2508 hwparams = rhwparams;
2509 }
2510
2511 /* calculate the data count to read from/to dsp */
calc_count(void)2512 static off64_t calc_count(void)
2513 {
2514 off64_t count;
2515
2516 if (timelimit == 0)
2517 if (sampleslimit == 0)
2518 count = pbrec_count;
2519 else
2520 count = snd_pcm_format_size(hwparams.format, sampleslimit * hwparams.channels);
2521 else {
2522 count = snd_pcm_format_size(hwparams.format, hwparams.rate * hwparams.channels);
2523 count *= (off64_t)timelimit;
2524 }
2525 return count < pbrec_count ? count : pbrec_count;
2526 }
2527
2528 /* write a .VOC-header */
begin_voc(int fd,size_t cnt)2529 static void begin_voc(int fd, size_t cnt)
2530 {
2531 VocHeader vh;
2532 VocBlockType bt;
2533 VocVoiceData vd;
2534 VocExtBlock eb;
2535
2536 memcpy(vh.magic, VOC_MAGIC_STRING, 20);
2537 vh.headerlen = LE_SHORT(sizeof(VocHeader));
2538 vh.version = LE_SHORT(VOC_ACTUAL_VERSION);
2539 vh.coded_ver = LE_SHORT(0x1233 - VOC_ACTUAL_VERSION);
2540
2541 if (xwrite(fd, &vh, sizeof(VocHeader)) != sizeof(VocHeader)) {
2542 error(_("write error"));
2543 prg_exit(EXIT_FAILURE);
2544 }
2545 if (hwparams.channels > 1) {
2546 /* write an extended block */
2547 bt.type = 8;
2548 bt.datalen = 4;
2549 bt.datalen_m = bt.datalen_h = 0;
2550 if (xwrite(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {
2551 error(_("write error"));
2552 prg_exit(EXIT_FAILURE);
2553 }
2554 eb.tc = LE_SHORT(65536 - 256000000L / (hwparams.rate << 1));
2555 eb.pack = 0;
2556 eb.mode = 1;
2557 if (xwrite(fd, &eb, sizeof(VocExtBlock)) != sizeof(VocExtBlock)) {
2558 error(_("write error"));
2559 prg_exit(EXIT_FAILURE);
2560 }
2561 }
2562 bt.type = 1;
2563 cnt += sizeof(VocVoiceData); /* Channel_data block follows */
2564 bt.datalen = (u_char) (cnt & 0xFF);
2565 bt.datalen_m = (u_char) ((cnt & 0xFF00) >> 8);
2566 bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16);
2567 if (xwrite(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {
2568 error(_("write error"));
2569 prg_exit(EXIT_FAILURE);
2570 }
2571 vd.tc = (u_char) (256 - (1000000 / hwparams.rate));
2572 vd.pack = 0;
2573 if (xwrite(fd, &vd, sizeof(VocVoiceData)) != sizeof(VocVoiceData)) {
2574 error(_("write error"));
2575 prg_exit(EXIT_FAILURE);
2576 }
2577 }
2578
2579 /* write a WAVE-header */
begin_wave(int fd,size_t cnt)2580 static void begin_wave(int fd, size_t cnt)
2581 {
2582 WaveHeader h;
2583 WaveFmtBody f;
2584 WaveChunkHeader cf, cd;
2585 int bits;
2586 u_int tmp;
2587 u_short tmp2;
2588
2589 /* WAVE cannot handle greater than 32bit (signed?) int */
2590 if (cnt == (size_t)-2)
2591 cnt = 0x7fffff00;
2592
2593 bits = 8;
2594 switch ((unsigned long) hwparams.format) {
2595 case SND_PCM_FORMAT_U8:
2596 bits = 8;
2597 break;
2598 case SND_PCM_FORMAT_S16_LE:
2599 bits = 16;
2600 break;
2601 case SND_PCM_FORMAT_S32_LE:
2602 case SND_PCM_FORMAT_FLOAT_LE:
2603 bits = 32;
2604 break;
2605 case SND_PCM_FORMAT_S24_LE:
2606 case SND_PCM_FORMAT_S24_3LE:
2607 bits = 24;
2608 break;
2609 default:
2610 error(_("Wave doesn't support %s format..."), snd_pcm_format_name(hwparams.format));
2611 prg_exit(EXIT_FAILURE);
2612 }
2613 h.magic = WAV_RIFF;
2614 tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;
2615 h.length = LE_INT(tmp);
2616 h.type = WAV_WAVE;
2617
2618 cf.type = WAV_FMT;
2619 cf.length = LE_INT(16);
2620
2621 if (hwparams.format == SND_PCM_FORMAT_FLOAT_LE)
2622 f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT);
2623 else
2624 f.format = LE_SHORT(WAV_FMT_PCM);
2625 f.channels = LE_SHORT(hwparams.channels);
2626 f.sample_fq = LE_INT(hwparams.rate);
2627 #if 0
2628 tmp2 = (samplesize == 8) ? 1 : 2;
2629 f.byte_p_spl = LE_SHORT(tmp2);
2630 tmp = dsp_speed * hwparams.channels * (u_int) tmp2;
2631 #else
2632 tmp2 = hwparams.channels * snd_pcm_format_physical_width(hwparams.format) / 8;
2633 f.byte_p_spl = LE_SHORT(tmp2);
2634 tmp = (u_int) tmp2 * hwparams.rate;
2635 #endif
2636 f.byte_p_sec = LE_INT(tmp);
2637 f.bit_p_spl = LE_SHORT(bits);
2638
2639 cd.type = WAV_DATA;
2640 cd.length = LE_INT(cnt);
2641
2642 if (xwrite(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
2643 xwrite(fd, &cf, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader) ||
2644 xwrite(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) ||
2645 xwrite(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
2646 error(_("write error"));
2647 prg_exit(EXIT_FAILURE);
2648 }
2649 }
2650
2651 /* write a Au-header */
begin_au(int fd,size_t cnt)2652 static void begin_au(int fd, size_t cnt)
2653 {
2654 AuHeader ah;
2655
2656 ah.magic = AU_MAGIC;
2657 ah.hdr_size = BE_INT(24);
2658 ah.data_size = BE_INT(cnt);
2659 switch ((unsigned long) hwparams.format) {
2660 case SND_PCM_FORMAT_MU_LAW:
2661 ah.encoding = BE_INT(AU_FMT_ULAW);
2662 break;
2663 case SND_PCM_FORMAT_U8:
2664 ah.encoding = BE_INT(AU_FMT_LIN8);
2665 break;
2666 case SND_PCM_FORMAT_S16_BE:
2667 ah.encoding = BE_INT(AU_FMT_LIN16);
2668 break;
2669 default:
2670 error(_("Sparc Audio doesn't support %s format..."), snd_pcm_format_name(hwparams.format));
2671 prg_exit(EXIT_FAILURE);
2672 }
2673 ah.sample_rate = BE_INT(hwparams.rate);
2674 ah.channels = BE_INT(hwparams.channels);
2675 if (xwrite(fd, &ah, sizeof(AuHeader)) != sizeof(AuHeader)) {
2676 error(_("write error"));
2677 prg_exit(EXIT_FAILURE);
2678 }
2679 }
2680
2681 /* closing .VOC */
end_voc(int fd)2682 static void end_voc(int fd)
2683 {
2684 off64_t length_seek;
2685 VocBlockType bt;
2686 size_t cnt;
2687 char dummy = 0; /* Write a Terminator */
2688
2689 if (xwrite(fd, &dummy, 1) != 1) {
2690 error(_("write error"));
2691 prg_exit(EXIT_FAILURE);
2692 }
2693 length_seek = sizeof(VocHeader);
2694 if (hwparams.channels > 1)
2695 length_seek += sizeof(VocBlockType) + sizeof(VocExtBlock);
2696 bt.type = 1;
2697 cnt = fdcount;
2698 cnt += sizeof(VocVoiceData); /* Channel_data block follows */
2699 if (cnt > 0x00ffffff)
2700 cnt = 0x00ffffff;
2701 bt.datalen = (u_char) (cnt & 0xFF);
2702 bt.datalen_m = (u_char) ((cnt & 0xFF00) >> 8);
2703 bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16);
2704 if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
2705 xwrite(fd, &bt, sizeof(VocBlockType));
2706 }
2707
end_wave(int fd)2708 static void end_wave(int fd)
2709 { /* only close output */
2710 WaveChunkHeader cd;
2711 off64_t length_seek;
2712 off64_t filelen;
2713 u_int rifflen;
2714
2715 length_seek = sizeof(WaveHeader) +
2716 sizeof(WaveChunkHeader) +
2717 sizeof(WaveFmtBody);
2718 cd.type = WAV_DATA;
2719 cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount);
2720 filelen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
2721 rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen);
2722 if (lseek64(fd, 4, SEEK_SET) == 4)
2723 xwrite(fd, &rifflen, 4);
2724 if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
2725 xwrite(fd, &cd, sizeof(WaveChunkHeader));
2726 }
2727
end_au(int fd)2728 static void end_au(int fd)
2729 { /* only close output */
2730 AuHeader ah;
2731 off64_t length_seek;
2732
2733 length_seek = (char *)&ah.data_size - (char *)&ah;
2734 ah.data_size = fdcount > 0xffffffff ? 0xffffffff : BE_INT(fdcount);
2735 if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
2736 xwrite(fd, &ah.data_size, sizeof(ah.data_size));
2737 }
2738
header(int rtype,char * name)2739 static void header(int rtype, char *name)
2740 {
2741 if (!quiet_mode) {
2742 if (! name)
2743 name = (stream == SND_PCM_STREAM_PLAYBACK) ? "stdout" : "stdin";
2744 fprintf(stderr, "%s %s '%s' : ",
2745 (stream == SND_PCM_STREAM_PLAYBACK) ? _("Playing") : _("Recording"),
2746 gettext(fmt_rec_table[rtype].what),
2747 name);
2748 fprintf(stderr, "%s, ", snd_pcm_format_description(hwparams.format));
2749 fprintf(stderr, _("Rate %d Hz, "), hwparams.rate);
2750 if (hwparams.channels == 1)
2751 fprintf(stderr, _("Mono"));
2752 else if (hwparams.channels == 2)
2753 fprintf(stderr, _("Stereo"));
2754 else
2755 fprintf(stderr, _("Channels %i"), hwparams.channels);
2756 fprintf(stderr, "\n");
2757 }
2758 }
2759
2760 /* playing raw data */
2761
playback_go(int fd,size_t loaded,off64_t count,int rtype,char * name)2762 static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *name)
2763 {
2764 int l, r;
2765 off64_t written = 0;
2766 off64_t c;
2767
2768 header(rtype, name);
2769 set_params();
2770
2771 while (loaded > chunk_bytes && written < count && !in_aborting) {
2772 if (pcm_write(audiobuf + written, chunk_size) <= 0)
2773 return;
2774 written += chunk_bytes;
2775 loaded -= chunk_bytes;
2776 }
2777 if (written > 0 && loaded > 0)
2778 memmove(audiobuf, audiobuf + written, loaded);
2779
2780 l = loaded;
2781 while (written < count && !in_aborting) {
2782 do {
2783 c = count - written;
2784 if (c > chunk_bytes)
2785 c = chunk_bytes;
2786
2787 /* c < l, there is more data loaded
2788 * then we actually need to write
2789 */
2790 if (c < l)
2791 l = c;
2792
2793 c -= l;
2794
2795 if (c == 0)
2796 break;
2797 r = safe_read(fd, audiobuf + l, c);
2798 if (r < 0) {
2799 perror(name);
2800 prg_exit(EXIT_FAILURE);
2801 }
2802 fdcount += r;
2803 if (r == 0)
2804 break;
2805 l += r;
2806 } while ((size_t)l < chunk_bytes);
2807 l = l * 8 / bits_per_frame;
2808 r = pcm_write(audiobuf, l);
2809 if (r != l)
2810 break;
2811 r = r * bits_per_frame / 8;
2812 written += r;
2813 l = 0;
2814 }
2815 snd_pcm_nonblock(handle, 0);
2816 snd_pcm_drain(handle);
2817 snd_pcm_nonblock(handle, nonblock);
2818 }
2819
read_header(int * loaded,int header_size)2820 static int read_header(int *loaded, int header_size)
2821 {
2822 int ret;
2823 struct stat buf;
2824
2825 ret = fstat(fd, &buf);
2826 if (ret < 0) {
2827 perror("fstat");
2828 prg_exit(EXIT_FAILURE);
2829 }
2830
2831 /* don't be adventurous, get out if file size is smaller than
2832 * requested header size */
2833 if ((buf.st_mode & S_IFMT) == S_IFREG &&
2834 buf.st_size < header_size)
2835 return -1;
2836
2837 if (*loaded < header_size) {
2838 header_size -= *loaded;
2839 ret = safe_read(fd, audiobuf + *loaded, header_size);
2840 if (ret != header_size) {
2841 error(_("read error"));
2842 prg_exit(EXIT_FAILURE);
2843 }
2844 *loaded += header_size;
2845 }
2846 return 0;
2847 }
2848
playback_au(char * name,int * loaded)2849 static int playback_au(char *name, int *loaded)
2850 {
2851 if (read_header(loaded, sizeof(AuHeader)) < 0)
2852 return -1;
2853
2854 if (test_au(fd, audiobuf) < 0)
2855 return -1;
2856
2857 rhwparams.format = hwparams.format;
2858 pbrec_count = calc_count();
2859 playback_go(fd, *loaded - sizeof(AuHeader), pbrec_count, FORMAT_AU, name);
2860
2861 return 0;
2862 }
2863
playback_voc(char * name,int * loaded)2864 static int playback_voc(char *name, int *loaded)
2865 {
2866 int ofs;
2867
2868 if (read_header(loaded, sizeof(VocHeader)) < 0)
2869 return -1;
2870
2871 if ((ofs = test_vocfile(audiobuf)) < 0)
2872 return -1;
2873
2874 pbrec_count = calc_count();
2875 voc_play(fd, ofs, name);
2876
2877 return 0;
2878 }
2879
playback_wave(char * name,int * loaded)2880 static int playback_wave(char *name, int *loaded)
2881 {
2882 ssize_t dtawave;
2883
2884 if (read_header(loaded, sizeof(WaveHeader)) < 0)
2885 return -1;
2886
2887 if ((dtawave = test_wavefile(fd, audiobuf, *loaded)) < 0)
2888 return -1;
2889
2890 pbrec_count = calc_count();
2891 playback_go(fd, dtawave, pbrec_count, FORMAT_WAVE, name);
2892
2893 return 0;
2894 }
2895
playback_raw(char * name,int * loaded)2896 static int playback_raw(char *name, int *loaded)
2897 {
2898 init_raw_data();
2899 pbrec_count = calc_count();
2900 playback_go(fd, *loaded, pbrec_count, FORMAT_RAW, name);
2901
2902 return 0;
2903 }
2904
2905 /*
2906 * let's play or capture it (capture_type says VOC/WAVE/raw)
2907 */
2908
playback(char * name)2909 static void playback(char *name)
2910 {
2911 int loaded = 0;
2912
2913 pbrec_count = LLONG_MAX;
2914 fdcount = 0;
2915 if (!name || !strcmp(name, "-")) {
2916 fd = fileno(stdin);
2917 name = "stdin";
2918 } else {
2919 init_stdin();
2920 if ((fd = open(name, O_RDONLY, 0)) == -1) {
2921 perror(name);
2922 prg_exit(EXIT_FAILURE);
2923 }
2924 }
2925
2926 switch(file_type) {
2927 case FORMAT_AU:
2928 playback_au(name, &loaded);
2929 break;
2930 case FORMAT_VOC:
2931 playback_voc(name, &loaded);
2932 break;
2933 case FORMAT_WAVE:
2934 playback_wave(name, &loaded);
2935 break;
2936 case FORMAT_RAW:
2937 playback_raw(name, &loaded);
2938 break;
2939 default:
2940 /* parse the file header */
2941 if (playback_au(name, &loaded) < 0 &&
2942 playback_voc(name, &loaded) < 0 &&
2943 playback_wave(name, &loaded) < 0)
2944 playback_raw(name, &loaded); /* should be raw data */
2945 break;
2946 }
2947
2948 if (fd != fileno(stdin))
2949 close(fd);
2950 }
2951
2952 /**
2953 * mystrftime
2954 *
2955 * Variant of strftime(3) that supports additional format
2956 * specifiers in the format string.
2957 *
2958 * Parameters:
2959 *
2960 * s - destination string
2961 * max - max number of bytes to write
2962 * userformat - format string
2963 * tm - time information
2964 * filenumber - the number of the file, starting at 1
2965 *
2966 * Returns: number of bytes written to the string s
2967 */
mystrftime(char * s,size_t max,const char * userformat,const struct tm * tm,const int filenumber)2968 size_t mystrftime(char *s, size_t max, const char *userformat,
2969 const struct tm *tm, const int filenumber)
2970 {
2971 char formatstring[PATH_MAX] = "";
2972 char tempstring[PATH_MAX] = "";
2973 char *format, *tempstr;
2974 const char *pos_userformat;
2975
2976 format = formatstring;
2977
2978 /* if mystrftime is called with userformat = NULL we return a zero length string */
2979 if (userformat == NULL) {
2980 *s = '\0';
2981 return 0;
2982 }
2983
2984 for (pos_userformat = userformat; *pos_userformat; ++pos_userformat) {
2985 if (*pos_userformat == '%') {
2986 tempstr = tempstring;
2987 tempstr[0] = '\0';
2988 switch (*++pos_userformat) {
2989
2990 case '\0': // end of string
2991 --pos_userformat;
2992 break;
2993
2994 case 'v': // file number
2995 sprintf(tempstr, "%02d", filenumber);
2996 break;
2997
2998 default: // All other codes will be handled by strftime
2999 *format++ = '%';
3000 *format++ = *pos_userformat;
3001 continue;
3002 }
3003
3004 /* If a format specifier was found and used, copy the result. */
3005 if (tempstr[0]) {
3006 while ((*format = *tempstr++) != '\0')
3007 ++format;
3008 continue;
3009 }
3010 }
3011
3012 /* For any other character than % we simply copy the character */
3013 *format++ = *pos_userformat;
3014 }
3015
3016 *format = '\0';
3017 format = formatstring;
3018 return strftime(s, max, format, tm);
3019 }
3020
new_capture_file(char * name,char * namebuf,size_t namelen,int filecount)3021 static int new_capture_file(char *name, char *namebuf, size_t namelen,
3022 int filecount)
3023 {
3024 char *s;
3025 char buf[PATH_MAX-10];
3026 time_t t;
3027 struct tm *tmp;
3028
3029 if (use_strftime) {
3030 t = time(NULL);
3031 tmp = localtime(&t);
3032 if (tmp == NULL) {
3033 perror("localtime");
3034 prg_exit(EXIT_FAILURE);
3035 }
3036 if (mystrftime(namebuf, namelen, name, tmp, filecount+1) == 0) {
3037 fprintf(stderr, "mystrftime returned 0");
3038 prg_exit(EXIT_FAILURE);
3039 }
3040 return filecount;
3041 }
3042
3043 /* get a copy of the original filename */
3044 strncpy(buf, name, sizeof(buf));
3045
3046 /* separate extension from filename */
3047 s = buf + strlen(buf);
3048 while (s > buf && *s != '.' && *s != '/')
3049 --s;
3050 if (*s == '.')
3051 *s++ = 0;
3052 else if (*s == '/')
3053 s = buf + strlen(buf);
3054
3055 /* upon first jump to this if block rename the first file */
3056 if (filecount == 1) {
3057 if (*s)
3058 snprintf(namebuf, namelen, "%s-01.%s", buf, s);
3059 else
3060 snprintf(namebuf, namelen, "%s-01", buf);
3061 remove(namebuf);
3062 rename(name, namebuf);
3063 filecount = 2;
3064 }
3065
3066 /* name of the current file */
3067 if (*s)
3068 snprintf(namebuf, namelen, "%s-%02i.%s", buf, filecount, s);
3069 else
3070 snprintf(namebuf, namelen, "%s-%02i", buf, filecount);
3071
3072 return filecount;
3073 }
3074
3075 /**
3076 * create_path
3077 *
3078 * This function creates a file path, like mkdir -p.
3079 *
3080 * Parameters:
3081 *
3082 * path - the path to create
3083 *
3084 * Returns: 0 on success, -1 on failure
3085 * On failure, a message has been printed to stderr.
3086 */
create_path(const char * path)3087 int create_path(const char *path)
3088 {
3089 char *start;
3090 mode_t mode = S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH;
3091
3092 if (path[0] == '/')
3093 start = strchr(path + 1, '/');
3094 else
3095 start = strchr(path, '/');
3096
3097 while (start) {
3098 char *buffer = strdup(path);
3099 buffer[start-path] = 0x00;
3100
3101 if (mkdir(buffer, mode) == -1 && errno != EEXIST) {
3102 fprintf(stderr, "Problem creating directory %s", buffer);
3103 perror(" ");
3104 free(buffer);
3105 return -1;
3106 }
3107 free(buffer);
3108 start = strchr(start + 1, '/');
3109 }
3110 return 0;
3111 }
3112
safe_open(const char * name)3113 static int safe_open(const char *name)
3114 {
3115 int fd;
3116
3117 fd = open(name, O_WRONLY | O_CREAT, 0644);
3118 if (fd == -1) {
3119 if (errno != ENOENT || !use_strftime)
3120 return -1;
3121 if (create_path(name) == 0)
3122 fd = open(name, O_WRONLY | O_CREAT, 0644);
3123 }
3124 return fd;
3125 }
3126
capture(char * orig_name)3127 static void capture(char *orig_name)
3128 {
3129 int tostdout=0; /* boolean which describes output stream */
3130 int filecount=0; /* number of files written */
3131 char *name = orig_name; /* current filename */
3132 char namebuf[PATH_MAX+2];
3133 off64_t count, rest; /* number of bytes to capture */
3134 struct stat statbuf;
3135
3136 /* get number of bytes to capture */
3137 count = calc_count();
3138 if (count == 0)
3139 count = LLONG_MAX;
3140 /* compute the number of bytes per file */
3141 max_file_size = (long long) max_file_time *
3142 snd_pcm_format_size(hwparams.format,
3143 hwparams.rate * hwparams.channels);
3144 /* WAVE-file should be even (I'm not sure), but wasting one byte
3145 isn't a problem (this can only be in 8 bit mono) */
3146 if (count < LLONG_MAX)
3147 count += count % 2;
3148 else
3149 count -= count % 2;
3150
3151 /* display verbose output to console */
3152 header(file_type, name);
3153
3154 /* setup sound hardware */
3155 set_params();
3156
3157 /* write to stdout? */
3158 if (!name || !strcmp(name, "-")) {
3159 fd = fileno(stdout);
3160 name = "stdout";
3161 tostdout = 1;
3162 if (count > fmt_rec_table[file_type].max_filesize)
3163 count = fmt_rec_table[file_type].max_filesize;
3164 }
3165 init_stdin();
3166
3167 do {
3168 /* open a file to write */
3169 if (!tostdout) {
3170 /* upon the second file we start the numbering scheme */
3171 if (filecount || use_strftime) {
3172 filecount = new_capture_file(orig_name, namebuf,
3173 sizeof(namebuf),
3174 filecount);
3175 name = namebuf;
3176 }
3177
3178 /* open a new file */
3179 if (!lstat(name, &statbuf)) {
3180 if (S_ISREG(statbuf.st_mode))
3181 remove(name);
3182 }
3183 fd = safe_open(name);
3184 if (fd < 0) {
3185 perror(name);
3186 prg_exit(EXIT_FAILURE);
3187 }
3188 filecount++;
3189 }
3190
3191 rest = count;
3192 if (rest > fmt_rec_table[file_type].max_filesize)
3193 rest = fmt_rec_table[file_type].max_filesize;
3194 if (max_file_size && (rest > max_file_size))
3195 rest = max_file_size;
3196
3197 /* setup sample header */
3198 if (fmt_rec_table[file_type].start)
3199 fmt_rec_table[file_type].start(fd, rest);
3200
3201 /* capture */
3202 fdcount = 0;
3203 while (rest > 0 && recycle_capture_file == 0 && !in_aborting) {
3204 size_t c = (rest <= (off64_t)chunk_bytes) ?
3205 (size_t)rest : chunk_bytes;
3206 size_t f = c * 8 / bits_per_frame;
3207 if (pcm_read(audiobuf, f) != f) {
3208 in_aborting = 1;
3209 break;
3210 }
3211 if (xwrite(fd, audiobuf, c) != c) {
3212 perror(name);
3213 in_aborting = 1;
3214 break;
3215 }
3216 count -= c;
3217 rest -= c;
3218 fdcount += c;
3219 }
3220
3221 /* re-enable SIGUSR1 signal */
3222 if (recycle_capture_file) {
3223 recycle_capture_file = 0;
3224 signal(SIGUSR1, signal_handler_recycle);
3225 }
3226
3227 /* finish sample container */
3228 if (!tostdout) {
3229 if (fmt_rec_table[file_type].end)
3230 fmt_rec_table[file_type].end(fd);
3231 close(fd);
3232 fd = -1;
3233 }
3234
3235 if (in_aborting)
3236 prg_exit(EXIT_FAILURE);
3237
3238 /* repeat the loop when format is raw without timelimit or
3239 * requested counts of data are recorded
3240 */
3241 } while ((file_type == FORMAT_RAW && !timelimit && !sampleslimit) || count > 0);
3242 }
3243
playbackv_go(int * fds,unsigned int channels,size_t loaded,off64_t count,int rtype,char ** names)3244 static void playbackv_go(int* fds, unsigned int channels, size_t loaded, off64_t count, int rtype, char **names)
3245 {
3246 int r;
3247 size_t vsize;
3248
3249 unsigned int channel;
3250 u_char *bufs[channels];
3251
3252 header(rtype, names[0]);
3253 set_params();
3254
3255 vsize = chunk_bytes / channels;
3256
3257 // Not yet implemented
3258 assert(loaded == 0);
3259
3260 for (channel = 0; channel < channels; ++channel)
3261 bufs[channel] = audiobuf + vsize * channel;
3262
3263 while (count > 0 && !in_aborting) {
3264 size_t c = 0;
3265 size_t expected = count / channels;
3266 if (expected > vsize)
3267 expected = vsize;
3268 do {
3269 r = safe_read(fds[0], bufs[0], expected);
3270 if (r < 0) {
3271 perror(names[channel]);
3272 prg_exit(EXIT_FAILURE);
3273 }
3274 for (channel = 1; channel < channels; ++channel) {
3275 if (safe_read(fds[channel], bufs[channel], r) != r) {
3276 perror(names[channel]);
3277 prg_exit(EXIT_FAILURE);
3278 }
3279 }
3280 if (r == 0)
3281 break;
3282 c += r;
3283 } while (c < expected);
3284 c = c * 8 / bits_per_sample;
3285 r = pcm_writev(bufs, channels, c);
3286 if ((size_t)r != c)
3287 break;
3288 r = r * bits_per_frame / 8;
3289 count -= r;
3290 }
3291 snd_pcm_nonblock(handle, 0);
3292 snd_pcm_drain(handle);
3293 snd_pcm_nonblock(handle, nonblock);
3294 }
3295
capturev_go(int * fds,unsigned int channels,off64_t count,int rtype,char ** names)3296 static void capturev_go(int* fds, unsigned int channels, off64_t count, int rtype, char **names)
3297 {
3298 size_t c;
3299 ssize_t r;
3300 unsigned int channel;
3301 size_t vsize;
3302 u_char *bufs[channels];
3303
3304 header(rtype, names[0]);
3305 set_params();
3306
3307 vsize = chunk_bytes / channels;
3308
3309 for (channel = 0; channel < channels; ++channel)
3310 bufs[channel] = audiobuf + vsize * channel;
3311
3312 while (count > 0 && !in_aborting) {
3313 size_t rv;
3314 c = count;
3315 if (c > chunk_bytes)
3316 c = chunk_bytes;
3317 c = c * 8 / bits_per_frame;
3318 if ((size_t)(r = pcm_readv(bufs, channels, c)) != c)
3319 break;
3320 rv = r * bits_per_sample / 8;
3321 for (channel = 0; channel < channels; ++channel) {
3322 if ((size_t)xwrite(fds[channel], bufs[channel], rv) != rv) {
3323 perror(names[channel]);
3324 prg_exit(EXIT_FAILURE);
3325 }
3326 }
3327 r = r * bits_per_frame / 8;
3328 count -= r;
3329 fdcount += r;
3330 }
3331 }
3332
playbackv(char ** names,unsigned int count)3333 static void playbackv(char **names, unsigned int count)
3334 {
3335 int ret = 0;
3336 unsigned int channel;
3337 unsigned int channels = rhwparams.channels;
3338 int alloced = 0;
3339 int fds[channels];
3340 for (channel = 0; channel < channels; ++channel)
3341 fds[channel] = -1;
3342
3343 if (count == 1 && channels > 1) {
3344 size_t len = strlen(names[0]);
3345 char format[1024];
3346 memcpy(format, names[0], len);
3347 strcpy(format + len, ".%d");
3348 len += 4;
3349 names = malloc(sizeof(*names) * channels);
3350 for (channel = 0; channel < channels; ++channel) {
3351 names[channel] = malloc(len);
3352 sprintf(names[channel], format, channel);
3353 }
3354 alloced = 1;
3355 } else if (count != channels) {
3356 error(_("You need to specify %u files"), channels);
3357 prg_exit(EXIT_FAILURE);
3358 }
3359
3360 for (channel = 0; channel < channels; ++channel) {
3361 fds[channel] = open(names[channel], O_RDONLY, 0);
3362 if (fds[channel] < 0) {
3363 perror(names[channel]);
3364 ret = EXIT_FAILURE;
3365 goto __end;
3366 }
3367 }
3368 /* should be raw data */
3369 init_raw_data();
3370 pbrec_count = calc_count();
3371 playbackv_go(fds, channels, 0, pbrec_count, FORMAT_RAW, names);
3372
3373 __end:
3374 for (channel = 0; channel < channels; ++channel) {
3375 if (fds[channel] >= 0)
3376 close(fds[channel]);
3377 if (alloced)
3378 free(names[channel]);
3379 }
3380 if (alloced)
3381 free(names);
3382 if (ret)
3383 prg_exit(ret);
3384 }
3385
capturev(char ** names,unsigned int count)3386 static void capturev(char **names, unsigned int count)
3387 {
3388 int ret = 0;
3389 unsigned int channel;
3390 unsigned int channels = rhwparams.channels;
3391 int alloced = 0;
3392 int fds[channels];
3393 for (channel = 0; channel < channels; ++channel)
3394 fds[channel] = -1;
3395
3396 if (count == 1) {
3397 size_t len = strlen(names[0]);
3398 char format[1024];
3399 memcpy(format, names[0], len);
3400 strcpy(format + len, ".%d");
3401 len += 4;
3402 names = malloc(sizeof(*names) * channels);
3403 for (channel = 0; channel < channels; ++channel) {
3404 names[channel] = malloc(len);
3405 sprintf(names[channel], format, channel);
3406 }
3407 alloced = 1;
3408 } else if (count != channels) {
3409 error(_("You need to specify %d files"), channels);
3410 prg_exit(EXIT_FAILURE);
3411 }
3412
3413 for (channel = 0; channel < channels; ++channel) {
3414 fds[channel] = open(names[channel], O_WRONLY + O_CREAT, 0644);
3415 if (fds[channel] < 0) {
3416 perror(names[channel]);
3417 ret = EXIT_FAILURE;
3418 goto __end;
3419 }
3420 }
3421 /* should be raw data */
3422 init_raw_data();
3423 pbrec_count = calc_count();
3424 capturev_go(fds, channels, pbrec_count, FORMAT_RAW, names);
3425
3426 __end:
3427 for (channel = 0; channel < channels; ++channel) {
3428 if (fds[channel] >= 0)
3429 close(fds[channel]);
3430 if (alloced)
3431 free(names[channel]);
3432 }
3433 if (alloced)
3434 free(names);
3435 if (ret)
3436 prg_exit(ret);
3437 }
3438