1 /*
2 $Id: cddb_disc.c,v 1.25 2007/08/07 03:12:53 jcaratzas Exp $
3
4 Copyright (C) 2003, 2004, 2005 Kris Verbeeck <airborne@advalvas.be>
5
6 This library is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This library is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public
17 License along with this library; if not, write to the
18 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.
20 */
21
22
23 #include "cddb/cddb_ni.h"
24
25 #include <math.h>
26 #include <stdlib.h>
27 #ifdef HAVE_STRING_H
28 #include <string.h>
29 #endif
30
31
32 const char *CDDB_CATEGORY[CDDB_CAT_LAST] = {
33 "data", "folk", "jazz", "misc", "rock", "country", "blues", "newage",
34 "reggae", "classical", "soundtrack",
35 "invalid"
36 };
37
38
39 /* --- private functions */
40
41
cddb_disc_iconv(iconv_t cd,cddb_disc_t * disc)42 int cddb_disc_iconv(iconv_t cd, cddb_disc_t *disc)
43 {
44 char *result;
45 cddb_track_t *track;
46
47 if (!cd) {
48 return TRUE; /* no user character set defined */
49 }
50 if (disc->genre) {
51 if (cddb_str_iconv(cd, disc->genre, &result)) {
52 free(disc->genre);
53 disc->genre = result;
54 } else {
55 return FALSE;
56 }
57 }
58 if (disc->title) {
59 if (cddb_str_iconv(cd, disc->title, &result)) {
60 free(disc->title);
61 disc->title = result;
62 } else {
63 return FALSE;
64 }
65 }
66 if (disc->artist) {
67 if (cddb_str_iconv(cd, disc->artist, &result)) {
68 free(disc->artist);
69 disc->artist = result;
70 } else {
71 return FALSE;
72 }
73 }
74 if (disc->ext_data) {
75 if (cddb_str_iconv(cd, disc->ext_data, &result)) {
76 free(disc->ext_data);
77 disc->ext_data = result;
78 } else {
79 return FALSE;
80 }
81 }
82 track = disc->tracks;
83 while (track) {
84 if (!cddb_track_iconv(cd, track)) {
85 return FALSE;
86 }
87 track = track->next;
88 }
89 return TRUE;
90 }
91
92
93 /* --- construction / destruction */
94
95
cddb_disc_new(void)96 cddb_disc_t *cddb_disc_new(void)
97 {
98 cddb_disc_t *disc;
99
100 disc = (cddb_disc_t*)calloc(1, sizeof(cddb_disc_t));
101 if (disc) {
102 disc->category = CDDB_CAT_INVALID;
103 } else {
104 cddb_log_crit(cddb_error_str(CDDB_ERR_OUT_OF_MEMORY));
105 }
106
107 return disc;
108 }
109
cddb_disc_destroy(cddb_disc_t * disc)110 void cddb_disc_destroy(cddb_disc_t *disc)
111 {
112 cddb_track_t *track, *next;
113
114 if (disc) {
115 FREE_NOT_NULL(disc->genre);
116 FREE_NOT_NULL(disc->title);
117 FREE_NOT_NULL(disc->artist);
118 FREE_NOT_NULL(disc->ext_data);
119 track = disc->tracks;
120 while (track) {
121 next = track->next;
122 cddb_track_destroy(track);
123 track = next;
124 }
125 free(disc);
126 }
127 }
128
cddb_disc_clone(const cddb_disc_t * disc)129 cddb_disc_t *cddb_disc_clone(const cddb_disc_t *disc)
130 {
131 cddb_disc_t *clone;
132 cddb_track_t *track;
133
134 cddb_log_debug("cddb_disc_clone()");
135 clone = cddb_disc_new();
136 clone->discid = disc->discid;
137 clone->category = disc->category;
138 clone->year = disc->year;
139 clone->genre = (disc->genre ? strdup(disc->genre) : NULL);
140 clone->title = (disc->title ? strdup(disc->title) : NULL);
141 clone->artist = (disc->artist ? strdup(disc->artist) : NULL);
142 clone->length = disc->length;
143 clone->revision = disc->revision;
144 clone->ext_data = (disc->ext_data ? strdup(disc->ext_data) : NULL);
145 /* clone the tracks */
146 track = disc->tracks;
147 while (track) {
148 cddb_disc_add_track(clone, cddb_track_clone(track));
149 track = track->next;
150 }
151 return clone;
152 }
153
154
155 /* --- track manipulation */
156
157
cddb_disc_add_track(cddb_disc_t * disc,cddb_track_t * track)158 void cddb_disc_add_track(cddb_disc_t *disc, cddb_track_t *track)
159 {
160 cddb_log_debug("cddb_disc_add_track()");
161 if (!disc->tracks) {
162 /* first track on disc */
163 disc->tracks = track;
164 } else {
165 /* next track on disc */
166 cddb_track_t *t;
167
168 t = disc->tracks;
169 while (t->next) {
170 t = t->next;
171 }
172 t->next = track;
173 track->prev = t;
174 }
175 disc->track_cnt++;
176 track->num = disc->track_cnt;
177 track->disc = disc;
178 }
179
cddb_disc_get_track(const cddb_disc_t * disc,int track_no)180 cddb_track_t *cddb_disc_get_track(const cddb_disc_t *disc, int track_no)
181 {
182 cddb_track_t *track;
183
184 if (track_no >= disc->track_cnt) {
185 return NULL;
186 }
187
188 for (track = disc->tracks;
189 track_no > 0;
190 track_no--, track = track->next) { /* no-op */ }
191 /* XXX: should we check track->num?? */
192 return track;
193 }
194
cddb_disc_get_track_first(cddb_disc_t * disc)195 cddb_track_t *cddb_disc_get_track_first(cddb_disc_t *disc)
196 {
197 disc->iterator = disc->tracks;
198 return disc->iterator;
199 }
200
cddb_disc_get_track_next(cddb_disc_t * disc)201 cddb_track_t *cddb_disc_get_track_next(cddb_disc_t *disc)
202 {
203 if (disc->iterator != NULL) {
204 disc->iterator = disc->iterator->next;
205 }
206 return disc->iterator;
207 }
208
209
210 /* --- setters / getters --- */
211
212
cddb_disc_get_discid(const cddb_disc_t * disc)213 unsigned int cddb_disc_get_discid(const cddb_disc_t *disc)
214 {
215 if (disc) {
216 return disc->discid;
217 } return 0;
218 }
219
cddb_disc_set_discid(cddb_disc_t * disc,unsigned int id)220 void cddb_disc_set_discid(cddb_disc_t *disc, unsigned int id)
221 {
222 if (disc) {
223 disc->discid = id;
224 }
225 }
226
cddb_disc_get_category(const cddb_disc_t * disc)227 cddb_cat_t cddb_disc_get_category(const cddb_disc_t *disc)
228 {
229 if (disc) {
230 return disc->category;
231 }
232 return CDDB_CAT_INVALID;
233 }
234
cddb_disc_set_category(cddb_disc_t * disc,cddb_cat_t cat)235 void cddb_disc_set_category(cddb_disc_t *disc, cddb_cat_t cat)
236 {
237 if (disc) {
238 disc->category = cat;
239 }
240 }
241
cddb_disc_get_category_str(cddb_disc_t * disc)242 const char *cddb_disc_get_category_str(cddb_disc_t *disc)
243 {
244 const char *cat = NULL;
245
246 if (disc) {
247 cat = CDDB_CATEGORY[disc->category];
248 }
249 RETURN_STR_OR_EMPTY(cat);
250 }
251
cddb_disc_set_category_str(cddb_disc_t * disc,const char * cat)252 void cddb_disc_set_category_str(cddb_disc_t *disc, const char *cat)
253 {
254 int i;
255
256 FREE_NOT_NULL(disc->genre);
257 disc->genre = strdup(cat);
258 disc->category = CDDB_CAT_MISC;
259 for (i = 0; i < CDDB_CAT_LAST; i++) {
260 if (strcmp(cat, CDDB_CATEGORY[i]) == 0) {
261 disc->category = i;
262 return;
263 }
264 }
265 }
266
cddb_disc_get_genre(const cddb_disc_t * disc)267 const char *cddb_disc_get_genre(const cddb_disc_t *disc)
268 {
269 const char *genre = NULL;
270
271 if (disc) {
272 genre = disc->genre;
273 }
274 RETURN_STR_OR_EMPTY(genre);
275 }
276
cddb_disc_set_genre(cddb_disc_t * disc,const char * genre)277 void cddb_disc_set_genre(cddb_disc_t *disc, const char *genre)
278 {
279 if (disc) {
280 FREE_NOT_NULL(disc->genre);
281 disc->genre = strdup(genre);
282 }
283 }
284
cddb_disc_get_length(const cddb_disc_t * disc)285 unsigned int cddb_disc_get_length(const cddb_disc_t *disc)
286 {
287 if (disc) {
288 return disc->length;
289 }
290 return 0;
291 }
292
cddb_disc_set_length(cddb_disc_t * disc,unsigned int l)293 void cddb_disc_set_length(cddb_disc_t *disc, unsigned int l)
294 {
295 if (disc) {
296 disc->length = l;
297 }
298 }
299
cddb_disc_get_revision(const cddb_disc_t * disc)300 unsigned int cddb_disc_get_revision(const cddb_disc_t *disc)
301 {
302 if (disc) {
303 return disc->revision;
304 }
305 return 0;
306 }
307
cddb_disc_set_revision(cddb_disc_t * disc,unsigned int rev)308 void cddb_disc_set_revision(cddb_disc_t *disc, unsigned int rev)
309 {
310 if (disc) {
311 disc->revision = rev;
312 }
313 }
314
cddb_disc_get_year(const cddb_disc_t * disc)315 unsigned int cddb_disc_get_year(const cddb_disc_t *disc)
316 {
317 if (disc) {
318 return disc->year;
319 }
320 return 0;
321 }
322
cddb_disc_set_year(cddb_disc_t * disc,unsigned int y)323 void cddb_disc_set_year(cddb_disc_t *disc, unsigned int y)
324 {
325 if (disc) {
326 disc->year = y;
327 }
328 }
329
cddb_disc_get_track_count(const cddb_disc_t * disc)330 int cddb_disc_get_track_count(const cddb_disc_t *disc)
331 {
332 if (disc) {
333 return disc->track_cnt;
334 }
335 return -1;
336 }
337
cddb_disc_get_title(const cddb_disc_t * disc)338 const char *cddb_disc_get_title(const cddb_disc_t *disc)
339 {
340 const char *title = NULL;
341
342 if (disc) {
343 title = disc->title;
344 }
345 RETURN_STR_OR_EMPTY(title);
346 }
347
cddb_disc_set_title(cddb_disc_t * disc,const char * title)348 void cddb_disc_set_title(cddb_disc_t *disc, const char *title)
349 {
350 if (disc) {
351 FREE_NOT_NULL(disc->title);
352 if (title) {
353 disc->title = strdup(title);
354 }
355 }
356 }
357
cddb_disc_append_title(cddb_disc_t * disc,const char * title)358 void cddb_disc_append_title(cddb_disc_t *disc, const char *title)
359 {
360 int old_len = 0, len;
361
362 if (disc && title) {
363 /* only append if there is something to append */
364 if (disc->title) {
365 old_len = strlen(disc->title);
366 }
367 len = strlen(title);
368 disc->title = realloc(disc->title, old_len+len+1);
369 strcpy(disc->title+old_len, title);
370 disc->title[old_len+len] = '\0';
371 }
372 }
373
cddb_disc_get_artist(const cddb_disc_t * disc)374 const char *cddb_disc_get_artist(const cddb_disc_t *disc)
375 {
376 const char *artist = NULL;
377
378 if (disc) {
379 artist = disc->artist;
380 }
381 RETURN_STR_OR_EMPTY(artist);
382 }
383
cddb_disc_set_artist(cddb_disc_t * disc,const char * artist)384 void cddb_disc_set_artist(cddb_disc_t *disc, const char *artist)
385 {
386 if (disc) {
387 FREE_NOT_NULL(disc->artist);
388 if (artist) {
389 disc->artist = strdup(artist);
390 }
391 }
392 }
393
cddb_disc_append_artist(cddb_disc_t * disc,const char * artist)394 void cddb_disc_append_artist(cddb_disc_t *disc, const char *artist)
395 {
396 int old_len = 0, len;
397
398 if (disc && artist) {
399 /* only append if there is something to append */
400 if (disc->artist) {
401 old_len = strlen(disc->artist);
402 }
403 len = strlen(artist);
404 disc->artist = realloc(disc->artist, old_len+len+1);
405 strcpy(disc->artist+old_len, artist);
406 disc->artist[old_len+len] = '\0';
407 }
408 }
409
cddb_disc_get_ext_data(const cddb_disc_t * disc)410 const char *cddb_disc_get_ext_data(const cddb_disc_t *disc)
411 {
412 const char *ext_data = NULL;
413
414 if (disc) {
415 ext_data = disc->ext_data;
416 }
417 RETURN_STR_OR_EMPTY(ext_data);
418 }
419
cddb_disc_set_ext_data(cddb_disc_t * disc,const char * ext_data)420 void cddb_disc_set_ext_data(cddb_disc_t *disc, const char *ext_data)
421 {
422 if (disc) {
423 FREE_NOT_NULL(disc->ext_data);
424 if (ext_data) {
425 disc->ext_data = strdup(ext_data);
426 }
427 }
428 }
429
cddb_disc_append_ext_data(cddb_disc_t * disc,const char * ext_data)430 void cddb_disc_append_ext_data(cddb_disc_t *disc, const char *ext_data)
431 {
432 int old_len = 0, len;
433
434 if (disc && ext_data) {
435 /* only append if there is something to append */
436 if (disc->ext_data) {
437 old_len = strlen(disc->ext_data);
438 }
439 len = strlen(ext_data);
440 disc->ext_data = realloc(disc->ext_data, old_len+len+1);
441 strcpy(disc->ext_data+old_len, ext_data);
442 disc->ext_data[old_len+len] = '\0';
443 }
444 }
445
446
447 /* --- miscellaneous */
448
449
cddb_disc_copy(cddb_disc_t * dst,cddb_disc_t * src)450 void cddb_disc_copy(cddb_disc_t *dst, cddb_disc_t *src)
451 {
452 cddb_track_t *src_track, *dst_track;
453
454 cddb_log_debug("cddb_disc_copy()");
455 if (src->discid != 0) {
456 dst->discid = src->discid;
457 }
458 if (src->category != CDDB_CAT_INVALID) {
459 dst->category = src->category;
460 }
461 if (src->year != 0) {
462 dst->year = src->year;
463 }
464 if (src->genre != NULL) {
465 FREE_NOT_NULL(dst->genre);
466 dst->genre = strdup(src->genre);
467 }
468 if (src->title != NULL) {
469 FREE_NOT_NULL(dst->title);
470 dst->title = strdup(src->title);
471 }
472 if (src->artist) {
473 FREE_NOT_NULL(dst->artist);
474 dst->artist = strdup(src->artist);
475 }
476 if (src->length != 0) {
477 dst->length = src->length;
478 }
479 if (src->revision != 0) {
480 dst->revision = src->revision;
481 }
482 if (src->ext_data != NULL) {
483 FREE_NOT_NULL(dst->ext_data);
484 dst->ext_data = strdup(src->ext_data);
485 }
486 /* copy the tracks */
487 src_track = src->tracks;
488 dst_track = dst->tracks;
489 while (src_track) {
490 if (dst_track == NULL) {
491 dst_track = cddb_track_new();
492 cddb_disc_add_track(dst, dst_track);
493 }
494 cddb_track_copy(dst_track, src_track);
495 src_track = src_track->next;
496 dst_track = dst_track->next;
497 }
498 }
499
cddb_disc_calc_discid(cddb_disc_t * disc)500 int cddb_disc_calc_discid(cddb_disc_t *disc)
501 {
502 long result = 0;
503 long tmp;
504 cddb_track_t *track, *first;
505
506 cddb_log_debug("cddb_disc_calc_discid()");
507 for (first = track = cddb_disc_get_track_first(disc);
508 track != NULL;
509 track = cddb_disc_get_track_next(disc)) {
510 tmp = FRAMES_TO_SECONDS(track->frame_offset);
511 do {
512 result += tmp % 10;
513 tmp /= 10;
514 } while (tmp != 0);
515 }
516
517 if (first == NULL) {
518 /* set disc id to zero if there are no tracks */
519 disc->discid = 0;
520 } else {
521 /* first byte is offsets of tracks
522 * 2 next bytes total length in seconds
523 * last byte is nr of tracks
524 */
525 disc->discid = (result % 0xff) << 24 |
526 (disc->length - FRAMES_TO_SECONDS(first->frame_offset)) << 8 |
527 disc->track_cnt;
528 }
529 cddb_log_debug("...Disc ID: %08x", disc->discid);
530
531 return TRUE;
532 }
533
cddb_disc_print(cddb_disc_t * disc)534 void cddb_disc_print(cddb_disc_t *disc)
535 {
536 cddb_track_t *track;
537 int cnt;
538
539 printf("Disc ID: %08x\n", disc->discid);
540 printf("CDDB category: %s (%d)\n", CDDB_CATEGORY[disc->category], disc->category);
541 printf("Music genre: '%s'\n", STR_OR_NULL(disc->genre));
542 printf("Year: %d\n", disc->year);
543 printf("Artist: '%s'\n", STR_OR_NULL(disc->artist));
544 printf("Title: '%s'\n", STR_OR_NULL(disc->title));
545 printf("Extended data: '%s'\n", STR_OR_NULL(disc->ext_data));
546 printf("Length: %d seconds\n", disc->length);
547 printf("Revision: %d\n", disc->revision);
548 printf("Number of tracks: %d\n", disc->track_cnt);
549 track = disc->tracks;
550 cnt = 1;
551 while (track) {
552 printf(" Track %2d\n", cnt);
553 cddb_track_print(track);
554 track = track->next;
555 cnt++;
556 }
557 }
558