1 #include "acd.h"
2
3 static int
iscmd(char * s,char * cmd)4 iscmd(char *s, char *cmd)
5 {
6 int len;
7
8 len = strlen(cmd);
9 return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n');
10 }
11
12 static char*
skip(char * s,char * cmd)13 skip(char *s, char *cmd)
14 {
15 s += strlen(cmd);
16 while(*s==' ' || *s=='\t' || *s=='\n')
17 s++;
18 return s;
19 }
20
21 //#define PLAYSTRING "/^[0-9:]+>"
22 //#define PLAYSTRINGSPACE "/^[0-9:]+> ?"
23 //#define INITSTRING "0:00> "
24
25 #define INITSTRING "> "
26 #define PLAYSTRING "/^>"
27 #define PLAYSTRINGSPACE "/^> ?"
28
29 /*
30 * find the playing string, leave in addr
31 * if q0, q1 are non-nil, set them to the addr of the string.
32 */
33 int
findplay(Window * w,char * s,ulong * q0,ulong * q1)34 findplay(Window *w, char *s, ulong *q0, ulong *q1)
35 {
36 char xbuf[25];
37 if(w->data < 0)
38 w->data = winopenfile(w, "data");
39
40 if(!winsetaddr(w, "#0", 1) || !winsetaddr(w, s, 1))
41 return 0;
42
43 seek(w->addr, 0, 0);
44 if(read(w->addr, xbuf, 24) != 24)
45 return 0;
46
47 xbuf[24] = 0;
48 if(q0)
49 *q0 = atoi(xbuf);
50 if(q1)
51 *q1 = atoi(xbuf+12);
52
53 return 1;
54 }
55
56 /*
57 * find the playing string and replace the time
58 */
59 int
setplaytime(Window * w,char * new)60 setplaytime(Window *w, char *new)
61 {
62 char buf[40];
63 ulong q0, q1;
64
65 return 1;
66 if(!findplay(w, PLAYSTRING, &q0, &q1))
67 return 0;
68
69 q1--; /* > */
70 sprint(buf, "#%lud,#%lud", q0, q1);
71 DPRINT(2, "setaddr %s\n", buf);
72 if(!winsetaddr(w, buf, 1))
73 return 0;
74
75 if(write(w->data, new, strlen(new)) != strlen(new))
76 return 0;
77
78 return 1;
79 }
80
81 /*
82 * find the playing string, and remove it.
83 * return the string at the beginning of hte next line in buf
84 * (presumably a track number).
85 */
86 static int
unmarkplay(Window * w,char * buf,int n,ulong * q0,ulong * q1,ulong * qbegin)87 unmarkplay(Window *w, char *buf, int n, ulong *q0, ulong *q1, ulong *qbegin)
88 {
89 char xbuf[24];
90
91 if(!findplay(w, PLAYSTRINGSPACE, q0, q1))
92 return 0;
93
94 if(write(w->data, "", 0) < 0 || !winsetaddr(w, "+1+#0", 1))
95 return 0;
96
97 if(qbegin) {
98 seek(w->addr, 0, 0);
99 if(read(w->addr, xbuf, 24) != 24)
100 return 0;
101 *qbegin = atoi(xbuf);
102 }
103
104 if(buf) {
105 if((n = read(w->data, buf, n-1)) < 0)
106 return 0;
107
108 buf[n] = '\0';
109 }
110
111 return 1;
112 }
113
114 int
markplay(Window * w,ulong q0)115 markplay(Window *w, ulong q0)
116 {
117 char buf[20];
118
119 if(w->data < 0)
120 w->data = winopenfile(w, "data");
121
122 sprint(buf, "#%lud", q0);
123 DPRINT(2, "addr %s\n", buf);
124 if(!winsetaddr(w, buf, 1) || !winsetaddr(w, "-0", 1))
125 return 0;
126 if(write(w->data, INITSTRING, strlen(INITSTRING)) != strlen(INITSTRING))
127 return 0;
128 return 1;
129 }
130
131 /* return 1 if handled, 0 otherwise */
132 int
cdcommand(Window * w,Drive * d,char * s)133 cdcommand(Window *w, Drive *d, char *s)
134 {
135 s = skip(s, "");
136
137 if(iscmd(s, "Del")){
138 if(windel(w, 0))
139 threadexitsall(nil);
140 return 1;
141 }
142 if(iscmd(s, "Stop")){
143 unmarkplay(w, nil, 0, nil, nil, nil);
144 stop(d);
145 return 1;
146 }
147 if(iscmd(s, "Eject")){
148 unmarkplay(w, nil, 0, nil, nil, nil);
149 eject(d);
150 return 1;
151 }
152 if(iscmd(s, "Ingest")){
153 unmarkplay(w, nil, 0, nil, nil, nil);
154 ingest(d);
155 return 1;
156 }
157 if(iscmd(s, "Pause")){
158 pause(d);
159 return 1;
160 }
161 if(iscmd(s, "Resume")){
162 resume(d);
163 return 1;
164 }
165 return 0;
166 }
167
168 void
drawtoc(Window * w,Drive * d,Toc * t)169 drawtoc(Window *w, Drive *d, Toc *t)
170 {
171 int i, playing;
172
173 if(w->data < 0)
174 w->data = winopenfile(w, "data");
175 if(!winsetaddr(w, ",", 1))
176 return;
177
178 fprint(w->data, "Title\n\n");
179 playing = -1;
180 if(d->status.state == Splaying || d->status.state == Spaused)
181 playing = d->status.track-t->track0;
182
183 for(i=0; i<t->ntrack; i++)
184 fprint(w->data, "%s%d/ Track %d\n", i==playing ? "> " : "", i+1, i+1);
185 fprint(w->data, "");
186 }
187
188 void
redrawtoc(Window * w,Toc * t)189 redrawtoc(Window *w, Toc *t)
190 {
191 int i;
192 char old[50];
193
194 if(w->data < 0)
195 w->data = winopenfile(w, "data");
196 if(t->title) {
197 if(winsetaddr(w, "/Title", 1))
198 write(w->data, t->title, strlen(t->title));
199 }
200 for(i=0; i<t->ntrack; i++) {
201 if(t->track[i].title) {
202 sprint(old, "/Track %d", i+1);
203 if(winsetaddr(w, old, 1))
204 write(w->data, t->track[i].title, strlen(t->track[i].title));
205 }
206 }
207 }
208
209 void
advancetrack(Drive * d,Window * w)210 advancetrack(Drive *d, Window *w)
211 {
212 int n;
213 ulong q0, q1, qnext;
214 char buf[20];
215
216 q0 = q1 = 0;
217 if(!unmarkplay(w, buf, sizeof(buf), &q0, &q1, &qnext)) {
218 DPRINT(2, "unmark: %r\n");
219 return;
220 }
221
222 DPRINT(2, "buf: %s\n", buf);
223 if(strncmp(buf, "repeat", 6) == 0) {
224 if(!winsetaddr(w, "#0", 1) || !findplay(w, "/^[0-9]+\\/", &qnext, nil)) {
225 DPRINT(2, "set/find: %r\n");
226 return;
227 }
228 if(w->data < 0)
229 w->data = winopenfile(w, "data");
230 if((n = read(w->data, buf, sizeof(buf)-1)) <= 0) {
231 DPRINT(2, "read %d: %r\n", n);
232 return;
233 }
234 buf[n] = 0;
235 DPRINT(2, "buf: %s\n", buf);
236 }
237
238 if((n = atoi(buf)) == 0)
239 return;
240
241 if(!markplay(w, qnext))
242 DPRINT(2, "err: %r");
243
244 playtrack(d, n-1, n-1);
245 }
246
247 void
acmeevent(Drive * d,Window * w,Event * e)248 acmeevent(Drive *d, Window *w, Event *e)
249 {
250 Event *ea, *e2, *eq;
251 char *s, *t, *buf;
252 int n, na;
253 ulong q0, q1;
254
255 switch(e->c1){ /* origin of action */
256 default:
257 Unknown:
258 fprint(2, "unknown message %c%c\n", e->c1, e->c2);
259 break;
260
261 case 'E': /* write to body or tag; can't affect us */
262 break;
263
264 case 'F': /* generated by our actions; ignore */
265 break;
266
267 case 'K': /* type away; we don't care */
268 break;
269
270 case 'M': /* mouse event */
271 switch(e->c2){ /* type of action */
272 case 'x': /* mouse: button 2 in tag */
273 case 'X': /* mouse: button 2 in body */
274 ea = nil;
275 // e2 = nil;
276 s = e->b;
277 if(e->flag & 2){ /* null string with non-null expansion */
278 e2 = recvp(w->cevent);
279 if(e->nb==0)
280 s = e2->b;
281 }
282 if(e->flag & 8){ /* chorded argument */
283 ea = recvp(w->cevent); /* argument */
284 na = ea->nb;
285 recvp(w->cevent); /* ignore origin */
286 }else
287 na = 0;
288
289 /* append chorded arguments */
290 if(na){
291 t = emalloc(strlen(s)+1+na+1);
292 sprint(t, "%s %s", s, ea->b);
293 s = t;
294 }
295 /* if it's a known command, do it */
296 /* if it's a long message, it can't be for us anyway */
297 DPRINT(2, "exec: %s\n", s);
298 if(!cdcommand(w, d, s)) /* send it back */
299 winwriteevent(w, e);
300 if(na)
301 free(s);
302 break;
303
304 case 'l': /* mouse: button 3 in tag */
305 case 'L': /* mouse: button 3 in body */
306 // buf = nil;
307 eq = e;
308 if(e->flag & 2){
309 e2 = recvp(w->cevent);
310 eq = e2;
311 }
312 s = eq->b;
313 if(eq->q1>eq->q0 && eq->nb==0){
314 buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
315 winread(w, eq->q0, eq->q1, buf);
316 s = buf;
317 }
318 DPRINT(2, "load %s\n", s);
319 if((n = atoi(s)) != 0) {
320 DPRINT(2, "mark %d\n", n);
321 q0 = q1 = 0;
322 unmarkplay(w, nil, 0, &q0, &q1, nil);
323
324 /* adjust eq->q* for deletion */
325 if(eq->q0 > q1) {
326 eq->q0 -= (q1-q0);
327 eq->q1 -= (q1-q0);
328 }
329 if(!markplay(w, eq->q0))
330 DPRINT(2, "err: %r\n");
331
332 playtrack(d, n-1, n-1);
333 } else
334 winwriteevent(w, e);
335 break;
336
337 case 'i': /* mouse: text inserted in tag */
338 case 'I': /* mouse: text inserted in body */
339 case 'd': /* mouse: text deleted from tag */
340 case 'D': /* mouse: text deleted from body */
341 break;
342
343 default:
344 goto Unknown;
345 }
346 }
347 }
348