61
|
1 /*********************************************************************
|
|
2 *
|
|
3 * Copyright (C) 1999, 2001, 2002, Espen Skoglund
|
|
4 * Department of Computer Science, University of Tromsų
|
|
5 *
|
|
6 * Filename: id3_frame_text.c
|
|
7 * Description: Code for handling ID3 text frames.
|
|
8 * Author: Espen Skoglund <espensk@stud.cs.uit.no>
|
|
9 * Created at: Fri Feb 5 23:50:33 1999
|
|
10 *
|
|
11 * $Id: id3_frame_text.c,v 1.7 2004/08/21 13:04:47 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 #include <stdarg.h>
|
|
31 #include <stdlib.h>
|
|
32 #include <string.h>
|
|
33
|
|
34 #include "xmms-id3.h"
|
|
35 #include "id3_header.h"
|
|
36
|
|
37
|
|
38 char *
|
|
39 id3_utf16_to_ascii(void *utf16)
|
|
40 {
|
|
41 char ascii[256];
|
|
42 char *uc = (char *) utf16 + 2;
|
|
43 int i;
|
|
44
|
|
45 for (i = 0; *uc != 0 && i < sizeof(ascii); i++, uc += 2)
|
|
46 ascii[i] = *uc;
|
|
47
|
|
48 ascii[i] = 0;
|
|
49 return g_strdup(ascii);
|
|
50 }
|
|
51
|
|
52
|
|
53 /*
|
|
54 * Function id3_get_encoding (frame)
|
|
55 *
|
|
56 * Return text encoding for frame, or -1 if frame does not have any
|
|
57 * text encoding.
|
|
58 *
|
|
59 */
|
|
60 gint8
|
|
61 id3_get_encoding(struct id3_frame * frame)
|
|
62 {
|
|
63 /* Type check */
|
|
64 if (!id3_frame_is_text(frame) &&
|
|
65 frame->fr_desc->fd_id != ID3_WXXX &&
|
|
66 frame->fr_desc->fd_id != ID3_IPLS &&
|
|
67 frame->fr_desc->fd_id != ID3_USLT &&
|
|
68 frame->fr_desc->fd_id != ID3_SYLT &&
|
|
69 frame->fr_desc->fd_id != ID3_COMM &&
|
|
70 frame->fr_desc->fd_id != ID3_APIC &&
|
|
71 frame->fr_desc->fd_id != ID3_GEOB &&
|
|
72 frame->fr_desc->fd_id != ID3_USER &&
|
|
73 frame->fr_desc->fd_id != ID3_OWNE &&
|
|
74 frame->fr_desc->fd_id != ID3_COMR)
|
|
75 return -1;
|
|
76
|
|
77 /* Check if frame is compressed */
|
|
78 if (id3_decompress_frame(frame) == -1)
|
|
79 return -1;
|
|
80
|
|
81 return *(gint8 *) frame->fr_data;
|
|
82 }
|
|
83
|
|
84
|
|
85 /*
|
|
86 * Function id3_set_encoding (frame, encoding)
|
|
87 *
|
|
88 * Set text encoding for frame. Return 0 upon success, or -1 if an
|
|
89 * error occured.
|
|
90 *
|
|
91 */
|
|
92 int
|
|
93 id3_set_encoding(struct id3_frame *frame, gint8 encoding)
|
|
94 {
|
|
95 /* Type check */
|
|
96 if (frame->fr_desc->fd_idstr[0] != 'T' &&
|
|
97 frame->fr_desc->fd_id != ID3_WXXX &&
|
|
98 frame->fr_desc->fd_id != ID3_IPLS &&
|
|
99 frame->fr_desc->fd_id != ID3_USLT &&
|
|
100 frame->fr_desc->fd_id != ID3_SYLT &&
|
|
101 frame->fr_desc->fd_id != ID3_COMM &&
|
|
102 frame->fr_desc->fd_id != ID3_APIC &&
|
|
103 frame->fr_desc->fd_id != ID3_GEOB &&
|
|
104 frame->fr_desc->fd_id != ID3_USER &&
|
|
105 frame->fr_desc->fd_id != ID3_OWNE &&
|
|
106 frame->fr_desc->fd_id != ID3_COMR)
|
|
107 return -1;
|
|
108
|
|
109 /* Check if frame is compressed */
|
|
110 if (id3_decompress_frame(frame) == -1)
|
|
111 return -1;
|
|
112
|
|
113 /* Changing the encoding of frames is not supported yet */
|
|
114 if (*(gint8 *) frame->fr_data != encoding)
|
|
115 return -1;
|
|
116
|
|
117 /* Set encoding */
|
|
118 *(gint8 *) frame->fr_data = encoding;
|
|
119 return 0;
|
|
120 }
|
|
121
|
|
122
|
|
123 /*
|
|
124 * Function id3_get_text (frame)
|
|
125 *
|
|
126 * Return string contents of frame.
|
|
127 *
|
|
128 */
|
|
129 char *
|
|
130 id3_get_text(struct id3_frame *frame)
|
|
131 {
|
|
132 /* Type check */
|
|
133 if (frame->fr_desc->fd_idstr[0] != 'T' && frame->fr_desc->fd_id != ID3_COMM)
|
|
134 return NULL;
|
|
135
|
|
136 /* Check if frame is compressed */
|
|
137 if (id3_decompress_frame(frame) == -1)
|
|
138 return NULL;
|
|
139
|
|
140 if (frame->fr_desc->fd_id == ID3_TXXX || frame->fr_desc->fd_id == ID3_COMM) {
|
|
141 /*
|
|
142 * This is a user defined text frame. Skip the description.
|
|
143 */
|
|
144 switch (*(guint8 *) frame->fr_data) {
|
|
145 case ID3_ENCODING_ISO_8859_1:
|
|
146 {
|
|
147 char *text = (char *) frame->fr_data + 1;
|
|
148
|
|
149 while (*text != 0)
|
|
150 text++;
|
|
151
|
|
152 return g_strdup(++text);
|
|
153 }
|
|
154 case ID3_ENCODING_UTF16:
|
|
155 {
|
|
156 char *text16 = (char *) frame->fr_data + 1;
|
|
157
|
|
158 while (*text16 != 0 || *(text16 + 1) != 0)
|
|
159 text16 += 2;
|
|
160
|
|
161 return id3_utf16_to_ascii(text16 + 2);
|
|
162 }
|
|
163 default:
|
|
164 return NULL;
|
|
165 }
|
|
166 }
|
|
167
|
|
168 if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
|
|
169 return g_strdup((char *) frame->fr_data + 1);
|
|
170 else
|
|
171 return id3_utf16_to_ascii(((char *) frame->fr_data + 1));
|
|
172 }
|
|
173
|
|
174
|
|
175 /*
|
|
176 * Function id3_get_text_desc (frame)
|
|
177 *
|
|
178 * Get description part of a text frame.
|
|
179 *
|
|
180 */
|
|
181 char *
|
|
182 id3_get_text_desc(struct id3_frame *frame)
|
|
183 {
|
|
184 /* Type check */
|
|
185 if (frame->fr_desc->fd_idstr[0] != 'T')
|
|
186 return NULL;
|
|
187
|
|
188 /* If predefined text frame, return description. */
|
|
189 if (frame->fr_desc->fd_id != ID3_TXXX)
|
|
190 return frame->fr_desc->fd_description;
|
|
191
|
|
192 /* Check if frame is compressed */
|
|
193 if (id3_decompress_frame(frame) == -1)
|
|
194 return NULL;
|
|
195
|
|
196 if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
|
|
197 return g_strdup((char *) frame->fr_data + 1);
|
|
198 else
|
|
199 return id3_utf16_to_ascii((char *) frame->fr_data + 1);
|
|
200 }
|
|
201
|
|
202
|
|
203 /*
|
|
204 * Function id3_get_text_number (frame)
|
|
205 *
|
|
206 * Return string contents of frame translated to a positive
|
|
207 * integer, or -1 if an error occured.
|
|
208 *
|
|
209 */
|
|
210 int
|
|
211 id3_get_text_number(struct id3_frame *frame)
|
|
212 {
|
|
213 int number = 0;
|
|
214
|
|
215 /* Check if frame is compressed */
|
|
216 if (id3_decompress_frame(frame) == -1)
|
|
217 return -1;
|
|
218
|
|
219 /*
|
|
220 * Generate integer according to encoding.
|
|
221 */
|
|
222 switch (*(guint8 *) frame->fr_data) {
|
|
223 case ID3_ENCODING_ISO_8859_1:
|
|
224 {
|
|
225 char *text = ((char *) frame->fr_data) + 1;
|
|
226
|
|
227 while (*text >= '0' && *text <= '9') {
|
|
228 number *= 10;
|
|
229 number += *text - '0';
|
|
230 text++;
|
|
231 }
|
|
232
|
|
233 return number;
|
|
234 }
|
|
235 case ID3_ENCODING_UTF16:
|
|
236 {
|
|
237 char *text = ((char *) frame->fr_data) + 3;
|
|
238
|
|
239 /* if (*(gint16 *) frame->fr_data == 0xfeff) */
|
|
240 /* text++; */
|
|
241
|
|
242 while (*text >= '0' && *text <= '9') {
|
|
243 number *= 10;
|
|
244 number += *text - '0';
|
|
245 text++;
|
|
246 }
|
|
247
|
|
248 return number;
|
|
249 }
|
|
250
|
|
251 default:
|
|
252 return -1;
|
|
253 }
|
|
254 }
|
|
255
|
|
256
|
|
257 /*
|
|
258 * Function id3_set_text (frame, text)
|
|
259 *
|
|
260 * Set text for the indicated frame (only ISO-8859-1 is currently
|
|
261 * supported). Return 0 upon success, or -1 if an error occured.
|
|
262 *
|
|
263 */
|
|
264 int
|
|
265 id3_set_text(struct id3_frame *frame, char *text)
|
|
266 {
|
|
267 /* Type check */
|
|
268 if (frame->fr_desc->fd_idstr[0] != 'T')
|
|
269 return -1;
|
|
270
|
|
271 /*
|
|
272 * Release memory occupied by previous data.
|
|
273 */
|
|
274 id3_frame_clear_data(frame);
|
|
275
|
|
276 /*
|
|
277 * Allocate memory for new data.
|
|
278 */
|
|
279 frame->fr_raw_size = strlen(text) + 1;
|
|
280 frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1);
|
|
281
|
|
282 /*
|
|
283 * Copy contents.
|
|
284 */
|
|
285 *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1;
|
|
286 memcpy((char *) frame->fr_raw_data + 1, text, frame->fr_raw_size);
|
|
287
|
|
288 frame->fr_altered = 1;
|
|
289 frame->fr_owner->id3_altered = 1;
|
|
290
|
|
291 frame->fr_data = frame->fr_raw_data;
|
|
292 frame->fr_size = frame->fr_raw_size;
|
|
293
|
|
294 return 0;
|
|
295 }
|
|
296
|
|
297
|
|
298 /*
|
|
299 * Function id3_set_text_number (frame, number)
|
|
300 *
|
|
301 * Set number for the indicated frame (only ISO-8859-1 is currently
|
|
302 * supported). Return 0 upon success, or -1 if an error occured.
|
|
303 *
|
|
304 */
|
|
305 int
|
|
306 id3_set_text_number(struct id3_frame *frame, int number)
|
|
307 {
|
|
308 char buf[64];
|
|
309 int pos;
|
|
310 char *text;
|
|
311
|
|
312 /* Type check */
|
|
313 if (frame->fr_desc->fd_idstr[0] != 'T')
|
|
314 return -1;
|
|
315
|
|
316 /*
|
|
317 * Release memory occupied by previous data.
|
|
318 */
|
|
319 id3_frame_clear_data(frame);
|
|
320
|
|
321 /*
|
|
322 * Create a string with a reversed number.
|
|
323 */
|
|
324 pos = 0;
|
|
325 while (number > 0 && pos < 64) {
|
|
326 buf[pos++] = (number % 10) + '0';
|
|
327 number /= 10;
|
|
328 }
|
|
329 if (pos == 64)
|
|
330 return -1;
|
|
331 if (pos == 0)
|
|
332 buf[pos++] = '0';
|
|
333
|
|
334 /*
|
|
335 * Allocate memory for new data.
|
|
336 */
|
|
337 frame->fr_raw_size = pos + 1;
|
|
338 frame->fr_raw_data = g_malloc(frame->fr_raw_size + 1);
|
|
339
|
|
340 /*
|
|
341 * Insert contents.
|
|
342 */
|
|
343 *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1;
|
|
344 text = (char *) frame->fr_raw_data + 1;
|
|
345 while (--pos >= 0)
|
|
346 *text++ = buf[pos];
|
|
347 *text = '\0';
|
|
348
|
|
349 frame->fr_altered = 1;
|
|
350 frame->fr_owner->id3_altered = 1;
|
|
351
|
|
352 frame->fr_data = frame->fr_raw_data;
|
|
353 frame->fr_size = frame->fr_raw_size;
|
|
354
|
|
355 return 0;
|
|
356 }
|
|
357
|
|
358 gboolean
|
|
359 id3_frame_is_text(struct id3_frame * frame)
|
|
360 {
|
|
361 if (frame && frame->fr_desc &&
|
|
362 (frame->fr_desc->fd_idstr[0] == 'T' ||
|
|
363 frame->fr_desc->fd_idstr[0] == 'W'))
|
|
364 return TRUE;
|
|
365 return FALSE;
|
|
366 }
|