1 /*
2     $Id: cddb_track.c,v 1.20 2006/10/15 11:55:25 airborne 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 #ifdef HAVE_STDLIB_H
26 #include <stdlib.h>
27 #endif
28 #ifdef HAVE_STRING_H
29 #include <string.h>
30 #endif
31 
32 
33 /* --- private functions */
34 
cddb_track_iconv(iconv_t cd,cddb_track_t * track)35 int cddb_track_iconv(iconv_t cd, cddb_track_t *track)
36 {
37     char *result;
38 
39     if (!cd) {
40         return TRUE;            /* no user character set defined */
41     }
42     if (track->title) {
43         if (cddb_str_iconv(cd, track->title, &result)) {
44             free(track->title);
45             track->title = result;
46         } else {
47             return FALSE;
48         }
49     }
50     if (track->artist) {
51         if (cddb_str_iconv(cd, track->artist, &result)) {
52             free(track->artist);
53             track->artist = result;
54         } else {
55             return FALSE;
56         }
57     }
58     if (track->ext_data) {
59         if (cddb_str_iconv(cd, track->ext_data, &result)) {
60             free(track->ext_data);
61             track->ext_data = result;
62         } else {
63             return FALSE;
64         }
65     }
66     return TRUE;
67 }
68 
69 
70 /* --- construction / destruction */
71 
72 
cddb_track_new(void)73 cddb_track_t *cddb_track_new(void)
74 {
75     cddb_track_t *track;
76 
77     track = (cddb_track_t*)calloc(1, sizeof(cddb_track_t));
78     if (track) {
79         track->num = -1;
80         track->frame_offset = -1;
81         track->length = -1;
82         track->disc = NULL;
83     } else {
84         cddb_log_crit(cddb_error_str(CDDB_ERR_OUT_OF_MEMORY));
85     }
86 
87     return track;
88 }
89 
cddb_track_destroy(cddb_track_t * track)90 void cddb_track_destroy(cddb_track_t *track)
91 {
92     if (track) {
93         FREE_NOT_NULL(track->title);
94         FREE_NOT_NULL(track->artist);
95         FREE_NOT_NULL(track->ext_data);
96         free(track);
97     }
98 }
99 
cddb_track_clone(const cddb_track_t * track)100 cddb_track_t *cddb_track_clone(const cddb_track_t *track)
101 {
102     cddb_track_t *clone;
103 
104     cddb_log_debug("cddb_track_clone()");
105     clone = cddb_track_new();
106     clone->num = track->num;
107     clone->frame_offset = track->frame_offset;
108     clone->length = track->length;
109     clone->title = (track->title ? strdup(track->title) : NULL);
110     clone->artist = (track->artist ? strdup(track->artist) : NULL);
111     clone->ext_data = (track->ext_data ? strdup(track->ext_data) : NULL);
112     clone->disc = NULL;
113     return clone;
114 }
115 
116 
117 /* --- getters & setters --- */
118 
119 
cddb_track_get_number(const cddb_track_t * track)120 int cddb_track_get_number(const cddb_track_t *track)
121 {
122     if (track) {
123         return track->num;
124     }
125     return -1;                  /* invalid track */
126 }
127 
cddb_track_get_frame_offset(const cddb_track_t * track)128 int cddb_track_get_frame_offset(const cddb_track_t *track)
129 {
130     if (track) {
131         return track->frame_offset;
132     }
133     return -1;                  /* invalid track */
134 }
135 
cddb_track_set_frame_offset(cddb_track_t * track,int offset)136 void cddb_track_set_frame_offset(cddb_track_t *track, int offset)
137 {
138     if (track) {
139         track->frame_offset = offset;
140     }
141 }
142 
cddb_track_get_title(const cddb_track_t * track)143 const char *cddb_track_get_title(const cddb_track_t *track)
144 {
145     const char *title = NULL;
146 
147     if (track) {
148         title = track->title;
149     }
150     RETURN_STR_OR_EMPTY(title);
151 }
152 
cddb_track_set_title(cddb_track_t * track,const char * title)153 void cddb_track_set_title(cddb_track_t *track, const char *title)
154 {
155     if (track) {
156         FREE_NOT_NULL(track->title);
157         if (title) {
158             track->title = strdup(title);
159         }
160     }
161 }
162 
cddb_track_get_length(cddb_track_t * track)163 int cddb_track_get_length(cddb_track_t *track)
164 {
165     cddb_track_t *next;
166     int start, end;
167 
168     if (track) {
169         if (track->length == -1) {
170             start = track->frame_offset;
171             next = track->next;
172             if (next != NULL) {
173                 /* not last track on disc, use frame offset of next track */
174                 end = next->frame_offset;
175                 if (end > start) {
176                     /* XXX: rounding errors */
177                     track->length = FRAMES_TO_SECONDS(end - start);
178                 }
179             } else {
180                 /* last track on disc, use disc length */
181                 if (track->disc != NULL) {
182                     /* XXX: rounding errors */
183                     start = FRAMES_TO_SECONDS(start);
184                     end = cddb_disc_get_length(track->disc);
185                     if (end > start) {
186                         track->length = end - start;
187                     }
188                 }
189             }
190         }
191         return track->length;
192     }
193     return -1;
194 }
195 
cddb_track_set_length(cddb_track_t * track,int length)196 void cddb_track_set_length(cddb_track_t *track, int length)
197 {
198     cddb_track_t *prev;
199 
200     if (track && (length >= 0)) {
201         track->length = length;
202         /* calculate frame offset if possible and not yet set */
203         if (track->disc && (track->frame_offset == -1)) {
204             prev = track->prev;
205             if (prev) {
206                 /* not first track on disc */
207                 if ((prev->frame_offset != -1) && (prev->length != -1)) {
208                     track->frame_offset = prev->frame_offset + SECONDS_TO_FRAMES(prev->length);
209                 }
210             } else {
211                 /* first track, let it start at frame offset 150 */
212                 track->frame_offset = 150;
213             }
214             cddb_log_debug("frame offset set to %d", track->frame_offset);
215         }
216     }
217 }
218 
cddb_track_append_title(cddb_track_t * track,const char * title)219 void cddb_track_append_title(cddb_track_t *track, const char *title)
220 {
221     int old_len = 0, len;
222 
223     if (track && title) {
224         /* only append if there is something to append */
225         if (track->title) {
226             old_len = strlen(track->title);
227         }
228         len = strlen(title);
229         track->title = realloc(track->title, old_len+len+1);
230         strcpy(track->title+old_len, title);
231         track->title[old_len+len] = '\0';
232     }
233 }
234 
cddb_track_get_artist(cddb_track_t * track)235 const char *cddb_track_get_artist(cddb_track_t *track)
236 {
237     const char *artist = NULL;
238 
239     if (track) {
240         if (track->artist) {
241             artist = track->artist;
242         } else {
243             if (!(libcddb_flags() & CDDB_F_NO_TRACK_ARTIST)) {
244                 artist =  track->disc->artist; /* might be NULL */
245             }
246         }
247     }
248     RETURN_STR_OR_EMPTY(artist);
249 }
250 
cddb_track_set_artist(cddb_track_t * track,const char * artist)251 void cddb_track_set_artist(cddb_track_t *track, const char *artist)
252 {
253     if (track) {
254         FREE_NOT_NULL(track->artist);
255         if (artist) {
256             track->artist = strdup(artist);
257         }
258     }
259 }
260 
cddb_track_append_artist(cddb_track_t * track,const char * artist)261 void cddb_track_append_artist(cddb_track_t *track, const char *artist)
262 {
263     int old_len = 0, len;
264 
265     if (track && artist) {
266         /* only append if there is something to append */
267         if (track->artist) {
268             old_len = strlen(track->artist);
269         }
270         len = strlen(artist);
271         track->artist = realloc(track->artist, old_len+len+1);
272         strcpy(track->artist+old_len, artist);
273         track->artist[old_len+len] = '\0';
274     }
275 }
276 
cddb_track_get_ext_data(cddb_track_t * track)277 const char *cddb_track_get_ext_data(cddb_track_t *track)
278 {
279     const char *ext_data = NULL;
280 
281     if (track) {
282         ext_data = track->ext_data;
283     }
284     RETURN_STR_OR_EMPTY(ext_data);
285 }
286 
cddb_track_set_ext_data(cddb_track_t * track,const char * ext_data)287 void cddb_track_set_ext_data(cddb_track_t *track, const char *ext_data)
288 {
289     if (track) {
290         FREE_NOT_NULL(track->ext_data);
291         if (ext_data) {
292             track->ext_data = strdup(ext_data);
293         }
294     }
295 }
296 
cddb_track_append_ext_data(cddb_track_t * track,const char * ext_data)297 void cddb_track_append_ext_data(cddb_track_t *track, const char *ext_data)
298 {
299     int old_len = 0, len;
300 
301     if (track && ext_data) {
302         /* only append if there is something to append */
303         if (track->ext_data) {
304             old_len = strlen(track->ext_data);
305         }
306         len = strlen(ext_data);
307         track->ext_data = realloc(track->ext_data, old_len+len+1);
308         strcpy(track->ext_data+old_len, ext_data);
309         track->ext_data[old_len+len] = '\0';
310     }
311 }
312 
313 
314 /* --- miscellaneous */
315 
316 
cddb_track_copy(cddb_track_t * dst,cddb_track_t * src)317 void cddb_track_copy(cddb_track_t *dst, cddb_track_t *src)
318 {
319     cddb_log_debug("cddb_track_copy()");
320     if (src->num != -1) {
321         dst->num = src->num;
322     }
323     if (src->frame_offset != -1) {
324         dst->frame_offset = src->frame_offset;
325     }
326     if (src->length != -1) {
327         dst->length = src->length;
328     }
329     if (src->title != NULL) {
330         FREE_NOT_NULL(dst->title);
331         dst->title = strdup(src->title);
332     }
333     if (src->artist) {
334         FREE_NOT_NULL(dst->artist);
335         dst->artist = strdup(src->artist);
336     }
337     if (src->ext_data != NULL) {
338         FREE_NOT_NULL(dst->ext_data);
339         dst->ext_data = strdup(src->ext_data);
340     }
341 }
342 
cddb_track_print(cddb_track_t * track)343 void cddb_track_print(cddb_track_t *track)
344 {
345     printf("    number: %d\n", track->num);
346     printf("    frame offset: %d\n", track->frame_offset);
347     printf("    length: %d seconds\n", cddb_track_get_length(track));
348     printf("    artist: '%s'\n", STR_OR_NULL(cddb_track_get_artist(track)));
349     printf("    title: '%s'\n", STR_OR_NULL(track->title));
350     printf("    extended data: '%s'\n", STR_OR_NULL(track->ext_data));
351 }
352