cddb.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include "acd.h"
  10. #include <ctype.h>
  11. /* see CDDBPROTO */
  12. static uint32_t
  13. cddb_sum(int n)
  14. {
  15. int ret;
  16. ret = 0;
  17. while(n > 0) {
  18. ret += n%10;
  19. n /= 10;
  20. }
  21. return ret;
  22. }
  23. static uint32_t
  24. diskid(Toc *t)
  25. {
  26. int i, n, tmp;
  27. Msf *ms, *me;
  28. n = 0;
  29. for(i=0; i < t->ntrack; i++)
  30. n += cddb_sum(t->track[i].start.m*60+t->track[i].start.s);
  31. ms = &t->track[0].start;
  32. me = &t->track[t->ntrack].start;
  33. tmp = (me->m*60+me->s) - (ms->m*60+ms->s);
  34. /*
  35. * the spec says n%0xFF rather than n&0xFF. it's unclear which is correct.
  36. * most CDs are in the database under both entries.
  37. */
  38. return ((n & 0xFF) << 24 | (tmp << 8) | t->ntrack);
  39. }
  40. static void
  41. append(char **d, char *s)
  42. {
  43. char *r;
  44. if (*d == nil)
  45. *d = estrdup(s);
  46. else {
  47. r = emalloc(strlen(*d) + strlen(s) + 1);
  48. strcpy(r, *d);
  49. strcat(r, s);
  50. free(*d);
  51. *d = r;
  52. }
  53. }
  54. static int
  55. cddbfilltoc(Toc *t)
  56. {
  57. int fd;
  58. int i;
  59. char *p, *q;
  60. Biobuf bin;
  61. Msf *m;
  62. char *f[10];
  63. int nf;
  64. char *id, *categ;
  65. char gottrack[MTRACK];
  66. int gottitle;
  67. fd = dial("tcp!freedb.freedb.org!888", 0, 0, 0);
  68. if(fd < 0) {
  69. fprint(2, "cannot dial: %r\n");
  70. return -1;
  71. }
  72. Binit(&bin, fd, OREAD);
  73. if((p=Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2) {
  74. died:
  75. close(fd);
  76. Bterm(&bin);
  77. fprint(2, "error talking to server\n");
  78. if(p) {
  79. p[Blinelen(&bin)-1] = 0;
  80. fprint(2, "server says: %s\n", p);
  81. }
  82. return -1;
  83. }
  84. fprint(fd, "cddb hello gre plan9 9cd 1.0\r\n");
  85. if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2)
  86. goto died;
  87. fprint(fd, "cddb query %8.8lux %d", diskid(t), t->ntrack);
  88. DPRINT(2, "cddb query %8.8lux %d", diskid(t), t->ntrack);
  89. for(i=0; i<t->ntrack; i++) {
  90. m = &t->track[i].start;
  91. fprint(fd, " %d", (m->m*60+m->s)*75+m->f);
  92. DPRINT(2, " %d", (m->m*60+m->s)*75+m->f);
  93. }
  94. m = &t->track[t->ntrack-1].end;
  95. fprint(fd, " %d\r\n", m->m*60+m->s);
  96. DPRINT(2, " %d\r\n", m->m*60+m->s);
  97. if((p = Brdline(&bin, '\n')) == nil || atoi(p)/100 != 2)
  98. goto died;
  99. p[Blinelen(&bin)-1] = 0;
  100. DPRINT(2, "cddb: %s\n", p);
  101. nf = tokenize(p, f, nelem(f));
  102. if(nf < 1)
  103. goto died;
  104. switch(atoi(f[0])) {
  105. case 200: /* exact match */
  106. if(nf < 3)
  107. goto died;
  108. categ = f[1];
  109. id = f[2];
  110. break;
  111. case 211: /* close matches */
  112. if((p = Brdline(&bin, '\n')) == nil)
  113. goto died;
  114. if(p[0] == '.') /* no close matches? */
  115. goto died;
  116. p[Blinelen(&bin)-1] = '\0';
  117. /* accept first match */
  118. nf = tokenize(p, f, nelem(f));
  119. if(nf < 2)
  120. goto died;
  121. categ = f[0];
  122. id = f[1];
  123. /* snarf rest of buffer */
  124. while(p[0] != '.') {
  125. if((p = Brdline(&bin, '\n')) == nil)
  126. goto died;
  127. p[Blinelen(&bin)-1] = '\0';
  128. DPRINT(2, "cddb: %s\n", p);
  129. }
  130. break;
  131. case 202: /* no match */
  132. default:
  133. goto died;
  134. }
  135. /* fetch results for this cd */
  136. fprint(fd, "cddb read %s %s\r\n", categ, id);
  137. memset(gottrack, 0, sizeof(gottrack));
  138. gottitle = 0;
  139. do {
  140. if((p = Brdline(&bin, '\n')) == nil)
  141. goto died;
  142. q = p+Blinelen(&bin)-1;
  143. while(isspace(*q))
  144. *q-- = 0;
  145. DPRINT(2, "cddb %s\n", p);
  146. if(strncmp(p, "DTITLE=", 7) == 0) {
  147. if (gottitle)
  148. append(&t->title, p + 7);
  149. else
  150. t->title = estrdup(p+7);
  151. gottitle = 1;
  152. } else if(strncmp(p, "TTITLE", 6) == 0 && isdigit(p[6])) {
  153. i = atoi(p+6);
  154. if(i < t->ntrack) {
  155. p += 6;
  156. while(isdigit(*p))
  157. p++;
  158. if(*p == '=')
  159. p++;
  160. if (gottrack[i])
  161. append(&t->track[i].title, p);
  162. else
  163. t->track[i].title = estrdup(p);
  164. gottrack[i] = 1;
  165. }
  166. }
  167. } while(*p != '.');
  168. fprint(fd, "quit\r\n");
  169. close(fd);
  170. Bterm(&bin);
  171. return 0;
  172. }
  173. void
  174. cddbproc(void *v)
  175. {
  176. Drive *d;
  177. Toc t;
  178. threadsetname("cddbproc");
  179. d = v;
  180. while(recv(d->cdbreq, &t))
  181. if(cddbfilltoc(&t) == 0)
  182. send(d->cdbreply, &t);
  183. }