123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170 |
- #include "acd.h"
- #include <ctype.h>
- /* see CDDBPROTO */
- static ulong
- cddb_sum(int n)
- {
- int ret;
- ret = 0;
- while(n > 0) {
- ret += n%10;
- n /= 10;
- }
- return ret;
- }
- static ulong
- diskid(Toc *t)
- {
- int i, n, tmp;
- Msf *ms, *me;
- n = 0;
- for(i=0; i < t->ntrack; i++)
- n += cddb_sum(t->track[i].start.m*60+t->track[i].start.s);
- ms = &t->track[0].start;
- me = &t->track[t->ntrack].start;
- tmp = (me->m*60+me->s) - (ms->m*60+ms->s);
- /*
- * the spec says n%0xFF rather than n&0xFF. it's unclear which is correct.
- * most CDs are in the database under both entries.
- */
- return ((n & 0xFF) << 24 | (tmp << 8) | t->ntrack);
- }
- static int
- cddbfilltoc(Toc *t)
- {
- int fd;
- int i;
- char *p, *q;
- Biobuf bin;
- Msf *m;
- char *f[10];
- int nf;
- char *id, *categ;
- fd = dial("tcp!freedb.freedb.org!888", 0, 0, 0);
- if(fd < 0) {
- fprint(2, "cannot dial: %r\n");
- return -1;
- }
- Binit(&bin, fd, OREAD);
- if((p=Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2) {
- died:
- close(fd);
- Bterm(&bin);
- fprint(2, "error talking to server\n");
- if(p) {
- p[Blinelen(&bin)-1] = 0;
- fprint(2, "server says: %s\n", p);
- }
- return -1;
- }
- fprint(fd, "cddb hello gre plan9 9cd 1.0\r\n");
- if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2)
- goto died;
- fprint(fd, "cddb query %8.8lux %d", diskid(t), t->ntrack);
- DPRINT(2, "cddb query %8.8lux %d", diskid(t), t->ntrack);
- for(i=0; i<t->ntrack; i++) {
- m = &t->track[i].start;
- fprint(fd, " %d", (m->m*60+m->s)*75+m->f);
- DPRINT(2, " %d", (m->m*60+m->s)*75+m->f);
- }
- m = &t->track[t->ntrack-1].end;
- fprint(fd, " %d\r\n", m->m*60+m->s);
- DPRINT(2, " %d\r\n", m->m*60+m->s);
- if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2)
- goto died;
- p[Blinelen(&bin)-1] = 0;
- DPRINT(2, "cddb: %s\n", p);
- nf = tokenize(p, f, nelem(f));
- if(nf < 1)
- goto died;
- switch(atoi(f[0])) {
- case 200: /* exact match */
- if(nf < 3)
- goto died;
- categ = f[1];
- id = f[2];
- break;
- case 211: /* close matches */
- if((p = Brdline(&bin, '\n')) == nil)
- goto died;
- if(p[0] == '.') /* no close matches? */
- goto died;
- p[Blinelen(&bin)-1] = '\0';
- /* accept first match */
- nf = tokenize(p, f, nelem(f));
- if(nf < 2)
- goto died;
- categ = f[0];
- id = f[1];
- /* snarf rest of buffer */
- while(p[0] != '.') {
- if((p = Brdline(&bin, '\n')) == nil)
- goto died;
- p[Blinelen(&bin)-1] = '\0';
- DPRINT(2, "cddb: %s\n", p);
- }
- break;
- case 202: /* no match */
- default:
- goto died;
- }
- /* fetch results for this cd */
- fprint(fd, "cddb read %s %s\r\n", categ, id);
- do {
- if((p = Brdline(&bin, '\n')) == nil)
- goto died;
- q = p+Blinelen(&bin)-1;
- while(isspace(*q))
- *q-- = 0;
- DPRINT(2, "cddb %s\n", p);
- if(strncmp(p, "DTITLE=", 7) == 0)
- t->title = estrdup(p+7);
- else if(strncmp(p, "TTITLE", 6) == 0 && isdigit(p[6])) {
- i = atoi(p+6);
- if(i < t->ntrack) {
- p += 6;
- while(isdigit(*p))
- p++;
- if(*p == '=')
- p++;
- t->track[i].title = estrdup(p);
- }
- }
- } while(*p != '.');
- fprint(fd, "quit\r\n");
- close(fd);
- Bterm(&bin);
- return 0;
- }
- void
- cddbproc(void *v)
- {
- Drive *d;
- Toc t;
- threadsetname("cddbproc");
- d = v;
- while(recv(d->cdbreq, &t))
- if(cddbfilltoc(&t) == 0)
- send(d->cdbreply, &t);
- }
|