Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 - 1
#include <u.h>
2
#include <libc.h>
3
#include <thread.h>
4
#include <draw.h>
5
#include <keyboard.h>
6
#include <mouse.h>
7
#include <control.h>
8
#include "playlist.h"
9
#include "../debug.h"
10
 
11
char *playlistfile = "/mnt/playlist";
12
char *playctlfile = "/mnt/playctl";
13
char *playvolfile = "/mnt/playvol";
14
char *volumefile = "/dev/audioctl";
15
 
16
Playlist	playlist;
17
int		playctlfd;
18
 
19
void
20
playlistproc(void*)
21
{
22
	int fd, m, n, nf;
23
	static char buf[8192+1];
24
	char *p, *q, *fields[4];
25
 
26
	threadsetname("playlistproc");
27
	fd = open(playlistfile, OREAD);
28
	if(fd < 0)
29
		sysfatal("%s: %r", playlistfile);
30
	p = buf;
31
	n = 0;
32
	if(debug & DBGPLAY)
33
		fprint(2, "playlistproc: starting\n");
34
	for(;;){
35
		m = read(fd, buf+n, sizeof buf - 1 - n);
36
		if(m == 0){
37
			if(debug & DBGPLAY)
38
				fprint(2, "playlistproc: empty read\n");
39
			continue;
40
		}
41
		if(m < 0){
42
			rerrstr(buf, sizeof(buf));
43
			if(strcmp(buf, "reading past eof"))
44
				sysfatal("%s: %r", playlistfile);
45
			for(n = 0; n < playlist.nentries; n++){
46
				free(playlist.entry[n].file);
47
				free(playlist.entry[n].onum);
48
			}
49
			if(debug & DBGPLAY)
50
				fprint(2, "playlistproc: trunc\n");
51
			playlist.nentries = 0;
52
			free(playlist.entry);
53
			playlist.entry = nil;
54
			updateplaylist(1);
55
			seek(fd, 0, 0);
56
			p = buf;
57
			n = 0;
58
			continue;
59
		}
60
		if(debug & DBGPLAY)
61
			fprint(2, "playlistproc: read %d bytes\n", m);
62
		n += m;
63
		p[n] = '\0';
64
		while(q = strchr(p, '\n')){
65
			*q = 0;
66
			nf = tokenize(p, fields, nelem(fields));
67
			if(nf){
68
				playlist.entry = realloc(playlist.entry, (playlist.nentries+1)*sizeof playlist.entry[0]);
69
				if(playlist.entry == nil)
70
					sysfatal("realloc %r");
71
				playlist.entry[playlist.nentries].file = strdup(fields[0]);
72
				if(nf > 1){
73
					playlist.entry[playlist.nentries].onum = strdup(fields[1]);
74
					if(debug & DBGPLAY)
75
						fprint(2, "playlistproc: [%d]: %q %q\n", playlist.nentries,
76
							playlist.entry[playlist.nentries].file,
77
							playlist.entry[playlist.nentries].onum);
78
				}else{
79
					playlist.entry[playlist.nentries].onum = nil;
80
					if(debug & DBGPLAY)
81
						fprint(2, "playlistproc: [%d]: %q nil\n", playlist.nentries,
82
							playlist.entry[playlist.nentries].file);
83
				}
84
				updateplaylist(0);	// this will also update nentries
85
			}
86
			q++;
87
			n -= q-p;
88
			p = q;
89
		}
90
		if(n)
91
			memmove(buf, p, n);
92
		p = buf;
93
	}
94
}
95
 
96
void
97
sendplaylist(char *file, char *onum)
98
{
99
	static int fd = -1;
100
	char *b;
101
 
102
	if(file == nil){
103
		if(fd >= 0)
104
			close(fd);
105
		fd = open(playlistfile, OWRITE|OTRUNC);
106
		if(fd < 0)
107
			sysfatal("%s: truncate: %r", playlistfile);
108
		return;
109
	}
110
	if(fd < 0){
111
		fd = open(playlistfile, OWRITE);
112
		if(fd < 0)
113
			sysfatal("%s: %r", playlistfile);
114
	}
115
	b = smprint("%q	%q\n", file, onum);
116
	if(debug & DBGPLAY)
117
		fprint(2, "sendplaylist @%s@\n", b);
118
	if(write(fd , b, strlen(b)) != strlen(b))
119
		sysfatal("sendplaylist: %r");
120
}
121
 
122
void
123
playctlproc(void*a)
124
{
125
	int fd, n, nf;
126
	static char buf[512+1];
127
	char *fields[4];
128
	Channel *chan;
129
 
130
	threadsetname("playctlproc");
131
	chan = a;
132
	fd = open(playctlfile, OREAD);
133
	if(fd < 0)
134
		sysfatal("%s: %r", playctlfile);
135
	for(;;){
136
		n = read(fd, buf, sizeof buf -1);
137
		if(n == 0)
138
			continue;
139
		if(n < 0)
140
			sysfatal("%s: %r", playctlfile);
141
		buf[n] = '\0';
142
		nf = tokenize(buf, fields, nelem(fields));
143
		if(nf == 0)
144
			continue;
145
		switch (nf){
146
		default:
147
			sysfatal("playctlproc: [%d]: %s", nf, fields[0]);
148
		case 3:
149
			chanprint(chan, "playctlproc: error %lud %q", strtoul(fields[1], nil, 0), fields[2]);
150
			if(strcmp(fields[0], "error") == 0)
151
				break;
152
			// fall through
153
		case 2:
154
			chanprint(chan, "playctlproc: %s %lud", fields[0], strtoul(fields[1], nil, 0));
155
		}
156
	}
157
}
158
 
159
void
160
sendplayctl(char *fmt, ...)
161
{
162
	va_list arg;
163
	static int fd = -1;
164
 
165
	va_start(arg, fmt);
166
	if(debug & DBGPLAY){
167
		fprint(2, "sendplayctl: fmt=%s: ", fmt);
168
		fprint(2, fmt, arg);
169
		fprint(2, "\n");
170
	}
171
	fprint(fd, fmt, arg);
172
	va_end(arg);
173
}
174
 
175
void
176
setvolume(char *volume)
177
{
178
	static int fd;
179
 
180
	if(fd == 0){
181
		fd = open(playvolfile, OWRITE);
182
		if(fd < 0){
183
			fprint(2, "can't open %s, (%r) opening %s instead\n", playvolfile, "/dev/volume");
184
			if((fd = open("/dev/volume", OWRITE)) < 0){
185
				fprint(2, "setvolume: open: %r\n");
186
				return;
187
			}
188
		}
189
	}
190
	if(fd < 0)
191
		return;
192
	fprint(fd, "volume %s", volume);
193
}
194
 
195
void
196
volumeproc(void *arg)
197
{
198
	int fd, n, nf, nnf, i, nlines;
199
	static char buf[1024];
200
	char *lines[32];
201
	char *fields[8];
202
	char *subfields[8];
203
	Channel *ctl;
204
	int volume, minvolume, maxvolume, nvolume;
205
 
206
	ctl = arg;
207
	threadsetname("volumeproc");
208
	fd = open(volumefile, OREAD);
209
	if(fd < 0){
210
		fprint(2, "%s: %r\n", volumefile);
211
		threadexits(nil);
212
	}
213
	for(;;){
214
		n = read(fd, buf, sizeof buf -1);
215
		if(n == 0)
216
			continue;
217
		if(n < 0){
218
			fprint(2, "volumeproc: read: %r\n");
219
			threadexits("volumeproc");
220
		}
221
		buf[n] = '\0';
222
		nlines = getfields(buf, lines, nelem(lines), 1, "\n");
223
		for(i = 0; i < nlines; i++){
224
			nf = tokenize(lines[i], fields, nelem(fields));
225
			if(nf == 0)
226
				continue;
227
			if(nf != 6 || strcmp(fields[0], "volume") || strcmp(fields[1], "out"))
228
				continue;
229
			minvolume = strtol(fields[3], nil, 0);
230
			maxvolume = strtol(fields[4], nil, 0);
231
			if(minvolume >= maxvolume)
232
				continue;
233
			nnf = tokenize(fields[2], subfields, nelem(subfields));
234
			if(nnf <= 0 || nnf > 8){
235
				fprint(2, "volume format error\n");
236
				threadexits(nil);
237
			}
238
			volume = 0;
239
			nvolume = 0;
240
			for(i = 0; i < nnf; i++){
241
				volume += strtol(subfields[i], nil, 0);
242
				nvolume++;
243
			}
244
			volume /= nvolume;
245
			volume = 100*(volume - minvolume)/(maxvolume-minvolume);
246
			chanprint(ctl, "volume value %d", volume);
247
		}
248
	}
249
}
250
 
251
void
252
playvolproc(void*a)
253
{
254
	int fd, n, nf, volume, nvolume, i;
255
	static char buf[256+1];
256
	static errors;
257
	char *fields[3], *subfields[9];
258
	Channel *chan;
259
 
260
	threadsetname("playvolproc");
261
	chan = a;
262
	fd = open(playvolfile, OREAD);
263
	if(fd < 0)
264
		sysfatal("%s: %r", playvolfile);
265
	for(;;){
266
		n = read(fd, buf, sizeof buf -1);
267
		if(n == 0)
268
			continue;
269
		if(n < 0){
270
			fprint(2, "%s: %r\n", playvolfile);
271
			threadexits("playvolproc");
272
		}
273
		buf[n] = '\0';
274
		if(debug) fprint(2, "volumestring: %s\n", buf);
275
		nf = tokenize(buf, fields, nelem(fields));
276
		if(nf == 0)
277
			continue;
278
		if(nf != 2 || strcmp(fields[0], "volume")){
279
			fprint(2, "playvolproc: [%d]: %s\n", nf, fields[0]);
280
			if(errors++ > 32)
281
				threadexits("playvolproc");
282
			continue;
283
		}
284
		nvolume = tokenize(fields[1], subfields, nelem(subfields));
285
		if(nvolume <= 0 || nvolume > 8){
286
			fprint(2, "volume format error\n");
287
			if(errors++ > 32)
288
				threadexits("playvolproc");
289
			continue;
290
		}
291
		volume = 0;
292
		for(i = 0; i < nvolume; i++)
293
			volume += strtol(subfields[i], nil, 0);
294
		volume /= nvolume;
295
		chanprint(chan, "volume value %d", volume);
296
	}
297
}