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