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