Mercurial > audlegacy
annotate Plugins/Input/mpg123/id3_frame.c @ 867:86e8224baa0e trunk
[svn] fixed multiple spawns of flac aboutbox
author | giacomo |
---|---|
date | Fri, 24 Mar 2006 08:00:06 -0800 |
parents | d15862899bbe |
children |
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 | |
788 | 253 /* |
254 * These need to be signed, because otherwise this code will get wonky. | |
255 * BTW, I hate this code and I hope it dies someday. | |
256 * --nenolod | |
257 */ | |
61 | 258 static struct id3_framedesc * |
259 find_frame_description(guint32 id) | |
260 { | |
788 | 261 int i; |
262 for (i = 0; i < (int) sizeof(framedesc) / (int) sizeof(struct id3_framedesc); i++) | |
61 | 263 if (framedesc[i].fd_id == id) |
264 return &framedesc[i]; | |
265 return NULL; | |
266 } | |
267 | |
268 | |
269 /* | |
270 * Function id3_read_frame (id3) | |
271 * | |
272 * Read next frame from the indicated ID3 tag. Return 0 upon | |
273 * success, or -1 if an error occured. | |
274 * | |
275 */ | |
276 int | |
277 id3_read_frame(struct id3_tag *id3) | |
278 { | |
279 struct id3_frame *frame; | |
280 guint32 id; | |
281 char *buf; | |
282 | |
283 if (id3->id3_version == 2) | |
284 return id3_read_frame_v22(id3); | |
285 | |
286 /* | |
287 * Read frame header. | |
288 */ | |
289 buf = id3->id3_read(id3, NULL, ID3_FRAMEHDR_SIZE); | |
290 if (buf == NULL) | |
291 return -1; | |
292 | |
293 /* | |
294 * If we encounter an invalid frame id, we assume that there is | |
295 * some padding in the header. We just skip the rest of the ID3 | |
296 * tag. | |
297 */ | |
298 if (!((buf[0] >= '0' && buf[0] <= '9') | |
299 || (buf[0] >= 'A' && buf[0] <= 'Z'))) { | |
300 id3->id3_seek(id3, id3->id3_tagsize - id3->id3_pos); | |
301 return 0; | |
302 } | |
303 id = ID3_FRAME_ID(buf[0], buf[1], buf[2], buf[3]); | |
304 | |
305 /* | |
306 * Allocate frame. | |
307 */ | |
787
e776161c16db
[svn] - more fixes, sizeof *frame !($&($&(@!#$@#*&@!$# whoever wrote this code is an idiot
nenolod
parents:
785
diff
changeset
|
308 frame = g_malloc0(sizeof(struct id3_frame)); |
61 | 309 |
310 frame->fr_owner = id3; | |
311 /* FIXME v2.4.0 */ | |
312 frame->fr_raw_size = buf[4] << 24 | buf[5] << 16 | buf[6] << 8 | buf[7]; | |
313 if (frame->fr_raw_size < 0 || frame->fr_raw_size > 1000000) { | |
314 g_free(frame); | |
315 return -1; | |
316 } | |
317 frame->fr_flags = buf[8] << 8 | buf[9]; | |
318 | |
319 /* | |
320 * Determine the type of the frame. | |
321 */ | |
322 | |
323 frame->fr_desc = find_frame_description(id); | |
324 | |
325 /* | |
326 * Check if frame had a valid id. | |
327 */ | |
328 if (frame->fr_desc == NULL) { | |
329 /* | |
330 * No. Ignore the frame. | |
331 */ | |
332 if (id3->id3_seek(id3, frame->fr_raw_size) < 0) { | |
333 g_free(frame); | |
334 return -1; | |
335 } | |
336 return 0; | |
337 } | |
338 | |
339 /* | |
340 * Initialize frame. | |
341 */ | |
342 | |
343 /* | |
344 * We allocate 2 extra bytes. This simplifies retrieval of | |
345 * text strings. | |
346 */ | |
347 frame->fr_raw_data = g_malloc0(frame->fr_raw_size + 2); | |
348 if (id3->id3_read(id3, frame->fr_raw_data, frame->fr_raw_size) == NULL) { | |
349 g_free(frame->fr_raw_data); | |
350 g_free(frame); | |
351 return -1; | |
352 } | |
353 | |
354 /* | |
355 * Insert frame into linked list. | |
356 */ | |
357 id3->id3_frame = g_list_append(id3->id3_frame, frame); | |
358 | |
359 /* | |
360 * Check if frame is compressed using zlib. | |
361 */ | |
362 if (frame->fr_flags & ID3_FHFLAG_COMPRESS) | |
363 return 0; | |
364 | |
365 frame->fr_data = id3_frame_get_dataptr(frame); | |
366 frame->fr_size = id3_frame_get_size(frame); | |
367 | |
368 return 0; | |
369 } | |
370 | |
371 | |
372 /* | |
373 * Function id3_get_frame (id3, type, num) | |
374 * | |
375 * Search in the list of frames for the ID3-tag, and return a frame | |
376 * of the indicated type. If tag contains several frames of the | |
377 * indicated type, the third argument tells which of the frames to | |
378 * return. | |
379 * | |
380 */ | |
381 struct id3_frame * | |
382 id3_get_frame(struct id3_tag *id3, guint32 type, int num) | |
383 { | |
384 GList *node; | |
385 | |
386 for (node = id3->id3_frame; node != NULL; node = node->next) { | |
387 struct id3_frame *fr = node->data; | |
388 if (fr->fr_desc && fr->fr_desc->fd_id == type) { | |
389 if (--num <= 0) | |
390 return fr; | |
391 } | |
392 } | |
393 return NULL; | |
394 } | |
395 | |
396 /* | |
397 * Function decompress_frame(frame) | |
398 * | |
399 * Uncompress the indicated frame. Return 0 upon success, or -1 if | |
400 * an error occured. | |
401 * | |
402 */ | |
403 static int | |
404 decompress_frame(struct id3_frame *frame) | |
405 { | |
406 #ifdef HAVE_LIBZ | |
407 z_stream z; | |
408 int r; | |
409 | |
410 /* | |
411 * Fetch the size of the decompressed data. | |
412 */ | |
413 frame->fr_size_z = g_ntohl(*((guint32 *) frame->fr_raw_data)); | |
414 if (frame->fr_size_z < 0 || frame->fr_size_z > 1000000) | |
415 return -1; | |
416 | |
417 /* | |
418 * Allocate memory to hold uncompressed frame. | |
419 */ | |
420 frame->fr_data_z = g_malloc(frame->fr_size_z + | |
421 (id3_frame_is_text(frame) ? 2 : 0)); | |
422 | |
423 /* | |
424 * Initialize zlib. | |
425 */ | |
426 z.next_in = id3_frame_get_dataptr(frame); | |
427 z.avail_in = id3_frame_get_size(frame); | |
428 z.zalloc = NULL; | |
429 z.zfree = NULL; | |
430 z.opaque = NULL; | |
431 | |
432 r = inflateInit(&z); | |
433 switch (r) { | |
434 case Z_OK: | |
435 break; | |
436 case Z_MEM_ERROR: | |
437 id3_error(frame->fr_owner, "zlib - no memory"); | |
438 goto Error_init; | |
439 case Z_VERSION_ERROR: | |
440 id3_error(frame->fr_owner, "zlib - invalid version"); | |
441 goto Error_init; | |
442 default: | |
443 id3_error(frame->fr_owner, "zlib - unknown error"); | |
444 goto Error_init; | |
445 } | |
446 | |
447 /* | |
448 * Decompress frame. | |
449 */ | |
450 z.next_out = frame->fr_data_z; | |
451 z.avail_out = frame->fr_size_z; | |
452 r = inflate(&z, Z_SYNC_FLUSH); | |
453 switch (r) { | |
454 case Z_STREAM_END: | |
455 break; | |
456 case Z_OK: | |
457 if (z.avail_in == 0) | |
458 /* | |
459 * This should not be possible with a correct stream. | |
460 * We will be nice however, and try to go on. | |
461 */ | |
462 break; | |
463 id3_error(frame->fr_owner, "zlib - buffer exhausted"); | |
464 goto Error_inflate; | |
465 default: | |
466 id3_error(frame->fr_owner, "zlib - unknown error"); | |
467 goto Error_inflate; | |
468 } | |
469 | |
470 r = inflateEnd(&z); | |
471 if (r != Z_OK) | |
472 id3_error(frame->fr_owner, "zlib - inflateEnd error"); | |
473 | |
474 /* | |
475 * Null-terminate text frames. | |
476 */ | |
477 if (id3_frame_is_text(frame)) { | |
478 ((char *) frame->fr_data_z)[frame->fr_size_z] = 0; | |
479 ((char *) frame->fr_data_z)[frame->fr_size_z + 1] = 0; | |
480 } | |
481 frame->fr_data = frame->fr_data_z; | |
482 frame->fr_size = frame->fr_size_z + (id3_frame_is_text(frame) ? 2 : 0); | |
483 | |
484 return 0; | |
485 | |
486 /* | |
487 * Cleanup code. | |
488 */ | |
489 Error_inflate: | |
490 r = inflateEnd(&z); | |
491 Error_init: | |
492 g_free(frame->fr_data_z); | |
493 frame->fr_data_z = NULL; | |
494 #endif | |
495 return -1; | |
496 } | |
497 | |
498 /* | |
499 * Function id3_decompress_frame(frame) | |
500 * | |
501 * Check if frame is compressed, and uncompress if necessary. | |
502 * Return 0 upon success, or -1 if an error occured. | |
503 * | |
504 */ | |
505 int | |
506 id3_decompress_frame(struct id3_frame *frame) | |
507 { | |
508 if (!(frame->fr_flags & ID3_FHFLAG_COMPRESS)) | |
509 /* Frame not compressed */ | |
510 return 0; | |
511 if (frame->fr_data_z) | |
512 /* Frame already decompressed */ | |
513 return 0; | |
514 /* Do decompression */ | |
515 return decompress_frame(frame); | |
516 } | |
517 | |
518 | |
519 /* | |
520 * Function id3_delete_frame (frame) | |
521 * | |
522 * Remove frame from ID3 tag and release memory ocupied by it. | |
523 * | |
524 */ | |
525 int | |
526 id3_delete_frame(struct id3_frame *frame) | |
527 { | |
528 GList *list = frame->fr_owner->id3_frame; | |
529 int ret; | |
530 | |
531 /* | |
532 * Search for frame in list. | |
533 */ | |
534 | |
535 if (g_list_find(list, frame) != NULL) { | |
536 /* | |
537 * Frame does not exist in frame list. | |
538 */ | |
539 ret = -1; | |
540 | |
541 } | |
542 else { | |
543 /* | |
544 * Remove frame from frame list. | |
545 */ | |
546 list = g_list_remove(list, frame); | |
547 frame->fr_owner->id3_altered = 1; | |
548 ret = 0; | |
549 } | |
550 | |
551 /* | |
552 * Release memory occupied by frame. | |
553 */ | |
554 if (frame->fr_raw_data) | |
555 g_free(frame->fr_raw_data); | |
556 if (frame->fr_data_z) | |
557 g_free(frame->fr_data_z); | |
558 g_free(frame); | |
559 | |
560 return ret; | |
561 } | |
562 | |
563 | |
564 /* | |
565 * Function id3_add_frame (id3, type) | |
566 * | |
567 * Add a new frame to the ID3 tag. Return a pointer to the new | |
568 * frame, or NULL if an error occured. | |
569 * | |
570 */ | |
571 struct id3_frame * | |
572 id3_add_frame(struct id3_tag *id3, guint32 type) | |
573 { | |
574 struct id3_frame *frame; | |
788 | 575 int i; |
61 | 576 |
577 /* | |
578 * Allocate frame. | |
579 */ | |
787
e776161c16db
[svn] - more fixes, sizeof *frame !($&($&(@!#$@#*&@!$# whoever wrote this code is an idiot
nenolod
parents:
785
diff
changeset
|
580 frame = g_malloc0(sizeof(struct id3_frame)); |
61 | 581 |
582 /* | |
583 * Initialize frame | |
584 */ | |
585 frame->fr_owner = id3; | |
586 | |
587 /* | |
588 * Try finding the correct frame descriptor. | |
589 */ | |
788 | 590 for (i = 0; i < (int) sizeof(framedesc) / (int) sizeof(struct id3_framedesc); i++) { |
61 | 591 if (framedesc[i].fd_id == type) { |
592 frame->fr_desc = &framedesc[i]; | |
593 break; | |
594 } | |
595 } | |
596 | |
597 /* | |
598 * Insert frame into linked list. | |
599 */ | |
600 id3->id3_frame = g_list_append(id3->id3_frame, frame); | |
601 id3->id3_altered = 1; | |
602 | |
603 return frame; | |
604 } | |
605 | |
606 | |
607 /* | |
608 * Destroy all frames in an id3 tag, and free all data | |
609 */ | |
610 void | |
611 id3_destroy_frames(struct id3_tag *id) | |
612 { | |
613 GList *node; | |
614 | |
615 for (node = id->id3_frame; node != NULL; node = node->next) { | |
616 struct id3_frame *frame = node->data; | |
617 /* | |
618 * Release memory occupied by frame. | |
619 */ | |
620 if (frame->fr_raw_data) | |
621 g_free(frame->fr_raw_data); | |
622 if (frame->fr_data_z) | |
623 g_free(frame->fr_data_z); | |
624 g_free(frame); | |
625 } | |
626 g_list_free(id->id3_frame); | |
627 id->id3_frame = NULL; | |
628 } | |
629 | |
630 static int | |
631 id3_frame_extra_headers(struct id3_frame *frame) | |
632 { | |
633 int retv = 0; | |
634 /* | |
635 * If frame is encrypted, we have four extra bytes in the | |
636 * header. | |
637 */ | |
638 if (frame->fr_flags & ID3_FHFLAG_COMPRESS) | |
639 retv += 4; | |
640 /* | |
641 * If frame is encrypted, we have one extra byte in the | |
642 * header. | |
643 */ | |
644 if (frame->fr_flags & ID3_FHFLAG_ENCRYPT) | |
645 retv += 1; | |
646 | |
647 /* | |
648 * If frame has grouping identity, we have one extra byte in | |
649 * the header. | |
650 */ | |
651 if (frame->fr_flags & ID3_FHFLAG_GROUP) | |
652 retv += 1; | |
653 | |
654 return retv; | |
655 } | |
656 | |
657 static void * | |
658 id3_frame_get_dataptr(struct id3_frame *frame) | |
659 { | |
660 char *ptr = frame->fr_raw_data; | |
661 | |
662 ptr += id3_frame_extra_headers(frame); | |
663 | |
664 return ptr; | |
665 } | |
666 | |
667 static int | |
668 id3_frame_get_size(struct id3_frame *frame) | |
669 { | |
670 return frame->fr_raw_size - id3_frame_extra_headers(frame); | |
671 } | |
672 | |
673 void | |
674 id3_frame_clear_data(struct id3_frame *frame) | |
675 { | |
676 if (frame->fr_raw_data) | |
677 g_free(frame->fr_raw_data); | |
678 if (frame->fr_data_z) | |
679 g_free(frame->fr_data_z); | |
680 frame->fr_raw_data = NULL; | |
681 frame->fr_raw_size = 0; | |
682 frame->fr_data = NULL; | |
683 frame->fr_size = 0; | |
684 frame->fr_data_z = NULL; | |
685 frame->fr_size_z = 0; | |
686 } | |
687 | |
688 static guint32 | |
689 find_v24_id(guint32 v22) | |
690 { | |
788 | 691 int i; |
692 for (i = 0; i < (int) sizeof(framedesc22) / (int) sizeof(struct id3_framedesc22); i++) | |
61 | 693 if (framedesc22[i].fd_v22 == v22) |
694 return framedesc22[i].fd_v24; | |
695 | |
696 return 0; | |
697 } | |
698 | |
699 static int | |
700 id3_read_frame_v22(struct id3_tag *id3) | |
701 { | |
702 struct id3_frame *frame; | |
703 guint32 id, idv24; | |
704 char *buf; | |
705 int size; | |
706 | |
707 /* | |
708 * Read frame header. | |
709 */ | |
710 buf = id3->id3_read(id3, NULL, ID3_FRAMEHDR_SIZE_22); | |
711 if (buf == NULL) | |
712 return -1; | |
713 | |
714 /* | |
715 * If we encounter an invalid frame id, we assume that there | |
716 * is some. We just skip the rest of the ID3 tag. | |
717 */ | |
718 if (!((buf[0] >= '0' && buf[0] <= '9') | |
719 || (buf[0] >= 'A' && buf[0] <= 'Z'))) { | |
720 id3->id3_seek(id3, id3->id3_tagsize - id3->id3_pos); | |
721 return 0; | |
722 } | |
723 | |
724 id = ID3_FRAME_ID_22(buf[0], buf[1], buf[2]); | |
725 size = buf[3] << 16 | buf[4] << 8 | buf[5]; | |
726 | |
727 if ((idv24 = find_v24_id(id)) == 0) { | |
728 if (id3->id3_seek(id3, size) < 0) | |
729 return -1; | |
730 return 0; | |
731 } | |
732 | |
733 /* | |
734 * Allocate frame. | |
735 */ | |
785
20a62ae86b6e
[svn] - some compilers couldn't figure the original call out, so put a struct infront of it
nenolod
parents:
784
diff
changeset
|
736 frame = g_malloc0(sizeof(struct id3_frame)); |
61 | 737 |
738 frame->fr_owner = id3; | |
739 frame->fr_raw_size = size; | |
740 if (frame->fr_raw_size < 0 || frame->fr_raw_size > 1000000) { | |
741 g_free(frame); | |
742 return -1; | |
743 } | |
744 | |
745 /* | |
746 * Initialize frame. | |
747 */ | |
748 frame->fr_desc = find_frame_description(idv24); | |
749 | |
750 /* | |
751 * We allocate 2 extra bytes. This simplifies retrieval of | |
752 * text strings. | |
753 */ | |
754 frame->fr_raw_data = g_malloc0(frame->fr_raw_size + 2); | |
755 if (id3->id3_read(id3, frame->fr_raw_data, frame->fr_raw_size) == NULL) { | |
756 g_free(frame->fr_raw_data); | |
757 g_free(frame); | |
758 return -1; | |
759 } | |
760 | |
761 /* | |
762 * Insert frame into linked list. | |
763 */ | |
764 id3->id3_frame = g_list_append(id3->id3_frame, frame); | |
765 | |
766 frame->fr_data = frame->fr_raw_data; | |
767 frame->fr_size = frame->fr_raw_size; | |
768 | |
769 return 0; | |
770 } |