Subversion Repositories planix.SVN

Rev

Rev 2 | Details | Compare with Previous | Last modification | View Log | RSS feed

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