]> git.lizzy.rs Git - plan9front.git/blob - acme/bin/source/acd/acme.c
fill /acme
[plan9front.git] / acme / bin / source / acd / acme.c
1 #include "acd.h"
2
3 static int
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*
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
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
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
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
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
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
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
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
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
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 }