Mercurial > audlegacy
annotate Plugins/Input/mpg123/id3_frame.c @ 787:e776161c16db trunk
[svn] - more fixes, sizeof *frame !($&($&(@!#$@#*&@!$# whoever wrote this code is an idiot
author | nenolod |
---|---|
date | Fri, 03 Mar 2006 10:31:57 -0800 |
parents | 20a62ae86b6e |
children | d15862899bbe |
rev | line source |
---|---|
61 | 1 /********************************************************************* |
2 * | |
3 * Copyright (C) 1999-2000, 2001, Espen Skoglund | |
4 * Department of Computer Science, University of Tromsų | |
5 * | |
6 * Filename: id3_frame.c | |
7 * Description: Code for handling ID3 frames. | |
8 * Author: Espen Skoglund <espensk@stud.cs.uit.no> | |
9 * Created at: Fri Feb 5 23:47:08 1999 | |
10 * | |
11 * $Id: id3_frame.c,v 1.5 2004/07/20 21:47:22 descender Exp $ | |
12 * | |
13 * This program is free software; you can redistribute it and/or | |
14 * modify it under the terms of the GNU General Public License | |
15 * as published by the Free Software Foundation; either version 2 | |
16 * of the License, or (at your option) any later version. | |
17 * | |
18 * This program is distributed in the hope that it will be useful, | |
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
21 * GNU General Public License for more details. | |
22 * | |
23 * You should have received a copy of the GNU General Public License | |
24 * along with this program; if not, write to the Free Software | |
25 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | |
26 * | |
27 ********************************************************************/ | |
28 #include "config.h" | |
29 | |
30 #ifdef HAVE_LIBZ | |
31 #include <zlib.h> | |
32 #endif | |
33 #include <glib.h> | |
34 #include <stdio.h> | |
35 #include <string.h> | |
36 #include <stdlib.h> | |
37 #include <stdarg.h> | |
38 | |
39 #include "xmms-id3.h" | |
40 #include "id3_header.h" | |
41 | |
42 static void *id3_frame_get_dataptr(struct id3_frame *frame); | |
43 static int id3_frame_get_size(struct id3_frame *frame); | |
44 static int id3_read_frame_v22(struct id3_tag *id3); | |
45 | |
46 | |
47 /* | |
48 * Description of all valid ID3v2 frames. | |
49 */ | |
50 static struct id3_framedesc framedesc[] = { | |
51 {ID3_AENC, "AENC", "Audio encryption"}, | |
52 {ID3_APIC, "APIC", "Attached picture"}, | |
53 {ID3_ASPI, "ASPI", "Audio seek point index"}, /* v4 only */ | |
54 | |
55 {ID3_COMM, "COMM", "Comments"}, | |
56 {ID3_COMR, "COMR", "Commercial frame"}, | |
57 | |
58 {ID3_ENCR, "ENCR", "Encryption method registration"}, | |
59 {ID3_EQUA, "EQUA", "Equalization"}, /* v3 only */ | |
60 {ID3_EQU2, "EQU2", "Equalization (2)"}, /* v4 only */ | |
61 {ID3_ETCO, "ETCO", "Event timing codes"}, | |
62 | |
63 {ID3_GEOB, "GEOB", "General encapsulated object"}, | |
64 {ID3_GRID, "GRID", "Group identification registration"}, | |
65 | |
66 {ID3_IPLS, "IPLS", "Involved people list"}, /* v3 only */ | |
67 | |
68 {ID3_LINK, "LINK", "Linked information"}, | |
69 | |
70 {ID3_MCDI, "MCDI", "Music CD identifier"}, | |
71 {ID3_MLLT, "MLLT", "MPEG location lookup table"}, | |
72 | |
73 {ID3_OWNE, "OWNE", "Ownership frame"}, | |
74 | |
75 {ID3_PRIV, "PRIV", "Private frame"}, | |
76 {ID3_PCNT, "PCNT", "Play counter"}, | |
77 {ID3_POPM, "POPM", "Popularimeter"}, | |
78 {ID3_POSS, "POSS", "Position synchronisation frame"}, | |
79 | |
80 {ID3_RBUF, "RBUF", "Recommended buffer size"}, | |
81 {ID3_RVAD, "RVAD", "Relative volume adjustment"}, /* v3 only */ | |
82 {ID3_RVA2, "RVA2", "RVA2 Relative volume adjustment (2)"}, /* v4 only */ | |
83 {ID3_RVRB, "RVRB", "Reverb"}, | |
84 | |
85 {ID3_SEEK, "SEEK", "Seek frame"}, /* v4 only */ | |
86 {ID3_SIGN, "SIGN", "Signature frame"}, /* v4 only */ | |
87 {ID3_SYLT, "SYLT", "Synchronized lyric/text"}, | |
88 {ID3_SYTC, "SYTC", "Synchronized tempo codes"}, | |
89 | |
90 {ID3_TALB, "TALB", "Album/Movie/Show title"}, | |
91 {ID3_TBPM, "TBPM", "BPM (beats per minute)"}, | |
92 {ID3_TCOM, "TCOM", "Composer"}, | |
93 {ID3_TCON, "TCON", "Content type"}, | |
94 {ID3_TCOP, "TCOP", "Copyright message"}, | |
95 {ID3_TDAT, "TDAT", "Date"}, /* v3 only */ | |
96 {ID3_TDEN, "TDEN", "Encoding time"}, /* v4 only */ | |
97 {ID3_TDLY, "TDLY", "Playlist delay"}, | |
98 {ID3_TDOR, "TDOR", "Original release time"}, /* v4 only */ | |
99 {ID3_TDRC, "TDRC", "Recording time"}, /* v4 only */ | |
100 {ID3_TDRL, "TDRL", "Release time"}, /* v4 only */ | |
101 {ID3_TDTG, "TDTG", "Tagging time"}, /* v4 only */ | |
102 | |
103 {ID3_TENC, "TENC", "Encoded by"}, | |
104 {ID3_TEXT, "TEXT", "Lyricist/Text writer"}, | |
105 {ID3_TFLT, "TFLT", "File type"}, | |
106 {ID3_TIME, "TIME", "Time"}, /* v3 only */ | |
107 {ID3_TIPL, "TIPL", "Involved people list"}, /* v4 only */ | |
108 {ID3_TIT1, "TIT1", "Content group description"}, | |
109 {ID3_TIT2, "TIT2", "Title/songname/content description"}, | |
110 {ID3_TIT3, "TIT3", "Subtitle/Description refinement"}, | |
111 {ID3_TKEY, "TKEY", "Initial key"}, | |
112 {ID3_TLAN, "TLAN", "Language(s)"}, | |
113 {ID3_TLEN, "TLEN", "Length"}, | |
114 {ID3_TMCL, "TMCL", "Musician credits list"}, /* v4 only */ | |
115 {ID3_TMOO, "TMOO", "Mood"}, /* v4 only */ | |
116 {ID3_TMED, "TMED", "Media type"}, | |
117 {ID3_TOAL, "TOAL", "Original album/movie/show title"}, | |
118 {ID3_TOFN, "TOFN", "Original filename"}, | |
119 {ID3_TOLY, "TOLY", "Original lyricist(s)/text writer(s)"}, | |
120 {ID3_TOPE, "TOPE", "Original artist(s)/performer(s)"}, | |
121 {ID3_TORY, "TORY", "Original release year"}, /* v3 only */ | |
122 {ID3_TOWN, "TOWN", "File owner/licensee"}, | |
123 {ID3_TPE1, "TPE1", "Lead performer(s)/Soloist(s)"}, | |
124 {ID3_TPE2, "TPE2", "Band/orchestra/accompaniment"}, | |
125 {ID3_TPE3, "TPE3", "Conductor/performer refinement"}, | |
126 {ID3_TPE4, "TPE4", "Interpreted, remixed, or otherwise modified by"}, | |
127 {ID3_TPOS, "TPOS", "Part of a set"}, | |
128 {ID3_TPRO, "TPRO", "Produced notice"}, /* v4 only */ | |
129 {ID3_TPUB, "TPUB", "Publisher"}, | |
130 {ID3_TRCK, "TRCK", "Track number/Position in set"}, | |
131 {ID3_TRDA, "TRDA", "Recording dates"}, /* v3 only */ | |
132 {ID3_TRSN, "TRSN", "Internet radio station name"}, | |
133 {ID3_TRSO, "TRSO", "Internet radio station owner"}, | |
134 {ID3_TSIZ, "TSIZ", "Size"}, /* v3 only */ | |
135 {ID3_TSOA, "TSOA", "Album sort order"}, /* v4 only */ | |
136 {ID3_TSOP, "TSOP", "Performer sort order"}, /* v4 only */ | |
137 {ID3_TSOT, "TSOT", "Title sort order"}, /* v4 only */ | |
138 | |
139 {ID3_TSRC, "TSRC", "ISRC (international standard recording code)"}, | |
140 {ID3_TSSE, "TSSE", "Software/Hardware and settings used for encoding"}, | |
141 {ID3_TSST, "TSST", "Set subtitle"}, /* v4 only */ | |
142 {ID3_TYER, "TYER", "Year"}, /* v3 only */ | |
143 {ID3_TXXX, "TXXX", "User defined text information frame"}, | |
144 | |
145 {ID3_UFID, "UFID", "Unique file identifier"}, | |
146 {ID3_USER, "USER", "Terms of use"}, | |
147 {ID3_USLT, "USLT", "Unsychronized lyric/text transcription"}, | |
148 | |
149 {ID3_WCOM, "WCOM", "Commercial information"}, | |
150 {ID3_WCOP, "WCOP", "Copyright/Legal information"}, | |
151 {ID3_WOAF, "WOAF", "Official audio file webpage"}, | |
152 {ID3_WOAR, "WOAR", "Official artist/performer webpage"}, | |
153 {ID3_WOAS, "WOAS", "Official audio source webpage"}, | |
154 {ID3_WORS, "WORS", "Official internet radio station homepage"}, | |
155 {ID3_WPAY, "WPAY", "Payment"}, | |
156 {ID3_WPUB, "WPUB", "Publishers official webpage"}, | |
157 {ID3_WXXX, "WXXX", "User defined URL link frame"}, | |
158 }; | |
159 | |
160 struct id3_framedesc22 { | |
161 guint32 fd_v22, fd_v24; | |
162 }; | |
163 | |
164 static struct id3_framedesc22 framedesc22[] = { | |
165 {ID3_BUF, ID3_RBUF}, /* Recommended buffer size */ | |
166 | |
167 {ID3_CNT, ID3_PCNT}, /* Play counter */ | |
168 {ID3_COM, ID3_COMM}, /* Comments */ | |
169 {ID3_CRA, ID3_AENC}, /* Audio encryption */ | |
170 {ID3_CRM, 0}, /* Encrypted meta frame */ | |
171 | |
172 {ID3_ETC, ID3_ETCO}, /* Event timing codes */ | |
173 /* Could be converted to EQU2 */ | |
174 {ID3_EQU, 0}, /* Equalization */ | |
175 | |
176 {ID3_GEO, ID3_GEOB}, /* General encapsulated object */ | |
177 | |
178 /* Would need conversion to TIPL */ | |
179 {ID3_IPL, 0}, /* Involved people list */ | |
180 | |
181 /* This is so fragile it's not worth trying to save */ | |
182 {ID3_LNK, 0}, /* Linked information */ | |
183 | |
184 {ID3_MCI, ID3_MCDI}, /* Music CD Identifier */ | |
185 {ID3_MLL, ID3_MLLT}, /* MPEG location lookup table */ | |
186 | |
187 /* Would need to convert header for APIC */ | |
188 {ID3_PIC, 0}, /* Attached picture */ | |
189 {ID3_POP, ID3_POPM}, /* Popularimeter */ | |
190 | |
191 {ID3_REV, ID3_RVRB}, /* Reverb */ | |
192 /* Could be converted to RVA2 */ | |
193 {ID3_RVA, 0}, /* Relative volume adjustment */ | |
194 | |
195 {ID3_SLT, ID3_SYLT}, /* Synchronized lyric/text */ | |
196 {ID3_STC, ID3_SYTC}, /* Synced tempo codes */ | |
197 | |
198 {ID3_TAL, ID3_TALB}, /* Album/Movie/Show title */ | |
199 {ID3_TBP, ID3_TBPM}, /* BPM (Beats Per Minute) */ | |
200 {ID3_TCM, ID3_TCOM}, /* Composer */ | |
201 {ID3_TCO, ID3_TCON}, /* Content type */ | |
202 {ID3_TCR, ID3_TCOP}, /* Copyright message */ | |
203 /* This could be incorporated into TDRC */ | |
204 {ID3_TDA, 0}, /* Date */ | |
205 {ID3_TDY, ID3_TDLY}, /* Playlist delay */ | |
206 {ID3_TEN, ID3_TENC}, /* Encoded by */ | |
207 {ID3_TFT, ID3_TFLT}, /* File type */ | |
208 /* This could be incorporated into TDRC */ | |
209 {ID3_TIM, 0}, /* Time */ | |
210 {ID3_TKE, ID3_TKEY}, /* Initial key */ | |
211 {ID3_TLA, ID3_TLAN}, /* Language(s) */ | |
212 {ID3_TLE, ID3_TLEN}, /* Length */ | |
213 {ID3_TMT, ID3_TMED}, /* Media type */ | |
214 {ID3_TOA, ID3_TOPE}, /* Original artist(s)/performer(s) */ | |
215 {ID3_TOF, ID3_TOFN}, /* Original filename */ | |
216 {ID3_TOL, ID3_TOLY}, /* Original Lyricist(s)/text writer(s) */ | |
217 /* | |
218 * The docs says that original release year should be in | |
219 * milliseconds! Hopefully that is a typo. | |
220 */ | |
221 {ID3_TOR, ID3_TDOR}, /* Original release year */ | |
222 {ID3_TOT, ID3_TOAL}, /* Original album/Movie/Show title */ | |
223 {ID3_TP1, ID3_TPE1}, /* Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group */ | |
224 {ID3_TP2, ID3_TPE2}, /* Band/Orchestra/Accompaniment */ | |
225 {ID3_TP3, ID3_TPE3}, /* Conductor/Performer refinement */ | |
226 {ID3_TP4, ID3_TPE4}, /* Interpreted, remixed, or otherwise modified by */ | |
227 {ID3_TPA, ID3_TPOS}, /* Part of a set */ | |
228 {ID3_TPB, ID3_TPUB}, /* Publisher */ | |
229 {ID3_TRC, ID3_TSRC}, /* ISRC (International Standard Recording Code) */ | |
230 {ID3_TRD, 0}, /* Recording dates */ | |
231 {ID3_TRK, ID3_TRCK}, /* Track number/Position in set */ | |
232 {ID3_TSI, 0}, /* Size */ | |
233 {ID3_TSS, ID3_TSSE}, /* Software/hardware and settings used for encoding */ | |
234 {ID3_TT1, ID3_TIT1}, /* Content group description */ | |
235 {ID3_TT2, ID3_TIT2}, /* Title/Songname/Content description */ | |
236 {ID3_TT3, ID3_TIT3}, /* Subtitle/Description refinement */ | |
237 {ID3_TXT, ID3_TEXT}, /* Lyricist/text writer */ | |
238 {ID3_TXX, ID3_TXXX}, /* User defined text information frame */ | |
239 {ID3_TYE, ID3_TDRC}, /* Year */ | |
240 | |
241 {ID3_UFI, ID3_UFID}, /* Unique file identifier */ | |
242 {ID3_ULT, ID3_USLT}, /* Unsychronized lyric/text transcription */ | |
243 | |
244 {ID3_WAF, ID3_WOAF}, /* Official audio file webpage */ | |
245 {ID3_WAR, ID3_WOAR}, /* Official artist/performer webpage */ | |
246 {ID3_WAS, ID3_WOAS}, /* Official audio source webpage */ | |
247 {ID3_WCM, ID3_WCOM}, /* Commercial information */ | |
248 {ID3_WCP, ID3_WCOP}, /* Copyright/Legal information */ | |
249 {ID3_WPB, ID3_WPUB}, /* Publishers official webpage */ | |
250 {ID3_WXX, ID3_WXXX}, /* User defined URL link frame */ | |
251 }; | |
252 | |
253 static struct id3_framedesc * | |
254 find_frame_description(guint32 id) | |
255 { | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
61
diff
changeset
|
256 size_t i; |
61 | 257 for (i = 0; i < sizeof(framedesc) / sizeof(struct id3_framedesc); i++) |
258 if (framedesc[i].fd_id == id) | |
259 return &framedesc[i]; | |
260 return NULL; | |
261 } | |
262 | |
263 | |
264 /* | |
265 * Function id3_read_frame (id3) | |
266 * | |
267 * Read next frame from the indicated ID3 tag. Return 0 upon | |
268 * success, or -1 if an error occured. | |
269 * | |
270 */ | |
271 int | |
272 id3_read_frame(struct id3_tag *id3) | |
273 { | |
274 struct id3_frame *frame; | |
275 guint32 id; | |
276 char *buf; | |
277 | |
278 if (id3->id3_version == 2) | |
279 return id3_read_frame_v22(id3); | |
280 | |
281 /* | |
282 * Read frame header. | |
283 */ | |
284 buf = id3->id3_read(id3, NULL, ID3_FRAMEHDR_SIZE); | |
285 if (buf == NULL) | |
286 return -1; | |
287 | |
288 /* | |
289 * If we encounter an invalid frame id, we assume that there is | |
290 * some padding in the header. We just skip the rest of the ID3 | |
291 * tag. | |
292 */ | |
293 if (!((buf[0] >= '0' && buf[0] <= '9') | |
294 || (buf[0] >= 'A' && buf[0] <= 'Z'))) { | |
295 id3->id3_seek(id3, id3->id3_tagsize - id3->id3_pos); | |
296 return 0; | |
297 } | |
298 id = ID3_FRAME_ID(buf[0], buf[1], buf[2], buf[3]); | |
299 | |
300 /* | |
301 * Allocate frame. | |
302 */ | |
787
e776161c16db
[svn] - more fixes, sizeof *frame !($&($&(@!#$@#*&@!$# whoever wrote this code is an idiot
nenolod
parents:
785
diff
changeset
|
303 frame = g_malloc0(sizeof(struct id3_frame)); |
61 | 304 |
305 frame->fr_owner = id3; | |
306 /* FIXME v2.4.0 */ | |
307 frame->fr_raw_size = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]; | |
308 if (frame->fr_raw_size < 0 || frame->fr_raw_size > 1000000) { | |
309 g_free(frame); | |
310 return -1; | |
311 } | |
312 frame->fr_flags = buf[8] << 8 | buf[9]; | |
313 | |
314 /* | |
315 * Determine the type of the frame. | |
316 */ | |
317 | |
318 frame->fr_desc = find_frame_description(id); | |
319 | |
320 /* | |
321 * Check if frame had a valid id. | |
322 */ | |
323 if (frame->fr_desc == NULL) { | |
324 /* | |
325 * No. Ignore the frame. | |
326 */ | |
327 if (id3->id3_seek(id3, frame->fr_raw_size) < 0) { | |
328 g_free(frame); | |
329 return -1; | |
330 } | |
331 return 0; | |
332 } | |
333 | |
334 /* | |
335 * Initialize frame. | |
336 */ | |
337 | |
338 /* | |
339 * We allocate 2 extra bytes. This simplifies retrieval of | |
340 * text strings. | |
341 */ | |
342 frame->fr_raw_data = g_malloc0(frame->fr_raw_size + 2); | |
343 if (id3->id3_read(id3, frame->fr_raw_data, frame->fr_raw_size) == NULL) { | |
344 g_free(frame->fr_raw_data); | |
345 g_free(frame); | |
346 return -1; | |
347 } | |
348 | |
349 /* | |
350 * Insert frame into linked list. | |
351 */ | |
352 id3->id3_frame = g_list_append(id3->id3_frame, frame); | |
353 | |
354 /* | |
355 * Check if frame is compressed using zlib. | |
356 */ | |
357 if (frame->fr_flags & ID3_FHFLAG_COMPRESS) | |
358 return 0; | |
359 | |
360 frame->fr_data = id3_frame_get_dataptr(frame); | |
361 frame->fr_size = id3_frame_get_size(frame); | |
362 | |
363 return 0; | |
364 } | |
365 | |
366 | |
367 /* | |
368 * Function id3_get_frame (id3, type, num) | |
369 * | |
370 * Search in the list of frames for the ID3-tag, and return a frame | |
371 * of the indicated type. If tag contains several frames of the | |
372 * indicated type, the third argument tells which of the frames to | |
373 * return. | |
374 * | |
375 */ | |
376 struct id3_frame * | |
377 id3_get_frame(struct id3_tag *id3, guint32 type, int num) | |
378 { | |
379 GList *node; | |
380 | |
381 for (node = id3->id3_frame; node != NULL; node = node->next) { | |
382 struct id3_frame *fr = node->data; | |
383 if (fr->fr_desc && fr->fr_desc->fd_id == type) { | |
384 if (--num <= 0) | |
385 return fr; | |
386 } | |
387 } | |
388 return NULL; | |
389 } | |
390 | |
391 /* | |
392 * Function decompress_frame(frame) | |
393 * | |
394 * Uncompress the indicated frame. Return 0 upon success, or -1 if | |
395 * an error occured. | |
396 * | |
397 */ | |
398 static int | |
399 decompress_frame(struct id3_frame *frame) | |
400 { | |
401 #ifdef HAVE_LIBZ | |
402 z_stream z; | |
403 int r; | |
404 | |
405 /* | |
406 * Fetch the size of the decompressed data. | |
407 */ | |
408 frame->fr_size_z = g_ntohl(*((guint32 *) frame->fr_raw_data)); | |
409 if (frame->fr_size_z < 0 || frame->fr_size_z > 1000000) | |
410 return -1; | |
411 | |
412 /* | |
413 * Allocate memory to hold uncompressed frame. | |
414 */ | |
415 frame->fr_data_z = g_malloc(frame->fr_size_z + | |
416 (id3_frame_is_text(frame) ? 2 : 0)); | |
417 | |
418 /* | |
419 * Initialize zlib. | |
420 */ | |
421 z.next_in = id3_frame_get_dataptr(frame); | |
422 z.avail_in = id3_frame_get_size(frame); | |
423 z.zalloc = NULL; | |
424 z.zfree = NULL; | |
425 z.opaque = NULL; | |
426 | |
427 r = inflateInit(&z); | |
428 switch (r) { | |
429 case Z_OK: | |
430 break; | |
431 case Z_MEM_ERROR: | |
432 id3_error(frame->fr_owner, "zlib - no memory"); | |
433 goto Error_init; | |
434 case Z_VERSION_ERROR: | |
435 id3_error(frame->fr_owner, "zlib - invalid version"); | |
436 goto Error_init; | |
437 default: | |
438 id3_error(frame->fr_owner, "zlib - unknown error"); | |
439 goto Error_init; | |
440 } | |
441 | |
442 /* | |
443 * Decompress frame. | |
444 */ | |
445 z.next_out = frame->fr_data_z; | |
446 z.avail_out = frame->fr_size_z; | |
447 r = inflate(&z, Z_SYNC_FLUSH); | |
448 switch (r) { | |
449 case Z_STREAM_END: | |
450 break; | |
451 case Z_OK: | |
452 if (z.avail_in == 0) | |
453 /* | |
454 * This should not be possible with a correct stream. | |
455 * We will be nice however, and try to go on. | |
456 */ | |
457 break; | |
458 id3_error(frame->fr_owner, "zlib - buffer exhausted"); | |
459 goto Error_inflate; | |
460 default: | |
461 id3_error(frame->fr_owner, "zlib - unknown error"); | |
462 goto Error_inflate; | |
463 } | |
464 | |
465 r = inflateEnd(&z); | |
466 if (r != Z_OK) | |
467 id3_error(frame->fr_owner, "zlib - inflateEnd error"); | |
468 | |
469 /* | |
470 * Null-terminate text frames. | |
471 */ | |
472 if (id3_frame_is_text(frame)) { | |
473 ((char *) frame->fr_data_z)[frame->fr_size_z] = 0; | |
474 ((char *) frame->fr_data_z)[frame->fr_size_z + 1] = 0; | |
475 } | |
476 frame->fr_data = frame->fr_data_z; | |
477 frame->fr_size = frame->fr_size_z + (id3_frame_is_text(frame) ? 2 : 0); | |
478 | |
479 return 0; | |
480 | |
481 /* | |
482 * Cleanup code. | |
483 */ | |
484 Error_inflate: | |
485 r = inflateEnd(&z); | |
486 Error_init: | |
487 g_free(frame->fr_data_z); | |
488 frame->fr_data_z = NULL; | |
489 #endif | |
490 return -1; | |
491 } | |
492 | |
493 /* | |
494 * Function id3_decompress_frame(frame) | |
495 * | |
496 * Check if frame is compressed, and uncompress if necessary. | |
497 * Return 0 upon success, or -1 if an error occured. | |
498 * | |
499 */ | |
500 int | |
501 id3_decompress_frame(struct id3_frame *frame) | |
502 { | |
503 if (!(frame->fr_flags & ID3_FHFLAG_COMPRESS)) | |
504 /* Frame not compressed */ | |
505 return 0; | |
506 if (frame->fr_data_z) | |
507 /* Frame already decompressed */ | |
508 return 0; | |
509 /* Do decompression */ | |
510 return decompress_frame(frame); | |
511 } | |
512 | |
513 | |
514 /* | |
515 * Function id3_delete_frame (frame) | |
516 * | |
517 * Remove frame from ID3 tag and release memory ocupied by it. | |
518 * | |
519 */ | |
520 int | |
521 id3_delete_frame(struct id3_frame *frame) | |
522 { | |
523 GList *list = frame->fr_owner->id3_frame; | |
524 int ret; | |
525 | |
526 /* | |
527 * Search for frame in list. | |
528 */ | |
529 | |
530 if (g_list_find(list, frame) != NULL) { | |
531 /* | |
532 * Frame does not exist in frame list. | |
533 */ | |
534 ret = -1; | |
535 | |
536 } | |
537 else { | |
538 /* | |
539 * Remove frame from frame list. | |
540 */ | |
541 list = g_list_remove(list, frame); | |
542 frame->fr_owner->id3_altered = 1; | |
543 ret = 0; | |
544 } | |
545 | |
546 /* | |
547 * Release memory occupied by frame. | |
548 */ | |
549 if (frame->fr_raw_data) | |
550 g_free(frame->fr_raw_data); | |
551 if (frame->fr_data_z) | |
552 g_free(frame->fr_data_z); | |
553 g_free(frame); | |
554 | |
555 return ret; | |
556 } | |
557 | |
558 | |
559 /* | |
560 * Function id3_add_frame (id3, type) | |
561 * | |
562 * Add a new frame to the ID3 tag. Return a pointer to the new | |
563 * frame, or NULL if an error occured. | |
564 * | |
565 */ | |
566 struct id3_frame * | |
567 id3_add_frame(struct id3_tag *id3, guint32 type) | |
568 { | |
569 struct id3_frame *frame; | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
61
diff
changeset
|
570 size_t i; |
61 | 571 |
572 /* | |
573 * Allocate frame. | |
574 */ | |
787
e776161c16db
[svn] - more fixes, sizeof *frame !($&($&(@!#$@#*&@!$# whoever wrote this code is an idiot
nenolod
parents:
785
diff
changeset
|
575 frame = g_malloc0(sizeof(struct id3_frame)); |
61 | 576 |
577 /* | |
578 * Initialize frame | |
579 */ | |
580 frame->fr_owner = id3; | |
581 | |
582 /* | |
583 * Try finding the correct frame descriptor. | |
584 */ | |
585 for (i = 0; i < sizeof(framedesc) / sizeof(struct id3_framedesc); i++) { | |
586 if (framedesc[i].fd_id == type) { | |
587 frame->fr_desc = &framedesc[i]; | |
588 break; | |
589 } | |
590 } | |
591 | |
592 /* | |
593 * Insert frame into linked list. | |
594 */ | |
595 id3->id3_frame = g_list_append(id3->id3_frame, frame); | |
596 id3->id3_altered = 1; | |
597 | |
598 return frame; | |
599 } | |
600 | |
601 | |
602 /* | |
603 * Destroy all frames in an id3 tag, and free all data | |
604 */ | |
605 void | |
606 id3_destroy_frames(struct id3_tag *id) | |
607 { | |
608 GList *node; | |
609 | |
610 for (node = id->id3_frame; node != NULL; node = node->next) { | |
611 struct id3_frame *frame = node->data; | |
612 /* | |
613 * Release memory occupied by frame. | |
614 */ | |
615 if (frame->fr_raw_data) | |
616 g_free(frame->fr_raw_data); | |
617 if (frame->fr_data_z) | |
618 g_free(frame->fr_data_z); | |
619 g_free(frame); | |
620 } | |
621 g_list_free(id->id3_frame); | |
622 id->id3_frame = NULL; | |
623 } | |
624 | |
625 static int | |
626 id3_frame_extra_headers(struct id3_frame *frame) | |
627 { | |
628 int retv = 0; | |
629 /* | |
630 * If frame is encrypted, we have four extra bytes in the | |
631 * header. | |
632 */ | |
633 if (frame->fr_flags & ID3_FHFLAG_COMPRESS) | |
634 retv += 4; | |
635 /* | |
636 * If frame is encrypted, we have one extra byte in the | |
637 * header. | |
638 */ | |
639 if (frame->fr_flags & ID3_FHFLAG_ENCRYPT) | |
640 retv += 1; | |
641 | |
642 /* | |
643 * If frame has grouping identity, we have one extra byte in | |
644 * the header. | |
645 */ | |
646 if (frame->fr_flags & ID3_FHFLAG_GROUP) | |
647 retv += 1; | |
648 | |
649 return retv; | |
650 } | |
651 | |
652 static void * | |
653 id3_frame_get_dataptr(struct id3_frame *frame) | |
654 { | |
655 char *ptr = frame->fr_raw_data; | |
656 | |
657 ptr += id3_frame_extra_headers(frame); | |
658 | |
659 return ptr; | |
660 } | |
661 | |
662 static int | |
663 id3_frame_get_size(struct id3_frame *frame) | |
664 { | |
665 return frame->fr_raw_size - id3_frame_extra_headers(frame); | |
666 } | |
667 | |
668 void | |
669 id3_frame_clear_data(struct id3_frame *frame) | |
670 { | |
671 if (frame->fr_raw_data) | |
672 g_free(frame->fr_raw_data); | |
673 if (frame->fr_data_z) | |
674 g_free(frame->fr_data_z); | |
675 frame->fr_raw_data = NULL; | |
676 frame->fr_raw_size = 0; | |
677 frame->fr_data = NULL; | |
678 frame->fr_size = 0; | |
679 frame->fr_data_z = NULL; | |
680 frame->fr_size_z = 0; | |
681 } | |
682 | |
683 static guint32 | |
684 find_v24_id(guint32 v22) | |
685 { | |
701
d539e5c5f730
[svn] Fixes of the remaining GCC 4.1 warnings from external contributor Diego "Flameeyes" Petteno (Gentoo).
chainsaw
parents:
61
diff
changeset
|
686 size_t i; |
61 | 687 for (i = 0; i < sizeof(framedesc22) / sizeof(framedesc22[0]); i++) |
688 if (framedesc22[i].fd_v22 == v22) | |
689 return framedesc22[i].fd_v24; | |
690 | |
691 return 0; | |
692 } | |
693 | |
694 static int | |
695 id3_read_frame_v22(struct id3_tag *id3) | |
696 { | |
697 struct id3_frame *frame; | |
698 guint32 id, idv24; | |
699 char *buf; | |
700 int size; | |
701 | |
702 /* | |
703 * Read frame header. | |
704 */ | |
705 buf = id3->id3_read(id3, NULL, ID3_FRAMEHDR_SIZE_22); | |
706 if (buf == NULL) | |
707 return -1; | |
708 | |
709 /* | |
710 * If we encounter an invalid frame id, we assume that there | |
711 * is some. We just skip the rest of the ID3 tag. | |
712 */ | |
713 if (!((buf[0] >= '0' && buf[0] <= '9') | |
714 || (buf[0] >= 'A' && buf[0] <= 'Z'))) { | |
715 id3->id3_seek(id3, id3->id3_tagsize - id3->id3_pos); | |
716 return 0; | |
717 } | |
718 | |
719 id = ID3_FRAME_ID_22(buf[0], buf[1], buf[2]); | |
720 size = buf[3] << 16 | buf[4] << 8 | buf[5]; | |
721 | |
722 if ((idv24 = find_v24_id(id)) == 0) { | |
723 if (id3->id3_seek(id3, size) < 0) | |
724 return -1; | |
725 return 0; | |
726 } | |
727 | |
728 /* | |
729 * Allocate frame. | |
730 */ | |
785
20a62ae86b6e
[svn] - some compilers couldn't figure the original call out, so put a struct infront of it
nenolod
parents:
784
diff
changeset
|
731 frame = g_malloc0(sizeof(struct id3_frame)); |
61 | 732 |
733 frame->fr_owner = id3; | |
734 frame->fr_raw_size = size; | |
735 if (frame->fr_raw_size < 0 || frame->fr_raw_size > 1000000) { | |
736 g_free(frame); | |
737 return -1; | |
738 } | |
739 | |
740 /* | |
741 * Initialize frame. | |
742 */ | |
743 frame->fr_desc = find_frame_description(idv24); | |
744 | |
745 /* | |
746 * We allocate 2 extra bytes. This simplifies retrieval of | |
747 * text strings. | |
748 */ | |
749 frame->fr_raw_data = g_malloc0(frame->fr_raw_size + 2); | |
750 if (id3->id3_read(id3, frame->fr_raw_data, frame->fr_raw_size) == NULL) { | |
751 g_free(frame->fr_raw_data); | |
752 g_free(frame); | |
753 return -1; | |
754 } | |
755 | |
756 /* | |
757 * Insert frame into linked list. | |
758 */ | |
759 id3->id3_frame = g_list_append(id3->id3_frame, frame); | |
760 | |
761 frame->fr_data = frame->fr_raw_data; | |
762 frame->fr_size = frame->fr_raw_size; | |
763 | |
764 return 0; | |
765 } |