summaryrefslogtreecommitdiff
path: root/usr.bin/aucat/wav.c
blob: 316f78673f0b3bf54e249f77c5f7352973434e04 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
#include <sys/types.h>
#include <err.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#include "conf.h"
#include "wav.h"

/*
 * max data of a .wav file. The total file size must be smaller than
 * 2^31, and we also have to leave some space for the headers (around 40
 * bytes)
 */
#define WAV_DATAMAX	(0x7fff0000)

struct fileops wav_ops = {
	"wav",
	sizeof(struct wav),
	wav_close,
	wav_read,
	wav_write,
	NULL, /* start */
	NULL, /* stop */
	pipe_nfds,
	pipe_pollfd,
	pipe_revents
};

struct wav *
wav_new_in(struct fileops *ops, int fd, char *name,
    struct aparams *par, unsigned hdr)
{
	struct wav *f;

	f = (struct wav *)pipe_new(ops, fd, name);
	if (f == NULL)
		return NULL;
	if (hdr == HDR_WAV) {
		if (!wav_readhdr(f->pipe.fd, par, &f->rbytes, NULL))
			exit(1);
		f->hpar = *par;
	} else
		f->rbytes = -1;
	f->hdr = 0;
	return f;
}

struct wav *
wav_new_out(struct fileops *ops, int fd, char *name,
    struct aparams *par, unsigned hdr)
{
	struct wav *f;

	f = (struct wav *)pipe_new(ops, fd, name);
	if (f == NULL)
		return NULL;
	if (hdr == HDR_WAV) {
		par->le = 1;
		par->sig = (par->bits <= 8) ? 0 : 1;
		par->bps = (par->bits + 7) / 8;
		if (!wav_writehdr(f->pipe.fd, par))
			exit(1);
		f->hpar = *par;
		f->wbytes = WAV_DATAMAX;
	} else
		f->wbytes = -1;
	f->hdr = hdr;
	return f;
}

unsigned
wav_read(struct file *file, unsigned char *data, unsigned count)
{
	struct wav *f = (struct wav *)file;
	unsigned n;

	if (f->rbytes >= 0 && count > f->rbytes) {
		count = f->rbytes; /* file->rbytes fits in count */
		if (count == 0) {
			DPRINTFN(2, "wav_read: %s: complete\n", f->pipe.file.name);
			file_eof(&f->pipe.file);
			return 0;
		}
	}
	n = pipe_read(file, data, count);
	if (f->rbytes >= 0)
		f->rbytes -= n;
	return n;
}


unsigned
wav_write(struct file *file, unsigned char *data, unsigned count)
{
	struct wav *f = (struct wav *)file;
	unsigned n;

	if (f->wbytes >= 0 && count > f->wbytes) {
		count = f->wbytes; /* wbytes fits in count */
		if (count == 0) {
			DPRINTFN(2, "wav_write: %s: complete\n",
			    f->pipe.file.name);
			file_hup(&f->pipe.file);
			return 0;
		}
	}
	n = pipe_write(file, data, count);
	if (f->wbytes >= 0)
		f->wbytes -= n;
	return n;
}

void
wav_close(struct file *file)
{
	struct wav *f = (struct wav *)file;

	if (f->hdr == HDR_WAV)
		wav_writehdr(f->pipe.fd, &f->hpar);
	pipe_close(file);
}