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