Home | History | Annotate | Download | only in aplay
      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 (at) 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
     26  *
     27  */
     28 
     29 #define _GNU_SOURCE
     30 #include <stdio.h>
     31 #include <malloc.h>
     32 #include <unistd.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <getopt.h>
     36 #include <fcntl.h>
     37 #include <ctype.h>
     38 #include <errno.h>
     39 #include <limits.h>
     40 #include <time.h>
     41 #include <locale.h>
     42 #include <alsa/asoundlib.h>
     43 #include <assert.h>
     44 #include <sys/poll.h>
     45 #include <sys/uio.h>
     46 #include <sys/time.h>
     47 #include <sys/signal.h>
     48 #include <asm/byteorder.h>
     49 #include "aconfig.h"
     50 #include "gettext.h"
     51 #include "formats.h"
     52 #include "version.h"
     53 
     54 #ifndef LLONG_MAX
     55 #define LLONG_MAX    9223372036854775807LL
     56 #endif
     57 
     58 #define DEFAULT_FORMAT		SND_PCM_FORMAT_U8
     59 #define DEFAULT_SPEED 		8000
     60 
     61 #define FORMAT_DEFAULT		-1
     62 #define FORMAT_RAW		0
     63 #define FORMAT_VOC		1
     64 #define FORMAT_WAVE		2
     65 #define FORMAT_AU		3
     66 
     67 /* global data */
     68 
     69 static snd_pcm_sframes_t (*readi_func)(snd_pcm_t *handle, void *buffer, snd_pcm_uframes_t size);
     70 static snd_pcm_sframes_t (*writei_func)(snd_pcm_t *handle, const void *buffer, snd_pcm_uframes_t size);
     71 static snd_pcm_sframes_t (*readn_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
     72 static snd_pcm_sframes_t (*writen_func)(snd_pcm_t *handle, void **bufs, snd_pcm_uframes_t size);
     73 
     74 enum {
     75 	VUMETER_NONE,
     76 	VUMETER_MONO,
     77 	VUMETER_STEREO
     78 };
     79 
     80 static char *command;
     81 static snd_pcm_t *handle;
     82 static struct {
     83 	snd_pcm_format_t format;
     84 	unsigned int channels;
     85 	unsigned int rate;
     86 } hwparams, rhwparams;
     87 static int timelimit = 0;
     88 static int quiet_mode = 0;
     89 static int file_type = FORMAT_DEFAULT;
     90 static int open_mode = 0;
     91 static snd_pcm_stream_t stream = SND_PCM_STREAM_PLAYBACK;
     92 static int mmap_flag = 0;
     93 static int interleaved = 1;
     94 static int nonblock = 0;
     95 static u_char *audiobuf = NULL;
     96 static snd_pcm_uframes_t chunk_size = 0;
     97 static unsigned period_time = 0;
     98 static unsigned buffer_time = 0;
     99 static snd_pcm_uframes_t period_frames = 0;
    100 static snd_pcm_uframes_t buffer_frames = 0;
    101 static int avail_min = -1;
    102 static int start_delay = 0;
    103 static int stop_delay = 0;
    104 static int verbose = 0;
    105 static int vumeter = VUMETER_NONE;
    106 static int buffer_pos = 0;
    107 static size_t bits_per_sample, bits_per_frame;
    108 static size_t chunk_bytes;
    109 static int test_position = 0;
    110 static snd_output_t *log;
    111 
    112 static int fd = -1;
    113 static off64_t pbrec_count = LLONG_MAX, fdcount;
    114 static int vocmajor, vocminor;
    115 
    116 /* needed prototypes */
    117 
    118 static void playback(char *filename);
    119 static void capture(char *filename);
    120 static void playbackv(char **filenames, unsigned int count);
    121 static void capturev(char **filenames, unsigned int count);
    122 
    123 static void begin_voc(int fd, size_t count);
    124 static void end_voc(int fd);
    125 static void begin_wave(int fd, size_t count);
    126 static void end_wave(int fd);
    127 static void begin_au(int fd, size_t count);
    128 static void end_au(int fd);
    129 
    130 static const struct fmt_capture {
    131 	void (*start) (int fd, size_t count);
    132 	void (*end) (int fd);
    133 	char *what;
    134 	long long max_filesize;
    135 } fmt_rec_table[] = {
    136 	{	NULL,		NULL,		N_("raw data"),		LLONG_MAX },
    137 	{	begin_voc,	end_voc,	N_("VOC"),		16000000LL },
    138 	/* FIXME: can WAV handle exactly 2GB or less than it? */
    139 	{	begin_wave,	end_wave,	N_("WAVE"),		2147483648LL },
    140 	{	begin_au,	end_au,		N_("Sparc Audio"),	LLONG_MAX }
    141 };
    142 
    143 #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95)
    144 #define error(...) do {\
    145 	fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
    146 	fprintf(stderr, __VA_ARGS__); \
    147 	putc('\n', stderr); \
    148 } while (0)
    149 #else
    150 #define error(args...) do {\
    151 	fprintf(stderr, "%s: %s:%d: ", command, __FUNCTION__, __LINE__); \
    152 	fprintf(stderr, ##args); \
    153 	putc('\n', stderr); \
    154 } while (0)
    155 #endif
    156 
    157 static void usage(char *command)
    158 {
    159 	snd_pcm_format_t k;
    160 	printf(
    161 _("Usage: %s [OPTION]... [FILE]...\n"
    162 "\n"
    163 "-h, --help              help\n"
    164 "    --version           print current version\n"
    165 "-l, --list-devices      list all soundcards and digital audio devices\n"
    166 "-L, --list-pcms         list device names\n"
    167 "-D, --device=NAME       select PCM by name\n"
    168 "-q, --quiet             quiet mode\n"
    169 "-t, --file-type TYPE    file type (voc, wav, raw or au)\n"
    170 "-c, --channels=#        channels\n"
    171 "-f, --format=FORMAT     sample format (case insensitive)\n"
    172 "-r, --rate=#            sample rate\n"
    173 "-d, --duration=#        interrupt after # seconds\n"
    174 "-M, --mmap              mmap stream\n"
    175 "-N, --nonblock          nonblocking mode\n"
    176 "-F, --period-time=#     distance between interrupts is # microseconds\n"
    177 "-B, --buffer-time=#     buffer duration is # microseconds\n"
    178 "    --period-size=#     distance between interrupts is # frames\n"
    179 "    --buffer-size=#     buffer duration is # frames\n"
    180 "-A, --avail-min=#       min available space for wakeup is # microseconds\n"
    181 "-R, --start-delay=#     delay for automatic PCM start is # microseconds \n"
    182 "                        (relative to buffer size if <= 0)\n"
    183 "-T, --stop-delay=#      delay for automatic PCM stop is # microseconds from xrun\n"
    184 "-v, --verbose           show PCM structure and setup (accumulative)\n"
    185 "-V, --vumeter=TYPE      enable VU meter (TYPE: mono or stereo)\n"
    186 "-I, --separate-channels one file for each channel\n"
    187 "    --disable-resample  disable automatic rate resample\n"
    188 "    --disable-channels  disable automatic channel conversions\n"
    189 "    --disable-format    disable automatic format conversions\n"
    190 "    --disable-softvol   disable software volume control (softvol)\n"
    191 "    --test-position     test ring buffer position\n")
    192 		, command);
    193 	printf(_("Recognized sample formats are:"));
    194 	for (k = 0; k < SND_PCM_FORMAT_LAST; ++k) {
    195 		const char *s = snd_pcm_format_name(k);
    196 		if (s)
    197 			printf(" %s", s);
    198 	}
    199 	printf(_("\nSome of these may not be available on selected hardware\n"));
    200 	printf(_("The availabled format shortcuts are:\n"));
    201 	printf(_("-f cd (16 bit little endian, 44100, stereo)\n"));
    202 	printf(_("-f cdr (16 bit big endian, 44100, stereo)\n"));
    203 	printf(_("-f dat (16 bit little endian, 48000, stereo)\n"));
    204 }
    205 
    206 static void device_list(void)
    207 {
    208 	snd_ctl_t *handle;
    209 	int card, err, dev, idx;
    210 	snd_ctl_card_info_t *info;
    211 	snd_pcm_info_t *pcminfo;
    212 	snd_ctl_card_info_alloca(&info);
    213 	snd_pcm_info_alloca(&pcminfo);
    214 
    215 	card = -1;
    216 	if (snd_card_next(&card) < 0 || card < 0) {
    217 		error(_("no soundcards found..."));
    218 		return;
    219 	}
    220 	printf(_("**** List of %s Hardware Devices ****\n"),
    221 	       snd_pcm_stream_name(stream));
    222 	while (card >= 0) {
    223 		char name[32];
    224 		sprintf(name, "hw:%d", card);
    225 		if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
    226 			error("control open (%i): %s", card, snd_strerror(err));
    227 			goto next_card;
    228 		}
    229 		if ((err = snd_ctl_card_info(handle, info)) < 0) {
    230 			error("control hardware info (%i): %s", card, snd_strerror(err));
    231 			snd_ctl_close(handle);
    232 			goto next_card;
    233 		}
    234 		dev = -1;
    235 		while (1) {
    236 			unsigned int count;
    237 			if (snd_ctl_pcm_next_device(handle, &dev)<0)
    238 				error("snd_ctl_pcm_next_device");
    239 			if (dev < 0)
    240 				break;
    241 			snd_pcm_info_set_device(pcminfo, dev);
    242 			snd_pcm_info_set_subdevice(pcminfo, 0);
    243 			snd_pcm_info_set_stream(pcminfo, stream);
    244 			if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
    245 				if (err != -ENOENT)
    246 					error("control digital audio info (%i): %s", card, snd_strerror(err));
    247 				continue;
    248 			}
    249 			printf(_("card %i: %s [%s], device %i: %s [%s]\n"),
    250 				card, snd_ctl_card_info_get_id(info), snd_ctl_card_info_get_name(info),
    251 				dev,
    252 				snd_pcm_info_get_id(pcminfo),
    253 				snd_pcm_info_get_name(pcminfo));
    254 			count = snd_pcm_info_get_subdevices_count(pcminfo);
    255 			printf( _("  Subdevices: %i/%i\n"),
    256 				snd_pcm_info_get_subdevices_avail(pcminfo), count);
    257 			for (idx = 0; idx < (int)count; idx++) {
    258 				snd_pcm_info_set_subdevice(pcminfo, idx);
    259 				if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
    260 					error("control digital audio playback info (%i): %s", card, snd_strerror(err));
    261 				} else {
    262 					printf(_("  Subdevice #%i: %s\n"),
    263 						idx, snd_pcm_info_get_subdevice_name(pcminfo));
    264 				}
    265 			}
    266 		}
    267 		snd_ctl_close(handle);
    268 	next_card:
    269 		if (snd_card_next(&card) < 0) {
    270 			error("snd_card_next");
    271 			break;
    272 		}
    273 	}
    274 }
    275 
    276 static void pcm_list(void)
    277 {
    278 	void **hints, **n;
    279 	char *name, *descr, *descr1, *io;
    280 	const char *filter;
    281 
    282 	if (snd_device_name_hint(-1, "pcm", &hints) < 0)
    283 		return;
    284 	n = hints;
    285 	filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";
    286 	while (*n != NULL) {
    287 		name = snd_device_name_get_hint(*n, "NAME");
    288 		descr = snd_device_name_get_hint(*n, "DESC");
    289 		io = snd_device_name_get_hint(*n, "IOID");
    290 		if (io != NULL && strcmp(io, filter) != 0)
    291 			goto __end;
    292 		printf("%s\n", name);
    293 		if ((descr1 = descr) != NULL) {
    294 			printf("    ");
    295 			while (*descr1) {
    296 				if (*descr1 == '\n')
    297 					printf("\n    ");
    298 				else
    299 					putchar(*descr1);
    300 				descr1++;
    301 			}
    302 			putchar('\n');
    303 		}
    304 	      __end:
    305 	      	if (name != NULL)
    306 	      		free(name);
    307 		if (descr != NULL)
    308 			free(descr);
    309 		if (io != NULL)
    310 			free(io);
    311 		n++;
    312 	}
    313 	snd_device_name_free_hint(hints);
    314 }
    315 
    316 static void version(void)
    317 {
    318 	printf("%s: version " SND_UTIL_VERSION_STR " by Jaroslav Kysela <perex (at) perex.cz>\n", command);
    319 }
    320 
    321 static void signal_handler(int sig)
    322 {
    323 	if (verbose==2)
    324 		putchar('\n');
    325 	if (!quiet_mode)
    326 		fprintf(stderr, _("Aborted by signal %s...\n"), strsignal(sig));
    327 	if (stream == SND_PCM_STREAM_CAPTURE) {
    328 		if (fmt_rec_table[file_type].end) {
    329 			fmt_rec_table[file_type].end(fd);
    330 			fd = -1;
    331 		}
    332 		stream = -1;
    333 	}
    334 	if (fd > 1) {
    335 		close(fd);
    336 		fd = -1;
    337 	}
    338 	if (handle && sig != SIGABRT) {
    339 		snd_pcm_close(handle);
    340 		handle = NULL;
    341 	}
    342 	exit(EXIT_FAILURE);
    343 }
    344 
    345 enum {
    346 	OPT_VERSION = 1,
    347 	OPT_PERIOD_SIZE,
    348 	OPT_BUFFER_SIZE,
    349 	OPT_DISABLE_RESAMPLE,
    350 	OPT_DISABLE_CHANNELS,
    351 	OPT_DISABLE_FORMAT,
    352 	OPT_DISABLE_SOFTVOL,
    353 	OPT_TEST_POSITION
    354 };
    355 
    356 int main(int argc, char *argv[])
    357 {
    358 	int option_index;
    359 	static const char short_options[] = "hnlLD:qt:c:f:r:d:MNF:A:R:T:B:vV:IPC";
    360 	static const struct option long_options[] = {
    361 		{"help", 0, 0, 'h'},
    362 		{"version", 0, 0, OPT_VERSION},
    363 		{"list-devnames", 0, 0, 'n'},
    364 		{"list-devices", 0, 0, 'l'},
    365 		{"list-pcms", 0, 0, 'L'},
    366 		{"device", 1, 0, 'D'},
    367 		{"quiet", 0, 0, 'q'},
    368 		{"file-type", 1, 0, 't'},
    369 		{"channels", 1, 0, 'c'},
    370 		{"format", 1, 0, 'f'},
    371 		{"rate", 1, 0, 'r'},
    372 		{"duration", 1, 0 ,'d'},
    373 		{"mmap", 0, 0, 'M'},
    374 		{"nonblock", 0, 0, 'N'},
    375 		{"period-time", 1, 0, 'F'},
    376 		{"period-size", 1, 0, OPT_PERIOD_SIZE},
    377 		{"avail-min", 1, 0, 'A'},
    378 		{"start-delay", 1, 0, 'R'},
    379 		{"stop-delay", 1, 0, 'T'},
    380 		{"buffer-time", 1, 0, 'B'},
    381 		{"buffer-size", 1, 0, OPT_BUFFER_SIZE},
    382 		{"verbose", 0, 0, 'v'},
    383 		{"vumeter", 1, 0, 'V'},
    384 		{"separate-channels", 0, 0, 'I'},
    385 		{"playback", 0, 0, 'P'},
    386 		{"capture", 0, 0, 'C'},
    387 		{"disable-resample", 0, 0, OPT_DISABLE_RESAMPLE},
    388 		{"disable-channels", 0, 0, OPT_DISABLE_CHANNELS},
    389 		{"disable-format", 0, 0, OPT_DISABLE_FORMAT},
    390 		{"disable-softvol", 0, 0, OPT_DISABLE_SOFTVOL},
    391 		{"test-position", 0, 0, OPT_TEST_POSITION},
    392 		{0, 0, 0, 0}
    393 	};
    394 	char *pcm_name = "default";
    395 	int tmp, err, c;
    396 	int do_device_list = 0, do_pcm_list = 0;
    397 	snd_pcm_info_t *info;
    398 
    399 #ifdef ENABLE_NLS
    400 	setlocale(LC_ALL, "");
    401 	textdomain(PACKAGE);
    402 #endif
    403 
    404 	snd_pcm_info_alloca(&info);
    405 
    406 	err = snd_output_stdio_attach(&log, stderr, 0);
    407 	assert(err >= 0);
    408 
    409 	command = argv[0];
    410 	file_type = FORMAT_DEFAULT;
    411 	if (strstr(argv[0], "arecord")) {
    412 		stream = SND_PCM_STREAM_CAPTURE;
    413 		file_type = FORMAT_WAVE;
    414 		command = "arecord";
    415 		start_delay = 1;
    416 	} else if (strstr(argv[0], "aplay")) {
    417 		stream = SND_PCM_STREAM_PLAYBACK;
    418 		command = "aplay";
    419 	} else {
    420 		error(_("command should be named either arecord or aplay"));
    421 		return 1;
    422 	}
    423 
    424 	chunk_size = -1;
    425 	rhwparams.format = DEFAULT_FORMAT;
    426 	rhwparams.rate = DEFAULT_SPEED;
    427 	rhwparams.channels = 1;
    428 
    429 	while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) {
    430 		switch (c) {
    431 		case 'h':
    432 			usage(command);
    433 			return 0;
    434 		case OPT_VERSION:
    435 			version();
    436 			return 0;
    437 		case 'l':
    438 			do_device_list = 1;
    439 			break;
    440 		case 'L':
    441 			do_pcm_list = 1;
    442 			break;
    443 		case 'D':
    444 			pcm_name = optarg;
    445 			break;
    446 		case 'q':
    447 			quiet_mode = 1;
    448 			break;
    449 		case 't':
    450 			if (strcasecmp(optarg, "raw") == 0)
    451 				file_type = FORMAT_RAW;
    452 			else if (strcasecmp(optarg, "voc") == 0)
    453 				file_type = FORMAT_VOC;
    454 			else if (strcasecmp(optarg, "wav") == 0)
    455 				file_type = FORMAT_WAVE;
    456 			else if (strcasecmp(optarg, "au") == 0 || strcasecmp(optarg, "sparc") == 0)
    457 				file_type = FORMAT_AU;
    458 			else {
    459 				error(_("unrecognized file format %s"), optarg);
    460 				return 1;
    461 			}
    462 			break;
    463 		case 'c':
    464 			rhwparams.channels = strtol(optarg, NULL, 0);
    465 			if (rhwparams.channels < 1 || rhwparams.channels > 32) {
    466 				error(_("value %i for channels is invalid"), rhwparams.channels);
    467 				return 1;
    468 			}
    469 			break;
    470 		case 'f':
    471 			if (strcasecmp(optarg, "cd") == 0 || strcasecmp(optarg, "cdr") == 0) {
    472 				if (strcasecmp(optarg, "cdr") == 0)
    473 					rhwparams.format = SND_PCM_FORMAT_S16_BE;
    474 				else
    475 					rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
    476 				rhwparams.rate = 44100;
    477 				rhwparams.channels = 2;
    478 			} else if (strcasecmp(optarg, "dat") == 0) {
    479 				rhwparams.format = file_type == FORMAT_AU ? SND_PCM_FORMAT_S16_BE : SND_PCM_FORMAT_S16_LE;
    480 				rhwparams.rate = 48000;
    481 				rhwparams.channels = 2;
    482 			} else {
    483 				rhwparams.format = snd_pcm_format_value(optarg);
    484 				if (rhwparams.format == SND_PCM_FORMAT_UNKNOWN) {
    485 					error(_("wrong extended format '%s'"), optarg);
    486 					exit(EXIT_FAILURE);
    487 				}
    488 			}
    489 			break;
    490 		case 'r':
    491 			tmp = strtol(optarg, NULL, 0);
    492 			if (tmp < 300)
    493 				tmp *= 1000;
    494 			rhwparams.rate = tmp;
    495 			if (tmp < 2000 || tmp > 192000) {
    496 				error(_("bad speed value %i"), tmp);
    497 				return 1;
    498 			}
    499 			break;
    500 		case 'd':
    501 			timelimit = strtol(optarg, NULL, 0);
    502 			break;
    503 		case 'N':
    504 			nonblock = 1;
    505 			open_mode |= SND_PCM_NONBLOCK;
    506 			break;
    507 		case 'F':
    508 			period_time = strtol(optarg, NULL, 0);
    509 			break;
    510 		case 'B':
    511 			buffer_time = strtol(optarg, NULL, 0);
    512 			break;
    513 		case OPT_PERIOD_SIZE:
    514 			period_frames = strtol(optarg, NULL, 0);
    515 			break;
    516 		case OPT_BUFFER_SIZE:
    517 			buffer_frames = strtol(optarg, NULL, 0);
    518 			break;
    519 		case 'A':
    520 			avail_min = strtol(optarg, NULL, 0);
    521 			break;
    522 		case 'R':
    523 			start_delay = strtol(optarg, NULL, 0);
    524 			break;
    525 		case 'T':
    526 			stop_delay = strtol(optarg, NULL, 0);
    527 			break;
    528 		case 'v':
    529 			verbose++;
    530 			if (verbose > 1 && !vumeter)
    531 				vumeter = VUMETER_MONO;
    532 			break;
    533 		case 'V':
    534 			if (*optarg == 's')
    535 				vumeter = VUMETER_STEREO;
    536 			else if (*optarg == 'm')
    537 				vumeter = VUMETER_MONO;
    538 			else
    539 				vumeter = VUMETER_NONE;
    540 			break;
    541 		case 'M':
    542 			mmap_flag = 1;
    543 			break;
    544 		case 'I':
    545 			interleaved = 0;
    546 			break;
    547 		case 'P':
    548 			stream = SND_PCM_STREAM_PLAYBACK;
    549 			command = "aplay";
    550 			break;
    551 		case 'C':
    552 			stream = SND_PCM_STREAM_CAPTURE;
    553 			command = "arecord";
    554 			start_delay = 1;
    555 			if (file_type == FORMAT_DEFAULT)
    556 				file_type = FORMAT_WAVE;
    557 			break;
    558 		case OPT_DISABLE_RESAMPLE:
    559 			open_mode |= SND_PCM_NO_AUTO_RESAMPLE;
    560 			break;
    561 		case OPT_DISABLE_CHANNELS:
    562 			open_mode |= SND_PCM_NO_AUTO_CHANNELS;
    563 			break;
    564 		case OPT_DISABLE_FORMAT:
    565 			open_mode |= SND_PCM_NO_AUTO_FORMAT;
    566 			break;
    567 		case OPT_DISABLE_SOFTVOL:
    568 			open_mode |= SND_PCM_NO_SOFTVOL;
    569 			break;
    570 		case OPT_TEST_POSITION:
    571 			test_position = 1;
    572 			break;
    573 		default:
    574 			fprintf(stderr, _("Try `%s --help' for more information.\n"), command);
    575 			return 1;
    576 		}
    577 	}
    578 
    579 	if (do_device_list) {
    580 		if (do_pcm_list) pcm_list();
    581 		device_list();
    582 		goto __end;
    583 	} else if (do_pcm_list) {
    584 		pcm_list();
    585 		goto __end;
    586 	}
    587 
    588 	err = snd_pcm_open(&handle, pcm_name, stream, open_mode);
    589 	if (err < 0) {
    590 		error(_("audio open error: %s"), snd_strerror(err));
    591 		return 1;
    592 	}
    593 
    594 	if ((err = snd_pcm_info(handle, info)) < 0) {
    595 		error(_("info error: %s"), snd_strerror(err));
    596 		return 1;
    597 	}
    598 
    599 	if (nonblock) {
    600 		err = snd_pcm_nonblock(handle, 1);
    601 		if (err < 0) {
    602 			error(_("nonblock setting error: %s"), snd_strerror(err));
    603 			return 1;
    604 		}
    605 	}
    606 
    607 	chunk_size = 1024;
    608 	hwparams = rhwparams;
    609 
    610 	audiobuf = (u_char *)malloc(1024);
    611 	if (audiobuf == NULL) {
    612 		error(_("not enough memory"));
    613 		return 1;
    614 	}
    615 
    616 	if (mmap_flag) {
    617 		writei_func = snd_pcm_mmap_writei;
    618 		readi_func = snd_pcm_mmap_readi;
    619 		writen_func = snd_pcm_mmap_writen;
    620 		readn_func = snd_pcm_mmap_readn;
    621 	} else {
    622 		writei_func = snd_pcm_writei;
    623 		readi_func = snd_pcm_readi;
    624 		writen_func = snd_pcm_writen;
    625 		readn_func = snd_pcm_readn;
    626 	}
    627 
    628 
    629 	signal(SIGINT, signal_handler);
    630 	signal(SIGTERM, signal_handler);
    631 	signal(SIGABRT, signal_handler);
    632 	if (interleaved) {
    633 		if (optind > argc - 1) {
    634 			if (stream == SND_PCM_STREAM_PLAYBACK)
    635 				playback(NULL);
    636 			else
    637 				capture(NULL);
    638 		} else {
    639 			while (optind <= argc - 1) {
    640 				if (stream == SND_PCM_STREAM_PLAYBACK)
    641 					playback(argv[optind++]);
    642 				else
    643 					capture(argv[optind++]);
    644 			}
    645 		}
    646 	} else {
    647 		if (stream == SND_PCM_STREAM_PLAYBACK)
    648 			playbackv(&argv[optind], argc - optind);
    649 		else
    650 			capturev(&argv[optind], argc - optind);
    651 	}
    652 	if (verbose==2)
    653 		putchar('\n');
    654 	snd_pcm_close(handle);
    655 	free(audiobuf);
    656       __end:
    657 	snd_output_close(log);
    658 	snd_config_update_free_global();
    659 	return EXIT_SUCCESS;
    660 }
    661 
    662 /*
    663  * Safe read (for pipes)
    664  */
    665 
    666 static ssize_t safe_read(int fd, void *buf, size_t count)
    667 {
    668 	ssize_t result = 0, res;
    669 
    670 	while (count > 0) {
    671 		if ((res = read(fd, buf, count)) == 0)
    672 			break;
    673 		if (res < 0)
    674 			return result > 0 ? result : res;
    675 		count -= res;
    676 		result += res;
    677 		buf = (char *)buf + res;
    678 	}
    679 	return result;
    680 }
    681 
    682 /*
    683  * Test, if it is a .VOC file and return >=0 if ok (this is the length of rest)
    684  *                                       < 0 if not
    685  */
    686 static int test_vocfile(void *buffer)
    687 {
    688 	VocHeader *vp = buffer;
    689 
    690 	if (!memcmp(vp->magic, VOC_MAGIC_STRING, 20)) {
    691 		vocminor = LE_SHORT(vp->version) & 0xFF;
    692 		vocmajor = LE_SHORT(vp->version) / 256;
    693 		if (LE_SHORT(vp->version) != (0x1233 - LE_SHORT(vp->coded_ver)))
    694 			return -2;	/* coded version mismatch */
    695 		return LE_SHORT(vp->headerlen) - sizeof(VocHeader);	/* 0 mostly */
    696 	}
    697 	return -1;		/* magic string fail */
    698 }
    699 
    700 /*
    701  * helper for test_wavefile
    702  */
    703 
    704 static size_t test_wavefile_read(int fd, u_char *buffer, size_t *size, size_t reqsize, int line)
    705 {
    706 	if (*size >= reqsize)
    707 		return *size;
    708 	if ((size_t)safe_read(fd, buffer + *size, reqsize - *size) != reqsize - *size) {
    709 		error(_("read error (called from line %i)"), line);
    710 		exit(EXIT_FAILURE);
    711 	}
    712 	return *size = reqsize;
    713 }
    714 
    715 #define check_wavefile_space(buffer, len, blimit) \
    716 	if (len > blimit) { \
    717 		blimit = len; \
    718 		if ((buffer = realloc(buffer, blimit)) == NULL) { \
    719 			error(_("not enough memory"));		  \
    720 			exit(EXIT_FAILURE); \
    721 		} \
    722 	}
    723 
    724 /*
    725  * test, if it's a .WAV file, > 0 if ok (and set the speed, stereo etc.)
    726  *                            == 0 if not
    727  * Value returned is bytes to be discarded.
    728  */
    729 static ssize_t test_wavefile(int fd, u_char *_buffer, size_t size)
    730 {
    731 	WaveHeader *h = (WaveHeader *)_buffer;
    732 	u_char *buffer = NULL;
    733 	size_t blimit = 0;
    734 	WaveFmtBody *f;
    735 	WaveChunkHeader *c;
    736 	u_int type, len;
    737 
    738 	if (size < sizeof(WaveHeader))
    739 		return -1;
    740 	if (h->magic != WAV_RIFF || h->type != WAV_WAVE)
    741 		return -1;
    742 	if (size > sizeof(WaveHeader)) {
    743 		check_wavefile_space(buffer, size - sizeof(WaveHeader), blimit);
    744 		memcpy(buffer, _buffer + sizeof(WaveHeader), size - sizeof(WaveHeader));
    745 	}
    746 	size -= sizeof(WaveHeader);
    747 	while (1) {
    748 		check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
    749 		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
    750 		c = (WaveChunkHeader*)buffer;
    751 		type = c->type;
    752 		len = LE_INT(c->length);
    753 		len += len % 2;
    754 		if (size > sizeof(WaveChunkHeader))
    755 			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
    756 		size -= sizeof(WaveChunkHeader);
    757 		if (type == WAV_FMT)
    758 			break;
    759 		check_wavefile_space(buffer, len, blimit);
    760 		test_wavefile_read(fd, buffer, &size, len, __LINE__);
    761 		if (size > len)
    762 			memmove(buffer, buffer + len, size - len);
    763 		size -= len;
    764 	}
    765 
    766 	if (len < sizeof(WaveFmtBody)) {
    767 		error(_("unknown length of 'fmt ' chunk (read %u, should be %u at least)"),
    768 		      len, (u_int)sizeof(WaveFmtBody));
    769 		exit(EXIT_FAILURE);
    770 	}
    771 	check_wavefile_space(buffer, len, blimit);
    772 	test_wavefile_read(fd, buffer, &size, len, __LINE__);
    773 	f = (WaveFmtBody*) buffer;
    774 	if (LE_SHORT(f->format) == WAV_FMT_EXTENSIBLE) {
    775 		WaveFmtExtensibleBody *fe = (WaveFmtExtensibleBody*)buffer;
    776 		if (len < sizeof(WaveFmtExtensibleBody)) {
    777 			error(_("unknown length of extensible 'fmt ' chunk (read %u, should be %u at least)"),
    778 					len, (u_int)sizeof(WaveFmtExtensibleBody));
    779 			exit(EXIT_FAILURE);
    780 		}
    781 		if (memcmp(fe->guid_tag, WAV_GUID_TAG, 14) != 0) {
    782 			error(_("wrong format tag in extensible 'fmt ' chunk"));
    783 			exit(EXIT_FAILURE);
    784 		}
    785 		f->format = fe->guid_format;
    786 	}
    787         if (LE_SHORT(f->format) != WAV_FMT_PCM &&
    788             LE_SHORT(f->format) != WAV_FMT_IEEE_FLOAT) {
    789                 error(_("can't play WAVE-file format 0x%04x which is not PCM or FLOAT encoded"), LE_SHORT(f->format));
    790 		exit(EXIT_FAILURE);
    791 	}
    792 	if (LE_SHORT(f->channels) < 1) {
    793 		error(_("can't play WAVE-files with %d tracks"), LE_SHORT(f->channels));
    794 		exit(EXIT_FAILURE);
    795 	}
    796 	hwparams.channels = LE_SHORT(f->channels);
    797 	switch (LE_SHORT(f->bit_p_spl)) {
    798 	case 8:
    799 		if (hwparams.format != DEFAULT_FORMAT &&
    800 		    hwparams.format != SND_PCM_FORMAT_U8)
    801 			fprintf(stderr, _("Warning: format is changed to U8\n"));
    802 		hwparams.format = SND_PCM_FORMAT_U8;
    803 		break;
    804 	case 16:
    805 		if (hwparams.format != DEFAULT_FORMAT &&
    806 		    hwparams.format != SND_PCM_FORMAT_S16_LE)
    807 			fprintf(stderr, _("Warning: format is changed to S16_LE\n"));
    808 		hwparams.format = SND_PCM_FORMAT_S16_LE;
    809 		break;
    810 	case 24:
    811 		switch (LE_SHORT(f->byte_p_spl) / hwparams.channels) {
    812 		case 3:
    813 			if (hwparams.format != DEFAULT_FORMAT &&
    814 			    hwparams.format != SND_PCM_FORMAT_S24_3LE)
    815 				fprintf(stderr, _("Warning: format is changed to S24_3LE\n"));
    816 			hwparams.format = SND_PCM_FORMAT_S24_3LE;
    817 			break;
    818 		case 4:
    819 			if (hwparams.format != DEFAULT_FORMAT &&
    820 			    hwparams.format != SND_PCM_FORMAT_S24_LE)
    821 				fprintf(stderr, _("Warning: format is changed to S24_LE\n"));
    822 			hwparams.format = SND_PCM_FORMAT_S24_LE;
    823 			break;
    824 		default:
    825 			error(_(" can't play WAVE-files with sample %d bits in %d bytes wide (%d channels)"),
    826 			      LE_SHORT(f->bit_p_spl), LE_SHORT(f->byte_p_spl), hwparams.channels);
    827 			exit(EXIT_FAILURE);
    828 		}
    829 		break;
    830 	case 32:
    831                 if (LE_SHORT(f->format) == WAV_FMT_PCM)
    832                         hwparams.format = SND_PCM_FORMAT_S32_LE;
    833                 else if (LE_SHORT(f->format) == WAV_FMT_IEEE_FLOAT)
    834                         hwparams.format = SND_PCM_FORMAT_FLOAT_LE;
    835 		break;
    836 	default:
    837 		error(_(" can't play WAVE-files with sample %d bits wide"),
    838 		      LE_SHORT(f->bit_p_spl));
    839 		exit(EXIT_FAILURE);
    840 	}
    841 	hwparams.rate = LE_INT(f->sample_fq);
    842 
    843 	if (size > len)
    844 		memmove(buffer, buffer + len, size - len);
    845 	size -= len;
    846 
    847 	while (1) {
    848 		u_int type, len;
    849 
    850 		check_wavefile_space(buffer, sizeof(WaveChunkHeader), blimit);
    851 		test_wavefile_read(fd, buffer, &size, sizeof(WaveChunkHeader), __LINE__);
    852 		c = (WaveChunkHeader*)buffer;
    853 		type = c->type;
    854 		len = LE_INT(c->length);
    855 		if (size > sizeof(WaveChunkHeader))
    856 			memmove(buffer, buffer + sizeof(WaveChunkHeader), size - sizeof(WaveChunkHeader));
    857 		size -= sizeof(WaveChunkHeader);
    858 		if (type == WAV_DATA) {
    859 			if (len < pbrec_count && len < 0x7ffffffe)
    860 				pbrec_count = len;
    861 			if (size > 0)
    862 				memcpy(_buffer, buffer, size);
    863 			free(buffer);
    864 			return size;
    865 		}
    866 		len += len % 2;
    867 		check_wavefile_space(buffer, len, blimit);
    868 		test_wavefile_read(fd, buffer, &size, len, __LINE__);
    869 		if (size > len)
    870 			memmove(buffer, buffer + len, size - len);
    871 		size -= len;
    872 	}
    873 
    874 	/* shouldn't be reached */
    875 	return -1;
    876 }
    877 
    878 /*
    879 
    880  */
    881 
    882 static int test_au(int fd, void *buffer)
    883 {
    884 	AuHeader *ap = buffer;
    885 
    886 	if (ap->magic != AU_MAGIC)
    887 		return -1;
    888 	if (BE_INT(ap->hdr_size) > 128 || BE_INT(ap->hdr_size) < 24)
    889 		return -1;
    890 	pbrec_count = BE_INT(ap->data_size);
    891 	switch (BE_INT(ap->encoding)) {
    892 	case AU_FMT_ULAW:
    893 		if (hwparams.format != DEFAULT_FORMAT &&
    894 		    hwparams.format != SND_PCM_FORMAT_MU_LAW)
    895 			fprintf(stderr, _("Warning: format is changed to MU_LAW\n"));
    896 		hwparams.format = SND_PCM_FORMAT_MU_LAW;
    897 		break;
    898 	case AU_FMT_LIN8:
    899 		if (hwparams.format != DEFAULT_FORMAT &&
    900 		    hwparams.format != SND_PCM_FORMAT_U8)
    901 			fprintf(stderr, _("Warning: format is changed to U8\n"));
    902 		hwparams.format = SND_PCM_FORMAT_U8;
    903 		break;
    904 	case AU_FMT_LIN16:
    905 		if (hwparams.format != DEFAULT_FORMAT &&
    906 		    hwparams.format != SND_PCM_FORMAT_S16_BE)
    907 			fprintf(stderr, _("Warning: format is changed to S16_BE\n"));
    908 		hwparams.format = SND_PCM_FORMAT_S16_BE;
    909 		break;
    910 	default:
    911 		return -1;
    912 	}
    913 	hwparams.rate = BE_INT(ap->sample_rate);
    914 	if (hwparams.rate < 2000 || hwparams.rate > 256000)
    915 		return -1;
    916 	hwparams.channels = BE_INT(ap->channels);
    917 	if (hwparams.channels < 1 || hwparams.channels > 128)
    918 		return -1;
    919 	if ((size_t)safe_read(fd, buffer + sizeof(AuHeader), BE_INT(ap->hdr_size) - sizeof(AuHeader)) != BE_INT(ap->hdr_size) - sizeof(AuHeader)) {
    920 		error(_("read error"));
    921 		exit(EXIT_FAILURE);
    922 	}
    923 	return 0;
    924 }
    925 
    926 static void set_params(void)
    927 {
    928 	snd_pcm_hw_params_t *params;
    929 	snd_pcm_sw_params_t *swparams;
    930 	snd_pcm_uframes_t buffer_size;
    931 	int err;
    932 	size_t n;
    933 	unsigned int rate;
    934 	snd_pcm_uframes_t start_threshold, stop_threshold;
    935 	snd_pcm_hw_params_alloca(&params);
    936 	snd_pcm_sw_params_alloca(&swparams);
    937 	err = snd_pcm_hw_params_any(handle, params);
    938 	if (err < 0) {
    939 		error(_("Broken configuration for this PCM: no configurations available"));
    940 		exit(EXIT_FAILURE);
    941 	}
    942 	if (mmap_flag) {
    943 		snd_pcm_access_mask_t *mask = alloca(snd_pcm_access_mask_sizeof());
    944 		snd_pcm_access_mask_none(mask);
    945 		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_INTERLEAVED);
    946 		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_NONINTERLEAVED);
    947 		snd_pcm_access_mask_set(mask, SND_PCM_ACCESS_MMAP_COMPLEX);
    948 		err = snd_pcm_hw_params_set_access_mask(handle, params, mask);
    949 	} else if (interleaved)
    950 		err = snd_pcm_hw_params_set_access(handle, params,
    951 						   SND_PCM_ACCESS_RW_INTERLEAVED);
    952 	else
    953 		err = snd_pcm_hw_params_set_access(handle, params,
    954 						   SND_PCM_ACCESS_RW_NONINTERLEAVED);
    955 	if (err < 0) {
    956 		error(_("Access type not available"));
    957 		exit(EXIT_FAILURE);
    958 	}
    959 	err = snd_pcm_hw_params_set_format(handle, params, hwparams.format);
    960 	if (err < 0) {
    961 		error(_("Sample format non available"));
    962 		exit(EXIT_FAILURE);
    963 	}
    964 	err = snd_pcm_hw_params_set_channels(handle, params, hwparams.channels);
    965 	if (err < 0) {
    966 		error(_("Channels count non available"));
    967 		exit(EXIT_FAILURE);
    968 	}
    969 
    970 #if 0
    971 	err = snd_pcm_hw_params_set_periods_min(handle, params, 2);
    972 	assert(err >= 0);
    973 #endif
    974 	rate = hwparams.rate;
    975 	err = snd_pcm_hw_params_set_rate_near(handle, params, &hwparams.rate, 0);
    976 	assert(err >= 0);
    977 	if ((float)rate * 1.05 < hwparams.rate || (float)rate * 0.95 > hwparams.rate) {
    978 		if (!quiet_mode) {
    979 			char plugex[64];
    980 			const char *pcmname = snd_pcm_name(handle);
    981 			fprintf(stderr, _("Warning: rate is not accurate (requested = %iHz, got = %iHz)\n"), rate, hwparams.rate);
    982 			if (! pcmname || strchr(snd_pcm_name(handle), ':'))
    983 				*plugex = 0;
    984 			else
    985 				snprintf(plugex, sizeof(plugex), "(-Dplug:%s)",
    986 					 snd_pcm_name(handle));
    987 			fprintf(stderr, _("         please, try the plug plugin %s\n"),
    988 				plugex);
    989 		}
    990 	}
    991 	rate = hwparams.rate;
    992 	if (buffer_time == 0 && buffer_frames == 0) {
    993 		err = snd_pcm_hw_params_get_buffer_time_max(params,
    994 							    &buffer_time, 0);
    995 		assert(err >= 0);
    996 		if (buffer_time > 500000)
    997 			buffer_time = 500000;
    998 	}
    999 	if (period_time == 0 && period_frames == 0) {
   1000 		if (buffer_time > 0)
   1001 			period_time = buffer_time / 4;
   1002 		else
   1003 			period_frames = buffer_frames / 4;
   1004 	}
   1005 	if (period_time > 0)
   1006 		err = snd_pcm_hw_params_set_period_time_near(handle, params,
   1007 							     &period_time, 0);
   1008 	else
   1009 		err = snd_pcm_hw_params_set_period_size_near(handle, params,
   1010 							     &period_frames, 0);
   1011 	assert(err >= 0);
   1012 	if (buffer_time > 0) {
   1013 		err = snd_pcm_hw_params_set_buffer_time_near(handle, params,
   1014 							     &buffer_time, 0);
   1015 	} else {
   1016 		err = snd_pcm_hw_params_set_buffer_size_near(handle, params,
   1017 							     &buffer_frames);
   1018 	}
   1019 	assert(err >= 0);
   1020 	err = snd_pcm_hw_params(handle, params);
   1021 	if (err < 0) {
   1022 		error(_("Unable to install hw params:"));
   1023 		snd_pcm_hw_params_dump(params, log);
   1024 		exit(EXIT_FAILURE);
   1025 	}
   1026 	snd_pcm_hw_params_get_period_size(params, &chunk_size, 0);
   1027 	snd_pcm_hw_params_get_buffer_size(params, &buffer_size);
   1028 	if (chunk_size == buffer_size) {
   1029 		error(_("Can't use period equal to buffer size (%lu == %lu)"),
   1030 		      chunk_size, buffer_size);
   1031 		exit(EXIT_FAILURE);
   1032 	}
   1033 	snd_pcm_sw_params_current(handle, swparams);
   1034 	if (avail_min < 0)
   1035 		n = chunk_size;
   1036 	else
   1037 		n = (double) rate * avail_min / 1000000;
   1038 	err = snd_pcm_sw_params_set_avail_min(handle, swparams, n);
   1039 
   1040 	/* round up to closest transfer boundary */
   1041 	n = buffer_size;
   1042 	if (start_delay <= 0) {
   1043 		start_threshold = n + (double) rate * start_delay / 1000000;
   1044 	} else
   1045 		start_threshold = (double) rate * start_delay / 1000000;
   1046 	if (start_threshold < 1)
   1047 		start_threshold = 1;
   1048 	if (start_threshold > n)
   1049 		start_threshold = n;
   1050 	err = snd_pcm_sw_params_set_start_threshold(handle, swparams, start_threshold);
   1051 	assert(err >= 0);
   1052 	if (stop_delay <= 0)
   1053 		stop_threshold = buffer_size + (double) rate * stop_delay / 1000000;
   1054 	else
   1055 		stop_threshold = (double) rate * stop_delay / 1000000;
   1056 	err = snd_pcm_sw_params_set_stop_threshold(handle, swparams, stop_threshold);
   1057 	assert(err >= 0);
   1058 
   1059 	if (snd_pcm_sw_params(handle, swparams) < 0) {
   1060 		error(_("unable to install sw params:"));
   1061 		snd_pcm_sw_params_dump(swparams, log);
   1062 		exit(EXIT_FAILURE);
   1063 	}
   1064 
   1065 	if (verbose)
   1066 		snd_pcm_dump(handle, log);
   1067 
   1068 	bits_per_sample = snd_pcm_format_physical_width(hwparams.format);
   1069 	bits_per_frame = bits_per_sample * hwparams.channels;
   1070 	chunk_bytes = chunk_size * bits_per_frame / 8;
   1071 	audiobuf = realloc(audiobuf, chunk_bytes);
   1072 	if (audiobuf == NULL) {
   1073 		error(_("not enough memory"));
   1074 		exit(EXIT_FAILURE);
   1075 	}
   1076 	// fprintf(stderr, "real chunk_size = %i, frags = %i, total = %i\n", chunk_size, setup.buf.block.frags, setup.buf.block.frags * chunk_size);
   1077 
   1078 	/* stereo VU-meter isn't always available... */
   1079 	if (vumeter == VUMETER_STEREO) {
   1080 		if (hwparams.channels != 2 || !interleaved || verbose > 2)
   1081 			vumeter = VUMETER_MONO;
   1082 	}
   1083 
   1084 	/* show mmap buffer arragment */
   1085 	if (mmap_flag && verbose) {
   1086 		const snd_pcm_channel_area_t *areas;
   1087 		snd_pcm_uframes_t offset;
   1088 		int i;
   1089 		err = snd_pcm_mmap_begin(handle, &areas, &offset, &chunk_size);
   1090 		if (err < 0) {
   1091 			error("snd_pcm_mmap_begin problem: %s", snd_strerror(err));
   1092 			exit(EXIT_FAILURE);
   1093 		}
   1094 		for (i = 0; i < hwparams.channels; i++)
   1095 			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));
   1096 		/* not required, but for sure */
   1097 		snd_pcm_mmap_commit(handle, offset, 0);
   1098 	}
   1099 
   1100 	buffer_frames = buffer_size;	/* for position test */
   1101 }
   1102 
   1103 #ifndef timersub
   1104 #define	timersub(a, b, result) \
   1105 do { \
   1106 	(result)->tv_sec = (a)->tv_sec - (b)->tv_sec; \
   1107 	(result)->tv_usec = (a)->tv_usec - (b)->tv_usec; \
   1108 	if ((result)->tv_usec < 0) { \
   1109 		--(result)->tv_sec; \
   1110 		(result)->tv_usec += 1000000; \
   1111 	} \
   1112 } while (0)
   1113 #endif
   1114 
   1115 /* I/O error handler */
   1116 static void xrun(void)
   1117 {
   1118 	snd_pcm_status_t *status;
   1119 	int res;
   1120 
   1121 	snd_pcm_status_alloca(&status);
   1122 	if ((res = snd_pcm_status(handle, status))<0) {
   1123 		error(_("status error: %s"), snd_strerror(res));
   1124 		exit(EXIT_FAILURE);
   1125 	}
   1126 	if (snd_pcm_status_get_state(status) == SND_PCM_STATE_XRUN) {
   1127 		struct timeval now, diff, tstamp;
   1128 		gettimeofday(&now, 0);
   1129 		snd_pcm_status_get_trigger_tstamp(status, &tstamp);
   1130 		timersub(&now, &tstamp, &diff);
   1131 		fprintf(stderr, _("%s!!! (at least %.3f ms long)\n"),
   1132 			stream == SND_PCM_STREAM_PLAYBACK ? _("underrun") : _("overrun"),
   1133 			diff.tv_sec * 1000 + diff.tv_usec / 1000.0);
   1134 		if (verbose) {
   1135 			fprintf(stderr, _("Status:\n"));
   1136 			snd_pcm_status_dump(status, log);
   1137 		}
   1138 		if ((res = snd_pcm_prepare(handle))<0) {
   1139 			error(_("xrun: prepare error: %s"), snd_strerror(res));
   1140 			exit(EXIT_FAILURE);
   1141 		}
   1142 		return;		/* ok, data should be accepted again */
   1143 	} if (snd_pcm_status_get_state(status) == SND_PCM_STATE_DRAINING) {
   1144 		if (verbose) {
   1145 			fprintf(stderr, _("Status(DRAINING):\n"));
   1146 			snd_pcm_status_dump(status, log);
   1147 		}
   1148 		if (stream == SND_PCM_STREAM_CAPTURE) {
   1149 			fprintf(stderr, _("capture stream format change? attempting recover...\n"));
   1150 			if ((res = snd_pcm_prepare(handle))<0) {
   1151 				error(_("xrun(DRAINING): prepare error: %s"), snd_strerror(res));
   1152 				exit(EXIT_FAILURE);
   1153 			}
   1154 			return;
   1155 		}
   1156 	}
   1157 	if (verbose) {
   1158 		fprintf(stderr, _("Status(R/W):\n"));
   1159 		snd_pcm_status_dump(status, log);
   1160 	}
   1161 	error(_("read/write error, state = %s"), snd_pcm_state_name(snd_pcm_status_get_state(status)));
   1162 	exit(EXIT_FAILURE);
   1163 }
   1164 
   1165 /* I/O suspend handler */
   1166 static void suspend(void)
   1167 {
   1168 	int res;
   1169 
   1170 	if (!quiet_mode)
   1171 		fprintf(stderr, _("Suspended. Trying resume. ")); fflush(stderr);
   1172 	while ((res = snd_pcm_resume(handle)) == -EAGAIN)
   1173 		sleep(1);	/* wait until suspend flag is released */
   1174 	if (res < 0) {
   1175 		if (!quiet_mode)
   1176 			fprintf(stderr, _("Failed. Restarting stream. ")); fflush(stderr);
   1177 		if ((res = snd_pcm_prepare(handle)) < 0) {
   1178 			error(_("suspend: prepare error: %s"), snd_strerror(res));
   1179 			exit(EXIT_FAILURE);
   1180 		}
   1181 	}
   1182 	if (!quiet_mode)
   1183 		fprintf(stderr, _("Done.\n"));
   1184 }
   1185 
   1186 static void print_vu_meter_mono(int perc, int maxperc)
   1187 {
   1188 	const int bar_length = 50;
   1189 	char line[80];
   1190 	int val;
   1191 
   1192 	for (val = 0; val <= perc * bar_length / 100 && val < bar_length; val++)
   1193 		line[val] = '#';
   1194 	for (; val <= maxperc * bar_length / 100 && val < bar_length; val++)
   1195 		line[val] = ' ';
   1196 	line[val] = '+';
   1197 	for (++val; val <= bar_length; val++)
   1198 		line[val] = ' ';
   1199 	if (maxperc > 99)
   1200 		sprintf(line + val, "| MAX");
   1201 	else
   1202 		sprintf(line + val, "| %02i%%", maxperc);
   1203 	fputs(line, stdout);
   1204 	if (perc > 100)
   1205 		printf(_(" !clip  "));
   1206 }
   1207 
   1208 static void print_vu_meter_stereo(int *perc, int *maxperc)
   1209 {
   1210 	const int bar_length = 35;
   1211 	char line[80];
   1212 	int c;
   1213 
   1214 	memset(line, ' ', sizeof(line) - 1);
   1215 	line[bar_length + 3] = '|';
   1216 
   1217 	for (c = 0; c < 2; c++) {
   1218 		int p = perc[c] * bar_length / 100;
   1219 		char tmp[4];
   1220 		if (p > bar_length)
   1221 			p = bar_length;
   1222 		if (c)
   1223 			memset(line + bar_length + 6 + 1, '#', p);
   1224 		else
   1225 			memset(line + bar_length - p - 1, '#', p);
   1226 		p = maxperc[c] * bar_length / 100;
   1227 		if (p > bar_length)
   1228 			p = bar_length;
   1229 		if (c)
   1230 			line[bar_length + 6 + 1 + p] = '+';
   1231 		else
   1232 			line[bar_length - p - 1] = '+';
   1233 		if (maxperc[c] > 99)
   1234 			sprintf(tmp, "MAX");
   1235 		else
   1236 			sprintf(tmp, "%02d%%", maxperc[c]);
   1237 		if (c)
   1238 			memcpy(line + bar_length + 3 + 1, tmp, 3);
   1239 		else
   1240 			memcpy(line + bar_length, tmp, 3);
   1241 	}
   1242 	line[bar_length * 2 + 6 + 2] = 0;
   1243 	fputs(line, stdout);
   1244 }
   1245 
   1246 static void print_vu_meter(signed int *perc, signed int *maxperc)
   1247 {
   1248 	if (vumeter == VUMETER_STEREO)
   1249 		print_vu_meter_stereo(perc, maxperc);
   1250 	else
   1251 		print_vu_meter_mono(*perc, *maxperc);
   1252 }
   1253 
   1254 /* peak handler */
   1255 static void compute_max_peak(u_char *data, size_t count)
   1256 {
   1257 	signed int val, max, perc[2], max_peak[2];
   1258 	static	int	run = 0;
   1259 	size_t ocount = count;
   1260 	int	format_little_endian = snd_pcm_format_little_endian(hwparams.format);
   1261 	int ichans, c;
   1262 
   1263 	if (vumeter == VUMETER_STEREO)
   1264 		ichans = 2;
   1265 	else
   1266 		ichans = 1;
   1267 
   1268 	memset(max_peak, 0, sizeof(max_peak));
   1269 	switch (bits_per_sample) {
   1270 	case 8: {
   1271 		signed char *valp = (signed char *)data;
   1272 		signed char mask = snd_pcm_format_silence(hwparams.format);
   1273 		c = 0;
   1274 		while (count-- > 0) {
   1275 			val = *valp++ ^ mask;
   1276 			val = abs(val);
   1277 			if (max_peak[c] < val)
   1278 				max_peak[c] = val;
   1279 			if (vumeter == VUMETER_STEREO)
   1280 				c = !c;
   1281 		}
   1282 		break;
   1283 	}
   1284 	case 16: {
   1285 		signed short *valp = (signed short *)data;
   1286 		signed short mask = snd_pcm_format_silence_16(hwparams.format);
   1287 		signed short sval;
   1288 
   1289 		count /= 2;
   1290 		c = 0;
   1291 		while (count-- > 0) {
   1292 			if (format_little_endian)
   1293 				sval = __le16_to_cpu(*valp);
   1294 			else
   1295 				sval = __be16_to_cpu(*valp);
   1296 			sval = abs(sval) ^ mask;
   1297 			if (max_peak[c] < sval)
   1298 				max_peak[c] = sval;
   1299 			valp++;
   1300 			if (vumeter == VUMETER_STEREO)
   1301 				c = !c;
   1302 		}
   1303 		break;
   1304 	}
   1305 	case 24: {
   1306 		unsigned char *valp = data;
   1307 		signed int mask = snd_pcm_format_silence_32(hwparams.format);
   1308 
   1309 		count /= 3;
   1310 		c = 0;
   1311 		while (count-- > 0) {
   1312 			if (format_little_endian) {
   1313 				val = valp[0] | (valp[1]<<8) | (valp[2]<<16);
   1314 			} else {
   1315 				val = (valp[0]<<16) | (valp[1]<<8) | valp[2];
   1316 			}
   1317 			/* Correct signed bit in 32-bit value */
   1318 			if (val & (1<<(bits_per_sample-1))) {
   1319 				val |= 0xff<<24;	/* Negate upper bits too */
   1320 			}
   1321 			val = abs(val) ^ mask;
   1322 			if (max_peak[c] < val)
   1323 				max_peak[c] = val;
   1324 			valp += 3;
   1325 			if (vumeter == VUMETER_STEREO)
   1326 				c = !c;
   1327 		}
   1328 		break;
   1329 	}
   1330 	case 32: {
   1331 		signed int *valp = (signed int *)data;
   1332 		signed int mask = snd_pcm_format_silence_32(hwparams.format);
   1333 
   1334 		count /= 4;
   1335 		c = 0;
   1336 		while (count-- > 0) {
   1337 			if (format_little_endian)
   1338 				val = __le32_to_cpu(*valp);
   1339 			else
   1340 				val = __be32_to_cpu(*valp);
   1341 			val = abs(val) ^ mask;
   1342 			if (max_peak[c] < val)
   1343 				max_peak[c] = val;
   1344 			valp++;
   1345 			if (vumeter == VUMETER_STEREO)
   1346 				c = !c;
   1347 		}
   1348 		break;
   1349 	}
   1350 	default:
   1351 		if (run == 0) {
   1352 			fprintf(stderr, _("Unsupported bit size %d.\n"), (int)bits_per_sample);
   1353 			run = 1;
   1354 		}
   1355 		return;
   1356 	}
   1357 	max = 1 << (bits_per_sample-1);
   1358 	if (max <= 0)
   1359 		max = 0x7fffffff;
   1360 
   1361 	for (c = 0; c < ichans; c++) {
   1362 		if (bits_per_sample > 16)
   1363 			perc[c] = max_peak[c] / (max / 100);
   1364 		else
   1365 			perc[c] = max_peak[c] * 100 / max;
   1366 	}
   1367 
   1368 	if (interleaved && verbose <= 2) {
   1369 		static int maxperc[2];
   1370 		static time_t t=0;
   1371 		const time_t tt=time(NULL);
   1372 		if(tt>t) {
   1373 			t=tt;
   1374 			maxperc[0] = 0;
   1375 			maxperc[1] = 0;
   1376 		}
   1377 		for (c = 0; c < ichans; c++)
   1378 			if (perc[c] > maxperc[c])
   1379 				maxperc[c] = perc[c];
   1380 
   1381 		putchar('\r');
   1382 		print_vu_meter(perc, maxperc);
   1383 		fflush(stdout);
   1384 	}
   1385 	else if(verbose==3) {
   1386 		printf(_("Max peak (%li samples): 0x%08x "), (long)ocount, max_peak[0]);
   1387 		for (val = 0; val < 20; val++)
   1388 			if (val <= perc[0] / 5)
   1389 				putchar('#');
   1390 			else
   1391 				putchar(' ');
   1392 		printf(" %i%%\n", perc[0]);
   1393 		fflush(stdout);
   1394 	}
   1395 }
   1396 
   1397 static void do_test_position(void)
   1398 {
   1399 	static int counter = 0;
   1400 	snd_pcm_sframes_t avail, delay;
   1401 	int err;
   1402 
   1403 	err = snd_pcm_avail_delay(handle, &avail, &delay);
   1404 	if (err < 0)
   1405 		return;
   1406 	if (avail > 4 * (snd_pcm_sframes_t)buffer_frames ||
   1407 	    avail < -4 * (snd_pcm_sframes_t)buffer_frames ||
   1408 	    delay > 4 * (snd_pcm_sframes_t)buffer_frames ||
   1409 	    delay < -4 * (snd_pcm_sframes_t)buffer_frames) {
   1410 	  fprintf(stderr, "Suspicious buffer position (%i total): avail = %li, delay = %li, buffer = %li\n", ++counter, (long)avail, (long)delay, (long)buffer_frames);
   1411 	} else if (verbose) {
   1412 	  fprintf(stderr, "Buffer position: %li/%li (%li)\n", (long)avail, (long)delay, (long)buffer_frames);
   1413 	}
   1414 }
   1415 
   1416 /*
   1417  *  write function
   1418  */
   1419 
   1420 static ssize_t pcm_write(u_char *data, size_t count)
   1421 {
   1422 	ssize_t r;
   1423 	ssize_t result = 0;
   1424 
   1425 	if (count < chunk_size) {
   1426 		snd_pcm_format_set_silence(hwparams.format, data + count * bits_per_frame / 8, (chunk_size - count) * hwparams.channels);
   1427 		count = chunk_size;
   1428 	}
   1429 	while (count > 0) {
   1430 		if (test_position)
   1431 			do_test_position();
   1432 		r = writei_func(handle, data, count);
   1433 		if (test_position)
   1434 			do_test_position();
   1435 		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
   1436 			snd_pcm_wait(handle, 1000);
   1437 		} else if (r == -EPIPE) {
   1438 			xrun();
   1439 		} else if (r == -ESTRPIPE) {
   1440 			suspend();
   1441 		} else if (r < 0) {
   1442 			error(_("write error: %s"), snd_strerror(r));
   1443 			exit(EXIT_FAILURE);
   1444 		}
   1445 		if (r > 0) {
   1446 			if (vumeter)
   1447 				compute_max_peak(data, r * hwparams.channels);
   1448 			result += r;
   1449 			count -= r;
   1450 			data += r * bits_per_frame / 8;
   1451 		}
   1452 	}
   1453 	return result;
   1454 }
   1455 
   1456 static ssize_t pcm_writev(u_char **data, unsigned int channels, size_t count)
   1457 {
   1458 	ssize_t r;
   1459 	size_t result = 0;
   1460 
   1461 	if (count != chunk_size) {
   1462 		unsigned int channel;
   1463 		size_t offset = count;
   1464 		size_t remaining = chunk_size - count;
   1465 		for (channel = 0; channel < channels; channel++)
   1466 			snd_pcm_format_set_silence(hwparams.format, data[channel] + offset * bits_per_sample / 8, remaining);
   1467 		count = chunk_size;
   1468 	}
   1469 	while (count > 0) {
   1470 		unsigned int channel;
   1471 		void *bufs[channels];
   1472 		size_t offset = result;
   1473 		for (channel = 0; channel < channels; channel++)
   1474 			bufs[channel] = data[channel] + offset * bits_per_sample / 8;
   1475 		if (test_position)
   1476 			do_test_position();
   1477 		r = writen_func(handle, bufs, count);
   1478 		if (test_position)
   1479 			do_test_position();
   1480 		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
   1481 			snd_pcm_wait(handle, 1000);
   1482 		} else if (r == -EPIPE) {
   1483 			xrun();
   1484 		} else if (r == -ESTRPIPE) {
   1485 			suspend();
   1486 		} else if (r < 0) {
   1487 			error(_("writev error: %s"), snd_strerror(r));
   1488 			exit(EXIT_FAILURE);
   1489 		}
   1490 		if (r > 0) {
   1491 			if (vumeter) {
   1492 				for (channel = 0; channel < channels; channel++)
   1493 					compute_max_peak(data[channel], r);
   1494 			}
   1495 			result += r;
   1496 			count -= r;
   1497 		}
   1498 	}
   1499 	return result;
   1500 }
   1501 
   1502 /*
   1503  *  read function
   1504  */
   1505 
   1506 static ssize_t pcm_read(u_char *data, size_t rcount)
   1507 {
   1508 	ssize_t r;
   1509 	size_t result = 0;
   1510 	size_t count = rcount;
   1511 
   1512 	if (count != chunk_size) {
   1513 		count = chunk_size;
   1514 	}
   1515 
   1516 	while (count > 0) {
   1517 		if (test_position)
   1518 			do_test_position();
   1519 		r = readi_func(handle, data, count);
   1520 		if (test_position)
   1521 			do_test_position();
   1522 		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
   1523 			snd_pcm_wait(handle, 1000);
   1524 		} else if (r == -EPIPE) {
   1525 			xrun();
   1526 		} else if (r == -ESTRPIPE) {
   1527 			suspend();
   1528 		} else if (r < 0) {
   1529 			error(_("read error: %s"), snd_strerror(r));
   1530 			exit(EXIT_FAILURE);
   1531 		}
   1532 		if (r > 0) {
   1533 			if (vumeter)
   1534 				compute_max_peak(data, r * hwparams.channels);
   1535 			result += r;
   1536 			count -= r;
   1537 			data += r * bits_per_frame / 8;
   1538 		}
   1539 	}
   1540 	return rcount;
   1541 }
   1542 
   1543 static ssize_t pcm_readv(u_char **data, unsigned int channels, size_t rcount)
   1544 {
   1545 	ssize_t r;
   1546 	size_t result = 0;
   1547 	size_t count = rcount;
   1548 
   1549 	if (count != chunk_size) {
   1550 		count = chunk_size;
   1551 	}
   1552 
   1553 	while (count > 0) {
   1554 		unsigned int channel;
   1555 		void *bufs[channels];
   1556 		size_t offset = result;
   1557 		for (channel = 0; channel < channels; channel++)
   1558 			bufs[channel] = data[channel] + offset * bits_per_sample / 8;
   1559 		if (test_position)
   1560 			do_test_position();
   1561 		r = readn_func(handle, bufs, count);
   1562 		if (test_position)
   1563 			do_test_position();
   1564 		if (r == -EAGAIN || (r >= 0 && (size_t)r < count)) {
   1565 			snd_pcm_wait(handle, 1000);
   1566 		} else if (r == -EPIPE) {
   1567 			xrun();
   1568 		} else if (r == -ESTRPIPE) {
   1569 			suspend();
   1570 		} else if (r < 0) {
   1571 			error(_("readv error: %s"), snd_strerror(r));
   1572 			exit(EXIT_FAILURE);
   1573 		}
   1574 		if (r > 0) {
   1575 			if (vumeter) {
   1576 				for (channel = 0; channel < channels; channel++)
   1577 					compute_max_peak(data[channel], r);
   1578 			}
   1579 			result += r;
   1580 			count -= r;
   1581 		}
   1582 	}
   1583 	return rcount;
   1584 }
   1585 
   1586 /*
   1587  *  ok, let's play a .voc file
   1588  */
   1589 
   1590 static ssize_t voc_pcm_write(u_char *data, size_t count)
   1591 {
   1592 	ssize_t result = count, r;
   1593 	size_t size;
   1594 
   1595 	while (count > 0) {
   1596 		size = count;
   1597 		if (size > chunk_bytes - buffer_pos)
   1598 			size = chunk_bytes - buffer_pos;
   1599 		memcpy(audiobuf + buffer_pos, data, size);
   1600 		data += size;
   1601 		count -= size;
   1602 		buffer_pos += size;
   1603 		if ((size_t)buffer_pos == chunk_bytes) {
   1604 			if ((size_t)(r = pcm_write(audiobuf, chunk_size)) != chunk_size)
   1605 				return r;
   1606 			buffer_pos = 0;
   1607 		}
   1608 	}
   1609 	return result;
   1610 }
   1611 
   1612 static void voc_write_silence(unsigned x)
   1613 {
   1614 	unsigned l;
   1615 	u_char *buf;
   1616 
   1617 	buf = (u_char *) malloc(chunk_bytes);
   1618 	if (buf == NULL) {
   1619 		error(_("can't allocate buffer for silence"));
   1620 		return;		/* not fatal error */
   1621 	}
   1622 	snd_pcm_format_set_silence(hwparams.format, buf, chunk_size * hwparams.channels);
   1623 	while (x > 0) {
   1624 		l = x;
   1625 		if (l > chunk_size)
   1626 			l = chunk_size;
   1627 		if (voc_pcm_write(buf, l) != (ssize_t)l) {
   1628 			error(_("write error"));
   1629 			exit(EXIT_FAILURE);
   1630 		}
   1631 		x -= l;
   1632 	}
   1633 	free(buf);
   1634 }
   1635 
   1636 static void voc_pcm_flush(void)
   1637 {
   1638 	if (buffer_pos > 0) {
   1639 		size_t b;
   1640 		if (snd_pcm_format_set_silence(hwparams.format, audiobuf + buffer_pos, chunk_bytes - buffer_pos * 8 / bits_per_sample) < 0)
   1641 			fprintf(stderr, _("voc_pcm_flush - silence error"));
   1642 		b = chunk_size;
   1643 		if (pcm_write(audiobuf, b) != (ssize_t)b)
   1644 			error(_("voc_pcm_flush error"));
   1645 	}
   1646 	snd_pcm_nonblock(handle, 0);
   1647 	snd_pcm_drain(handle);
   1648 	snd_pcm_nonblock(handle, nonblock);
   1649 }
   1650 
   1651 static void voc_play(int fd, int ofs, char *name)
   1652 {
   1653 	int l;
   1654 	VocBlockType *bp;
   1655 	VocVoiceData *vd;
   1656 	VocExtBlock *eb;
   1657 	size_t nextblock, in_buffer;
   1658 	u_char *data, *buf;
   1659 	char was_extended = 0, output = 0;
   1660 	u_short *sp, repeat = 0;
   1661 	size_t silence;
   1662 	off64_t filepos = 0;
   1663 
   1664 #define COUNT(x)	nextblock -= x; in_buffer -= x; data += x
   1665 #define COUNT1(x)	in_buffer -= x; data += x
   1666 
   1667 	data = buf = (u_char *)malloc(64 * 1024);
   1668 	buffer_pos = 0;
   1669 	if (data == NULL) {
   1670 		error(_("malloc error"));
   1671 		exit(EXIT_FAILURE);
   1672 	}
   1673 	if (!quiet_mode) {
   1674 		fprintf(stderr, _("Playing Creative Labs Channel file '%s'...\n"), name);
   1675 	}
   1676 	/* first we waste the rest of header, ugly but we don't need seek */
   1677 	while (ofs > (ssize_t)chunk_bytes) {
   1678 		if ((size_t)safe_read(fd, buf, chunk_bytes) != chunk_bytes) {
   1679 			error(_("read error"));
   1680 			exit(EXIT_FAILURE);
   1681 		}
   1682 		ofs -= chunk_bytes;
   1683 	}
   1684 	if (ofs) {
   1685 		if (safe_read(fd, buf, ofs) != ofs) {
   1686 			error(_("read error"));
   1687 			exit(EXIT_FAILURE);
   1688 		}
   1689 	}
   1690 	hwparams.format = DEFAULT_FORMAT;
   1691 	hwparams.channels = 1;
   1692 	hwparams.rate = DEFAULT_SPEED;
   1693 	set_params();
   1694 
   1695 	in_buffer = nextblock = 0;
   1696 	while (1) {
   1697 	      Fill_the_buffer:	/* need this for repeat */
   1698 		if (in_buffer < 32) {
   1699 			/* move the rest of buffer to pos 0 and fill the buf up */
   1700 			if (in_buffer)
   1701 				memcpy(buf, data, in_buffer);
   1702 			data = buf;
   1703 			if ((l = safe_read(fd, buf + in_buffer, chunk_bytes - in_buffer)) > 0)
   1704 				in_buffer += l;
   1705 			else if (!in_buffer) {
   1706 				/* the file is truncated, so simulate 'Terminator'
   1707 				   and reduce the datablock for safe landing */
   1708 				nextblock = buf[0] = 0;
   1709 				if (l == -1) {
   1710 					perror(name);
   1711 					exit(EXIT_FAILURE);
   1712 				}
   1713 			}
   1714 		}
   1715 		while (!nextblock) {	/* this is a new block */
   1716 			if (in_buffer < sizeof(VocBlockType))
   1717 				goto __end;
   1718 			bp = (VocBlockType *) data;
   1719 			COUNT1(sizeof(VocBlockType));
   1720 			nextblock = VOC_DATALEN(bp);
   1721 			if (output && !quiet_mode)
   1722 				fprintf(stderr, "\n");	/* write /n after ASCII-out */
   1723 			output = 0;
   1724 			switch (bp->type) {
   1725 			case 0:
   1726 #if 0
   1727 				d_printf("Terminator\n");
   1728 #endif
   1729 				return;		/* VOC-file stop */
   1730 			case 1:
   1731 				vd = (VocVoiceData *) data;
   1732 				COUNT1(sizeof(VocVoiceData));
   1733 				/* we need a SYNC, before we can set new SPEED, STEREO ... */
   1734 
   1735 				if (!was_extended) {
   1736 					hwparams.rate = (int) (vd->tc);
   1737 					hwparams.rate = 1000000 / (256 - hwparams.rate);
   1738 #if 0
   1739 					d_printf("Channel data %d Hz\n", dsp_speed);
   1740 #endif
   1741 					if (vd->pack) {		/* /dev/dsp can't it */
   1742 						error(_("can't play packed .voc files"));
   1743 						return;
   1744 					}
   1745 					if (hwparams.channels == 2)		/* if we are in Stereo-Mode, switch back */
   1746 						hwparams.channels = 1;
   1747 				} else {	/* there was extended block */
   1748 					hwparams.channels = 2;
   1749 					was_extended = 0;
   1750 				}
   1751 				set_params();
   1752 				break;
   1753 			case 2:	/* nothing to do, pure data */
   1754 #if 0
   1755 				d_printf("Channel continuation\n");
   1756 #endif
   1757 				break;
   1758 			case 3:	/* a silence block, no data, only a count */
   1759 				sp = (u_short *) data;
   1760 				COUNT1(sizeof(u_short));
   1761 				hwparams.rate = (int) (*data);
   1762 				COUNT1(1);
   1763 				hwparams.rate = 1000000 / (256 - hwparams.rate);
   1764 				set_params();
   1765 				silence = (((size_t) * sp) * 1000) / hwparams.rate;
   1766 #if 0
   1767 				d_printf("Silence for %d ms\n", (int) silence);
   1768 #endif
   1769 				voc_write_silence(*sp);
   1770 				break;
   1771 			case 4:	/* a marker for syncronisation, no effect */
   1772 				sp = (u_short *) data;
   1773 				COUNT1(sizeof(u_short));
   1774 #if 0
   1775 				d_printf("Marker %d\n", *sp);
   1776 #endif
   1777 				break;
   1778 			case 5:	/* ASCII text, we copy to stderr */
   1779 				output = 1;
   1780 #if 0
   1781 				d_printf("ASCII - text :\n");
   1782 #endif
   1783 				break;
   1784 			case 6:	/* repeat marker, says repeatcount */
   1785 				/* my specs don't say it: maybe this can be recursive, but
   1786 				   I don't think somebody use it */
   1787 				repeat = *(u_short *) data;
   1788 				COUNT1(sizeof(u_short));
   1789 #if 0
   1790 				d_printf("Repeat loop %d times\n", repeat);
   1791 #endif
   1792 				if (filepos >= 0) {	/* if < 0, one seek fails, why test another */
   1793 					if ((filepos = lseek64(fd, 0, 1)) < 0) {
   1794 						error(_("can't play loops; %s isn't seekable\n"), name);
   1795 						repeat = 0;
   1796 					} else {
   1797 						filepos -= in_buffer;	/* set filepos after repeat */
   1798 					}
   1799 				} else {
   1800 					repeat = 0;
   1801 				}
   1802 				break;
   1803 			case 7:	/* ok, lets repeat that be rewinding tape */
   1804 				if (repeat) {
   1805 					if (repeat != 0xFFFF) {
   1806 #if 0
   1807 						d_printf("Repeat loop %d\n", repeat);
   1808 #endif
   1809 						--repeat;
   1810 					}
   1811 #if 0
   1812 					else
   1813 						d_printf("Neverending loop\n");
   1814 #endif
   1815 					lseek64(fd, filepos, 0);
   1816 					in_buffer = 0;	/* clear the buffer */
   1817 					goto Fill_the_buffer;
   1818 				}
   1819 #if 0
   1820 				else
   1821 					d_printf("End repeat loop\n");
   1822 #endif
   1823 				break;
   1824 			case 8:	/* the extension to play Stereo, I have SB 1.0 :-( */
   1825 				was_extended = 1;
   1826 				eb = (VocExtBlock *) data;
   1827 				COUNT1(sizeof(VocExtBlock));
   1828 				hwparams.rate = (int) (eb->tc);
   1829 				hwparams.rate = 256000000L / (65536 - hwparams.rate);
   1830 				hwparams.channels = eb->mode == VOC_MODE_STEREO ? 2 : 1;
   1831 				if (hwparams.channels == 2)
   1832 					hwparams.rate = hwparams.rate >> 1;
   1833 				if (eb->pack) {		/* /dev/dsp can't it */
   1834 					error(_("can't play packed .voc files"));
   1835 					return;
   1836 				}
   1837 #if 0
   1838 				d_printf("Extended block %s %d Hz\n",
   1839 					 (eb->mode ? "Stereo" : "Mono"), dsp_speed);
   1840 #endif
   1841 				break;
   1842 			default:
   1843 				error(_("unknown blocktype %d. terminate."), bp->type);
   1844 				return;
   1845 			}	/* switch (bp->type) */
   1846 		}		/* while (! nextblock)  */
   1847 		/* put nextblock data bytes to dsp */
   1848 		l = in_buffer;
   1849 		if (nextblock < (size_t)l)
   1850 			l = nextblock;
   1851 		if (l) {
   1852 			if (output && !quiet_mode) {
   1853 				if (write(2, data, l) != l) {	/* to stderr */
   1854 					error(_("write error"));
   1855 					exit(EXIT_FAILURE);
   1856 				}
   1857 			} else {
   1858 				if (voc_pcm_write(data, l) != l) {
   1859 					error(_("write error"));
   1860 					exit(EXIT_FAILURE);
   1861 				}
   1862 			}
   1863 			COUNT(l);
   1864 		}
   1865 	}			/* while(1) */
   1866       __end:
   1867         voc_pcm_flush();
   1868         free(buf);
   1869 }
   1870 /* that was a big one, perhaps somebody split it :-) */
   1871 
   1872 /* setting the globals for playing raw data */
   1873 static void init_raw_data(void)
   1874 {
   1875 	hwparams = rhwparams;
   1876 }
   1877 
   1878 /* calculate the data count to read from/to dsp */
   1879 static off64_t calc_count(void)
   1880 {
   1881 	off64_t count;
   1882 
   1883 	if (timelimit == 0) {
   1884 		count = pbrec_count;
   1885 	} else {
   1886 		count = snd_pcm_format_size(hwparams.format, hwparams.rate * hwparams.channels);
   1887 		count *= (off64_t)timelimit;
   1888 	}
   1889 	return count < pbrec_count ? count : pbrec_count;
   1890 }
   1891 
   1892 /* write a .VOC-header */
   1893 static void begin_voc(int fd, size_t cnt)
   1894 {
   1895 	VocHeader vh;
   1896 	VocBlockType bt;
   1897 	VocVoiceData vd;
   1898 	VocExtBlock eb;
   1899 
   1900 	memcpy(vh.magic, VOC_MAGIC_STRING, 20);
   1901 	vh.headerlen = LE_SHORT(sizeof(VocHeader));
   1902 	vh.version = LE_SHORT(VOC_ACTUAL_VERSION);
   1903 	vh.coded_ver = LE_SHORT(0x1233 - VOC_ACTUAL_VERSION);
   1904 
   1905 	if (write(fd, &vh, sizeof(VocHeader)) != sizeof(VocHeader)) {
   1906 		error(_("write error"));
   1907 		exit(EXIT_FAILURE);
   1908 	}
   1909 	if (hwparams.channels > 1) {
   1910 		/* write an extended block */
   1911 		bt.type = 8;
   1912 		bt.datalen = 4;
   1913 		bt.datalen_m = bt.datalen_h = 0;
   1914 		if (write(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {
   1915 			error(_("write error"));
   1916 			exit(EXIT_FAILURE);
   1917 		}
   1918 		eb.tc = LE_SHORT(65536 - 256000000L / (hwparams.rate << 1));
   1919 		eb.pack = 0;
   1920 		eb.mode = 1;
   1921 		if (write(fd, &eb, sizeof(VocExtBlock)) != sizeof(VocExtBlock)) {
   1922 			error(_("write error"));
   1923 			exit(EXIT_FAILURE);
   1924 		}
   1925 	}
   1926 	bt.type = 1;
   1927 	cnt += sizeof(VocVoiceData);	/* Channel_data block follows */
   1928 	bt.datalen = (u_char) (cnt & 0xFF);
   1929 	bt.datalen_m = (u_char) ((cnt & 0xFF00) >> 8);
   1930 	bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16);
   1931 	if (write(fd, &bt, sizeof(VocBlockType)) != sizeof(VocBlockType)) {
   1932 		error(_("write error"));
   1933 		exit(EXIT_FAILURE);
   1934 	}
   1935 	vd.tc = (u_char) (256 - (1000000 / hwparams.rate));
   1936 	vd.pack = 0;
   1937 	if (write(fd, &vd, sizeof(VocVoiceData)) != sizeof(VocVoiceData)) {
   1938 		error(_("write error"));
   1939 		exit(EXIT_FAILURE);
   1940 	}
   1941 }
   1942 
   1943 /* write a WAVE-header */
   1944 static void begin_wave(int fd, size_t cnt)
   1945 {
   1946 	WaveHeader h;
   1947 	WaveFmtBody f;
   1948 	WaveChunkHeader cf, cd;
   1949 	int bits;
   1950 	u_int tmp;
   1951 	u_short tmp2;
   1952 
   1953 	/* WAVE cannot handle greater than 32bit (signed?) int */
   1954 	if (cnt == (size_t)-2)
   1955 		cnt = 0x7fffff00;
   1956 
   1957 	bits = 8;
   1958 	switch ((unsigned long) hwparams.format) {
   1959 	case SND_PCM_FORMAT_U8:
   1960 		bits = 8;
   1961 		break;
   1962 	case SND_PCM_FORMAT_S16_LE:
   1963 		bits = 16;
   1964 		break;
   1965 	case SND_PCM_FORMAT_S32_LE:
   1966         case SND_PCM_FORMAT_FLOAT_LE:
   1967 		bits = 32;
   1968 		break;
   1969 	case SND_PCM_FORMAT_S24_LE:
   1970 	case SND_PCM_FORMAT_S24_3LE:
   1971 		bits = 24;
   1972 		break;
   1973 	default:
   1974 		error(_("Wave doesn't support %s format..."), snd_pcm_format_name(hwparams.format));
   1975 		exit(EXIT_FAILURE);
   1976 	}
   1977 	h.magic = WAV_RIFF;
   1978 	tmp = cnt + sizeof(WaveHeader) + sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + sizeof(WaveChunkHeader) - 8;
   1979 	h.length = LE_INT(tmp);
   1980 	h.type = WAV_WAVE;
   1981 
   1982 	cf.type = WAV_FMT;
   1983 	cf.length = LE_INT(16);
   1984 
   1985         if (hwparams.format == SND_PCM_FORMAT_FLOAT_LE)
   1986                 f.format = LE_SHORT(WAV_FMT_IEEE_FLOAT);
   1987         else
   1988                 f.format = LE_SHORT(WAV_FMT_PCM);
   1989 	f.channels = LE_SHORT(hwparams.channels);
   1990 	f.sample_fq = LE_INT(hwparams.rate);
   1991 #if 0
   1992 	tmp2 = (samplesize == 8) ? 1 : 2;
   1993 	f.byte_p_spl = LE_SHORT(tmp2);
   1994 	tmp = dsp_speed * hwparams.channels * (u_int) tmp2;
   1995 #else
   1996 	tmp2 = hwparams.channels * snd_pcm_format_physical_width(hwparams.format) / 8;
   1997 	f.byte_p_spl = LE_SHORT(tmp2);
   1998 	tmp = (u_int) tmp2 * hwparams.rate;
   1999 #endif
   2000 	f.byte_p_sec = LE_INT(tmp);
   2001 	f.bit_p_spl = LE_SHORT(bits);
   2002 
   2003 	cd.type = WAV_DATA;
   2004 	cd.length = LE_INT(cnt);
   2005 
   2006 	if (write(fd, &h, sizeof(WaveHeader)) != sizeof(WaveHeader) ||
   2007 	    write(fd, &cf, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader) ||
   2008 	    write(fd, &f, sizeof(WaveFmtBody)) != sizeof(WaveFmtBody) ||
   2009 	    write(fd, &cd, sizeof(WaveChunkHeader)) != sizeof(WaveChunkHeader)) {
   2010 		error(_("write error"));
   2011 		exit(EXIT_FAILURE);
   2012 	}
   2013 }
   2014 
   2015 /* write a Au-header */
   2016 static void begin_au(int fd, size_t cnt)
   2017 {
   2018 	AuHeader ah;
   2019 
   2020 	ah.magic = AU_MAGIC;
   2021 	ah.hdr_size = BE_INT(24);
   2022 	ah.data_size = BE_INT(cnt);
   2023 	switch ((unsigned long) hwparams.format) {
   2024 	case SND_PCM_FORMAT_MU_LAW:
   2025 		ah.encoding = BE_INT(AU_FMT_ULAW);
   2026 		break;
   2027 	case SND_PCM_FORMAT_U8:
   2028 		ah.encoding = BE_INT(AU_FMT_LIN8);
   2029 		break;
   2030 	case SND_PCM_FORMAT_S16_BE:
   2031 		ah.encoding = BE_INT(AU_FMT_LIN16);
   2032 		break;
   2033 	default:
   2034 		error(_("Sparc Audio doesn't support %s format..."), snd_pcm_format_name(hwparams.format));
   2035 		exit(EXIT_FAILURE);
   2036 	}
   2037 	ah.sample_rate = BE_INT(hwparams.rate);
   2038 	ah.channels = BE_INT(hwparams.channels);
   2039 	if (write(fd, &ah, sizeof(AuHeader)) != sizeof(AuHeader)) {
   2040 		error(_("write error"));
   2041 		exit(EXIT_FAILURE);
   2042 	}
   2043 }
   2044 
   2045 /* closing .VOC */
   2046 static void end_voc(int fd)
   2047 {
   2048 	off64_t length_seek;
   2049 	VocBlockType bt;
   2050 	size_t cnt;
   2051 	char dummy = 0;		/* Write a Terminator */
   2052 
   2053 	if (write(fd, &dummy, 1) != 1) {
   2054 		error(_("write error"));
   2055 		exit(EXIT_FAILURE);
   2056 	}
   2057 	length_seek = sizeof(VocHeader);
   2058 	if (hwparams.channels > 1)
   2059 		length_seek += sizeof(VocBlockType) + sizeof(VocExtBlock);
   2060 	bt.type = 1;
   2061 	cnt = fdcount;
   2062 	cnt += sizeof(VocVoiceData);	/* Channel_data block follows */
   2063 	if (cnt > 0x00ffffff)
   2064 		cnt = 0x00ffffff;
   2065 	bt.datalen = (u_char) (cnt & 0xFF);
   2066 	bt.datalen_m = (u_char) ((cnt & 0xFF00) >> 8);
   2067 	bt.datalen_h = (u_char) ((cnt & 0xFF0000) >> 16);
   2068 	if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
   2069 		write(fd, &bt, sizeof(VocBlockType));
   2070 	if (fd != 1)
   2071 		close(fd);
   2072 }
   2073 
   2074 static void end_wave(int fd)
   2075 {				/* only close output */
   2076 	WaveChunkHeader cd;
   2077 	off64_t length_seek;
   2078 	off64_t filelen;
   2079 	u_int rifflen;
   2080 
   2081 	length_seek = sizeof(WaveHeader) +
   2082 		      sizeof(WaveChunkHeader) +
   2083 		      sizeof(WaveFmtBody);
   2084 	cd.type = WAV_DATA;
   2085 	cd.length = fdcount > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(fdcount);
   2086 	filelen = fdcount + 2*sizeof(WaveChunkHeader) + sizeof(WaveFmtBody) + 4;
   2087 	rifflen = filelen > 0x7fffffff ? LE_INT(0x7fffffff) : LE_INT(filelen);
   2088 	if (lseek64(fd, 4, SEEK_SET) == 4)
   2089 		write(fd, &rifflen, 4);
   2090 	if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
   2091 		write(fd, &cd, sizeof(WaveChunkHeader));
   2092 	if (fd != 1)
   2093 		close(fd);
   2094 }
   2095 
   2096 static void end_au(int fd)
   2097 {				/* only close output */
   2098 	AuHeader ah;
   2099 	off64_t length_seek;
   2100 
   2101 	length_seek = (char *)&ah.data_size - (char *)&ah;
   2102 	ah.data_size = fdcount > 0xffffffff ? 0xffffffff : BE_INT(fdcount);
   2103 	if (lseek64(fd, length_seek, SEEK_SET) == length_seek)
   2104 		write(fd, &ah.data_size, sizeof(ah.data_size));
   2105 	if (fd != 1)
   2106 		close(fd);
   2107 }
   2108 
   2109 static void header(int rtype, char *name)
   2110 {
   2111 	if (!quiet_mode) {
   2112 		if (! name)
   2113 			name = (stream == SND_PCM_STREAM_PLAYBACK) ? "stdout" : "stdin";
   2114 		fprintf(stderr, "%s %s '%s' : ",
   2115 			(stream == SND_PCM_STREAM_PLAYBACK) ? _("Playing") : _("Recording"),
   2116 			gettext(fmt_rec_table[rtype].what),
   2117 			name);
   2118 		fprintf(stderr, "%s, ", snd_pcm_format_description(hwparams.format));
   2119 		fprintf(stderr, _("Rate %d Hz, "), hwparams.rate);
   2120 		if (hwparams.channels == 1)
   2121 			fprintf(stderr, _("Mono"));
   2122 		else if (hwparams.channels == 2)
   2123 			fprintf(stderr, _("Stereo"));
   2124 		else
   2125 			fprintf(stderr, _("Channels %i"), hwparams.channels);
   2126 		fprintf(stderr, "\n");
   2127 	}
   2128 }
   2129 
   2130 /* playing raw data */
   2131 
   2132 static void playback_go(int fd, size_t loaded, off64_t count, int rtype, char *name)
   2133 {
   2134 	int l, r;
   2135 	off64_t written = 0;
   2136 	off64_t c;
   2137 
   2138 	header(rtype, name);
   2139 	set_params();
   2140 
   2141 	while (loaded > chunk_bytes && written < count) {
   2142 		if (pcm_write(audiobuf + written, chunk_size) <= 0)
   2143 			return;
   2144 		written += chunk_bytes;
   2145 		loaded -= chunk_bytes;
   2146 	}
   2147 	if (written > 0 && loaded > 0)
   2148 		memmove(audiobuf, audiobuf + written, loaded);
   2149 
   2150 	l = loaded;
   2151 	while (written < count) {
   2152 		do {
   2153 			c = count - written;
   2154 			if (c > chunk_bytes)
   2155 				c = chunk_bytes;
   2156 			c -= l;
   2157 
   2158 			if (c == 0)
   2159 				break;
   2160 			r = safe_read(fd, audiobuf + l, c);
   2161 			if (r < 0) {
   2162 				perror(name);
   2163 				exit(EXIT_FAILURE);
   2164 			}
   2165 			fdcount += r;
   2166 			if (r == 0)
   2167 				break;
   2168 			l += r;
   2169 		} while ((size_t)l < chunk_bytes);
   2170 		l = l * 8 / bits_per_frame;
   2171 		r = pcm_write(audiobuf, l);
   2172 		if (r != l)
   2173 			break;
   2174 		r = r * bits_per_frame / 8;
   2175 		written += r;
   2176 		l = 0;
   2177 	}
   2178 	snd_pcm_nonblock(handle, 0);
   2179 	snd_pcm_drain(handle);
   2180 	snd_pcm_nonblock(handle, nonblock);
   2181 }
   2182 
   2183 
   2184 /*
   2185  *  let's play or capture it (capture_type says VOC/WAVE/raw)
   2186  */
   2187 
   2188 static void playback(char *name)
   2189 {
   2190 	int ofs;
   2191 	size_t dta;
   2192 	ssize_t dtawave;
   2193 
   2194 	pbrec_count = LLONG_MAX;
   2195 	fdcount = 0;
   2196 	if (!name || !strcmp(name, "-")) {
   2197 		fd = fileno(stdin);
   2198 		name = "stdin";
   2199 	} else {
   2200 		if ((fd = open64(name, O_RDONLY, 0)) == -1) {
   2201 			perror(name);
   2202 			exit(EXIT_FAILURE);
   2203 		}
   2204 	}
   2205 	/* read the file header */
   2206 	dta = sizeof(AuHeader);
   2207 	if ((size_t)safe_read(fd, audiobuf, dta) != dta) {
   2208 		error(_("read error"));
   2209 		exit(EXIT_FAILURE);
   2210 	}
   2211 	if (test_au(fd, audiobuf) >= 0) {
   2212 		rhwparams.format = hwparams.format;
   2213 		pbrec_count = calc_count();
   2214 		playback_go(fd, 0, pbrec_count, FORMAT_AU, name);
   2215 		goto __end;
   2216 	}
   2217 	dta = sizeof(VocHeader);
   2218 	if ((size_t)safe_read(fd, audiobuf + sizeof(AuHeader),
   2219 		 dta - sizeof(AuHeader)) != dta - sizeof(AuHeader)) {
   2220 		error(_("read error"));
   2221 		exit(EXIT_FAILURE);
   2222 	}
   2223 	if ((ofs = test_vocfile(audiobuf)) >= 0) {
   2224 		pbrec_count = calc_count();
   2225 		voc_play(fd, ofs, name);
   2226 		goto __end;
   2227 	}
   2228 	/* read bytes for WAVE-header */
   2229 	if ((dtawave = test_wavefile(fd, audiobuf, dta)) >= 0) {
   2230 		pbrec_count = calc_count();
   2231 		playback_go(fd, dtawave, pbrec_count, FORMAT_WAVE, name);
   2232 	} else {
   2233 		/* should be raw data */
   2234 		init_raw_data();
   2235 		pbrec_count = calc_count();
   2236 		playback_go(fd, dta, pbrec_count, FORMAT_RAW, name);
   2237 	}
   2238       __end:
   2239 	if (fd != 0)
   2240 		close(fd);
   2241 }
   2242 
   2243 static int new_capture_file(char *name, char *namebuf, size_t namelen,
   2244 			    int filecount)
   2245 {
   2246 	/* get a copy of the original filename */
   2247 	char *s;
   2248 	char buf[PATH_MAX+1];
   2249 
   2250 	strncpy(buf, name, sizeof(buf));
   2251 
   2252 	/* separate extension from filename */
   2253 	s = buf + strlen(buf);
   2254 	while (s > buf && *s != '.' && *s != '/')
   2255 		--s;
   2256 	if (*s == '.')
   2257 		*s++ = 0;
   2258 	else if (*s == '/')
   2259 		s = buf + strlen(buf);
   2260 
   2261 	/* upon first jump to this if block rename the first file */
   2262 	if (filecount == 1) {
   2263 		if (*s)
   2264 			snprintf(namebuf, namelen, "%s-01.%s", buf, s);
   2265 		else
   2266 			snprintf(namebuf, namelen, "%s-01", buf);
   2267 		remove(namebuf);
   2268 		rename(name, namebuf);
   2269 		filecount = 2;
   2270 	}
   2271 
   2272 	/* name of the current file */
   2273 	if (*s)
   2274 		snprintf(namebuf, namelen, "%s-%02i.%s", buf, filecount, s);
   2275 	else
   2276 		snprintf(namebuf, namelen, "%s-%02i", buf, filecount);
   2277 
   2278 	return filecount;
   2279 }
   2280 
   2281 static void capture(char *orig_name)
   2282 {
   2283 	int tostdout=0;		/* boolean which describes output stream */
   2284 	int filecount=0;	/* number of files written */
   2285 	char *name = orig_name;	/* current filename */
   2286 	char namebuf[PATH_MAX+1];
   2287 	off64_t count, rest;		/* number of bytes to capture */
   2288 
   2289 	/* get number of bytes to capture */
   2290 	count = calc_count();
   2291 	if (count == 0)
   2292 		count = LLONG_MAX;
   2293 	/* WAVE-file should be even (I'm not sure), but wasting one byte
   2294 	   isn't a problem (this can only be in 8 bit mono) */
   2295 	if (count < LLONG_MAX)
   2296 		count += count % 2;
   2297 	else
   2298 		count -= count % 2;
   2299 
   2300 	/* display verbose output to console */
   2301 	header(file_type, name);
   2302 
   2303 	/* setup sound hardware */
   2304 	set_params();
   2305 
   2306 	/* write to stdout? */
   2307 	if (!name || !strcmp(name, "-")) {
   2308 		fd = fileno(stdout);
   2309 		name = "stdout";
   2310 		tostdout=1;
   2311 		if (count > fmt_rec_table[file_type].max_filesize)
   2312 			count = fmt_rec_table[file_type].max_filesize;
   2313 	}
   2314 
   2315 	do {
   2316 		/* open a file to write */
   2317 		if(!tostdout) {
   2318 			/* upon the second file we start the numbering scheme */
   2319 			if (filecount) {
   2320 				filecount = new_capture_file(orig_name, namebuf,
   2321 							     sizeof(namebuf),
   2322 							     filecount);
   2323 				name = namebuf;
   2324 			}
   2325 
   2326 			/* open a new file */
   2327 			remove(name);
   2328 			if ((fd = open64(name, O_WRONLY | O_CREAT, 0644)) == -1) {
   2329 				perror(name);
   2330 				exit(EXIT_FAILURE);
   2331 			}
   2332 			filecount++;
   2333 		}
   2334 
   2335 		rest = count;
   2336 		if (rest > fmt_rec_table[file_type].max_filesize)
   2337 			rest = fmt_rec_table[file_type].max_filesize;
   2338 
   2339 		/* setup sample header */
   2340 		if (fmt_rec_table[file_type].start)
   2341 			fmt_rec_table[file_type].start(fd, rest);
   2342 
   2343 		/* capture */
   2344 		fdcount = 0;
   2345 		while (rest > 0) {
   2346 			size_t c = (rest <= (off64_t)chunk_bytes) ?
   2347 				(size_t)rest : chunk_bytes;
   2348 			size_t f = c * 8 / bits_per_frame;
   2349 			if (pcm_read(audiobuf, f) != f)
   2350 				break;
   2351 			if (write(fd, audiobuf, c) != c) {
   2352 				perror(name);
   2353 				exit(EXIT_FAILURE);
   2354 			}
   2355 			count -= c;
   2356 			rest -= c;
   2357 			fdcount += c;
   2358 		}
   2359 
   2360 		/* finish sample container */
   2361 		if (fmt_rec_table[file_type].end && !tostdout) {
   2362 			fmt_rec_table[file_type].end(fd);
   2363 			fd = -1;
   2364 		}
   2365 
   2366 		/* repeat the loop when format is raw without timelimit or
   2367 		 * requested counts of data are recorded
   2368 		 */
   2369 	} while ((file_type == FORMAT_RAW && !timelimit) || count > 0);
   2370 }
   2371 
   2372 static void playbackv_go(int* fds, unsigned int channels, size_t loaded, off64_t count, int rtype, char **names)
   2373 {
   2374 	int r;
   2375 	size_t vsize;
   2376 
   2377 	unsigned int channel;
   2378 	u_char *bufs[channels];
   2379 
   2380 	header(rtype, names[0]);
   2381 	set_params();
   2382 
   2383 	vsize = chunk_bytes / channels;
   2384 
   2385 	// Not yet implemented
   2386 	assert(loaded == 0);
   2387 
   2388 	for (channel = 0; channel < channels; ++channel)
   2389 		bufs[channel] = audiobuf + vsize * channel;
   2390 
   2391 	while (count > 0) {
   2392 		size_t c = 0;
   2393 		size_t expected = count / channels;
   2394 		if (expected > vsize)
   2395 			expected = vsize;
   2396 		do {
   2397 			r = safe_read(fds[0], bufs[0], expected);
   2398 			if (r < 0) {
   2399 				perror(names[channel]);
   2400 				exit(EXIT_FAILURE);
   2401 			}
   2402 			for (channel = 1; channel < channels; ++channel) {
   2403 				if (safe_read(fds[channel], bufs[channel], r) != r) {
   2404 					perror(names[channel]);
   2405 					exit(EXIT_FAILURE);
   2406 				}
   2407 			}
   2408 			if (r == 0)
   2409 				break;
   2410 			c += r;
   2411 		} while (c < expected);
   2412 		c = c * 8 / bits_per_sample;
   2413 		r = pcm_writev(bufs, channels, c);
   2414 		if ((size_t)r != c)
   2415 			break;
   2416 		r = r * bits_per_frame / 8;
   2417 		count -= r;
   2418 	}
   2419 	snd_pcm_nonblock(handle, 0);
   2420 	snd_pcm_drain(handle);
   2421 	snd_pcm_nonblock(handle, nonblock);
   2422 }
   2423 
   2424 static void capturev_go(int* fds, unsigned int channels, off64_t count, int rtype, char **names)
   2425 {
   2426 	size_t c;
   2427 	ssize_t r;
   2428 	unsigned int channel;
   2429 	size_t vsize;
   2430 	u_char *bufs[channels];
   2431 
   2432 	header(rtype, names[0]);
   2433 	set_params();
   2434 
   2435 	vsize = chunk_bytes / channels;
   2436 
   2437 	for (channel = 0; channel < channels; ++channel)
   2438 		bufs[channel] = audiobuf + vsize * channel;
   2439 
   2440 	while (count > 0) {
   2441 		size_t rv;
   2442 		c = count;
   2443 		if (c > chunk_bytes)
   2444 			c = chunk_bytes;
   2445 		c = c * 8 / bits_per_frame;
   2446 		if ((size_t)(r = pcm_readv(bufs, channels, c)) != c)
   2447 			break;
   2448 		rv = r * bits_per_sample / 8;
   2449 		for (channel = 0; channel < channels; ++channel) {
   2450 			if ((size_t)write(fds[channel], bufs[channel], rv) != rv) {
   2451 				perror(names[channel]);
   2452 				exit(EXIT_FAILURE);
   2453 			}
   2454 		}
   2455 		r = r * bits_per_frame / 8;
   2456 		count -= r;
   2457 		fdcount += r;
   2458 	}
   2459 }
   2460 
   2461 static void playbackv(char **names, unsigned int count)
   2462 {
   2463 	int ret = 0;
   2464 	unsigned int channel;
   2465 	unsigned int channels = rhwparams.channels;
   2466 	int alloced = 0;
   2467 	int fds[channels];
   2468 	for (channel = 0; channel < channels; ++channel)
   2469 		fds[channel] = -1;
   2470 
   2471 	if (count == 1 && channels > 1) {
   2472 		size_t len = strlen(names[0]);
   2473 		char format[1024];
   2474 		memcpy(format, names[0], len);
   2475 		strcpy(format + len, ".%d");
   2476 		len += 4;
   2477 		names = malloc(sizeof(*names) * channels);
   2478 		for (channel = 0; channel < channels; ++channel) {
   2479 			names[channel] = malloc(len);
   2480 			sprintf(names[channel], format, channel);
   2481 		}
   2482 		alloced = 1;
   2483 	} else if (count != channels) {
   2484 		error(_("You need to specify %d files"), channels);
   2485 		exit(EXIT_FAILURE);
   2486 	}
   2487 
   2488 	for (channel = 0; channel < channels; ++channel) {
   2489 		fds[channel] = open(names[channel], O_RDONLY, 0);
   2490 		if (fds[channel] < 0) {
   2491 			perror(names[channel]);
   2492 			ret = EXIT_FAILURE;
   2493 			goto __end;
   2494 		}
   2495 	}
   2496 	/* should be raw data */
   2497 	init_raw_data();
   2498 	pbrec_count = calc_count();
   2499 	playbackv_go(fds, channels, 0, pbrec_count, FORMAT_RAW, names);
   2500 
   2501       __end:
   2502 	for (channel = 0; channel < channels; ++channel) {
   2503 		if (fds[channel] >= 0)
   2504 			close(fds[channel]);
   2505 		if (alloced)
   2506 			free(names[channel]);
   2507 	}
   2508 	if (alloced)
   2509 		free(names);
   2510 	if (ret)
   2511 		exit(ret);
   2512 }
   2513 
   2514 static void capturev(char **names, unsigned int count)
   2515 {
   2516 	int ret = 0;
   2517 	unsigned int channel;
   2518 	unsigned int channels = rhwparams.channels;
   2519 	int alloced = 0;
   2520 	int fds[channels];
   2521 	for (channel = 0; channel < channels; ++channel)
   2522 		fds[channel] = -1;
   2523 
   2524 	if (count == 1) {
   2525 		size_t len = strlen(names[0]);
   2526 		char format[1024];
   2527 		memcpy(format, names[0], len);
   2528 		strcpy(format + len, ".%d");
   2529 		len += 4;
   2530 		names = malloc(sizeof(*names) * channels);
   2531 		for (channel = 0; channel < channels; ++channel) {
   2532 			names[channel] = malloc(len);
   2533 			sprintf(names[channel], format, channel);
   2534 		}
   2535 		alloced = 1;
   2536 	} else if (count != channels) {
   2537 		error(_("You need to specify %d files"), channels);
   2538 		exit(EXIT_FAILURE);
   2539 	}
   2540 
   2541 	for (channel = 0; channel < channels; ++channel) {
   2542 		fds[channel] = open(names[channel], O_WRONLY + O_CREAT, 0644);
   2543 		if (fds[channel] < 0) {
   2544 			perror(names[channel]);
   2545 			ret = EXIT_FAILURE;
   2546 			goto __end;
   2547 		}
   2548 	}
   2549 	/* should be raw data */
   2550 	init_raw_data();
   2551 	pbrec_count = calc_count();
   2552 	capturev_go(fds, channels, pbrec_count, FORMAT_RAW, names);
   2553 
   2554       __end:
   2555 	for (channel = 0; channel < channels; ++channel) {
   2556 		if (fds[channel] >= 0)
   2557 			close(fds[channel]);
   2558 		if (alloced)
   2559 			free(names[channel]);
   2560 	}
   2561 	if (alloced)
   2562 		free(names);
   2563 	if (ret)
   2564 		exit(ret);
   2565 }
   2566