xref: /inferno-os/appl/lib/riff.b (revision 37da2899f40661e3e9631e497da8dc59b971cbd0)
1*37da2899SCharles.Forsythimplement Riff;
2*37da2899SCharles.Forsyth
3*37da2899SCharles.Forsythinclude "sys.m";
4*37da2899SCharles.Forsyth
5*37da2899SCharles.Forsythsys: Sys;
6*37da2899SCharles.Forsyth
7*37da2899SCharles.Forsythinclude "riff.m";
8*37da2899SCharles.Forsyth
9*37da2899SCharles.Forsythinit()
10*37da2899SCharles.Forsyth{
11*37da2899SCharles.Forsyth	sys = load Sys Sys->PATH;
12*37da2899SCharles.Forsyth}
13*37da2899SCharles.Forsyth
14*37da2899SCharles.Forsythopen(file: string): (ref RD, string)
15*37da2899SCharles.Forsyth{
16*37da2899SCharles.Forsyth	fd := sys->open(file, sys->OREAD);
17*37da2899SCharles.Forsyth	if(fd == nil)
18*37da2899SCharles.Forsyth		return (nil, "open failed");
19*37da2899SCharles.Forsyth
20*37da2899SCharles.Forsyth	r := ref RD;
21*37da2899SCharles.Forsyth	r.fd = fd;
22*37da2899SCharles.Forsyth	r.buf = array[DEFBUF] of byte;
23*37da2899SCharles.Forsyth	r.ptr = 0;
24*37da2899SCharles.Forsyth	r.nbyte = 0;
25*37da2899SCharles.Forsyth
26*37da2899SCharles.Forsyth	(hdr, l) := r.gethdr();
27*37da2899SCharles.Forsyth	if(hdr != "RIFF")
28*37da2899SCharles.Forsyth		return (nil, "not a RIFF file");
29*37da2899SCharles.Forsyth
30*37da2899SCharles.Forsyth	return (r, nil);
31*37da2899SCharles.Forsyth}
32*37da2899SCharles.Forsyth
33*37da2899SCharles.ForsythRD.gethdr(r: self ref RD): (string, int)
34*37da2899SCharles.Forsyth{
35*37da2899SCharles.Forsyth	b := array[8] of byte;
36*37da2899SCharles.Forsyth
37*37da2899SCharles.Forsyth	if(r.readn(b, 8) != 8)
38*37da2899SCharles.Forsyth		return (nil, -1);
39*37da2899SCharles.Forsyth
40*37da2899SCharles.Forsyth	return (string b[0:4], ledword(b, 4));
41*37da2899SCharles.Forsyth}
42*37da2899SCharles.Forsyth
43*37da2899SCharles.ForsythRD.check4(r: self ref RD, code: string): string
44*37da2899SCharles.Forsyth{
45*37da2899SCharles.Forsyth	b := array[4] of byte;
46*37da2899SCharles.Forsyth
47*37da2899SCharles.Forsyth	if(r.readn(b, 4) != 4)
48*37da2899SCharles.Forsyth		return "file i/o error";
49*37da2899SCharles.Forsyth	if(string b != code)
50*37da2899SCharles.Forsyth		return "bad four code header information";
51*37da2899SCharles.Forsyth	return nil;
52*37da2899SCharles.Forsyth}
53*37da2899SCharles.Forsyth
54*37da2899SCharles.ForsythRD.avihdr(r: self ref RD): (ref AVIhdr, string)
55*37da2899SCharles.Forsyth{
56*37da2899SCharles.Forsyth	(s, l) := r.gethdr();
57*37da2899SCharles.Forsyth	if(s == nil || s != "avih")
58*37da2899SCharles.Forsyth		return (nil, "missing/malformed avih");
59*37da2899SCharles.Forsyth
60*37da2899SCharles.Forsyth	b := array[AVImainhdr] of byte;
61*37da2899SCharles.Forsyth	if(r.readn(b, AVImainhdr) != AVImainhdr)
62*37da2899SCharles.Forsyth		return (nil, "short read in avih");
63*37da2899SCharles.Forsyth
64*37da2899SCharles.Forsyth	h := ref AVIhdr;
65*37da2899SCharles.Forsyth
66*37da2899SCharles.Forsyth	h.usecperframe = ledword(b, 0);
67*37da2899SCharles.Forsyth	h.bytesec = ledword(b, 4);
68*37da2899SCharles.Forsyth	h.flag = ledword(b, 12);
69*37da2899SCharles.Forsyth	h.frames = ledword(b, 16);
70*37da2899SCharles.Forsyth	h.initframes = ledword(b, 20);
71*37da2899SCharles.Forsyth	h.streams = ledword(b, 24);
72*37da2899SCharles.Forsyth	h.bufsize = ledword(b, 28);
73*37da2899SCharles.Forsyth	h.width = ledword(b, 32);
74*37da2899SCharles.Forsyth	h.height = ledword(b, 36);
75*37da2899SCharles.Forsyth
76*37da2899SCharles.Forsyth	return (h, nil);
77*37da2899SCharles.Forsyth}
78*37da2899SCharles.Forsyth
79*37da2899SCharles.ForsythRD.streaminfo(r: self ref RD): (ref AVIstream, string)
80*37da2899SCharles.Forsyth{
81*37da2899SCharles.Forsyth	(h, l) := r.gethdr();
82*37da2899SCharles.Forsyth	if(h != "LIST")
83*37da2899SCharles.Forsyth		return (nil, "streaminfo expected LIST");
84*37da2899SCharles.Forsyth
85*37da2899SCharles.Forsyth	err := r.check4("strl");
86*37da2899SCharles.Forsyth	if(err != nil)
87*37da2899SCharles.Forsyth		return (nil, err);
88*37da2899SCharles.Forsyth
89*37da2899SCharles.Forsyth	(strh, sl) := r.gethdr();
90*37da2899SCharles.Forsyth	if(strh != "strh")
91*37da2899SCharles.Forsyth		return (nil, "streaminfo expected strh");
92*37da2899SCharles.Forsyth
93*37da2899SCharles.Forsyth	b := array[sl] of byte;
94*37da2899SCharles.Forsyth	if(r.readn(b, sl) != sl)
95*37da2899SCharles.Forsyth		return (nil, "streaminfo strl short read");
96*37da2899SCharles.Forsyth
97*37da2899SCharles.Forsyth	s := ref AVIstream;
98*37da2899SCharles.Forsyth
99*37da2899SCharles.Forsyth	s.stype = string b[0:4];
100*37da2899SCharles.Forsyth	s.handler = string b[4:8];
101*37da2899SCharles.Forsyth	s.flags = ledword(b, 8);
102*37da2899SCharles.Forsyth	s.priority = ledword(b, 12);
103*37da2899SCharles.Forsyth	s.initframes = ledword(b, 16);
104*37da2899SCharles.Forsyth	s.scale = ledword(b, 20);
105*37da2899SCharles.Forsyth	s.rate = ledword(b, 24);
106*37da2899SCharles.Forsyth	s.start = ledword(b, 28);
107*37da2899SCharles.Forsyth	s.length = ledword(b, 32);
108*37da2899SCharles.Forsyth	s.bufsize = ledword(b, 36);
109*37da2899SCharles.Forsyth	s.quality = ledword(b, 40);
110*37da2899SCharles.Forsyth	s.samplesz = ledword(b, 44);
111*37da2899SCharles.Forsyth
112*37da2899SCharles.Forsyth	(strf, sf) := r.gethdr();
113*37da2899SCharles.Forsyth	if(strf != "strf")
114*37da2899SCharles.Forsyth		return (nil, "streaminfo expected strf");
115*37da2899SCharles.Forsyth
116*37da2899SCharles.Forsyth	s.fmt = array[sf] of byte;
117*37da2899SCharles.Forsyth	if(r.readn(s.fmt, sf) != sf)
118*37da2899SCharles.Forsyth		return (nil, "streaminfo strf short read");
119*37da2899SCharles.Forsyth
120*37da2899SCharles.Forsyth	return (s, nil);
121*37da2899SCharles.Forsyth}
122*37da2899SCharles.Forsyth
123*37da2899SCharles.ForsythRD.readn(r: self ref RD, b: array of byte, l: int): int
124*37da2899SCharles.Forsyth{
125*37da2899SCharles.Forsyth	if(r.nbyte < l) {
126*37da2899SCharles.Forsyth		c := 0;
127*37da2899SCharles.Forsyth		if(r.nbyte != 0) {
128*37da2899SCharles.Forsyth			b[0:] = r.buf[r.ptr:];
129*37da2899SCharles.Forsyth			l -= r.nbyte;
130*37da2899SCharles.Forsyth			c += r.nbyte;
131*37da2899SCharles.Forsyth			b = b[r.nbyte:];
132*37da2899SCharles.Forsyth		}
133*37da2899SCharles.Forsyth		bsize := len r.buf;
134*37da2899SCharles.Forsyth		while(l != 0) {
135*37da2899SCharles.Forsyth			r.nbyte = sys->read(r.fd, r.buf, bsize);
136*37da2899SCharles.Forsyth			if(r.nbyte <= 0) {
137*37da2899SCharles.Forsyth				r.nbyte = 0;
138*37da2899SCharles.Forsyth				return -1;
139*37da2899SCharles.Forsyth			}
140*37da2899SCharles.Forsyth			n := l;
141*37da2899SCharles.Forsyth			if(n > bsize)
142*37da2899SCharles.Forsyth				n = bsize;
143*37da2899SCharles.Forsyth
144*37da2899SCharles.Forsyth			r.ptr = 0;
145*37da2899SCharles.Forsyth			b[0:] = r.buf[0:n];
146*37da2899SCharles.Forsyth			b = b[n:];
147*37da2899SCharles.Forsyth			r.nbyte -= n;
148*37da2899SCharles.Forsyth			r.ptr += n;
149*37da2899SCharles.Forsyth			l -= n;
150*37da2899SCharles.Forsyth			c += n;
151*37da2899SCharles.Forsyth		}
152*37da2899SCharles.Forsyth		return c;
153*37da2899SCharles.Forsyth	}
154*37da2899SCharles.Forsyth	b[0:] = r.buf[r.ptr:r.ptr+l];
155*37da2899SCharles.Forsyth	r.nbyte -= l;
156*37da2899SCharles.Forsyth	r.ptr += l;
157*37da2899SCharles.Forsyth	return l;
158*37da2899SCharles.Forsyth}
159*37da2899SCharles.Forsyth
160*37da2899SCharles.ForsythRD.skip(r: self ref RD, size: int): int
161*37da2899SCharles.Forsyth{
162*37da2899SCharles.Forsyth	if(r.nbyte != 0) {
163*37da2899SCharles.Forsyth		n := size;
164*37da2899SCharles.Forsyth		if(n > r.nbyte)
165*37da2899SCharles.Forsyth			n = r.nbyte;
166*37da2899SCharles.Forsyth		r.ptr += n;
167*37da2899SCharles.Forsyth		r.nbyte -= n;
168*37da2899SCharles.Forsyth		size -= n;
169*37da2899SCharles.Forsyth		if(size == 0)
170*37da2899SCharles.Forsyth			return 0;
171*37da2899SCharles.Forsyth	}
172*37da2899SCharles.Forsyth	return int sys->seek(r.fd, big size, sys->SEEKRELA);
173*37da2899SCharles.Forsyth}
174*37da2899SCharles.Forsyth
175*37da2899SCharles.ForsythAVIstream.fmt2binfo(a: self ref AVIstream): string
176*37da2899SCharles.Forsyth{
177*37da2899SCharles.Forsyth	if(len a.fmt < Binfosize)
178*37da2899SCharles.Forsyth		return "format is wrong size for BITMAPINFO";
179*37da2899SCharles.Forsyth
180*37da2899SCharles.Forsyth	b := ref Bitmapinfo;
181*37da2899SCharles.Forsyth
182*37da2899SCharles.Forsyth	# Pull out the bitmap info
183*37da2899SCharles.Forsyth	b.width = ledword(a.fmt, 4);
184*37da2899SCharles.Forsyth	b.height = ledword(a.fmt, 8);
185*37da2899SCharles.Forsyth	b.planes = leword(a.fmt, 12);
186*37da2899SCharles.Forsyth	b.bitcount = leword(a.fmt, 14);
187*37da2899SCharles.Forsyth	b.compression = ledword(a.fmt, 16);
188*37da2899SCharles.Forsyth	b.sizeimage = ledword(a.fmt, 20);
189*37da2899SCharles.Forsyth	b.xpelpermeter = ledword(a.fmt, 24);
190*37da2899SCharles.Forsyth	b.ypelpermeter = ledword(a.fmt, 28);
191*37da2899SCharles.Forsyth	b.clrused = ledword(a.fmt, 32);
192*37da2899SCharles.Forsyth	b.clrimportant = ledword(a.fmt, 36);
193*37da2899SCharles.Forsyth
194*37da2899SCharles.Forsyth	# Parse out the color map
195*37da2899SCharles.Forsyth	ncolor := len a.fmt - Binfosize;
196*37da2899SCharles.Forsyth	if(ncolor & 3)
197*37da2899SCharles.Forsyth		return "wrong size color map";
198*37da2899SCharles.Forsyth	ncolor /= 4;
199*37da2899SCharles.Forsyth
200*37da2899SCharles.Forsyth	b.cmap = array[ncolor] of RGB;
201*37da2899SCharles.Forsyth	idx := 40;
202*37da2899SCharles.Forsyth	for(i := 0; i < ncolor; i++) {
203*37da2899SCharles.Forsyth		b.cmap[i].r = int a.fmt[idx+2];
204*37da2899SCharles.Forsyth		b.cmap[i].g = int a.fmt[idx+1];
205*37da2899SCharles.Forsyth		b.cmap[i].b = int a.fmt[idx+0];
206*37da2899SCharles.Forsyth		idx += 4;
207*37da2899SCharles.Forsyth	}
208*37da2899SCharles.Forsyth
209*37da2899SCharles.Forsyth	a.fmt = nil;
210*37da2899SCharles.Forsyth	a.binfo = b;
211*37da2899SCharles.Forsyth	return nil;
212*37da2899SCharles.Forsyth}
213*37da2899SCharles.Forsyth
214*37da2899SCharles.Forsythleword(b: array of byte, o: int): int
215*37da2899SCharles.Forsyth{
216*37da2899SCharles.Forsyth	return 	(int b[o+1] << 8) | int b[o];
217*37da2899SCharles.Forsyth}
218*37da2899SCharles.Forsyth
219*37da2899SCharles.Forsythledword(b: array of byte, o: int): int
220*37da2899SCharles.Forsyth{
221*37da2899SCharles.Forsyth	return	(int b[o+3] << 24) |
222*37da2899SCharles.Forsyth		(int b[o+2] << 16) |
223*37da2899SCharles.Forsyth		(int b[o+1] << 8) |
224*37da2899SCharles.Forsyth		int b[o];
225*37da2899SCharles.Forsyth}
226