xref: /inferno-os/appl/lib/mpeg.b (revision e45fa0eb0763b57d6fb0649c064bc3b95ccdea6c)
1implement Mpeg;
2
3include "sys.m";
4sys: Sys;
5FD: import Sys;
6include "draw.m";
7draw: Draw;
8Display, Rect, Image: import draw;
9include "dial.m";
10dial: Dial;
11Connection: import dial;
12include "mpeg.m";
13
14Chroma: con 16r05;
15
16getenv()
17{
18	if(sys != nil)
19		return;
20
21	sys = load Sys Sys->PATH;
22	draw = load Draw Draw->PATH;
23	dial = load Dial Dial->PATH;
24}
25
26copy(files: list of string, notify: chan of string, mpctl, mpdata: ref FD)
27{
28	n: int;
29	c: ref Connection;
30	name: list of string;
31
32	while(files != nil) {
33		file := hd files;
34		(n, name) = sys->tokenize(file, "@");
35		m : ref FD;
36		case n {
37		1 =>
38			m = sys->open(file, sys->OREAD);
39			if(m == nil) {
40				notify <-= "mpeg open:" + file;
41				return;
42			}
43		2 =>
44			c = dial->dial(hd tl name, nil);
45			if(c == nil) {
46				notify <-= "dial:" + hd tl name;
47				return;
48			}
49			sys->fprint(c.dfd, "%s\n", hd name);
50			c.cfd = nil;
51			m = c.dfd;
52		* =>
53			notify <-= "bad file:"+hd name;
54			return;
55		}
56		sys->stream(m, mpdata, 64*1024);
57		files = tl files;
58	}
59	sys->fprint(mpctl, "stop");
60	sys->fprint(mpctl, "window 0 0 0 0");
61	notify <-= "";
62}
63
64play(display: ref Display, w: ref Image, paint: int, r: Rect, file: string, notify: chan of string): string
65{
66 	i, j: int;
67	line: string;
68	cfg: array of byte;
69	buf := array[1024] of byte;
70	arg, words, files: list of string;
71
72	getenv();
73
74	mpdata := sys->open("/dev/mpeg", sys->OWRITE);
75	if(mpdata == nil)
76		return sys->sprint("can't open /dev/mpeg: %r");
77
78	obj := sys->open(file, sys->OREAD);
79	if(obj == nil)
80		return "open failed:"+file;
81
82	n := sys->read(obj, buf, len buf);
83	if(n < 0)
84		return "mpeg object: read error";
85
86	mpctl := sys->open("/dev/mpegctl", sys->OWRITE);
87	if(mpctl == nil)
88		return "open mpeg ctl file";
89
90	# Parse into lines
91	(n, arg) = sys->tokenize(string buf[0:n], "\n");
92	for(i = 0; i < n; i++) {
93		# Parse into words
94		line = hd arg;
95		(j, words) = sys->tokenize(line, " \t");
96
97		# Pass device config lines through to the ctl file
98		if(hd words == "files")
99			files = tl words;
100		else {
101			cfg = array of byte line;
102			if(sys->write(mpctl, cfg, len cfg) < 0)
103				return "invalid device config:"+line;
104		}
105		arg = tl arg;
106	}
107
108	if(files == nil)
109		return "no file to play";
110
111	# now the driver is configured initialize the dsp's
112	# and set up the trident overlay
113	sys->fprint(mpctl, "init");
114	sys->fprint(mpctl, "window %d %d %d %d",
115			r.min.x, r.min.y, r.max.x, r.max.y);
116
117	# paint the window with the chroma key color
118	if(paint)
119		w.draw(r, keycolor(display), nil, r.min);
120
121	if(notify != nil) {
122		spawn copy(files, notify, mpctl, mpdata);
123		return "";
124	}
125	notify = chan of string;
126	spawn copy(files, notify, mpctl, mpdata);
127	return <-notify;
128}
129
130ctl(msg: string): int
131{
132	mpc: ref FD;
133
134	getenv();
135
136	mpc = sys->open("/dev/mpegctl", sys->OWRITE);
137	if(mpc == nil)
138		return -1;
139
140	b := array of byte msg;
141	n := sys->write(mpc, b, len b);
142	if(n != len b)
143		n = -1;
144
145	return n;
146}
147
148keycolor(display: ref Display): ref Image
149{
150	getenv();
151	return display.color(Chroma);
152}
153