347 lines
6.5 KiB
C
347 lines
6.5 KiB
C
#include "acd.h"
|
|
|
|
static int
|
|
iscmd(char *s, char *cmd)
|
|
{
|
|
int len;
|
|
|
|
len = strlen(cmd);
|
|
return strncmp(s, cmd, len)==0 && (s[len]=='\0' || s[len]==' ' || s[len]=='\t' || s[len]=='\n');
|
|
}
|
|
|
|
static char*
|
|
skip(char *s, char *cmd)
|
|
{
|
|
s += strlen(cmd);
|
|
while(*s==' ' || *s=='\t' || *s=='\n')
|
|
s++;
|
|
return s;
|
|
}
|
|
|
|
//#define PLAYSTRING "/^[0-9:]+>"
|
|
//#define PLAYSTRINGSPACE "/^[0-9:]+> ?"
|
|
//#define INITSTRING "0:00> "
|
|
|
|
#define INITSTRING "> "
|
|
#define PLAYSTRING "/^>"
|
|
#define PLAYSTRINGSPACE "/^> ?"
|
|
|
|
/*
|
|
* find the playing string, leave in addr
|
|
* if q0, q1 are non-nil, set them to the addr of the string.
|
|
*/
|
|
int
|
|
findplay(Window *w, char *s, ulong *q0, ulong *q1)
|
|
{
|
|
char xbuf[25];
|
|
if(w->data < 0)
|
|
w->data = winopenfile(w, "data");
|
|
|
|
if(!winsetaddr(w, "#0", 1) || !winsetaddr(w, s, 1))
|
|
return 0;
|
|
|
|
seek(w->addr, 0, 0);
|
|
if(read(w->addr, xbuf, 24) != 24)
|
|
return 0;
|
|
|
|
xbuf[24] = 0;
|
|
if(q0)
|
|
*q0 = atoi(xbuf);
|
|
if(q1)
|
|
*q1 = atoi(xbuf+12);
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* find the playing string and replace the time
|
|
*/
|
|
int
|
|
setplaytime(Window *w, char *new)
|
|
{
|
|
char buf[40];
|
|
ulong q0, q1;
|
|
|
|
return 1;
|
|
if(!findplay(w, PLAYSTRING, &q0, &q1))
|
|
return 0;
|
|
|
|
q1--; /* > */
|
|
sprint(buf, "#%lud,#%lud", q0, q1);
|
|
DPRINT(2, "setaddr %s\n", buf);
|
|
if(!winsetaddr(w, buf, 1))
|
|
return 0;
|
|
|
|
if(write(w->data, new, strlen(new)) != strlen(new))
|
|
return 0;
|
|
|
|
return 1;
|
|
}
|
|
|
|
/*
|
|
* find the playing string, and remove it.
|
|
* return the string at the beginning of hte next line in buf
|
|
* (presumably a track number).
|
|
*/
|
|
static int
|
|
unmarkplay(Window *w, char *buf, int n, ulong *q0, ulong *q1, ulong *qbegin)
|
|
{
|
|
char xbuf[24];
|
|
|
|
if(!findplay(w, PLAYSTRINGSPACE, q0, q1))
|
|
return 0;
|
|
|
|
if(write(w->data, "", 0) < 0 || !winsetaddr(w, "+1+#0", 1))
|
|
return 0;
|
|
|
|
if(qbegin) {
|
|
seek(w->addr, 0, 0);
|
|
if(read(w->addr, xbuf, 24) != 24)
|
|
return 0;
|
|
*qbegin = atoi(xbuf);
|
|
}
|
|
|
|
if(buf) {
|
|
if((n = read(w->data, buf, n-1)) < 0)
|
|
return 0;
|
|
|
|
buf[n] = '\0';
|
|
}
|
|
|
|
return 1;
|
|
}
|
|
|
|
int
|
|
markplay(Window *w, ulong q0)
|
|
{
|
|
char buf[20];
|
|
|
|
if(w->data < 0)
|
|
w->data = winopenfile(w, "data");
|
|
|
|
sprint(buf, "#%lud", q0);
|
|
DPRINT(2, "addr %s\n", buf);
|
|
if(!winsetaddr(w, buf, 1) || !winsetaddr(w, "-0", 1))
|
|
return 0;
|
|
if(write(w->data, INITSTRING, strlen(INITSTRING)) != strlen(INITSTRING))
|
|
return 0;
|
|
return 1;
|
|
}
|
|
|
|
/* return 1 if handled, 0 otherwise */
|
|
int
|
|
cdcommand(Window *w, Drive *d, char *s)
|
|
{
|
|
s = skip(s, "");
|
|
|
|
if(iscmd(s, "Del")){
|
|
if(windel(w, 0))
|
|
threadexitsall(nil);
|
|
return 1;
|
|
}
|
|
if(iscmd(s, "Stop")){
|
|
unmarkplay(w, nil, 0, nil, nil, nil);
|
|
stop(d);
|
|
return 1;
|
|
}
|
|
if(iscmd(s, "Eject")){
|
|
unmarkplay(w, nil, 0, nil, nil, nil);
|
|
eject(d);
|
|
return 1;
|
|
}
|
|
if(iscmd(s, "Ingest")){
|
|
unmarkplay(w, nil, 0, nil, nil, nil);
|
|
ingest(d);
|
|
return 1;
|
|
}
|
|
if(iscmd(s, "Pause")){
|
|
pause(d);
|
|
return 1;
|
|
}
|
|
if(iscmd(s, "Resume")){
|
|
resume(d);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void
|
|
drawtoc(Window *w, Drive *d, Toc *t)
|
|
{
|
|
int i, playing;
|
|
|
|
if(w->data < 0)
|
|
w->data = winopenfile(w, "data");
|
|
if(!winsetaddr(w, ",", 1))
|
|
return;
|
|
|
|
fprint(w->data, "Title\n\n");
|
|
playing = -1;
|
|
if(d->status.state == Splaying || d->status.state == Spaused)
|
|
playing = d->status.track-t->track0;
|
|
|
|
for(i=0; i<t->ntrack; i++)
|
|
fprint(w->data, "%s%d/ Track %d\n", i==playing ? "> " : "", i+1, i+1);
|
|
fprint(w->data, "");
|
|
}
|
|
|
|
void
|
|
redrawtoc(Window *w, Toc *t)
|
|
{
|
|
int i;
|
|
char old[50];
|
|
|
|
if(w->data < 0)
|
|
w->data = winopenfile(w, "data");
|
|
if(t->title) {
|
|
if(winsetaddr(w, "/Title", 1))
|
|
write(w->data, t->title, strlen(t->title));
|
|
}
|
|
for(i=0; i<t->ntrack; i++) {
|
|
if(t->track[i].title) {
|
|
sprint(old, "/Track %d", i+1);
|
|
if(winsetaddr(w, old, 1))
|
|
write(w->data, t->track[i].title, strlen(t->track[i].title));
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
advancetrack(Drive *d, Window *w)
|
|
{
|
|
int n;
|
|
ulong q0, q1, qnext;
|
|
char buf[20];
|
|
|
|
q0 = q1 = 0;
|
|
if(!unmarkplay(w, buf, sizeof(buf), &q0, &q1, &qnext)) {
|
|
DPRINT(2, "unmark: %r\n");
|
|
return;
|
|
}
|
|
|
|
DPRINT(2, "buf: %s\n", buf);
|
|
if(strncmp(buf, "repeat", 6) == 0) {
|
|
if(!winsetaddr(w, "#0", 1) || !findplay(w, "/^[0-9]+\\/", &qnext, nil)) {
|
|
DPRINT(2, "set/find: %r\n");
|
|
return;
|
|
}
|
|
if(w->data < 0)
|
|
w->data = winopenfile(w, "data");
|
|
if((n = read(w->data, buf, sizeof(buf)-1)) <= 0) {
|
|
DPRINT(2, "read %d: %r\n", n);
|
|
return;
|
|
}
|
|
buf[n] = 0;
|
|
DPRINT(2, "buf: %s\n", buf);
|
|
}
|
|
|
|
if((n = atoi(buf)) == 0)
|
|
return;
|
|
|
|
if(!markplay(w, qnext))
|
|
DPRINT(2, "err: %r");
|
|
|
|
playtrack(d, n-1, n-1);
|
|
}
|
|
|
|
void
|
|
acmeevent(Drive *d, Window *w, Event *e)
|
|
{
|
|
Event *ea, *e2, *eq;
|
|
char *s, *t, *buf;
|
|
int n, na;
|
|
ulong q0, q1;
|
|
|
|
switch(e->c1){ /* origin of action */
|
|
default:
|
|
Unknown:
|
|
fprint(2, "unknown message %c%c\n", e->c1, e->c2);
|
|
break;
|
|
|
|
case 'E': /* write to body or tag; can't affect us */
|
|
break;
|
|
|
|
case 'F': /* generated by our actions; ignore */
|
|
break;
|
|
|
|
case 'K': /* type away; we don't care */
|
|
break;
|
|
|
|
case 'M': /* mouse event */
|
|
switch(e->c2){ /* type of action */
|
|
case 'x': /* mouse: button 2 in tag */
|
|
case 'X': /* mouse: button 2 in body */
|
|
ea = nil;
|
|
// e2 = nil;
|
|
s = e->b;
|
|
if(e->flag & 2){ /* null string with non-null expansion */
|
|
e2 = recvp(w->cevent);
|
|
if(e->nb==0)
|
|
s = e2->b;
|
|
}
|
|
if(e->flag & 8){ /* chorded argument */
|
|
ea = recvp(w->cevent); /* argument */
|
|
na = ea->nb;
|
|
recvp(w->cevent); /* ignore origin */
|
|
}else
|
|
na = 0;
|
|
|
|
/* append chorded arguments */
|
|
if(na){
|
|
t = emalloc(strlen(s)+1+na+1);
|
|
sprint(t, "%s %s", s, ea->b);
|
|
s = t;
|
|
}
|
|
/* if it's a known command, do it */
|
|
/* if it's a long message, it can't be for us anyway */
|
|
DPRINT(2, "exec: %s\n", s);
|
|
if(!cdcommand(w, d, s)) /* send it back */
|
|
winwriteevent(w, e);
|
|
if(na)
|
|
free(s);
|
|
break;
|
|
|
|
case 'l': /* mouse: button 3 in tag */
|
|
case 'L': /* mouse: button 3 in body */
|
|
// buf = nil;
|
|
eq = e;
|
|
if(e->flag & 2){
|
|
e2 = recvp(w->cevent);
|
|
eq = e2;
|
|
}
|
|
s = eq->b;
|
|
if(eq->q1>eq->q0 && eq->nb==0){
|
|
buf = emalloc((eq->q1-eq->q0)*UTFmax+1);
|
|
winread(w, eq->q0, eq->q1, buf);
|
|
s = buf;
|
|
}
|
|
DPRINT(2, "load %s\n", s);
|
|
if((n = atoi(s)) != 0) {
|
|
DPRINT(2, "mark %d\n", n);
|
|
q0 = q1 = 0;
|
|
unmarkplay(w, nil, 0, &q0, &q1, nil);
|
|
|
|
/* adjust eq->q* for deletion */
|
|
if(eq->q0 > q1) {
|
|
eq->q0 -= (q1-q0);
|
|
eq->q1 -= (q1-q0);
|
|
}
|
|
if(!markplay(w, eq->q0))
|
|
DPRINT(2, "err: %r\n");
|
|
|
|
playtrack(d, n-1, n-1);
|
|
} else
|
|
winwriteevent(w, e);
|
|
break;
|
|
|
|
case 'i': /* mouse: text inserted in tag */
|
|
case 'I': /* mouse: text inserted in body */
|
|
case 'd': /* mouse: text deleted from tag */
|
|
case 'D': /* mouse: text deleted from body */
|
|
break;
|
|
|
|
default:
|
|
goto Unknown;
|
|
}
|
|
}
|
|
}
|