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