123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261 |
- #include <u.h>
- #include <libc.h>
- #include <bio.h>
- #include <ctype.h>
- char *server = "freedb.freedb.org";
- int debug;
- #define DPRINT if(debug)fprint
- int tflag;
- int Tflag;
- typedef struct Track Track;
- struct Track {
- int n;
- char *title;
- };
- enum {
- MTRACK = 64,
- };
- typedef struct Toc Toc;
- struct Toc {
- ulong diskid;
- int ntrack;
- char *title;
- Track track[MTRACK];
- };
- void*
- emalloc(uint n)
- {
- void *p;
- p = malloc(n);
- if(p == nil)
- sysfatal("can't malloc: %r");
- memset(p, 0, n);
- return p;
- }
- char*
- estrdup(char *s)
- {
- char *t;
- t = emalloc(strlen(s)+1);
- strcpy(t, s);
- return t;
- }
- static void
- dumpcddb(Toc *t)
- {
- int i, n, s;
- print("title %s\n", t->title);
- for(i=0; i<t->ntrack; i++){
- if(tflag){
- n = t->track[i+1].n;
- if(i == t->ntrack-1)
- n *= 75;
- s = (n - t->track[i].n)/75;
- print("%d\t%s\t%d:%2.2d\n", i+1, t->track[i].title, s/60, s%60);
- }
- else
- print("%d\t%s\n", i+1, t->track[i].title);
- }
- if(Tflag){
- s = t->track[i].n;
- print("Total time: %d:%2.2d\n", s/60, s%60);
- }
- }
- char*
- append(char *a, char *b)
- {
- char *c;
- c = emalloc(strlen(a)+strlen(b)+1);
- strcpy(c, a);
- strcat(c, b);
- return c;
- }
- static int
- cddbfilltoc(Toc *t)
- {
- int fd;
- int i;
- char *p, *q;
- Biobuf bin;
- char *f[10];
- int nf;
- char *id, *categ;
- fd = dial(netmkaddr(server, "tcp", "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;
- /*
- * Protocol level 6 is the same as level 5 except that
- * the character set is now UTF-8 instead of ISO-8859-1.
- */
- fprint(fd, "proto 6\r\n");
- DPRINT(2, "proto 6\r\n");
- if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2)
- goto died;
- p[Blinelen(&bin)-1] = 0;
- DPRINT(2, "cddb: %s\n", p);
- fprint(fd, "cddb query %8.8lux %d", t->diskid, t->ntrack);
- DPRINT(2, "cddb query %8.8lux %d", t->diskid, t->ntrack);
- for(i=0; i<t->ntrack; i++) {
- fprint(fd, " %d", t->track[i].n);
- DPRINT(2, " %d", t->track[i].n);
- }
- fprint(fd, " %d\r\n", t->track[t->ntrack].n);
- DPRINT(2, " %d\r\n", t->track[t->ntrack].n);
- 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;
- }
- t->title = "";
- for(i=0; i<t->ntrack; i++)
- t->track[i].title = "";
- /* 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 = append(t->title, 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 = append(t->track[i].title, estrdup(p));
- }
- }
- } while(*p != '.');
- fprint(fd, "quit\r\n");
- close(fd);
- Bterm(&bin);
- return 0;
- }
- void
- usage(void)
- {
- fprint(2, "usage: aux/cddb [-DTt] [-s server] query diskid n ...\n");
- exits("usage");
- }
- void
- main(int argc, char **argv)
- {
- int i;
- Toc toc;
- ARGBEGIN{
- case 'D':
- debug = 1;
- break;
- case 's':
- server = EARGF(usage());
- break;
- case 'T':
- Tflag = 1;
- /*FALLTHROUGH*/
- case 't':
- tflag = 1;
- break;
- }ARGEND
- if(argc < 3 || strcmp(argv[0], "query") != 0)
- usage();
- toc.diskid = strtoul(argv[1], 0, 16);
- toc.ntrack = atoi(argv[2]);
- if(argc != 3+toc.ntrack+1)
- sysfatal("argument count does not match given ntrack");
- for(i=0; i<=toc.ntrack; i++)
- toc.track[i].n = atoi(argv[3+i]);
- if(cddbfilltoc(&toc) < 0)
- exits("whoops");
- dumpcddb(&toc);
- exits(nil);
- }
|