View | Details | Raw Unified | Return to bug 7555
Collapse All | Expand All

(-)xmms-1.2.10.orig/Input/mpg123/charset.h (+420 lines)
Line 0 Link Here
1
/* charset.h - 2001/12/04 */
2
/*
3
 *  EasyTAG - Tag editor for MP3 and OGG files
4
 *  Copyright (C) 2000-2002  Jerome Couderc <j.couderc@ifrance.com>
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; either version 2 of the License, or
9
 *  (at your option) any later version.
10
 *
11
 *  This program 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
14
 *  GNU General Public License for more details.
15
 *
16
 *  You should have received a copy of the GNU General Public License
17
 *  along with this program; if not, write to the Free Software
18
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
 */
20
21
#ifndef FALSE
22
#define FALSE 0
23
#endif
24
#ifndef TRUE
25
#define TRUE 1
26
#endif
27
28
/*
29
 * Standard gettext macros.
30
 */
31
#ifdef ENABLE_NLS
32
#  include <libintl.h>
33
#  define _(String) gettext (String)
34
#  ifdef gettext_noop
35
#    define N_(String) gettext_noop (String)
36
#  else
37
#    define N_(String) (String)
38
#  endif
39
#else
40
#  define textdomain(String) (String)
41
#  define gettext(String) (String)
42
#  define dgettext(Domain,Message) (Message)
43
#  define dcgettext(Domain,Message,Type) (Message)
44
#  define bindtextdomain(Domain,Directory) (Domain)
45
#  define _(String) (String)
46
#  define N_(String) (String)
47
#endif
48
49
#ifndef DLL_H
50
#define DLL_H
51
typedef struct DLL_s
52
{
53
	void *prev;
54
	void *data;
55
	void *next;
56
} DLL;
57
#endif
58
59
#ifndef __CHARSET_H__
60
#define __CHARSET_H__
61
62
63
/***************
64
 * Declaration *
65
 ***************/
66
67
typedef struct {
68
	char *charset_title;
69
	char *charset_name;
70
} CharsetInfo;
71
72
73
/**************
74
 * Prototypes *
75
 **************/
76
77
//static gchar* get_current_charset (void);
78
79
/* Used for ogg tags */
80
char* convert_to_utf8   (const char *string);
81
char* convert_from_utf8 (const char *string);
82
83
char* convert_from_file_to_user (const char *string);
84
char* convert_from_user_to_file (const char *string);
85
86
DLL *Charset_Create_List (void);
87
char *Charset_Get_Name_From_Title (char *charset_title);
88
char *Charset_Get_Title_From_Name (char *charset_name);
89
90
short int test_conversion_charset (char *from, char *to);
91
92
93
#endif /* __CHARSET_H__ */
94
95
/*
96
 * Main part of code, written by:
97
 *
98
 * Copyright (C) 1999-2001  Håvard Kvålen <havardk@xmms.org>
99
 *
100
 * This program is free software; you can redistribute it and/or
101
 * modify it under the terms of the GNU General Public License
102
 * as published by the Free Software Foundation; either version 2
103
 * of the License, or (at your option) any later version.
104
 *
105
 * This program is distributed in the hope that it will be useful,
106
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
107
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
108
 * GNU General Public License for more details.
109
 *
110
 * You should have received a copy of the GNU General Public License
111
 * along with this program; if not, write to the Free Software
112
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
113
 * 02111-1307, USA.
114
 *
115
 */
116
117
#include <stdlib.h>
118
#include <string.h>
119
#include <errno.h>
120
121
#ifdef HAVE_ICONV_OPEN
122
#include <iconv.h>
123
#endif
124
125
#ifdef HAVE_LANGINFO_CODESET
126
#include <langinfo.h>
127
#endif
128
129
/****************
130
 * Declarations *
131
 ****************/
132
133
#define CHARSET_TRANS_ARRAY_LEN ( sizeof(charset_trans_array) / sizeof((charset_trans_array)[0]) )
134
const CharsetInfo charset_trans_array[] = { 
135
    {N_("Arabic (IBM-864)"),                  "IBM864"        },
136
    {N_("Arabic (ISO-8859-6)"),               "ISO-8859-6"    },
137
    {N_("Arabic (Windows-1256)"),             "windows-1256"  },
138
    {N_("Baltic (ISO-8859-13)"),              "ISO-8859-13"   },
139
    {N_("Baltic (ISO-8859-4)"),               "ISO-8859-4"    },
140
    {N_("Baltic (Windows-1257)"),             "windows-1257"  },
141
    {N_("Celtic (ISO-8859-14)"),              "ISO-8859-14"   },
142
    {N_("Central European (IBM-852)"),        "IBM852"        },
143
    {N_("Central European (ISO-8859-2)"),     "ISO-8859-2"    },
144
    {N_("Central European (Windows-1250)"),   "windows-1250"  },
145
    {N_("Chinese Simplified (GB18030)"),      "gb18030"       },
146
    {N_("Chinese Simplified (GB2312)"),       "GB2312"        },
147
    {N_("Chinese Traditional (Big5)"),        "Big5"          },
148
    {N_("Chinese Traditional (Big5-HKSCS)"),  "Big5-HKSCS"    },
149
    {N_("Cyrillic (IBM-855)"),                "IBM855"        },
150
    {N_("Cyrillic (ISO-8859-5)"),             "ISO-8859-5"    },
151
    {N_("Cyrillic (ISO-IR-111)"),             "ISO-IR-111"    },
152
    {N_("Cyrillic (KOI8-R)"),                 "KOI8-R"        },
153
    {N_("Cyrillic (Windows-1251)"),           "windows-1251"  },
154
    {N_("Cyrillic/Russian (CP-866)"),         "IBM866"        },
155
    {N_("Cyrillic/Ukrainian (KOI8-U)"),       "KOI8-U"        },
156
    {N_("English (US-ASCII)"),                "us-ascii"      },
157
    {N_("Greek (ISO-8859-7)"),                "ISO-8859-7"    },
158
    {N_("Greek (Windows-1253)"),              "windows-1253"  },
159
    {N_("Hebrew (IBM-862)"),                  "IBM862"        },
160
    {N_("Hebrew (Windows-1255)"),             "windows-1255"  },
161
    {N_("Japanese (EUC-JP)"),                 "EUC-JP"        },
162
    {N_("Japanese (ISO-2022-JP)"),            "ISO-2022-JP"   },
163
    {N_("Japanese (Shift_JIS)"),              "Shift_JIS"     },
164
    {N_("Korean (EUC-KR)"),                   "EUC-KR"        },
165
    {N_("Nordic (ISO-8859-10)"),              "ISO-8859-10"   },
166
    {N_("South European (ISO-8859-3)"),       "ISO-8859-3"    },
167
    {N_("Thai (TIS-620)"),                    "TIS-620"       },
168
    {N_("Turkish (IBM-857)"),                 "IBM857"        },
169
    {N_("Turkish (ISO-8859-9)"),              "ISO-8859-9"    },
170
    {N_("Turkish (Windows-1254)"),            "windows-1254"  },
171
    {N_("Unicode (UTF-7)"),                   "UTF-7"         },
172
    {N_("Unicode (UTF-8)"),                   "UTF-8"         },
173
    {N_("Unicode (UTF-16BE)"),                "UTF-16BE"      },
174
    {N_("Unicode (UTF-16LE)"),                "UTF-16LE"      },
175
    {N_("Unicode (UTF-32BE)"),                "UTF-32BE"      },
176
    {N_("Unicode (UTF-32LE)"),                "UTF-32LE"      },
177
    {N_("Vietnamese (VISCII)"),               "VISCII"        },
178
    {N_("Vietnamese (Windows-1258)"),         "windows-1258"  },
179
    {N_("Visual Hebrew (ISO-8859-8)"),        "ISO-8859-8"    },
180
    {N_("Western (IBM-850)"),                 "IBM850"        },
181
    {N_("Western (ISO-8859-1)"),              "ISO-8859-1"    },
182
    {N_("Western (ISO-8859-15)"),             "ISO-8859-15"   },
183
    {N_("Western (Windows-1252)"),            "windows-1252"  }
184
185
    /*
186
     * From this point, character sets aren't supported by iconv
187
     */
188
/*    {N_("Arabic (IBM-864-I)"),                "IBM864i"              },
189
    {N_("Arabic (ISO-8859-6-E)"),             "ISO-8859-6-E"         },
190
    {N_("Arabic (ISO-8859-6-I)"),             "ISO-8859-6-I"         },
191
    {N_("Arabic (MacArabic)"),                "x-mac-arabic"         },
192
    {N_("Armenian (ARMSCII-8)"),              "armscii-8"            },
193
    {N_("Central European (MacCE)"),          "x-mac-ce"             },
194
    {N_("Chinese Simplified (GBK)"),          "x-gbk"                },
195
    {N_("Chinese Simplified (HZ)"),           "HZ-GB-2312"           },
196
    {N_("Chinese Traditional (EUC-TW)"),      "x-euc-tw"             },
197
    {N_("Croatian (MacCroatian)"),            "x-mac-croatian"       },
198
    {N_("Cyrillic (MacCyrillic)"),            "x-mac-cyrillic"       },
199
    {N_("Cyrillic/Ukrainian (MacUkrainian)"), "x-mac-ukrainian"      },
200
    {N_("Farsi (MacFarsi)"),                  "x-mac-farsi"},
201
    {N_("Greek (MacGreek)"),                  "x-mac-greek"          },
202
    {N_("Gujarati (MacGujarati)"),            "x-mac-gujarati"       },
203
    {N_("Gurmukhi (MacGurmukhi)"),            "x-mac-gurmukhi"       },
204
    {N_("Hebrew (ISO-8859-8-E)"),             "ISO-8859-8-E"         },
205
    {N_("Hebrew (ISO-8859-8-I)"),             "ISO-8859-8-I"         },
206
    {N_("Hebrew (MacHebrew)"),                "x-mac-hebrew"         },
207
    {N_("Hindi (MacDevanagari)"),             "x-mac-devanagari"     },
208
    {N_("Icelandic (MacIcelandic)"),          "x-mac-icelandic"      },
209
    {N_("Korean (JOHAB)"),                    "x-johab"              },
210
    {N_("Korean (UHC)"),                      "x-windows-949"        },
211
    {N_("Romanian (MacRomanian)"),            "x-mac-romanian"       },
212
    {N_("Turkish (MacTurkish)"),              "x-mac-turkish"        },
213
    {N_("User Defined"),                      "x-user-defined"       },
214
    {N_("Vietnamese (TCVN)"),                 "x-viet-tcvn5712"      },
215
    {N_("Vietnamese (VPS)"),                  "x-viet-vps"           },
216
    {N_("Western (MacRoman)"),                "x-mac-roman"          },
217
    // charsets whithout posibly translatable names
218
    {"T61.8bit",                              "T61.8bit"             },
219
    {"x-imap4-modified-utf7",                 "x-imap4-modified-utf7"},
220
    {"x-u-escaped",                           "x-u-escaped"          },
221
    {"windows-936",                           "windows-936"          }
222
*/
223
};
224
225
226
227
228
/*************
229
 * Functions *
230
 *************/
231
// Return the last item of an doubly linked list
232
static DLL *
233
dll_last_c (DLL *list)
234
{
235
	DLL *item = list;
236
	
237
	while ( item->next )
238
		item = item->next;
239
	
240
	return item;
241
}
242
243
// Append an item to the doubly linked list
244
static DLL *
245
dll_append_c (DLL *list, void *data)
246
{
247
	DLL *item = malloc (sizeof(DLL));
248
	
249
	item->data = data;
250
	item->prev = dll_last_c(list);
251
	item->next = NULL;
252
	
253
	return item;
254
}
255
256
static char* get_current_charset (void)
257
{
258
    char *charset = getenv("CHARSET");
259
260
#ifdef HAVE_LANGINFO_CODESET
261
    if (!charset)
262
        charset = nl_langinfo(CODESET);
263
#endif
264
    if (!charset)
265
        charset = "ISO-8859-1";
266
267
    return charset;
268
}
269
270
271
#ifdef HAVE_ICONV_OPEN
272
static char* convert_string (const char *string, char *from, char *to)
273
{
274
    size_t outleft, outsize, length;
275
    iconv_t cd;
276
    char *out, *outptr;
277
    const char *input = string;
278
279
    if (!string)
280
        return NULL;
281
282
    length = strlen(string);
283
284
    /*  g_message("converting %s from %s to %s", string, from, to); */
285
    if ((cd = iconv_open(to, from)) == (iconv_t)-1)
286
    {
287
		fprintf (stderr, "convert_string(): Conversion not supported. Charsets: %s -> %s", from, to);
288
        return strdup(string);
289
    }
290
291
    /* Due to a GLIBC bug, round outbuf_size up to a multiple of 4 */
292
    /* + 1 for nul in case len == 1 */
293
    outsize = ((length + 3) & ~3) + 1;
294
    out = g_malloc(outsize);
295
    outleft = outsize - 1;
296
    outptr = out;
297
298
 retry:
299
    if (iconv(cd, (char **)&input, &length, &outptr, &outleft) == -1)
300
    {
301
        int used;
302
        switch (errno)
303
        {
304
            case E2BIG:
305
                used = outptr - out;
306
                outsize = (outsize - 1) * 2 + 1;
307
                out = g_realloc(out, outsize);
308
                outptr = out + used;
309
                outleft = outsize - 1 - used;
310
                goto retry;
311
            case EINVAL:
312
                break;
313
            case EILSEQ:
314
                /* Invalid sequence, try to get the
315
                                   rest of the string */
316
                input++;
317
                length = strlen(input);
318
                goto retry;
319
            default:
320
                fprintf (stderr, "convert_string(): Conversion failed. Inputstring: %s; Error: %s", string, strerror(errno));
321
                break;
322
        }
323
    }
324
    *outptr = '\0';
325
326
    iconv_close(cd);
327
    return out;
328
}
329
#else
330
static char* convert_string (const char *string, char *from, char *to)
331
{
332
    if (!string)
333
        return NULL;
334
    return strdup(string);
335
}
336
#endif
337
338
339
/*
340
 * Conversion with UTF-8 for ogg tags
341
 */
342
char* convert_to_utf8 (const char *string)
343
{
344
    char *charset = get_current_charset();
345
346
    return convert_string(string, charset, "UTF-8");
347
}
348
349
char* convert_from_utf8 (const char *string)
350
{
351
    char *charset = get_current_charset();
352
353
    return convert_string(string, "UTF-8", charset);
354
}
355
356
357
DLL *Charset_Create_List (void)
358
{
359
    DLL *list = NULL;
360
    int i;
361
362
    for (i=0; i<CHARSET_TRANS_ARRAY_LEN; i++)
363
        list = dll_append_c (list,_(charset_trans_array[i].charset_title));
364
    return list;
365
}
366
367
368
/*
369
 * Return charset_name from charset_title
370
 */
371
char *Charset_Get_Name_From_Title (char *charset_title)
372
{
373
    int i;
374
375
    if (charset_title)
376
        for (i=0; i<CHARSET_TRANS_ARRAY_LEN; i++)
377
            if ( strcasecmp(_(charset_title),_(charset_trans_array[i].charset_title)) == 0 )
378
                return charset_trans_array[i].charset_name;
379
    return "";
380
}
381
382
383
/*
384
 * Return charset_title from charset_name
385
 */
386
char *Charset_Get_Title_From_Name (char *charset_name)
387
{
388
    int i;
389
390
    if (charset_name)
391
        for (i=0; i<CHARSET_TRANS_ARRAY_LEN; i++)
392
            if ( strcasecmp(charset_name,charset_trans_array[i].charset_name) == 0 )
393
                return _(charset_trans_array[i].charset_title);
394
    return "";
395
}
396
397
398
399
/*
400
 * Test if the conversion is supported between two character sets ('from' and 'to)
401
 */
402
#ifdef HAVE_ICONV_OPEN
403
short int test_conversion_charset (char *from, char *to)
404
{
405
    iconv_t cd;
406
407
    if ((cd=iconv_open(to,from)) == (iconv_t)-1)
408
    {
409
        /* Conversion not supported */
410
        return FALSE;
411
    }
412
    iconv_close(cd);
413
    return TRUE;
414
}
415
#else
416
short int test_conversion_charset (char *from, char *to)
417
{
418
    return TRUE;
419
}
420
#endif
(-)xmms-1.2.10.orig/Input/mpg123/fileinfo.c (-292 / +739 lines)
Lines 25-52 Link Here
25
#include <errno.h>
25
#include <errno.h>
26
#include <libxmms/xentry.h>
26
#include <libxmms/xentry.h>
27
#include "mpg123.h"
27
#include "mpg123.h"
28
#include "lib_id3v2.h"
29
30
#define MAX_STR_LEN 100
31
#define MAX_ENTRY_LEN2 1023
28
32
29
static GtkWidget *window = NULL;
33
static GtkWidget *window = NULL;
30
static GtkWidget *filename_entry, *id3_frame;
34
static GtkWidget *notebook = NULL;
31
static GtkWidget *title_entry, *artist_entry, *album_entry, *year_entry;
35
static GtkWidget *filename_entry, *id3v1_frame, *id3v2_frame;
32
static GtkWidget *tracknum_entry, *comment_entry, *genre_combo;
36
static GtkWidget *v1_checkbox, *v2_checkbox;
37
static GtkWidget *v1_title_entry, *v1_artist_entry, *v1_album_entry, *v1_year_entry, *v1_tracknum_entry, *v1_comment_entry;
38
static GtkWidget *v2_title_entry, *v2_artist_entry, *v2_album_entry, *v2_year_entry, *v2_tracknum_entry, *v2_comment_entry,
39
				 *v2_composer_entry, *v2_orig_artist_entry, *v2_url_entry, *v2_encoded_by_entry;
40
static GtkWidget *v1_genre_combo, *v2_genre_combo;
33
static GtkWidget *mpeg_level, *mpeg_bitrate, *mpeg_samplerate, *mpeg_flags;
41
static GtkWidget *mpeg_level, *mpeg_bitrate, *mpeg_samplerate, *mpeg_flags;
34
static GtkWidget *mpeg_fileinfo;
42
static GtkWidget *mpeg_fileinfo;
35
43
44
static GPtrArray *v1_labels_list = NULL, *v2_labels_list = NULL;    // TODO: Where will these be freed?
36
static GList *genre_list;
45
static GList *genre_list;
37
struct genre_item {
46
struct genre_item {
38
	const char *name;
47
	const char *name;
39
	int id;
48
	int id;
40
};
49
};
41
static int current_genre;
50
static int v1_current_genre;
51
static int v2_current_genre;
42
static char *current_filename;
52
static char *current_filename;
43
53
44
extern char *mpg123_filename;
54
extern char *mpg123_filename;
45
extern int mpg123_bitrate, mpg123_frequency, mpg123_layer, mpg123_lsf, mpg123_mode;
55
extern int mpg123_bitrate, mpg123_frequency, mpg123_layer, mpg123_lsf, mpg123_mode;
46
extern gboolean mpg123_stereo, mpg123_mpeg25;
56
extern gboolean mpg123_stereo, mpg123_mpeg25;
47
57
48
#define MAX_STR_LEN 100
49
50
static void label_set_text(GtkWidget * label, char *str, ...)
58
static void label_set_text(GtkWidget * label, char *str, ...)
51
G_GNUC_PRINTF(2, 3);
59
G_GNUC_PRINTF(2, 3);
52
60
Lines 66-71 Link Here
66
	strncpy(tag, gtk_entry_get_text(entry), length);
74
	strncpy(tag, gtk_entry_get_text(entry), length);
67
}
75
}
68
76
77
void copy_entry_tag(GtkEntry * src, GtkEntry * dest, int length)
78
{
79
	set_entry_tag(dest, gtk_entry_get_text(src), length);
80
	return;
81
}
82
69
static int genre_find_index(GList *genre_list, int id)
83
static int genre_find_index(GList *genre_list, int id)
70
{
84
{
71
	int idx = 0;
85
	int idx = 0;
Lines 80-94 Link Here
80
	return idx;
94
	return idx;
81
}
95
}
82
96
97
static int genre_find_index_str(GList *genre_list, const char* str)
98
{
99
	int idx = 0;
100
	while (genre_list)
101
	{
102
		struct genre_item *item = genre_list->data;
103
		if (strcmp(item->name, str) == 0)
104
			break;
105
		idx++;
106
		genre_list = genre_list->next;
107
	}
108
	return idx;
109
}
110
83
static int genre_comp_func(gconstpointer a, gconstpointer b)
111
static int genre_comp_func(gconstpointer a, gconstpointer b)
84
{
112
{
85
	const struct genre_item *ga = a, *gb = b;
113
	const struct genre_item *ga = a, *gb = b;
86
	return strcasecmp(ga->name, gb->name);
114
	return strcasecmp(ga->name, gb->name);
87
}
115
}
88
116
89
static void save_cb(GtkWidget * w, gpointer data)
117
static void remove_id3v1(void)
90
{
118
{
91
	int fd;
119
	int fd, len;
92
	struct id3v1tag_t tag;
120
	struct id3v1tag_t tag;
93
	char *msg = NULL;
121
	char *msg = NULL;
94
122
Lines 97-167 Link Here
97
125
98
	if ((fd = open(current_filename, O_RDWR)) != -1)
126
	if ((fd = open(current_filename, O_RDWR)) != -1)
99
	{
127
	{
100
		int tracknum;
128
		len = lseek(fd, -128, SEEK_END);
101
102
		lseek(fd, -128, SEEK_END);
103
		read(fd, &tag, sizeof (struct id3v1tag_t));
129
		read(fd, &tag, sizeof (struct id3v1tag_t));
104
130
105
		if (!strncmp(tag.tag, "TAG", 3))
131
		if (!strncmp(tag.tag, "TAG", 3))
106
			lseek(fd, -128, SEEK_END);
107
		else
108
			lseek(fd, 0, SEEK_END);
109
		tag.tag[0] = 'T';
110
		tag.tag[1] = 'A';
111
		tag.tag[2] = 'G';
112
		get_entry_tag(GTK_ENTRY(title_entry), tag.title, 30);
113
		get_entry_tag(GTK_ENTRY(artist_entry), tag.artist, 30);
114
		get_entry_tag(GTK_ENTRY(album_entry), tag.album, 30);
115
		get_entry_tag(GTK_ENTRY(year_entry), tag.year, 4);
116
		tracknum = atoi(gtk_entry_get_text(GTK_ENTRY(tracknum_entry)));
117
		if (tracknum > 0)
118
		{
132
		{
119
			get_entry_tag(GTK_ENTRY(comment_entry),
133
			if (ftruncate(fd, len))
120
				      tag.u.v1_1.comment, 28);
134
				msg = g_strdup_printf(_("%s\n"
121
			tag.u.v1_1.__zero = 0;
135
							"Unable to truncate file: %s"),
122
			tag.u.v1_1.track_number = MIN(tracknum, 255);
136
						      _("Couldn't remove tag!"),
137
						      strerror(errno));
123
		}
138
		}
124
		else
125
			get_entry_tag(GTK_ENTRY(comment_entry),
126
				      tag.u.v1_0.comment, 30);
127
		tag.genre = current_genre;
128
		if (write(fd, &tag, sizeof (tag)) != sizeof (tag))
129
			msg = g_strdup_printf(_("%s\nUnable to write to file: %s"),
130
					      _("Couldn't write tag!"),
131
					      strerror(errno));
132
		close(fd);
139
		close(fd);
133
	}
140
	}
134
	else
141
	else
135
		msg = g_strdup_printf(_("%s\nUnable to open file: %s"),
142
		msg = g_strdup_printf(_("%s\nUnable to open file: %s"),
136
				      _("Couldn't write tag!"),
143
				      _("Couldn't remove tag!"),
137
				      strerror(errno));
144
				      strerror(errno));
138
	if (msg)
145
	if (msg)
139
	{
146
	{
140
		GtkWidget *mwin = xmms_show_message(_("File Info"), msg,
147
		GtkWidget *mwin = xmms_show_message(_("File Info"), msg, _("Ok"),
141
						    _("Ok"), FALSE, NULL, NULL);
148
						    FALSE, NULL, NULL);
142
		gtk_window_set_transient_for(GTK_WINDOW(mwin),
149
		gtk_window_set_transient_for(GTK_WINDOW(mwin),
143
					     GTK_WINDOW(window));
150
					     GTK_WINDOW(window));
144
		g_free(msg);
151
		g_free(msg);
145
	}
152
	}
146
	else
147
		gtk_widget_destroy(window);
148
}
149
150
static void label_set_text(GtkWidget * label, char *str, ...)
151
{
152
	va_list args;
153
	char tempstr[MAX_STR_LEN];
154
155
	va_start(args, str);
156
	g_vsnprintf(tempstr, MAX_STR_LEN, str, args);
157
	va_end(args);
158
159
	gtk_label_set_text(GTK_LABEL(label), tempstr);
160
}
153
}
161
154
162
static void remove_id3_cb(GtkWidget * w, gpointer data)
155
static void save_cb(GtkWidget * w, gpointer data)
163
{
156
{
164
	int fd, len;
157
	int fd;
165
	struct id3v1tag_t tag;
158
	struct id3v1tag_t tag;
166
	char *msg = NULL;
159
	char *msg = NULL;
167
160
Lines 170-205 Link Here
170
163
171
	if ((fd = open(current_filename, O_RDWR)) != -1)
164
	if ((fd = open(current_filename, O_RDWR)) != -1)
172
	{
165
	{
173
		len = lseek(fd, -128, SEEK_END);
166
		if (!GTK_TOGGLE_BUTTON(v1_checkbox)->active) {
174
		read(fd, &tag, sizeof (struct id3v1tag_t));
167
			// Try to save id3v1 tag
168
			int tracknum;
175
169
176
		if (!strncmp(tag.tag, "TAG", 3))
170
			lseek(fd, -128, SEEK_END);
177
		{
171
			read(fd, &tag, sizeof (struct id3v1tag_t));
178
			if (ftruncate(fd, len))
172
179
				msg = g_strdup_printf(
173
			if (!strncmp(tag.tag, "TAG", 3))
180
					_("%s\n"
174
				lseek(fd, -128, SEEK_END);
181
					  "Unable to truncate file: %s"),
175
			else
182
					_("Couldn't remove tag!"),
176
				lseek(fd, 0, SEEK_END);
183
					strerror(errno));
177
			tag.tag[0] = 'T';
178
			tag.tag[1] = 'A';
179
			tag.tag[2] = 'G';
180
			get_entry_tag(GTK_ENTRY(v1_title_entry), tag.title, 30);
181
			get_entry_tag(GTK_ENTRY(v1_artist_entry), tag.artist, 30);
182
			get_entry_tag(GTK_ENTRY(v1_album_entry), tag.album, 30);
183
			get_entry_tag(GTK_ENTRY(v1_year_entry), tag.year, 4);
184
			tracknum = atoi(gtk_entry_get_text(GTK_ENTRY(v1_tracknum_entry)));
185
			if (tracknum > 0)
186
			{
187
				get_entry_tag(GTK_ENTRY(v1_comment_entry),
188
                        tag.u.v1_1.comment, 28);
189
				tag.u.v1_1.__zero = 0;
190
				tag.u.v1_1.track_number = MIN(tracknum, 255);
191
			}
192
			else
193
				get_entry_tag(GTK_ENTRY(v1_comment_entry),
194
                        tag.u.v1_0.comment, 30);
195
			tag.genre = v1_current_genre;
196
		    if (write(fd, &tag, sizeof (tag)) != sizeof (tag))
197
            	msg = g_strdup_printf(_("%s\nUnable to write to file: %s"),
198
					                 _("Couldn't write tag!"),
199
					                 strerror(errno));
200
		} else {
201
			// Remove the id3v1 tag from the file
202
            remove_id3v1();
184
		}
203
		}
185
		else
204
186
			msg = strdup(_("No tag to remove!"));
205
		if (!GTK_TOGGLE_BUTTON(v2_checkbox)->active) {
187
		close(fd);
206
207
            id3Tag v2_tag;
208
            memset(&v2_tag, 0, sizeof (v2_tag));
209
            strncpy(v2_tag.title, gtk_entry_get_text(GTK_ENTRY(v2_title_entry)), MAX_ENTRY_LEN2);
210
            strncpy(v2_tag.artist, gtk_entry_get_text(GTK_ENTRY(v2_artist_entry)), MAX_ENTRY_LEN2);
211
            strncpy(v2_tag.album, gtk_entry_get_text(GTK_ENTRY(v2_album_entry)), MAX_ENTRY_LEN2);
212
            strncpy(v2_tag.year, gtk_entry_get_text(GTK_ENTRY(v2_year_entry)), 4);
213
            strncpy(v2_tag.comment, gtk_entry_get_text(GTK_ENTRY(v2_comment_entry)), MAX_ENTRY_LEN2);
214
            strncpy(v2_tag.track, gtk_entry_get_text(GTK_ENTRY(v2_tracknum_entry)), 3);
215
            snprintf(v2_tag.genre, 6, "(%d)", v2_current_genre);
216
217
            strncpy(v2_tag.composer, gtk_entry_get_text(GTK_ENTRY(v2_composer_entry)), MAX_ENTRY_LEN2);
218
            strncpy(v2_tag.url, gtk_entry_get_text(GTK_ENTRY(v2_url_entry)), MAX_ENTRY_LEN2);
219
            strncpy(v2_tag.orig_artist, gtk_entry_get_text(GTK_ENTRY(v2_orig_artist_entry)), MAX_ENTRY_LEN2);
220
            strncpy(v2_tag.enc_by, gtk_entry_get_text(GTK_ENTRY(v2_encoded_by_entry)), MAX_ENTRY_LEN2);
221
222
            set_id3v2_tag(&v2_tag, current_filename);
223
224
		} else {
225
			// remove the id3v2 tag from the file
226
            del_id3v2_tag(current_filename);
227
		}
228
229
		if (fd)
230
			close(fd);
188
	}
231
	}
189
	else
232
	else
190
		msg = g_strdup_printf(_("%s\nUnable to open file: %s"),
233
		msg = g_strdup_printf(_("%s\nUnable to open file: %s"),
191
				      _("Couldn't remove tag!"),
234
				      _("Couldn't write tag!"),
192
				      strerror(errno));
235
				      strerror(errno));
193
	if (msg)
236
	if (msg)
194
	{
237
	{
195
		GtkWidget *mwin = xmms_show_message(_("File Info"), msg,
238
		GtkWidget *mwin = xmms_show_message(_("File Info"), msg, _("Ok"),
196
						    _("Ok"), FALSE, NULL, NULL);
239
						    FALSE, NULL, NULL);
197
		gtk_window_set_transient_for(GTK_WINDOW(mwin),
240
		gtk_window_set_transient_for(GTK_WINDOW(mwin),
198
					     GTK_WINDOW(window));
241
					     GTK_WINDOW(window));
199
		g_free(msg);
242
		g_free(msg);
200
	}
243
	}
201
	else
244
}
202
		gtk_widget_destroy(window);
245
246
static void label_set_text(GtkWidget * label, char *str, ...)
247
{
248
	va_list args;
249
	char tempstr[MAX_STR_LEN];
250
251
	va_start(args, str);
252
	g_vsnprintf(tempstr, MAX_STR_LEN, str, args);
253
	va_end(args);
254
255
	gtk_label_set_text(GTK_LABEL(label), tempstr);
203
}
256
}
204
257
205
static void set_mpeg_level_label(gboolean mpeg25, int lsf, int layer)
258
static void set_mpeg_level_label(gboolean mpeg25, int lsf, int layer)
Lines 222-249 Link Here
222
275
223
static void file_info_http(char *filename)
276
static void file_info_http(char *filename)
224
{
277
{
225
	gtk_widget_set_sensitive(id3_frame, FALSE);
278
	gtk_widget_set_sensitive(id3v1_frame, FALSE);
279
	gtk_widget_set_sensitive(id3v2_frame, FALSE);
226
	if (mpg123_filename && !strcmp(filename, mpg123_filename) &&
280
	if (mpg123_filename && !strcmp(filename, mpg123_filename) &&
227
	    mpg123_bitrate != 0)
281
	    mpg123_bitrate != 0)
228
	{
282
	{
229
		set_mpeg_level_label(mpg123_mpeg25, mpg123_lsf, mpg123_layer);
283
		set_mpeg_level_label(mpg123_mpeg25, mpg123_lsf,
284
                mpg123_layer);
230
		label_set_text(mpeg_bitrate, _("Bitrate: %d kb/s"),
285
		label_set_text(mpeg_bitrate, _("Bitrate: %d kb/s"),
231
			       mpg123_bitrate);
286
                mpg123_bitrate);
232
		label_set_text(mpeg_samplerate, _("Samplerate: %d Hz"),
287
		label_set_text(mpeg_samplerate, _("Samplerate: %d Hz"),
233
			       mpg123_frequency);
288
                mpg123_frequency);
234
		label_set_text(mpeg_flags, "%s",
289
		label_set_text(mpeg_flags, "%s",
235
			       channel_mode_name(mpg123_mode));
290
                channel_mode_name(mpg123_mode));
236
	}
291
	}
237
}
292
}
238
293
239
static void genre_selected(GtkList *list, GtkWidget *w, gpointer data)
294
void copy_v2_to_v1_cb(GtkButton *button, gpointer user_data)
295
{
296
    copy_entry_tag(GTK_ENTRY(v2_title_entry),   GTK_ENTRY(v1_title_entry), 30);
297
    copy_entry_tag(GTK_ENTRY(v2_artist_entry),  GTK_ENTRY(v1_artist_entry), 30);
298
    copy_entry_tag(GTK_ENTRY(v2_album_entry),   GTK_ENTRY(v1_album_entry), 30);
299
    copy_entry_tag(GTK_ENTRY(v2_year_entry),    GTK_ENTRY(v1_year_entry), 4);
300
    copy_entry_tag(GTK_ENTRY(v2_comment_entry), GTK_ENTRY(v1_comment_entry), 30);
301
    copy_entry_tag(GTK_ENTRY(v2_tracknum_entry), GTK_ENTRY(v1_tracknum_entry), 3);
302
303
    gtk_list_select_item(GTK_LIST(GTK_COMBO(v1_genre_combo)->list), genre_find_index(genre_list, v2_current_genre));
304
    return;
305
}
306
307
void copy_v1_to_v2_cb(GtkButton *button, gpointer user_data)
308
{
309
    copy_entry_tag(GTK_ENTRY(v1_title_entry),   GTK_ENTRY(v2_title_entry), MAX_ENTRY_LEN2);
310
    copy_entry_tag(GTK_ENTRY(v1_artist_entry),  GTK_ENTRY(v2_artist_entry), MAX_ENTRY_LEN2);
311
    copy_entry_tag(GTK_ENTRY(v1_album_entry),   GTK_ENTRY(v2_album_entry), MAX_ENTRY_LEN2);
312
    copy_entry_tag(GTK_ENTRY(v1_year_entry),    GTK_ENTRY(v2_year_entry), 4);
313
    copy_entry_tag(GTK_ENTRY(v1_comment_entry), GTK_ENTRY(v2_comment_entry), MAX_ENTRY_LEN2);
314
    copy_entry_tag(GTK_ENTRY(v1_tracknum_entry), GTK_ENTRY(v2_tracknum_entry), 3);
315
316
    gtk_list_select_item(GTK_LIST(GTK_COMBO(v2_genre_combo)->list), genre_find_index(genre_list, v1_current_genre));
317
    //int genreID = find_genre_id(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(v1_genre_combo)->entry)));
318
	//gtk_list_select_item(GTK_LIST(GTK_COMBO(v2_genre_combo)->list), 
319
    //                     g_list_index(genre_list, (char *) mpg123_id3_genres[genreID]));
320
    return;
321
}
322
323
void v1_toggle_cb (GtkWidget *widget, gpointer data)
324
{
325
    int i = 0;
326
    if (GTK_TOGGLE_BUTTON (widget)->active)
327
    {
328
        // If control reaches here, the toggle button is down
329
        // Gray out labels
330
        for (i = 0; i < v1_labels_list->len; i++) {
331
            gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v1_labels_list, i) ), FALSE);
332
        }
333
        gtk_widget_set_sensitive(v1_title_entry, FALSE);
334
        gtk_widget_set_sensitive(v1_artist_entry, FALSE);
335
        gtk_widget_set_sensitive(v1_album_entry, FALSE);
336
        gtk_widget_set_sensitive(v1_year_entry, FALSE);
337
        gtk_widget_set_sensitive(v1_tracknum_entry, FALSE);
338
        gtk_widget_set_sensitive(v1_comment_entry, FALSE);
339
        gtk_widget_set_sensitive(v1_genre_combo, FALSE);
340
    } else {
341
342
        // If control reaches here, the toggle button is up
343
        // Enable labels
344
        for (i = 0; i < v1_labels_list->len; i++) {
345
            gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v1_labels_list, i) ), TRUE);
346
        }
347
        gtk_widget_set_sensitive(v1_title_entry, TRUE);
348
        gtk_widget_set_sensitive(v1_artist_entry, TRUE);
349
        gtk_widget_set_sensitive(v1_album_entry, TRUE);
350
        gtk_widget_set_sensitive(v1_year_entry, TRUE);
351
        gtk_widget_set_sensitive(v1_tracknum_entry, TRUE);
352
        gtk_widget_set_sensitive(v1_comment_entry, TRUE);
353
        gtk_widget_set_sensitive(v1_genre_combo, TRUE);
354
    }
355
}
356
357
void v2_toggle_cb (GtkWidget *widget, gpointer data)
358
{
359
    int i = 0;
360
    if (GTK_TOGGLE_BUTTON (widget)->active)
361
    {
362
        // If control reaches here, the toggle button is down
363
        // Gray out labels
364
        for (i = 0; i < v2_labels_list->len; i++) {
365
            gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v2_labels_list, i) ), FALSE);
366
        }
367
        gtk_widget_set_sensitive(v2_title_entry, FALSE);
368
        gtk_widget_set_sensitive(v2_artist_entry, FALSE);
369
        gtk_widget_set_sensitive(v2_album_entry, FALSE);
370
        gtk_widget_set_sensitive(v2_year_entry, FALSE);
371
        gtk_widget_set_sensitive(v2_tracknum_entry, FALSE);
372
        gtk_widget_set_sensitive(v2_comment_entry, FALSE);
373
        gtk_widget_set_sensitive(v2_composer_entry, FALSE);
374
        gtk_widget_set_sensitive(v2_orig_artist_entry, FALSE);
375
        gtk_widget_set_sensitive(v2_url_entry, FALSE);
376
        gtk_widget_set_sensitive(v2_encoded_by_entry, FALSE);
377
        gtk_widget_set_sensitive(v2_genre_combo, FALSE);
378
    } else {
379
380
        // If control reaches here, the toggle button is up
381
        // Enable labels
382
        for (i = 0; i < v2_labels_list->len; i++) {
383
            gtk_widget_set_sensitive(GTK_WIDGET( g_ptr_array_index(v2_labels_list, i) ), TRUE);
384
        }
385
        gtk_widget_set_sensitive(v2_title_entry, TRUE);
386
        gtk_widget_set_sensitive(v2_artist_entry, TRUE);
387
        gtk_widget_set_sensitive(v2_album_entry, TRUE);
388
        gtk_widget_set_sensitive(v2_year_entry, TRUE);
389
        gtk_widget_set_sensitive(v2_tracknum_entry, TRUE);
390
        gtk_widget_set_sensitive(v2_comment_entry, TRUE);
391
        gtk_widget_set_sensitive(v2_composer_entry, TRUE);
392
        gtk_widget_set_sensitive(v2_orig_artist_entry, TRUE);
393
        gtk_widget_set_sensitive(v2_url_entry, TRUE);
394
        gtk_widget_set_sensitive(v2_encoded_by_entry, TRUE);
395
        gtk_widget_set_sensitive(v2_genre_combo, TRUE);
396
    }
397
}
398
static void v1_genre_selected(GtkList *list, GtkWidget *w, gpointer data)
399
{
400
	void * p;
401
	p = gtk_object_get_data(GTK_OBJECT(w), "genre_id");
402
	if (p != NULL)
403
		v1_current_genre = GPOINTER_TO_INT(p);
404
	else
405
		v1_current_genre = 0;
406
}
407
408
static void v2_genre_selected(GtkList *list, GtkWidget *w, gpointer data)
240
{
409
{
241
	void * p;
410
	void * p;
242
	p = gtk_object_get_data(GTK_OBJECT(w), "genre_id");
411
	p = gtk_object_get_data(GTK_OBJECT(w), "genre_id");
243
	if (p != NULL)
412
	if (p != NULL)
244
		current_genre = GPOINTER_TO_INT(p);
413
		v2_current_genre = GPOINTER_TO_INT(p);
245
	else
414
	else
246
		current_genre = 0;
415
		v2_current_genre = 0;
247
}
416
}
248
417
249
static void genre_set_popdown(GtkWidget *combo, GList *genres)
418
static void genre_set_popdown(GtkWidget *combo, GList *genres)
Lines 266-276 Link Here
266
void mpg123_file_info_box(char *filename)
435
void mpg123_file_info_box(char *filename)
267
{
436
{
268
	int i;
437
	int i;
269
	struct id3v1tag_t tag;
438
	struct id3v1tag_t id3v1tag;
270
	FILE *fh;
439
	FILE *fh;
271
	char *tmp, *title;
440
	char *tmp, *title;
272
	const char *emphasis[4];
441
	const char *emphasis[4];
273
	const char *bool_label[2];
442
	const char *bool_label[2];
443
	struct id3tag_t id3v2tag;
274
444
275
	emphasis[0] = _("None");
445
	emphasis[0] = _("None");
276
	emphasis[1] = _("50/15 ms");
446
	emphasis[1] = _("50/15 ms");
Lines 281-396 Link Here
281
451
282
	if (!window)
452
	if (!window)
283
	{
453
	{
284
		GtkWidget *vbox, *hbox, *left_vbox, *table;
454
	    GtkWidget *window_vbox, 
285
		GtkWidget *mpeg_frame, *mpeg_box;
455
                  *id3v1_vbox, *id3v2_vbox, *id3v1_frame_vbox, *id3v2_frame_vbox, 
286
		GtkWidget *label, *filename_hbox;
456
                  *mpeg_lvbox, *mpeg_rvbox, *mpeg_hbox, *mpeg_box, *mpeg_frame, 
287
		GtkWidget *bbox, *save, *remove_id3, *cancel;
457
	              *bbox, *save, *close, *copy_to, *copy_from,
288
		
458
                  *table, *label, *filename_hbox;
289
		window = gtk_window_new(GTK_WINDOW_DIALOG);
459
290
		gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
460
	    v1_labels_list = g_ptr_array_new();
291
		gtk_signal_connect(GTK_OBJECT(window), "destroy",
461
	    v2_labels_list = g_ptr_array_new();
292
				   gtk_widget_destroyed, &window);
462
293
		gtk_container_set_border_width(GTK_CONTAINER(window), 10);
463
	    window = gtk_window_new(GTK_WINDOW_DIALOG);
294
464
	    //gtk_window_set_policy(GTK_WINDOW(window), FALSE, FALSE, FALSE);
295
		vbox = gtk_vbox_new(FALSE, 10);
465
	    gtk_signal_connect(GTK_OBJECT(window), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &window);
296
		gtk_container_add(GTK_CONTAINER(window), vbox);
466
	    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
297
467
468
        window_vbox = gtk_vbox_new(FALSE,10);
298
		filename_hbox = gtk_hbox_new(FALSE, 5);
469
		filename_hbox = gtk_hbox_new(FALSE, 5);
299
		gtk_box_pack_start(GTK_BOX(vbox), filename_hbox,
470
		gtk_box_pack_start(GTK_BOX(window_vbox), filename_hbox, FALSE, TRUE, 0);
300
				   FALSE, TRUE, 0);
301
471
302
		label = gtk_label_new(_("Filename:"));
472
		label = gtk_label_new(_("Filename:"));
303
		gtk_box_pack_start(GTK_BOX(filename_hbox), label,
473
		gtk_box_pack_start(GTK_BOX(filename_hbox), label, FALSE, TRUE, 0);
304
				   FALSE, TRUE, 0);
305
		filename_entry = xmms_entry_new();
474
		filename_entry = xmms_entry_new();
306
		gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE);
475
		gtk_editable_set_editable(GTK_EDITABLE(filename_entry), FALSE);
307
		gtk_box_pack_start(GTK_BOX(filename_hbox),
476
		gtk_box_pack_start(GTK_BOX(filename_hbox), filename_entry, TRUE, TRUE, 0);
308
				   filename_entry, TRUE, TRUE, 0);
477
309
		
478
	    id3v1_vbox = gtk_vbox_new(FALSE, 10);
310
		hbox = gtk_hbox_new(FALSE, 10);
479
	    id3v1_frame = gtk_frame_new("ID3v1 Information");
311
		gtk_box_pack_start(GTK_BOX(vbox), hbox, FALSE, TRUE, 0);
480
	    gtk_box_pack_start(GTK_BOX(id3v1_vbox), id3v1_frame, TRUE, TRUE, 0);
312
		
481
313
		left_vbox = gtk_vbox_new(FALSE, 10);
482
	    id3v1_frame_vbox = gtk_vbox_new(FALSE,10);
314
		gtk_box_pack_start(GTK_BOX(hbox), left_vbox, FALSE, FALSE, 0);
483
	    gtk_container_add(GTK_CONTAINER(id3v1_frame), id3v1_frame_vbox);
315
484
316
		id3_frame = gtk_frame_new(_("ID3 Tag:"));
485
	    table = gtk_table_new(6, 6, FALSE);
317
		gtk_box_pack_start(GTK_BOX(left_vbox), id3_frame,
486
	    gtk_container_set_border_width(GTK_CONTAINER(table), 5);
318
				   FALSE, FALSE, 0);
487
	    //gtk_widget_set_usize(GTK_WIDGET(table), 325, -1);
319
488
	    //gtk_container_add(GTK_CONTAINER(id3v1_frame), table);
320
		table = gtk_table_new(5, 5, FALSE);
489
	    gtk_box_pack_start(GTK_BOX(id3v1_frame_vbox), table, FALSE, FALSE, 0);
321
		gtk_container_set_border_width(GTK_CONTAINER(table), 5);
490
322
		gtk_container_add(GTK_CONTAINER(id3_frame), table);
491
	    v1_checkbox = gtk_check_button_new_with_label ("Disable ID3v1 Tag");
323
492
	    gtk_signal_connect(GTK_OBJECT(v1_checkbox), "toggled", GTK_SIGNAL_FUNC(v1_toggle_cb), NULL);
324
		label = gtk_label_new(_("Title:"));
493
	    gtk_table_attach(GTK_TABLE(table), v1_checkbox, 1, 3, 0, 1,
325
		gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
494
                GTK_FILL, GTK_FILL, 0, 2);
326
		gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1,
495
327
				 GTK_FILL, GTK_FILL, 5, 5);
496
	    label = gtk_label_new("Track number:"); 
328
497
	    g_ptr_array_add(v1_labels_list, (gpointer)label);
329
		title_entry = gtk_entry_new_with_max_length(30);
498
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
330
		gtk_table_attach(GTK_TABLE(table), title_entry, 1, 4, 0, 1,
499
	    gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1,
331
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
500
                GTK_FILL, GTK_FILL, 5,5);
332
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
501
333
502
	    v1_tracknum_entry = gtk_entry_new_with_max_length(3);
334
		label = gtk_label_new(_("Artist:"));
503
	    gtk_widget_set_usize(v1_tracknum_entry, 20, -1);
335
		gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
504
	    gtk_table_attach(GTK_TABLE(table), v1_tracknum_entry, 4, 5, 0, 1,
336
		gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
505
                GTK_FILL, GTK_FILL, 0, 2);
337
				 GTK_FILL, GTK_FILL, 5, 5);
506
338
507
	    label = gtk_label_new("Title:");
339
		artist_entry = gtk_entry_new_with_max_length(30);
508
	    g_ptr_array_add(v1_labels_list, (gpointer)label);
340
		gtk_table_attach(GTK_TABLE(table), artist_entry, 1, 4, 1, 2,
509
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
341
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
510
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
342
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
511
                GTK_FILL, GTK_FILL, 5, 5);
343
512
344
		label = gtk_label_new(_("Album:"));
513
	    v1_title_entry = gtk_entry_new_with_max_length(30);
345
		gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
514
	    gtk_table_attach(GTK_TABLE(table), v1_title_entry, 1, 5, 1, 2,
346
		gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
515
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
347
				 GTK_FILL, GTK_FILL, 5, 5);
516
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
348
517
349
		album_entry = gtk_entry_new_with_max_length(30);
518
	    label = gtk_label_new("Artist:");
350
		gtk_table_attach(GTK_TABLE(table), album_entry, 1, 4, 2, 3,
519
	    g_ptr_array_add(v1_labels_list, (gpointer)label);
351
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
520
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
352
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
521
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
353
522
                GTK_FILL, GTK_FILL, 5, 5);
354
		label = gtk_label_new(_("Comment:"));
523
355
		gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
524
	    v1_artist_entry = gtk_entry_new_with_max_length(30);
356
		gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4,
525
	    gtk_table_attach(GTK_TABLE(table), v1_artist_entry, 1, 5, 2, 3,
357
				 GTK_FILL, GTK_FILL, 5, 5);
526
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
358
527
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
359
		comment_entry = gtk_entry_new_with_max_length(30);
528
360
		gtk_table_attach(GTK_TABLE(table), comment_entry, 1, 4, 3, 4,
529
	    label = gtk_label_new("Album:");
361
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
530
	    g_ptr_array_add(v1_labels_list, (gpointer)label);
362
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
531
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
363
532
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4,
364
		label = gtk_label_new(_("Year:"));
533
                GTK_FILL, GTK_FILL, 5, 5);
365
		gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
534
366
		gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
535
	    v1_album_entry = gtk_entry_new_with_max_length(30);
367
				 GTK_FILL, GTK_FILL, 5, 5);
536
	    gtk_table_attach(GTK_TABLE(table), v1_album_entry, 1, 5, 3, 4,
368
537
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
369
		year_entry = gtk_entry_new_with_max_length(4);
538
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
370
		gtk_widget_set_usize(year_entry, 40, -1);
539
371
		gtk_table_attach(GTK_TABLE(table), year_entry, 1, 2, 4, 5,
540
	    label = gtk_label_new("Comment:");
372
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
541
	    g_ptr_array_add(v1_labels_list, (gpointer)label);
373
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
542
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
374
543
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
375
		label = gtk_label_new(_("Track number:"));
544
                GTK_FILL, GTK_FILL, 5, 5);
376
		gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
545
377
		gtk_table_attach(GTK_TABLE(table), label, 2, 3, 4, 5,
546
	    v1_comment_entry = gtk_entry_new_with_max_length(30);
378
				 GTK_FILL, GTK_FILL, 5, 5);
547
	    gtk_table_attach(GTK_TABLE(table), v1_comment_entry, 1, 5, 4, 5,
379
548
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
380
		tracknum_entry = gtk_entry_new_with_max_length(3);
549
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
381
		gtk_widget_set_usize(tracknum_entry, 40, -1);
550
382
		gtk_table_attach(GTK_TABLE(table), tracknum_entry, 3, 4, 4, 5,
551
	    label = gtk_label_new("Year:");
383
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
552
	    g_ptr_array_add(v1_labels_list, (gpointer)label);
384
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
553
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
385
554
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6,
386
		label = gtk_label_new(_("Genre:"));
555
                GTK_FILL, GTK_FILL, 5, 5);
387
		gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
556
388
		gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6,
557
	    v1_year_entry = gtk_entry_new_with_max_length(4);
389
				 GTK_FILL, GTK_FILL, 5, 5);
558
	    gtk_widget_set_usize(v1_year_entry, 45, -1);
390
559
	    gtk_table_attach(GTK_TABLE(table), v1_year_entry, 1, 2, 5, 6,
391
		genre_combo = gtk_combo_new();
560
                GTK_FILL, GTK_FILL, 0, 2);
392
		gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(genre_combo)->entry),
561
393
				       FALSE);
562
	    label = gtk_label_new("Genre:");
563
	    g_ptr_array_add(v1_labels_list, (gpointer)label);
564
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
565
	    gtk_table_attach(GTK_TABLE(table), label, 2, 3, 5, 6,
566
                GTK_FILL, GTK_FILL, 5, 5);
567
568
	    v1_genre_combo = gtk_combo_new();
569
	    gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(v1_genre_combo)->entry),
570
                FALSE);
394
		if (!genre_list)
571
		if (!genre_list)
395
		{
572
		{
396
			struct genre_item *item;
573
			struct genre_item *item;
Lines 408-484 Link Here
408
			genre_list = g_list_prepend(genre_list, item);
585
			genre_list = g_list_prepend(genre_list, item);
409
			genre_list = g_list_sort(genre_list, genre_comp_func);
586
			genre_list = g_list_sort(genre_list, genre_comp_func);
410
		}
587
		}
411
		genre_set_popdown(genre_combo, genre_list);
588
		genre_set_popdown(v1_genre_combo, genre_list);
412
		gtk_signal_connect(GTK_OBJECT(GTK_COMBO(genre_combo)->list),
589
		gtk_signal_connect(GTK_OBJECT(GTK_COMBO(v1_genre_combo)->list),
413
				   "select-child", genre_selected, NULL);
590
				   "select-child", v1_genre_selected, NULL);
414
591
415
		gtk_table_attach(GTK_TABLE(table), genre_combo, 1, 4, 5, 6,
592
	    gtk_table_attach(GTK_TABLE(table), v1_genre_combo, 3, 5, 5, 6,
416
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK,
593
                GTK_FILL | GTK_SHRINK, GTK_FILL |
417
				 GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 5);
594
                GTK_SHRINK, 0, 2);
418
595
419
		bbox = gtk_hbutton_box_new();
596
	    bbox = gtk_hbutton_box_new();
420
		gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox),
597
        gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START);
421
					  GTK_BUTTONBOX_END);
598
        gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 0);
422
		gtk_button_box_set_spacing(GTK_BUTTON_BOX(bbox), 5);
599
	    gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
423
		gtk_box_pack_start(GTK_BOX(left_vbox), bbox, FALSE, FALSE, 0);
600
	    gtk_box_pack_start(GTK_BOX(id3v1_frame_vbox), bbox, FALSE, FALSE, 0);
424
601
425
		save = gtk_button_new_with_label(_("Save"));
602
	    copy_from = gtk_button_new_with_label("ID3v1 to ID3v2");
426
		gtk_signal_connect(GTK_OBJECT(save), "clicked", save_cb, NULL);
603
	    gtk_signal_connect(GTK_OBJECT(copy_from), "clicked", GTK_SIGNAL_FUNC(copy_v1_to_v2_cb), NULL);
427
		GTK_WIDGET_SET_FLAGS(save, GTK_CAN_DEFAULT);
604
        // remove the next line to thicken the button width
428
		gtk_box_pack_start(GTK_BOX(bbox), save, TRUE, TRUE, 0);
605
        GTK_WIDGET_SET_FLAGS(copy_from, GTK_CAN_DEFAULT);
429
		gtk_widget_grab_default(save);
606
	    gtk_box_pack_start(GTK_BOX(bbox), copy_from, FALSE, TRUE, 0);
430
607
431
		remove_id3 = gtk_button_new_with_label(_("Remove ID3"));
608
				 
432
		gtk_signal_connect(GTK_OBJECT(remove_id3), "clicked",
609
	    notebook = gtk_notebook_new ();
433
				   remove_id3_cb, NULL);
610
	    gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP);
434
		GTK_WIDGET_SET_FLAGS(remove_id3, GTK_CAN_DEFAULT);
611
435
		gtk_box_pack_start(GTK_BOX(bbox), remove_id3, TRUE, TRUE, 0);
612
	    label = gtk_label_new ("ID3v1");
436
613
	    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), id3v1_vbox, label);
437
		cancel = gtk_button_new_with_label(_("Cancel"));
614
438
		gtk_signal_connect_object(GTK_OBJECT(cancel), "clicked",
615
439
					  gtk_widget_destroy, GTK_OBJECT(window));
616
	    ////////////////////////////////////////////////////////////////////////////////////////////////////
440
		GTK_WIDGET_SET_FLAGS(cancel, GTK_CAN_DEFAULT);
617
	    ////////////////////////////////////////////////////////////////////////////////////////////////////
441
		gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
618
442
619
	    id3v2_vbox = gtk_vbox_new(FALSE, 0);
443
		mpeg_frame = gtk_frame_new(_("MPEG Info:"));
620
444
		gtk_box_pack_start(GTK_BOX(hbox), mpeg_frame, FALSE, FALSE, 0);
621
	    id3v2_frame = gtk_frame_new("ID3v2 Information");
445
622
	    gtk_box_pack_start(GTK_BOX(id3v2_vbox), id3v2_frame, FALSE, FALSE, 0);
446
		mpeg_box = gtk_vbox_new(FALSE, 5);
623
447
		gtk_container_add(GTK_CONTAINER(mpeg_frame), mpeg_box);
624
	    id3v2_frame_vbox = gtk_vbox_new(FALSE, 0);
448
		gtk_container_set_border_width(GTK_CONTAINER(mpeg_box), 10);
625
	    gtk_container_add(GTK_CONTAINER(id3v2_frame), id3v2_frame_vbox);
449
		gtk_box_set_spacing(GTK_BOX(mpeg_box), 0);
626
450
627
	    table = gtk_table_new(6, 6, FALSE);
451
		mpeg_level = gtk_label_new("");
628
	    gtk_container_set_border_width(GTK_CONTAINER(table), 5);
452
		gtk_widget_set_usize(mpeg_level, 120, -2);
629
	    gtk_widget_set_usize(GTK_WIDGET(table), 400, -1);
453
		gtk_misc_set_alignment(GTK_MISC(mpeg_level), 0, 0);
630
	    //gtk_container_add(GTK_CONTAINER(id3v2_frame), table);
454
		gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_level, FALSE, FALSE, 0);
631
	    gtk_box_pack_start(GTK_BOX(id3v2_frame_vbox), table, FALSE, FALSE, 0);
455
632
456
		mpeg_bitrate = gtk_label_new("");
633
	    v2_checkbox = gtk_check_button_new_with_label ("Disable ID3v2 Tag");
457
		gtk_misc_set_alignment(GTK_MISC(mpeg_bitrate), 0, 0);
634
	    gtk_signal_connect(GTK_OBJECT(v2_checkbox), "toggled", GTK_SIGNAL_FUNC(v2_toggle_cb), NULL);
458
		gtk_label_set_justify(GTK_LABEL(mpeg_bitrate),
635
	    gtk_table_attach(GTK_TABLE(table), v2_checkbox, 1, 3, 0, 1,
459
				      GTK_JUSTIFY_LEFT);
636
                GTK_FILL, GTK_FILL, 0, 2);
460
		gtk_box_pack_start(GTK_BOX(mpeg_box),
637
461
				   mpeg_bitrate, FALSE, FALSE, 0);
638
	    label = gtk_label_new("Track number:"); 
462
639
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
463
		mpeg_samplerate = gtk_label_new("");
640
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
464
		gtk_misc_set_alignment(GTK_MISC(mpeg_samplerate), 0, 0);
641
	    gtk_table_attach(GTK_TABLE(table), label, 3, 4, 0, 1,
465
		gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_samplerate,
642
                GTK_FILL, GTK_FILL, 5,5);
466
				   FALSE, FALSE, 0);
643
467
644
	    v2_tracknum_entry = gtk_entry_new_with_max_length(3);
468
		mpeg_flags = gtk_label_new("");
645
	    gtk_widget_set_usize(v2_tracknum_entry, 20, -1);
469
		gtk_misc_set_alignment(GTK_MISC(mpeg_flags), 0, 0);
646
	    gtk_table_attach(GTK_TABLE(table), v2_tracknum_entry, 4, 5, 0, 1,
470
		gtk_label_set_justify(GTK_LABEL(mpeg_flags), GTK_JUSTIFY_LEFT);
647
                GTK_FILL, GTK_FILL, 0, 2);
471
		gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_flags,
648
472
				   FALSE, FALSE, 0);
649
	    label = gtk_label_new("Title:");
473
650
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
474
		mpeg_fileinfo = gtk_label_new("");
651
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
475
		gtk_misc_set_alignment(GTK_MISC(mpeg_fileinfo), 0, 0);
652
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2,
476
		gtk_label_set_justify(GTK_LABEL(mpeg_fileinfo),
653
                GTK_FILL, GTK_FILL, 5, 5);
477
				      GTK_JUSTIFY_LEFT);
654
478
		gtk_box_pack_start(GTK_BOX(mpeg_box), mpeg_fileinfo,
655
	    v2_title_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
479
				   FALSE, FALSE, 0);
656
	    gtk_table_attach(GTK_TABLE(table), v2_title_entry, 1, 5, 1, 2, 
657
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
658
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
659
660
	    label = gtk_label_new("Artist:");
661
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
662
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
663
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3,
664
                GTK_FILL, GTK_FILL, 5, 5);
665
666
	    v2_artist_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
667
	    gtk_table_attach(GTK_TABLE(table), v2_artist_entry, 1, 5, 2, 3, 
668
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
669
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
670
671
	    label = gtk_label_new("Album:");
672
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
673
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
674
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4,
675
                GTK_FILL, GTK_FILL, 5, 5);
676
677
	    v2_album_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
678
	    gtk_table_attach(GTK_TABLE(table), v2_album_entry, 1, 5, 3, 4, 
679
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
680
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
681
682
	    label = gtk_label_new("Comment:");
683
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
684
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
685
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5,
686
                GTK_FILL, GTK_FILL, 5, 5);
687
688
	    v2_comment_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
689
	    gtk_table_attach(GTK_TABLE(table), v2_comment_entry, 1, 5, 4, 5, 
690
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
691
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
692
693
	    label = gtk_label_new("Year:");
694
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
695
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
696
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 5, 6,
697
                GTK_FILL, GTK_FILL, 5, 5);
698
699
	    v2_year_entry = gtk_entry_new_with_max_length(4);
700
	    gtk_widget_set_usize(v2_year_entry, 45, -1);
701
	    gtk_table_attach(GTK_TABLE(table), v2_year_entry, 1, 2, 5, 6,
702
                GTK_FILL, GTK_FILL, 0, 2);
703
704
	    label = gtk_label_new("Genre:");
705
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
706
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
707
	    gtk_table_attach(GTK_TABLE(table), label, 2, 3, 5, 6,
708
                GTK_FILL, GTK_FILL, 5, 5);
709
710
	    v2_genre_combo = gtk_combo_new();
711
	    gtk_entry_set_editable(GTK_ENTRY(GTK_COMBO(v2_genre_combo)->entry), FALSE);
712
		genre_set_popdown(v2_genre_combo, genre_list);
713
		gtk_signal_connect(GTK_OBJECT(GTK_COMBO(v2_genre_combo)->list),
714
				   "select-child", v2_genre_selected, NULL);
715
716
	    gtk_table_attach(GTK_TABLE(table), v2_genre_combo, 3, 5, 5, 6, 
717
                GTK_FILL | GTK_SHRINK, GTK_FILL |
718
                GTK_SHRINK, 0, 2);
719
720
	    label = gtk_label_new("Composer:");
721
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
722
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
723
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 6, 7,
724
                GTK_FILL, GTK_FILL, 5, 5);
725
726
	    v2_composer_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
727
	    gtk_table_attach(GTK_TABLE(table), v2_composer_entry, 1, 5, 6, 7, 
728
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
729
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
730
731
	    label = gtk_label_new("Orig. Artist:");
732
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
733
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
734
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 7, 8,
735
                GTK_FILL, GTK_FILL, 5, 5);
736
737
	    v2_orig_artist_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
738
	    gtk_table_attach(GTK_TABLE(table), v2_orig_artist_entry, 1, 5, 7, 8, 
739
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
740
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
741
742
	    label = gtk_label_new("URL:");
743
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
744
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
745
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 8, 9,
746
                GTK_FILL, GTK_FILL, 5, 5);
747
748
	    v2_url_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
749
	    gtk_table_attach(GTK_TABLE(table), v2_url_entry, 1, 5, 8, 9, 
750
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
751
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
752
	    label = gtk_label_new("Encoded By:");
753
	    g_ptr_array_add(v2_labels_list, (gpointer)label);
754
	    gtk_misc_set_alignment(GTK_MISC(label), 1, 0.5);
755
	    gtk_table_attach(GTK_TABLE(table), label, 0, 1, 9, 10,
756
                GTK_FILL, GTK_FILL, 5, 5);
757
758
	    v2_encoded_by_entry = gtk_entry_new_with_max_length(MAX_ENTRY_LEN2);
759
	    gtk_table_attach(GTK_TABLE(table), v2_encoded_by_entry, 1, 5, 9, 10, 
760
                GTK_FILL | GTK_EXPAND | GTK_SHRINK,
761
                GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 2);
762
763
	    bbox = gtk_hbutton_box_new();
764
        gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_START);
765
        gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 0);
766
	    gtk_container_set_border_width(GTK_CONTAINER(bbox), 5);
767
	    gtk_box_pack_start(GTK_BOX(id3v2_frame_vbox), bbox, FALSE, FALSE, 0);
768
769
	    copy_to = gtk_button_new_with_label("ID3v2 to ID3v1");
770
	    gtk_signal_connect(GTK_OBJECT(copy_to), "clicked", GTK_SIGNAL_FUNC(copy_v2_to_v1_cb), NULL);
771
        // remove the next line to thicken the button width
772
        GTK_WIDGET_SET_FLAGS(copy_to, GTK_CAN_DEFAULT);
773
	    gtk_box_pack_start(GTK_BOX(bbox), copy_to, FALSE, TRUE, 0);
774
        
775
	    label = gtk_label_new ("ID3v2");
776
	    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), id3v2_vbox, label);
777
778
779
	    ////////////////////////////////////////////////////////////////////////////////////////////////////
780
	    ////////////////////////////////////////////////////////////////////////////////////////////////////
781
782
	    mpeg_frame = gtk_frame_new("MPEG Information");
783
	    mpeg_hbox = gtk_hbox_new(FALSE,50);
784
	    gtk_container_add(GTK_CONTAINER(mpeg_frame), mpeg_hbox);
785
786
	    mpeg_lvbox = gtk_vbox_new(FALSE, 5);
787
	    gtk_container_set_border_width(GTK_CONTAINER(mpeg_lvbox), 10);
788
	    gtk_box_pack_start(GTK_BOX(mpeg_hbox), mpeg_lvbox, FALSE, FALSE, 0);
789
790
	    //gtk_container_set_border_width(GTK_CONTAINER(table), 5);
791
	    //gtk_widget_set_usize(GTK_WIDGET(table), 325, -1);
792
	    //gtk_container_add(GTK_CONTAINER(mpeg_frame), table);
793
794
	    mpeg_box = gtk_vbox_new(FALSE, 5);
795
	    gtk_box_pack_start(GTK_BOX(mpeg_hbox), mpeg_box, FALSE, FALSE, 0);
796
	    gtk_container_set_border_width(GTK_CONTAINER(mpeg_box), 10);
797
	    gtk_box_set_spacing(GTK_BOX(mpeg_box), 0);
798
799
	    mpeg_level = gtk_label_new("");
800
	    //gtk_widget_set_usize(mpeg_level, 120, -2);
801
	    gtk_label_set_justify (GTK_LABEL(mpeg_level), GTK_JUSTIFY_LEFT);
802
	    gtk_misc_set_alignment(GTK_MISC(mpeg_level), 0, 0.5);
803
	    gtk_box_pack_start(GTK_BOX(mpeg_lvbox), mpeg_level, FALSE, FALSE, 0);
804
805
	    mpeg_samplerate = gtk_label_new("");
806
	    gtk_label_set_justify (GTK_LABEL(mpeg_samplerate), GTK_JUSTIFY_LEFT);
807
	    gtk_misc_set_alignment(GTK_MISC(mpeg_samplerate), 0, 0.5);
808
	    gtk_box_pack_start(GTK_BOX(mpeg_lvbox), mpeg_samplerate, FALSE, FALSE, 0);
809
810
	    mpeg_fileinfo = gtk_label_new("");
811
	    gtk_label_set_justify (GTK_LABEL(mpeg_fileinfo), GTK_JUSTIFY_LEFT);
812
	    gtk_misc_set_alignment(GTK_MISC(mpeg_fileinfo), 0, 0.5);
813
	    gtk_box_pack_start(GTK_BOX(mpeg_lvbox), mpeg_fileinfo, FALSE, FALSE, 0);
814
815
	    mpeg_rvbox = gtk_vbox_new(FALSE, 5);
816
	    gtk_box_pack_start(GTK_BOX(mpeg_hbox), mpeg_rvbox, FALSE, FALSE, 0);
817
	    gtk_container_set_border_width(GTK_CONTAINER(mpeg_rvbox), 10);
818
819
	    mpeg_bitrate = gtk_label_new("");
820
	    gtk_label_set_justify (GTK_LABEL(mpeg_bitrate), GTK_JUSTIFY_LEFT);
821
	    gtk_misc_set_alignment(GTK_MISC(mpeg_bitrate), 0, 0.5);
822
	    gtk_box_pack_start(GTK_BOX(mpeg_rvbox), mpeg_bitrate, FALSE, FALSE, 0);
823
824
	    mpeg_flags = gtk_label_new("");
825
	    gtk_label_set_justify (GTK_LABEL(mpeg_flags), GTK_JUSTIFY_LEFT);
826
	    gtk_misc_set_alignment(GTK_MISC(mpeg_flags), 0, 0.5);
827
	    gtk_box_pack_start(GTK_BOX(mpeg_rvbox), mpeg_flags, FALSE, FALSE, 0);
828
829
	    label = gtk_label_new ("MPEG");
830
	    gtk_notebook_append_page (GTK_NOTEBOOK (notebook), mpeg_frame, label);
831
832
        //////////////////////////////////////////////////////////////////
833
        //////////////////////////////////////////////////////////////////
834
        
835
        // add notebook to window vbox
836
        gtk_box_pack_start(GTK_BOX(window_vbox), notebook, FALSE, FALSE, 0);
837
838
        // add button box to window vbox
839
	    bbox = gtk_hbutton_box_new();
840
	    gtk_box_pack_start(GTK_BOX(window_vbox), bbox, FALSE, FALSE, 0);
841
        
842
        gtk_button_box_set_layout (GTK_BUTTON_BOX (bbox), GTK_BUTTONBOX_END);
843
        gtk_button_box_set_spacing (GTK_BUTTON_BOX (bbox), 5);
844
        //gtk_button_box_set_child_size (GTK_BUTTON_BOX (bbox), child_w, child_h);
845
        
846
        save = gtk_button_new_with_label("Save");
847
        gtk_signal_connect(GTK_OBJECT(save), "clicked", GTK_SIGNAL_FUNC(save_cb), NULL);
848
        //GTK_WIDGET_SET_FLAGS(save, GTK_CAN_DEFAULT);
849
        gtk_box_pack_start(GTK_BOX(bbox), save, TRUE, TRUE, 5);
850
        //gtk_widget_grab_default(save);
851
852
        close = gtk_button_new_with_label("Close");
853
        gtk_signal_connect_object(GTK_OBJECT(close), "clicked", 
854
                GTK_SIGNAL_FUNC(gtk_widget_destroy), GTK_OBJECT(window));
855
        //GTK_WIDGET_SET_FLAGS(close, GTK_CAN_DEFAULT);
856
        gtk_box_pack_start(GTK_BOX(bbox), close, TRUE, TRUE, 5);
480
857
481
		gtk_widget_show_all(window);
858
        gtk_container_add(GTK_CONTAINER(window), window_vbox);
859
	    gtk_widget_show_all(window);
482
	}
860
	}
483
861
484
	if (current_filename)
862
	if (current_filename)
Lines 495-523 Link Here
495
	title = g_strdup(g_basename(filename));
873
	title = g_strdup(g_basename(filename));
496
	if ((tmp = strrchr(title, '.')) != NULL)
874
	if ((tmp = strrchr(title, '.')) != NULL)
497
		*tmp = '\0';
875
		*tmp = '\0';
498
	gtk_entry_set_text(GTK_ENTRY(title_entry), title);
876
	gtk_entry_set_text(GTK_ENTRY(v1_title_entry), title);
877
	gtk_entry_set_text(GTK_ENTRY(v2_title_entry), title);
499
	g_free(title);
878
	g_free(title);
500
879
501
	gtk_entry_set_text(GTK_ENTRY(artist_entry), "");
880
	gtk_entry_set_text(GTK_ENTRY(v1_artist_entry), "");
502
	gtk_entry_set_text(GTK_ENTRY(album_entry), "");
881
	gtk_entry_set_text(GTK_ENTRY(v1_album_entry), "");
503
	gtk_entry_set_text(GTK_ENTRY(year_entry), "");
882
	gtk_entry_set_text(GTK_ENTRY(v1_year_entry), "");
504
	gtk_entry_set_text(GTK_ENTRY(tracknum_entry), "");
883
	gtk_entry_set_text(GTK_ENTRY(v1_tracknum_entry), "");
505
	gtk_entry_set_text(GTK_ENTRY(comment_entry), "");
884
	gtk_entry_set_text(GTK_ENTRY(v1_comment_entry), "");
506
	gtk_list_select_item(GTK_LIST(GTK_COMBO(genre_combo)->list),
885
	gtk_list_select_item(GTK_LIST(GTK_COMBO(v1_genre_combo)->list),
886
			     genre_find_index(genre_list, 0xff));
887
888
	gtk_entry_set_text(GTK_ENTRY(v2_artist_entry), "");
889
	gtk_entry_set_text(GTK_ENTRY(v2_album_entry), "");
890
	gtk_entry_set_text(GTK_ENTRY(v2_year_entry), "");
891
	gtk_entry_set_text(GTK_ENTRY(v2_tracknum_entry), "");
892
	gtk_entry_set_text(GTK_ENTRY(v2_comment_entry), "");
893
	gtk_entry_set_text(GTK_ENTRY(v2_composer_entry), "");
894
	gtk_entry_set_text(GTK_ENTRY(v2_orig_artist_entry), "");
895
	gtk_entry_set_text(GTK_ENTRY(v2_url_entry), "");
896
	gtk_entry_set_text(GTK_ENTRY(v2_encoded_by_entry), "");
897
	gtk_list_select_item(GTK_LIST(GTK_COMBO(v2_genre_combo)->list),
507
			     genre_find_index(genre_list, 0xff));
898
			     genre_find_index(genre_list, 0xff));
899
508
	gtk_label_set_text(GTK_LABEL(mpeg_level), "MPEG ?, layer ?");
900
	gtk_label_set_text(GTK_LABEL(mpeg_level), "MPEG ?, layer ?");
509
	gtk_label_set_text(GTK_LABEL(mpeg_bitrate), "");
901
	gtk_label_set_text(GTK_LABEL(mpeg_bitrate), "");
510
	gtk_label_set_text(GTK_LABEL(mpeg_samplerate), "");
902
	gtk_label_set_text(GTK_LABEL(mpeg_samplerate), "");
511
	gtk_label_set_text(GTK_LABEL(mpeg_flags), "");
903
	gtk_label_set_text(GTK_LABEL(mpeg_flags), "");
512
	gtk_label_set_text(GTK_LABEL(mpeg_fileinfo), "");
904
	gtk_label_set_text(GTK_LABEL(mpeg_fileinfo), "");
513
514
	if (!strncasecmp(filename, "http://", 7))
905
	if (!strncasecmp(filename, "http://", 7))
515
	{
906
	{
516
		file_info_http(filename);
907
		file_info_http(filename);
517
		return;
908
		return;
518
	}
909
	}
519
910
520
	gtk_widget_set_sensitive(id3_frame, TRUE);
911
	gtk_widget_set_sensitive(id3v1_frame, TRUE);
912
	gtk_widget_set_sensitive(id3v2_frame, TRUE);
521
913
522
	if ((fh = fopen(current_filename, "rb")) != NULL)
914
	if ((fh = fopen(current_filename, "rb")) != NULL)
523
	{
915
	{
Lines 525-564 Link Here
525
		unsigned char tmp[4];
917
		unsigned char tmp[4];
526
		struct frame frm;
918
		struct frame frm;
527
		gboolean id3_found = FALSE;
919
		gboolean id3_found = FALSE;
920
		char *temp = NULL;
921
		struct id3_tag *id3 = NULL;
528
922
529
		fseek(fh, -sizeof (tag), SEEK_END);
923
		/*
530
		if (fread(&tag, 1, sizeof (tag), fh) == sizeof (tag))
924
		 * Try reading ID3v2 tag.
925
		 */
926
		if (!mpg123_cfg.disable_id3v2)
531
		{
927
		{
532
			if (!strncmp(tag.tag, "TAG", 3))
928
			fseek(fh, 0, SEEK_SET);
929
			id3 = id3_open_fp(fh, 0);
930
			if (id3)
533
			{
931
			{
534
				id3_found = TRUE;
932
				mpg123_get_id3v2(id3, &id3v2tag);
535
				set_entry_tag(GTK_ENTRY(title_entry),
933
				set_entry_tag(GTK_ENTRY(v2_title_entry),
536
					      tag.title, 30);
934
								id3v2tag.title, 128);
537
				set_entry_tag(GTK_ENTRY(artist_entry),
935
				set_entry_tag(GTK_ENTRY(v2_artist_entry),
538
					      tag.artist, 30);
936
								id3v2tag.artist, 128);
539
				set_entry_tag(GTK_ENTRY(album_entry),
937
				set_entry_tag(GTK_ENTRY(v2_album_entry),
540
					      tag.album, 30);
938
								id3v2tag.album, 128);
541
				set_entry_tag(GTK_ENTRY(year_entry),
939
				set_entry_tag(GTK_ENTRY(v2_comment_entry),
542
					      tag.year, 4);
940
								id3v2tag.comment, 256);
543
				/* Check for v1.1 tags */
941
				set_entry_tag(GTK_ENTRY(v2_composer_entry),
544
				if (tag.u.v1_1.__zero == 0)
942
								id3v2tag.composer, MAX_ENTRY_LEN2);
545
				{
943
				set_entry_tag(GTK_ENTRY(v2_orig_artist_entry),
546
					char *temp = g_strdup_printf("%d", tag.u.v1_1.track_number);
944
								id3v2tag.orig_artist, MAX_ENTRY_LEN2);
547
					set_entry_tag(GTK_ENTRY(comment_entry),
945
				set_entry_tag(GTK_ENTRY(v2_url_entry),
548
						      tag.u.v1_1.comment, 28);
946
								id3v2tag.url, MAX_ENTRY_LEN2);
549
					gtk_entry_set_text(GTK_ENTRY(tracknum_entry), temp);
947
				set_entry_tag(GTK_ENTRY(v2_encoded_by_entry),
550
					g_free(temp);
948
								id3v2tag.encoded_by, MAX_ENTRY_LEN2);
551
				}
552
				else
553
				{
554
					set_entry_tag(GTK_ENTRY(comment_entry),
555
						      tag.u.v1_0.comment, 30);
556
					gtk_entry_set_text(GTK_ENTRY(tracknum_entry), "");
557
				}
558
				
949
				
559
				gtk_list_select_item(GTK_LIST(GTK_COMBO(genre_combo)->list), genre_find_index(genre_list, tag.genre));
950
				temp = g_strdup_printf("%d", id3v2tag.track_number);
951
				gtk_entry_set_text(GTK_ENTRY(v2_tracknum_entry), temp);
952
				g_free(temp);
953
954
				temp = g_strdup_printf("%d", id3v2tag.year);
955
				gtk_entry_set_text(GTK_ENTRY(v2_year_entry), temp);
956
				g_free(temp);
957
				
958
                printf("Loading genre: %s", id3v2tag.genre);
959
				gtk_list_select_item(GTK_LIST(GTK_COMBO(v2_genre_combo)->list), genre_find_index_str(genre_list, id3v2tag.genre));
960
				id3_close(id3);
560
			}
961
			}
962
            else
963
            {
964
                // Grey out the id3v2 tab
965
                gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(v2_checkbox), TRUE);
966
            }
967
		}
968
969
		/*
970
		 * Try reading ID3v1 tag.
971
		 */
972
		fseek(fh, -sizeof (id3v1tag), SEEK_END);
973
		if ( (fread(&id3v1tag, 1, sizeof (id3v1tag), fh) == sizeof (id3v1tag)) &&
974
              !strncmp(id3v1tag.tag, "TAG", 3))
975
		{
976
            id3_found = TRUE;
977
            set_entry_tag(GTK_ENTRY(v1_title_entry),
978
                    id3v1tag.title, 30);
979
            set_entry_tag(GTK_ENTRY(v1_artist_entry),
980
                    id3v1tag.artist, 30);
981
            set_entry_tag(GTK_ENTRY(v1_album_entry),
982
                    id3v1tag.album, 30);
983
            set_entry_tag(GTK_ENTRY(v1_year_entry),
984
                    id3v1tag.year, 4);
985
            /* Check for v1.1 tags */
986
            if (id3v1tag.u.v1_1.__zero == 0)
987
            {
988
                char *temp = g_strdup_printf("%d", id3v1tag.u.v1_1.track_number);
989
                set_entry_tag(GTK_ENTRY(v1_comment_entry),
990
                        id3v1tag.u.v1_1.comment, 28);
991
                gtk_entry_set_text(GTK_ENTRY(v1_tracknum_entry), temp);
992
                g_free(temp);
993
            }
994
            else
995
            {
996
                set_entry_tag(GTK_ENTRY(v1_comment_entry),
997
                        id3v1tag.u.v1_0.comment, 30);
998
                gtk_entry_set_text(GTK_ENTRY(v1_tracknum_entry), "");
999
            }
1000
1001
			gtk_list_select_item(GTK_LIST(GTK_COMBO(v1_genre_combo)->list), genre_find_index(genre_list, id3v1tag.genre));
561
		}
1002
		}
1003
        else
1004
        {
1005
            // Grey out id3v1 tab
1006
            gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(v1_checkbox), TRUE);
1007
        }
1008
562
		rewind(fh);
1009
		rewind(fh);
563
		if (fread(tmp, 1, 4, fh) != 4)
1010
		if (fread(tmp, 1, 4, fh) != 4)
564
		{
1011
		{
(-)xmms-1.2.10.orig/Input/mpg123/id3_frame_text.c (-116 / +168 lines)
Lines 38-52 Link Here
38
38
39
char *id3_utf16_to_ascii(void *utf16)
39
char *id3_utf16_to_ascii(void *utf16)
40
{
40
{
41
	char ascii[256];
41
    char ascii[256];
42
	char *uc = (char *) utf16 + 2;
42
    char *uc = (char *) utf16 + 2;
43
	int i;
43
    int i;
44
44
45
	for (i = 0; *uc != 0 && i < sizeof(ascii); i++, uc += 2)
45
    for (i = 0; *uc != 0 && i < sizeof(ascii); i++, uc += 2)
46
		ascii[i] = *uc;
46
        ascii[i] = *uc;
47
    
47
48
	ascii[i] = 0;
48
    ascii[i] = 0;
49
	return g_strdup(ascii);
49
    return g_strdup(ascii);
50
}
50
}
51
51
52
52
Lines 59-83 Link Here
59
 */
59
 */
60
gint8 id3_get_encoding(struct id3_frame *frame)
60
gint8 id3_get_encoding(struct id3_frame *frame)
61
{
61
{
62
	/* Type check */
62
    /* Type check */
63
	if (!id3_frame_is_text(frame) &&
63
    if (!id3_frame_is_text(frame) &&
64
	    frame->fr_desc->fd_id != ID3_WXXX &&
64
            frame->fr_desc->fd_id != ID3_WXXX &&
65
	    frame->fr_desc->fd_id != ID3_IPLS &&
65
            frame->fr_desc->fd_id != ID3_IPLS &&
66
	    frame->fr_desc->fd_id != ID3_USLT &&
66
            frame->fr_desc->fd_id != ID3_USLT &&
67
	    frame->fr_desc->fd_id != ID3_SYLT &&
67
            frame->fr_desc->fd_id != ID3_SYLT &&
68
	    frame->fr_desc->fd_id != ID3_COMM &&
68
            frame->fr_desc->fd_id != ID3_COMM &&
69
	    frame->fr_desc->fd_id != ID3_APIC &&
69
            frame->fr_desc->fd_id != ID3_APIC &&
70
	    frame->fr_desc->fd_id != ID3_GEOB &&
70
            frame->fr_desc->fd_id != ID3_GEOB &&
71
	    frame->fr_desc->fd_id != ID3_USER &&
71
            frame->fr_desc->fd_id != ID3_USER &&
72
	    frame->fr_desc->fd_id != ID3_OWNE &&
72
            frame->fr_desc->fd_id != ID3_OWNE &&
73
	    frame->fr_desc->fd_id != ID3_COMR)
73
            frame->fr_desc->fd_id != ID3_COMR)
74
		return -1;
74
        return -1;
75
75
76
	/* Check if frame is compressed */
76
    /* Check if frame is compressed */
77
	if (id3_decompress_frame(frame) == -1)
77
    if (id3_decompress_frame(frame) == -1)
78
		return -1;
78
        return -1;
79
79
80
	return *(gint8 *) frame->fr_data;
80
    return *(gint8 *) frame->fr_data;
81
}
81
}
82
82
83
83
Lines 92-116 Link Here
92
{
92
{
93
    /* Type check */
93
    /* Type check */
94
    if ( frame->fr_desc->fd_idstr[0] != 'T' &&
94
    if ( frame->fr_desc->fd_idstr[0] != 'T' &&
95
	 frame->fr_desc->fd_id != ID3_WXXX &&
95
            frame->fr_desc->fd_id != ID3_WXXX &&
96
	 frame->fr_desc->fd_id != ID3_IPLS &&
96
            frame->fr_desc->fd_id != ID3_IPLS &&
97
	 frame->fr_desc->fd_id != ID3_USLT &&
97
            frame->fr_desc->fd_id != ID3_USLT &&
98
	 frame->fr_desc->fd_id != ID3_SYLT &&
98
            frame->fr_desc->fd_id != ID3_SYLT &&
99
	 frame->fr_desc->fd_id != ID3_COMM &&
99
            frame->fr_desc->fd_id != ID3_COMM &&
100
	 frame->fr_desc->fd_id != ID3_APIC &&
100
            frame->fr_desc->fd_id != ID3_APIC &&
101
	 frame->fr_desc->fd_id != ID3_GEOB &&
101
            frame->fr_desc->fd_id != ID3_GEOB &&
102
	 frame->fr_desc->fd_id != ID3_USER &&
102
            frame->fr_desc->fd_id != ID3_USER &&
103
	 frame->fr_desc->fd_id != ID3_OWNE &&
103
            frame->fr_desc->fd_id != ID3_OWNE &&
104
	 frame->fr_desc->fd_id != ID3_COMR )
104
            frame->fr_desc->fd_id != ID3_COMR )
105
	return -1;
105
        return -1;
106
106
107
    /* Check if frame is compressed */
107
    /* Check if frame is compressed */
108
    if (id3_decompress_frame(frame) == -1)
108
    if (id3_decompress_frame(frame) == -1)
109
	    return -1;
109
        return -1;
110
110
111
    /* Changing the encoding of frames is not supported yet */
111
    /* Changing the encoding of frames is not supported yet */
112
    if ( *(gint8 *) frame->fr_data != encoding )
112
    if ( *(gint8 *) frame->fr_data != encoding )
113
	return -1;
113
        return -1;
114
114
115
    /* Set encoding */
115
    /* Set encoding */
116
    *(gint8 *) frame->fr_data = encoding;
116
    *(gint8 *) frame->fr_data = encoding;
Lines 128-171 Link Here
128
{
128
{
129
    /* Type check */
129
    /* Type check */
130
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
130
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
131
	return NULL;
131
        return NULL;
132
132
133
    /* Check if frame is compressed */
133
    /* Check if frame is compressed */
134
    if (id3_decompress_frame(frame) == -1)
134
    if (id3_decompress_frame(frame) == -1)
135
	    return NULL;
135
        return NULL;
136
136
137
    if ( frame->fr_desc->fd_id == ID3_TXXX ) {
137
    if ( frame->fr_desc->fd_id == ID3_TXXX ) {
138
	/*
138
        /*
139
	 * This is a user defined text frame.  Skip the description.
139
         * This is a user defined text frame.  Skip the description.
140
	 */
140
         */
141
	switch ( *(guint8 *) frame->fr_data ) {
141
        switch ( *(guint8 *) frame->fr_data ) {
142
	case ID3_ENCODING_ISO_8859_1:
142
            case ID3_ENCODING_ISO_8859_1:
143
	{
143
                {
144
	    char *text = (char *) frame->fr_data + 1;
144
                    char *text = (char *) frame->fr_data + 1;
145
145
146
	    while ( *text != 0 )
146
                    while ( *text != 0 )
147
		text++;
147
                        text++;
148
148
149
	    return g_strdup(++text);
149
                    return g_strdup(++text);
150
	}
150
                }
151
	case ID3_ENCODING_UTF16:
151
            case ID3_ENCODING_UTF16:
152
	{
152
                {
153
	    char *text16 = (char *) frame->fr_data + 1;
153
                    char *text16 = (char *) frame->fr_data + 1;
154
154
155
	    while (*text16 != 0 || *(text16 + 1) != 0)
155
                    while (*text16 != 0 || *(text16 + 1) != 0)
156
		text16 += 2;
156
                        text16 += 2;
157
157
158
	    return id3_utf16_to_ascii(text16 + 2);
158
                    return id3_utf16_to_ascii(text16 + 2);
159
	}
159
                }
160
	default:
160
            default:
161
	    return NULL;
161
                return NULL;
162
	}
162
        }
163
    }
163
    }
164
164
165
    if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
165
    if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
166
	return g_strdup((char *) frame->fr_data + 1);
166
        return g_strdup((char *) frame->fr_data + 1);
167
    else
167
    else
168
	return id3_utf16_to_ascii(((char *) frame->fr_data + 1));
168
        return id3_utf16_to_ascii(((char *) frame->fr_data + 1));
169
}
169
}
170
170
171
171
Lines 179-198 Link Here
179
{
179
{
180
    /* Type check */
180
    /* Type check */
181
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
181
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
182
	return NULL;
182
        return NULL;
183
183
184
    /* If predefined text frame, return description. */
184
    /* If predefined text frame, return description. */
185
    if ( frame->fr_desc->fd_id != ID3_TXXX )
185
    if ( frame->fr_desc->fd_id != ID3_TXXX )
186
	return frame->fr_desc->fd_description;
186
        return frame->fr_desc->fd_description;
187
187
188
    /* Check if frame is compressed */
188
    /* Check if frame is compressed */
189
    if (id3_decompress_frame(frame) == -1)
189
    if (id3_decompress_frame(frame) == -1)
190
	    return NULL;
190
        return NULL;
191
191
192
    if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
192
    if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
193
	return g_strdup((char *) frame->fr_data + 1);
193
        return g_strdup((char *) frame->fr_data + 1);
194
    else
194
    else
195
	return id3_utf16_to_ascii((char *) frame->fr_data + 1);
195
        return id3_utf16_to_ascii((char *) frame->fr_data + 1);
196
}
196
}
197
197
198
198
Lines 209-250 Link Here
209
209
210
    /* Check if frame is compressed */
210
    /* Check if frame is compressed */
211
    if (id3_decompress_frame(frame) == -1)
211
    if (id3_decompress_frame(frame) == -1)
212
	    return -1;
212
        return -1;
213
213
214
    /*
214
    /*
215
     * Generate integer according to encoding.
215
     * Generate integer according to encoding.
216
     */
216
     */
217
    switch ( *(guint8 *) frame->fr_data ) {
217
    switch ( *(guint8 *) frame->fr_data ) {
218
    case ID3_ENCODING_ISO_8859_1:
218
        case ID3_ENCODING_ISO_8859_1:
219
    {
219
            {
220
	char *text = ((char *) frame->fr_data) + 1;
220
                char *text = ((char *) frame->fr_data) + 1;
221
221
222
	while ( *text >= '0' && *text <= '9' ) {
222
                while ( *text >= '0' && *text <= '9' ) {
223
	    number *= 10;
223
                    number *= 10;
224
	    number += *text - '0';
224
                    number += *text - '0';
225
	    text++;
225
                    text++;
226
	}
226
                }
227
228
                return number;
229
            }
230
        case ID3_ENCODING_UTF16:
231
            {
232
                char *text = ((char *) frame->fr_data) + 3;
233
234
/*      if (*(gint16 *) frame->fr_data == 0xfeff) */
235
/*          text++; */
236
237
                while ( *text >= '0' && *text <= '9' ) {
238
                    number *= 10;
239
                    number += *text - '0';
240
                    text++;
241
                }
227
242
228
	return number;
243
                return number;
229
    }
244
            }
230
    case ID3_ENCODING_UTF16:
231
    {
232
	char *text = ((char *) frame->fr_data) + 3;
233
234
/*  	if (*(gint16 *) frame->fr_data == 0xfeff) */
235
/*  	    text++; */
236
237
	while ( *text >= '0' && *text <= '9' ) {
238
	    number *= 10;
239
	    number += *text - '0';
240
	    text++;
241
	}
242
245
243
	return number;
246
        default:
244
    }
247
            return -1;
245
246
    default:
247
	return -1;
248
    }
248
    }
249
}
249
}
250
250
Lines 260-266 Link Here
260
{
260
{
261
    /* Type check */
261
    /* Type check */
262
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
262
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
263
	return -1;
263
        return -1;
264
264
265
    /*
265
    /*
266
     * Release memory occupied by previous data.
266
     * Release memory occupied by previous data.
Lines 289-294 Link Here
289
}
289
}
290
290
291
291
292
293
294
char* id3_get_comm(struct id3_frame *frame)
295
{
296
297
    /* Type check */
298
    if ( frame->fr_desc->fd_id != ID3_COMM )
299
        return NULL;
300
301
    /* Check if frame is compressed */
302
    if (id3_decompress_frame(frame) == -1)
303
        return NULL;
304
305
    /*
306
     * <Header for 'Comment', ID: "COMM">
307
     * Text encoding          $xx
308
     * Language               $xx xx xx
309
     * Short content descrip. <text string according to encoding> $00 (00)
310
     * The actual text        <full text string according to encoding>
311
     *
312
     * Skip language and short description.
313
     */
314
    switch ( *(guint8 *) frame->fr_data ) {
315
        case ID3_ENCODING_ISO_8859_1:
316
            {
317
                char *text = (char *) frame->fr_data + 4;
318
319
                while ( *text != 0 )
320
                    text++;
321
                
322
                return g_strdup(++text);
323
            }
324
        case ID3_ENCODING_UTF16:
325
            {
326
                char *text16 = (char *) frame->fr_data + 4;
327
328
                while (*text16 != 0 || *(text16 + 1) != 0)
329
                    text16 += 2;
330
331
                return id3_utf16_to_ascii(text16 + 2);
332
            }
333
        default:
334
            return NULL;
335
    }
336
337
    if (*(guint8 *) frame->fr_data == ID3_ENCODING_ISO_8859_1)
338
        return g_strdup((char *) frame->fr_data + 1);
339
    else
340
        return id3_utf16_to_ascii(((char *) frame->fr_data + 1));
341
}
342
343
292
/*
344
/*
293
 * Function id3_set_text_number (frame, number)
345
 * Function id3_set_text_number (frame, number)
294
 *
346
 *
Lines 304-328 Link Here
304
356
305
    /* Type check */
357
    /* Type check */
306
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
358
    if ( frame->fr_desc->fd_idstr[0] != 'T' )
307
	return -1;
359
        return -1;
308
360
309
    /*
361
    /*
310
     * Release memory occupied by previous data.
362
     * Release memory occupied by previous data.
311
     */
363
     */
312
    id3_frame_clear_data(frame);
364
    id3_frame_clear_data(frame);
313
    
365
314
    /*
366
    /*
315
     * Create a string with a reversed number.
367
     * Create a string with a reversed number.
316
     */
368
     */
317
    pos = 0;
369
    pos = 0;
318
    while ( number > 0 && pos < 64 ) {
370
    while ( number > 0 && pos < 64 ) {
319
	buf[pos++] = (number % 10) + '0';
371
        buf[pos++] = (number % 10) + '0';
320
	number /= 10;
372
        number /= 10;
321
    }
373
    }
322
    if ( pos == 64 )
374
    if ( pos == 64 )
323
	return -1;
375
        return -1;
324
    if ( pos == 0 )
376
    if ( pos == 0 )
325
	buf[pos++] = '0';
377
        buf[pos++] = '0';
326
378
327
    /*
379
    /*
328
     * Allocate memory for new data.
380
     * Allocate memory for new data.
Lines 336-342 Link Here
336
    *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1;
388
    *(gint8 *) frame->fr_raw_data = ID3_ENCODING_ISO_8859_1;
337
    text = (char *) frame->fr_raw_data + 1;
389
    text = (char *) frame->fr_raw_data + 1;
338
    while ( --pos >= 0 ) 
390
    while ( --pos >= 0 ) 
339
	*text++ = buf[pos];
391
        *text++ = buf[pos];
340
    *text = '\0';
392
    *text = '\0';
341
393
342
    frame->fr_altered = 1;
394
    frame->fr_altered = 1;
Lines 350-358 Link Here
350
402
351
gboolean id3_frame_is_text(struct id3_frame *frame)
403
gboolean id3_frame_is_text(struct id3_frame *frame)
352
{
404
{
353
	if (frame && frame->fr_desc &&
405
    if (frame && frame->fr_desc &&
354
	    (frame->fr_desc->fd_idstr[0] == 'T' ||
406
            (frame->fr_desc->fd_idstr[0] == 'T' ||
355
	     frame->fr_desc->fd_idstr[0] == 'W' ))
407
             frame->fr_desc->fd_idstr[0] == 'W' ))
356
		return TRUE;
408
        return TRUE;
357
	return FALSE;
409
    return FALSE;
358
}
410
}
(-)xmms-1.2.10.orig/Input/mpg123/id3.h (+1 lines)
Lines 351-356 Link Here
351
int id3_set_text(struct id3_frame *, char *);
351
int id3_set_text(struct id3_frame *, char *);
352
int id3_set_text_number(struct id3_frame *, int);
352
int id3_set_text_number(struct id3_frame *, int);
353
gboolean id3_frame_is_text(struct id3_frame *frame);
353
gboolean id3_frame_is_text(struct id3_frame *frame);
354
char* id3_get_comm(struct id3_frame *frame);
354
355
355
/* From id3_frame_content.c */
356
/* From id3_frame_content.c */
356
char *id3_get_content(struct id3_frame *);
357
char *id3_get_content(struct id3_frame *);
(-)xmms-1.2.10.orig/Input/mpg123/lib_id3v2.h (+1280 lines)
Line 0 Link Here
1
/* the id3v2.3 library.
2
 * (c)2002 by Samuel Abels (sam@manicsadness.com)
3
 * This project's homepage is: http://software.manicsadness.com/cantus
4
 *
5
 * This library is designed for easyest possible access to id3 V2 tags.
6
 *
7
 * This program is free software; you can redistribute it and/or modify
8
 * it under the terms of the GNU General Public License as published by
9
 * the Free Software Foundation; either version 2 of the License, or
10
 * (at your option) any later version.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 * GNU General Public License for more details.
16
17
 * You should have received a copy of the GNU General Public License
18
 * along with this program; if not, write to the Free Software
19
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20
 */
21
22
#ifndef DLL_H
23
#define DLL_H
24
typedef struct DLL_s
25
{
26
	void *prev;
27
	void *data;
28
	void *next;
29
} DLL;
30
#endif
31
32
#ifndef FALSE
33
#define FALSE 0
34
#endif
35
#ifndef TRUE
36
#define TRUE 1
37
#endif
38
39
#ifndef id3Tag_def
40
#define id3Tag_def
41
42
typedef struct id3Tag_s
43
{
44
	char title[1024];
45
	char artist[1024];
46
	char album[1024];
47
	char year[5];
48
	char comment[1024];
49
	char track[3];
50
	char genre[512];
51
    char composer[1024];
52
    char url[1024];
53
    char orig_artist[1024];
54
    char enc_by[1024];
55
	unsigned int size;
56
	short int has_footer;
57
} id3Tag;
58
59
typedef struct id3v2Tag_s
60
{
61
// header
62
	int tag_size;
63
	short int unsync;
64
	short int has_extheader;
65
	short int is_experimental;
66
//extheader
67
	int extheader_size;
68
	int padding_size;
69
	short int crc_data_present;
70
	char crc_data[4];
71
// frames
72
	DLL *frames;
73
} id3v2Tag;
74
75
typedef struct id3v2Frame_s
76
{
77
	unsigned char id[4];
78
	int datasize;
79
	short int tagalter;
80
	short int filealter;
81
	short int readonly;
82
	short int compression;
83
	short int encryption;
84
	short int grouping;
85
	char *data;
86
} id3v2Frame;
87
88
#endif
89
90
/* the id3v2.3 library.
91
 * (c)2002 by Samuel Abels (sam@manicsadness.com)
92
 * This project's homepage is: http://software.manicsadness.com/cantus
93
 *
94
 * This library is designed for easyest possible access to id3 V2 tags.
95
 *
96
 * This program is free software; you can redistribute it and/or modify
97
 * it under the terms of the GNU General Public License as published by
98
 * the Free Software Foundation; either version 2 of the License, or
99
 * (at your option) any later version.
100
 *
101
 * This program is distributed in the hope that it will be useful,
102
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
103
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
104
 * GNU General Public License for more details.
105
106
 * You should have received a copy of the GNU General Public License
107
 * along with this program; if not, write to the Free Software
108
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
109
 */
110
111
#include <stdio.h>
112
#include <string.h>
113
#include <stdlib.h>
114
#include <ctype.h>
115
#include "charset.h"
116
117
118
119
/***************************************************************************************
120
 * BELOW FOLLOW THE STATICS
121
 ***************************************************************************************/
122
// Return the last item of an doubly linked list
123
static DLL *
124
dll_last (DLL *list)
125
{
126
	if( list == NULL )
127
		return (NULL);
128
	
129
	while ( list->next != NULL )
130
		list = list->next;
131
	
132
	return (list);
133
}
134
135
// Append an item to the doubly linked list
136
static DLL *
137
dll_append (DLL *list, void *data)
138
{
139
	DLL *item = malloc (sizeof(DLL));
140
	DLL *lastitem = dll_last(list);
141
	
142
	item->data = data;
143
	item->next = NULL;
144
	
145
	if ( lastitem == NULL )
146
	{
147
		item->prev = NULL;
148
		return (item);
149
	}
150
	else
151
	{
152
		item->prev = lastitem;
153
		lastitem->next = item;
154
	}
155
156
	return list;
157
}
158
  
159
static DLL *
160
dll_remove (DLL *list, void *data)
161
{
162
	DLL *item = list;
163
	
164
	while ( item )
165
	{
166
		if ( item->data == data )
167
		{
168
			if ( item->prev == NULL 
169
				&& item->next == NULL )
170
			{
171
// No other items there? Then return a zero pointer.
172
				free (item);
173
				return (NULL);
174
			}
175
			if ( item->prev == NULL )
176
			{
177
// remove the first item of the list here...
178
				list = item->next;
179
				list->prev = NULL;
180
				free (item);
181
				
182
				break;
183
			}
184
			if ( item->next == NULL )
185
			{
186
// ...remove the last item of the list here...
187
				((DLL*)(item->prev))->next = NULL;
188
				free (item);
189
				
190
				break;
191
			}
192
// ...or other items here
193
			((DLL*)(item->prev))->next = item->next;
194
			((DLL*)(item->next))->prev = item->prev;
195
			free (item);
196
			
197
			break;
198
		}
199
		item = item->next;
200
	}
201
	
202
	return list;
203
}
204
205
// Free a doubly linked list
206
static DLL *
207
dll_free (DLL *list)
208
{
209
	DLL *item = list;
210
	DLL *current = NULL;
211
	
212
	while (item)
213
	{
214
		current = item;
215
		item = item->next;
216
		
217
		free (current);
218
	}
219
	
220
	return NULL;
221
}
222
223
/*
224
 * Converts all occurences of a CR/LF to LF
225
 */
226
static void
227
crlf2cr (char *source)
228
{
229
	char *psource = source;
230
	char destination[2048];
231
232
	if(source != NULL)
233
	{
234
		memset (destination, 0, 2048);
235
		for (psource = source; *psource != '\0'; psource++)
236
		{
237
			if(*psource == 13
238
				&& *(psource+1) == 10 )
239
			{
240
				psource++;
241
			}
242
			destination[strlen(destination)] = *psource;
243
		}
244
	}
245
	
246
	strncpy (source, destination, strlen(destination)+1);
247
}
248
249
250
/*
251
 * Converts all occurences of a LF to CR/LF
252
 */
253
static void
254
cr2crlf (char *source)
255
{
256
	char *psource = source;
257
	char destination[2048];
258
	
259
	if( source != NULL )
260
	{
261
		memset (destination, 0, 2048);
262
		for (psource = source; *psource != '\0'; psource++)
263
		{
264
			if (*psource == 10)
265
				destination[strlen(destination)] = 13;
266
			destination[strlen(destination)] = *psource;
267
		}
268
	}
269
	
270
	strncpy (source, destination, strlen(destination)+1);
271
}
272
273
274
275
276
/*
277
 * Reads the first ten bytes of an file and checks, if it's a valid ID3 V2.3 file
278
 * If it is, the header flags are stored in the tag struct.
279
 * Returns TRUE on a valid header, otherwise FALSE.
280
 */
281
static short int
282
check_header (FILE *mp3file, id3v2Tag *v2)
283
{
284
	unsigned char buf[10];
285
	
286
// get header (=first ten bytes of the file)
287
	fseek (mp3file, 0, SEEK_SET);
288
	if ( fread (buf, 1, 10, mp3file) < 10 )
289
		return (FALSE);
290
291
// a valid tag must begin with "ID3" followed by the version (checked below)
292
// followed by a flag byte, where the last five bytes are unused and must be FALSE
293
	if ( memcmp(buf, "ID3", 3) != 0
294
		|| (buf[5] & 31) != 0 )
295
		return (FALSE);
296
297
// check if version is supported
298
	if ( buf[3] != 3
299
		|| buf[4] != 0 )
300
		return (FALSE);
301
302
// The next thing to come is the tag size. These are 4 bytes, the MSB should always be set to zero. check!
303
	if ( (buf[6] & 128) != 0
304
		|| (buf[7] & 128) != 0
305
		|| (buf[8] & 128) != 0
306
		|| (buf[9] & 128) != 0 )
307
		return (FALSE);
308
	
309
// The tag size is encoded to be syncsave, so I got to decode it.
310
// The tag size is the size of the complete tag EXCLUDING the 10-byte header.
311
 	v2->tag_size = buf[9] + (buf[8] << 7) + (buf[7] << 14) + (buf[6] << 21);
312
313
// ok, so were save. put the flags in the nicer struct.
314
	v2->unsync = (buf[5] & 128) >> 7;
315
	v2->has_extheader = (buf[5] & 64) >> 6;
316
	v2->is_experimental = (buf[5] & 32) >> 5;
317
	
318
	return (TRUE);
319
}
320
321
322
323
324
325
/*
326
 * Reads the extheader of a valid ID3V2.3 file and checks, if it's a valid.
327
 * If it is, the extheader flags are stored in the tag struct.
328
 * Returns TRUE on a valid extheader, otherwise FALSE.
329
 */
330
static short int
331
check_extheader (FILE *mp3file, id3v2Tag *v2)
332
{
333
	unsigned char buf[10];
334
335
// Read id3 extheader intro (5 bytes)
336
	fseek (mp3file, 10, SEEK_SET);
337
	if ( fread(buf, 1, 5, mp3file) < 5 )
338
		return (FALSE);
339
	
340
// First comes the extheader size. These are 4 bytes, the MSB should always be set to zero. check!
341
	if( (buf[0] & 128) != 0
342
		|| (buf[1] & 128) != 0
343
		|| (buf[2] & 128) != 0
344
		|| (buf[3] & 128) != 0 )
345
		return (FALSE);
346
	
347
// OK. In ID3V2.3 only six byte or ten byte extheaders are allowed.
348
	if( v2->extheader_size != 6 
349
		&& v2->extheader_size != 10 )
350
		return (FALSE);
351
	
352
// The first four bytes specify the extheader size.
353
	v2->extheader_size = buf[3] + (buf[2] << 7) + (buf[1] << 14) + (buf[0] << 21);
354
	
355
// The fifth byte specifies extendened flags. (in fact, only one flag is used for ID3V2.3
356
// The MSB of the byte 5 specifies, if there is CRC data to come, appended to the extheader.
357
	if( (buf[4] & 127) != 0
358
		|| buf[5] != 0 )
359
		return (FALSE);
360
	
361
	v2->crc_data_present = (buf[4] & 128) >> 7;
362
	
363
// if crc data is present, the extheader size must be ten bytes, otherwise 6.
364
	if ( (v2->extheader_size == 6 && v2->crc_data_present == TRUE)
365
		|| (v2->extheader_size == 10 && v2->crc_data_present == FALSE) )
366
		return (FALSE);
367
	
368
// now come four bytes specifying the padding size
369
	if ( (buf[6] & 128) != 0
370
		|| (buf[7] & 128) != 0
371
		|| (buf[8] & 128) != 0
372
		|| (buf[9] & 128) != 0 )
373
		return (FALSE);
374
	
375
	v2->padding_size = buf[9] + (buf[8] << 7) + (buf[7] << 14) + (buf[6] << 21);
376
	
377
// Now to the optional crc data.
378
	if( v2->crc_data_present )
379
	{
380
		if( fread (buf, 1, 4, mp3file) < 4 )
381
			return (FALSE);
382
		
383
		memcpy (v2->crc_data, buf, 4);
384
	}
385
	
386
	return (TRUE);
387
}
388
389
390
391
392
393
/*
394
 * Reads the complete frames of a valid ID3V2.3 file and checks, if they are valid.
395
 * If they are, the flags are stored in a DLL and appended to the tag struct.
396
 * Returns TRUE on success, otherwise FALSE.
397
 */
398
static short int
399
read_frames (FILE *mp3file, id3v2Tag *v2)
400
{
401
	unsigned char buf[10];
402
	int numframes = 0;
403
	unsigned int totalframesize = 0;
404
	id3v2Frame *frame = NULL;
405
	
406
// set the position to the first frame header (header = 10 bytes + extheadersize + 4 bytes "extheaderheader")
407
	if (v2->has_extheader)
408
		fseek (mp3file, 10 + v2->extheader_size + 4, SEEK_SET);
409
	else
410
		fseek (mp3file, 10, SEEK_SET);
411
412
// If the tag size is too small for frames, return with an error.
413
	if ( ((v2->tag_size + 10) - v2->padding_size) <= ftell(mp3file) )
414
		return FALSE;
415
	
416
// now read all the frames
417
	numframes = 0;
418
	v2->frames = NULL;
419
	while ( ftell (mp3file) < ((v2->tag_size + 10) - v2->padding_size) )
420
	{
421
		frame = calloc (1, sizeof(id3v2Frame));
422
423
// the frame header is ten bytes long
424
		if ( fread (buf, 1, 10, mp3file) < 10 )
425
			goto error;
426
427
// if we are already in the padding, we must no longer look for frames...
428
		if ( buf[0] == 0 && buf[1] == 0 && buf[2] ==  0 && buf[3] == 0 )
429
		{
430
			if (numframes == 0)
431
				goto error;
432
			
433
			free (frame);
434
			break;
435
		}
436
		
437
// first come four characters identifying the frame. It must be alphanumeric.
438
		if ( !isalnum(buf[0]) || !isalnum(buf[1]) || !isalnum(buf[2]) || !isalnum(buf[3]) )
439
			goto error;
440
		
441
		*(frame->id) = buf[0];
442
		*(frame->id + 1) = buf[1];
443
		*(frame->id + 2) = buf[2];
444
		*(frame->id + 3) = buf[3];
445
		
446
// then, the frame size is to come. Again, the four MSBs must be zero.
447
		if ( (buf[4] & 128) != 0
448
			|| (buf[5] & 128) != 0
449
			|| (buf[6] & 128) != 0
450
			|| (buf[7] & 128) != 0 )
451
			goto error;
452
		
453
		frame->datasize = buf[7] + (buf[6] << 7) + (buf[5] << 14) + (buf[4] << 21);
454
		
455
// A minimum size must be present!
456
		if ( frame->datasize <= 0 )
457
			goto error;
458
		
459
// The two following frame header flags have the 5 LSBs not set.
460
		if ( (buf[8] & 31) != 0
461
			|| (buf[9] & 31) != 0 )
462
			goto error;
463
464
// now, put the flags in the struct.
465
		frame->tagalter = (buf[8] & 128) >> 7;
466
		frame->filealter = (buf[8] & 64) >> 6;
467
		frame->readonly = (buf[8] & 32) >> 5;
468
		
469
		frame->compression = (buf[9] & 128) >> 7;
470
		frame->encryption = (buf[8] & 64) >> 6;
471
		frame->grouping = (buf[8] & 32) >> 5;
472
		
473
// ok, we are done with the frame header, so now we read the frame data.
474
		frame->data = calloc (1, frame->datasize + 1);
475
		if( fread (frame->data, 1, frame->datasize, mp3file) < frame->datasize )
476
			goto error;
477
		
478
		numframes++;
479
		totalframesize += 10 + frame->datasize;
480
		
481
// we append it to a glist, which is appended to the v2 struct.
482
		v2->frames = dll_append (v2->frames, frame);
483
	}
484
485
// if we have no extheader, that means, we don't know how much padding we have!
486
// thus, i calculate it here.
487
	if ( !v2->has_extheader )
488
		v2->padding_size = v2->tag_size - totalframesize;
489
	
490
// A minimum of one frame is mandatory.
491
	if( numframes > 0 )
492
		return (TRUE);
493
	
494
error:
495
// cleanups in case of an error.
496
	if( frame && frame->data )
497
		free (frame->data);
498
	if( frame )
499
		free (frame);
500
	return (FALSE);
501
}
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
/*
518
 * Reads all tag information of a valid ID3V2.3 file.
519
 * When successful, the info is stored in the tag struct.
520
 * Returns:
521
 * 0 = success
522
 * 1 = Cannot open file.
523
 * 2 = No header or wrong version.
524
 * 3 = broken extheader.
525
 * 4 = broken frames.
526
 */
527
static int
528
get_id3v2tag_raw (id3v2Tag *v2, char *filename)
529
{
530
	FILE *mp3file = NULL;
531
	int error = 0;
532
533
// open file
534
	error = 1;
535
	mp3file = fopen (filename, "rb");
536
	if (!mp3file)
537
		goto done;
538
	
539
// check/get header
540
	error = 2;
541
	if( !check_header (mp3file, v2) )
542
		goto done;
543
	
544
// check/get extheader
545
	error = 3;
546
	if( v2->has_extheader
547
		&& !check_extheader (mp3file, v2) )
548
		goto done;
549
550
// get the content frames
551
	error = 4;
552
	if( !read_frames (mp3file, v2) )
553
		goto done;
554
555
	error = 0;
556
done:
557
	fclose (mp3file);
558
	return (error);
559
}
560
	
561
	
562
	
563
	
564
	
565
/*
566
 * Find one frames data and give back its data in the correct format.
567
 * Returns TRUE on success, otherwise FALSE;
568
 */
569
static short int
570
frame_find (id3v2Tag *v2, char *name, char *value)
571
{
572
	DLL *curframe = NULL;
573
    id3v2Frame *frame = NULL;
574
575
    // we parse through the whole list of frames, giving back the correct frame value.
576
    curframe = v2->frames;
577
    while ( curframe )
578
    {
579
        frame = (id3v2Frame *)curframe->data;
580
581
        // Just to be sure...
582
        if( frame->datasize <= 0 )
583
            goto nextframe;
584
585
        // Matches the users request? Otherwise try the next frame.
586
        if( memcmp (frame->id, name, 4) != 0 )
587
            goto nextframe;
588
589
        // These types don't need much change, just give the whole data back to the user according to the encoding.
590
        // The first byte is the encoding.
591
        // TPE1: Artist
592
        // TIT2: Song Title
593
        // TALB: Album Title
594
        // TYER: Year
595
        // TRCK: Track
596
        // TCON: Genre
597
        // COMM: Comment
598
        // TCOM: Composer
599
        // TOPE: TOPE Original artist(s)/performer(s)
600
        // TENC: Encoded by
601
        if ( memcmp (frame->id, "TPE1", 4) == 0
602
                || memcmp (frame->id, "TIT2", 4) == 0
603
                || memcmp (frame->id, "TALB", 4) == 0
604
                || memcmp (frame->id, "TYER", 4) == 0
605
                || memcmp (frame->id, "TRCK", 4) == 0
606
                || memcmp (frame->id, "TCON", 4) == 0
607
                || memcmp (frame->id, "TCOM", 4) == 0
608
                || memcmp (frame->id, "TOPE", 4) == 0
609
                || memcmp (frame->id, "TENC", 4) == 0)
610
            //|| memcmp (frame->id, "WXXX", 4) == 0)
611
        {
612
            if ( *frame->data == 0 )
613
                memcpy(value, frame->data + 1, frame->datasize - 1);
614
            if ( *frame->data == 1 )
615
            {
616
                char nulltermvalue[frame->datasize];
617
                char *isovalue = NULL;
618
619
                // the tag is not null terminated, so i have to create a null terminated string first.
620
                memset (nulltermvalue, 0, frame->datasize);
621
                memcpy (nulltermvalue, frame->data + 1, frame->datasize - 1);
622
623
                // Convert from UTF to ISO and copy to the users variable.
624
                isovalue = convert_from_utf8 (nulltermvalue);
625
                strncpy (value, isovalue, sizeof(value) - 1);
626
                free (isovalue);
627
            }
628
629
            // change linefeeds to a single "return" key.
630
            crlf2cr (value);
631
            return (TRUE);
632
        }
633
        if ( memcmp (frame->id, "WCOM", 4) == 0
634
                || memcmp (frame->id, "WCOP", 4) == 0
635
                || memcmp (frame->id, "WOAF", 4) == 0
636
                || memcmp (frame->id, "WOAR", 4) == 0
637
                || memcmp (frame->id, "WOAS", 4) == 0
638
                || memcmp (frame->id, "WPAY", 4) == 0
639
                || memcmp (frame->id, "WPUB", 4) == 0)
640
        {
641
            memcpy(value, frame->data, frame->datasize - 1);
642
            
643
            // change linefeeds to a single "return" key.
644
            crlf2cr (value);
645
            return (TRUE);
646
        }
647
648
        // The comment requires special handling.
649
        // Its data has: One byte "encoding" (0 = ISO-8859-1, 1 = UNICODE)
650
        // followed by the language (three bytes, e.g. "eng"),
651
        // followed by a short description,
652
        // then a NULL,
653
        // and the full description
654
        // For now, i simply drop the short description
655
        if( memcmp(frame->id, "COMM", 4) == 0 )
656
        {
657
            // check for the right format. (minsize 5, must contain a "\0" after the language)
658
            if ( frame->datasize < 5 )
659
                goto nextframe;
660
            if ( !memchr (frame->data + 4, '\0', frame->datasize - 4) )
661
                goto nextframe;
662
663
            // now, give the data back to the user, according to the encoding.
664
            if ( *frame->data == 0 )
665
                memcpy (value, frame->data + 5, frame->datasize - 5);
666
            if ( *frame->data == 1 )
667
            {
668
                char nulltermvalue[frame->datasize];
669
                char *isovalue = NULL;
670
671
                // the tag is not null terminated, so i have to create a null terminated string first.
672
                memset (nulltermvalue, 0, frame->datasize);
673
                memcpy (nulltermvalue, frame->data + 5, frame->datasize - 5);
674
675
                // Convert from UTF to ISO and copy to the users variable.
676
                isovalue = convert_from_utf8 (nulltermvalue);
677
                strncpy (value, isovalue, sizeof(value) - 1);
678
                free (isovalue);
679
            }
680
681
            // change linefeeds to a single "return" key.
682
            crlf2cr (value);
683
            return TRUE;
684
        }
685
686
nextframe:
687
        curframe = curframe->next;
688
    }
689
690
    return FALSE;
691
}
692
	
693
694
695
696
/*
697
 * Remove one frame out of the id3v2Tag struct
698
 * Returns TRUE on success, otherwise FALSE;
699
 */
700
static short int
701
frame_remove (id3v2Tag *v2, char *name)
702
{
703
	id3v2Frame *frame = NULL;
704
	DLL *curframe = NULL;
705
	DLL *tempframe = NULL;
706
	
707
// Parse through the list of frames.
708
	curframe = v2->frames;
709
	while ( curframe )
710
	{
711
		frame = (id3v2Frame *)curframe->data;
712
		tempframe = curframe;
713
		curframe = curframe->next;
714
		
715
		if ( memcmp (frame->id, name, 4) == 0 )
716
		{
717
// we have found the item! removing will NOT shrink the tag, but increase the padding.
718
			v2->padding_size += (frame->datasize + 10);
719
// and free memory.
720
			v2->frames = dll_remove (v2->frames, tempframe->data);
721
			free (frame->data);
722
			free (frame);
723
			
724
			return TRUE;
725
		}
726
	}
727
	
728
	return FALSE;
729
}
730
731
732
733
/*
734
 * Add a frame to the framelist. If the frame name is already in the list, it will be replaced.
735
 * Returns:
736
 * TRUE: The tag size HAS BEEN increased.
737
 * FALSE: The tag size has NOT been increased.
738
 */
739
static short int
740
frame_set (id3v2Tag *v2, char *name, char *value)
741
{
742
	id3v2Frame *frame = NULL;
743
	short int sizechange = FALSE;
744
	
745
// prevent the user to send CR/LF, which is forbidden.
746
	cr2crlf (value);
747
// eventually remove an existing item!
748
	frame_remove (v2, name);
749
750
// alloc space for the new frame.
751
	frame = malloc (sizeof(id3v2Frame));
752
	
753
	memcpy (frame->id, name, 4);
754
	frame->datasize = strlen (value);
755
	frame->tagalter = 0;
756
	frame->filealter = 0;
757
	frame->readonly = 0;
758
	frame->compression = 0;
759
	frame->encryption = 0;
760
	frame->grouping = 0;
761
762
// The comment requires special handling. If you need to know why, look at the documentation
763
// of the "frame_find" function above.
764
    if( memcmp (frame->id, "COMM", 4) == 0 )
765
    {
766
        char fullvalue[frame->datasize + 6];
767
768
        sprintf(fullvalue, "%ceng%c%s", 0, 0, value);
769
770
        frame->datasize += 5;
771
        frame->data = malloc (frame->datasize);
772
        memcpy (frame->data, fullvalue, frame->datasize);
773
    } 
774
    else if ((memcmp(frame->id, "WCOM", 4) == 0)
775
            || memcmp (frame->id, "WCOP", 4) == 0
776
            || memcmp (frame->id, "WOAF", 4) == 0
777
            || memcmp (frame->id, "WOAR", 4) == 0
778
            || memcmp (frame->id, "WOAS", 4) == 0
779
            || memcmp (frame->id, "WPAY", 4) == 0
780
            || memcmp (frame->id, "WPUB", 4) == 0)
781
    {
782
        frame->data = malloc (frame->datasize);
783
        memcpy (frame->data, value, frame->datasize);
784
    }
785
    else 
786
    {
787
        char fullvalue[frame->datasize + 2];
788
789
        // Put encoding type just before the value
790
        sprintf (fullvalue, "%c%s", 0, value);
791
792
        frame->datasize += 1;
793
        frame->data = malloc (frame->datasize);
794
        memcpy (frame->data, fullvalue, frame->datasize);
795
    }
796
	
797
// Ok. This decreases the available padding. If we have no padding left, we must increase the padding (and thus, the tag).
798
	if( v2->padding_size - (frame->datasize + 10) <= 0 )
799
	{
800
// add: framesize + frameheadersize + padding.
801
		v2->padding_size += frame->datasize + 10 + 1024;
802
		v2->tag_size += frame->datasize + 10 + 1024;
803
		
804
		sizechange = TRUE;
805
	}
806
	
807
// In every case, we must subtract the new allocated space from the padding.
808
	v2->padding_size -= frame->datasize + 10;
809
	
810
	v2->frames = dll_append (v2->frames, frame);
811
	
812
	return sizechange;
813
}
814
815
816
817
/*
818
 * Create raw header.
819
 * Returns:
820
 * TRUE: successful.
821
 * FALSE: unsuccessful.
822
 */
823
static int
824
create_header_raw (char *raw, id3v2Tag *v2)
825
{
826
// now we are going to write the tags raw data into the raw string
827
	memset (raw, 0, v2->tag_size + 10);
828
// ID3 identifier bytes
829
	memcpy (raw, "ID3", 3);
830
	raw += 3;
831
// major version byte
832
	*raw++ = 3;
833
// minor version byte
834
	*raw++ = 0;
835
// Flags byte
836
	*raw++ = ((v2->unsync & 1) << 7)
837
		| ((v2->has_extheader & 1) << 6)
838
		| ((v2->is_experimental & 1) << 5);
839
// Tag size. It must be syncsafe!
840
	*raw++ = ((v2->tag_size & 0x800000) >> 23) | (((v2->tag_size & 0x7f000000) >> 24) << 1);
841
	*raw++ = ((v2->tag_size & 0x8000) >> 15) | (((v2->tag_size & 0x7f0000) >> 16) << 1);
842
	*raw++ = ((v2->tag_size & 0x80) >> 7) | (((v2->tag_size & 0x7f00) >> 8) << 1);
843
	*raw++ = (v2->tag_size & 0x7f);
844
	
845
	return TRUE;
846
}
847
848
849
850
851
/*
852
 * Generates the frames. btw.: ID3 sucks!
853
 * Returns: TRUE if succesful, otherwise FALSE.
854
 */
855
static short int
856
create_frames_raw (char *raw, id3v2Tag *v2)
857
{
858
	id3v2Frame *frame = NULL;
859
	DLL *curframe = NULL;
860
	
861
// if we have no frames, just quit.
862
	if ( v2->frames == NULL )
863
		return FALSE;
864
	
865
// the header and extheader have already been written.
866
	raw += 10;
867
	if ( v2->has_extheader )
868
		raw += 4 + v2->extheader_size;
869
	
870
	curframe = v2->frames;
871
	while ( curframe )
872
	{
873
		frame = (id3v2Frame *)curframe->data;
874
875
// secure is secure
876
		if ( frame->datasize <= 0 )
877
			goto nextframe;
878
		
879
// add the frame id
880
		memcpy(raw, frame->id, 4);
881
		raw += 4;
882
// add the frame size (syncsafe)
883
		*raw++ = ((frame->datasize & 0x800000) >> 23) | (((frame->datasize & 0x7f000000) >> 24) << 1);
884
		*raw++ = ((frame->datasize & 0x8000) >> 15) | (((frame->datasize & 0x7f0000) >> 16) << 1);
885
		*raw++ = ((frame->datasize & 0x80) >> 7) | (((frame->datasize & 0x7f00) >> 8) << 1);
886
		*raw++ = (frame->datasize & 0x7f);
887
888
// The two flagbytes
889
		*raw++ = ((frame->tagalter & 1) << 7)
890
			| ((frame->filealter & 1) << 6)
891
			| ((frame->readonly & 1) << 5);
892
		
893
		*raw++ = ((frame->compression & 1) << 7)
894
			| ((frame->encryption & 1) << 6)
895
			| ((frame->grouping & 1) << 5);
896
897
// now the frame data.
898
		memcpy(raw, frame->data, frame->datasize);
899
		raw += frame->datasize;
900
901
nextframe:
902
		curframe = curframe->next;
903
	}
904
	
905
	return TRUE;
906
}
907
908
/***************************************************************************************
909
 * END OF STATICS
910
 ***************************************************************************************/
911
912
913
914
915
916
917
918
/*
919
 * Purpose: Reads the ID3 tag from a file.
920
 * Parameters: tag - The structure to store the tag in, filename - The name of the file to operate on.
921
 * Returns:
922
 * 0 if successful,
923
 * 1 if an error occured when opening the file
924
 * 2 if error while reading tag.
925
 * 3 if no TAG found.
926
 */
927
int
928
get_id3v2_tag (id3Tag *tag, char *filename)
929
{
930
	id3v2Tag *v2 = calloc (1, sizeof(id3v2Tag));
931
	DLL *curframe = NULL;
932
	int error = 0;
933
	
934
// Read the tag.
935
	error = get_id3v2tag_raw (v2, filename);
936
	
937
// Init the users tag
938
	memset (tag, 0, sizeof (id3Tag));
939
	
940
	if( error == 0 )
941
	{
942
// if we have a valid tag we copy the raw data to the users struct
943
		tag->size = v2->tag_size;
944
		
945
		frame_find (v2, "TPE1", tag->artist);
946
		frame_find (v2, "TIT2", tag->title);
947
		frame_find (v2, "TALB", tag->album);
948
		frame_find (v2, "TYER", tag->year);
949
		frame_find (v2, "COMM", tag->comment);
950
		frame_find (v2, "TRCK", tag->track);
951
		frame_find (v2, "TCON", tag->genre);
952
		frame_find (v2, "TCOM", tag->composer);     // Composer
953
		frame_find (v2, "TOPE", tag->orig_artist);  // Original artist(s)/performer(s)
954
		frame_find (v2, "WCOM", tag->url);          // URL
955
		frame_find (v2, "TENC", tag->enc_by);       // Encoded by
956
	}
957
	
958
// Free all the stuff
959
	if (v2->frames)
960
	{
961
		id3v2Frame *frame = NULL;
962
		
963
		curframe = v2->frames;
964
		while ( curframe )
965
		{
966
			frame = (id3v2Frame *)curframe->data;
967
			
968
			free (frame->data);
969
			free (frame);
970
			
971
			curframe = curframe->next;
972
		}
973
		v2->frames = dll_free (v2->frames);
974
	}
975
	
976
	free (v2);
977
	return (error);
978
}
979
980
981
982
983
984
985
986
987
988
/*
989
 * Purpose: Clear the ID3 tag of a file.
990
 * Parameters: a filename.
991
 * Returns:
992
 * 0 if successful,
993
 * 1 if an error occured when opening the file
994
 * 2 if an error while reading/writing the tag.
995
 */
996
int
997
del_id3v2_tag (char *filename)
998
{
999
	id3v2Tag *v2 = calloc (1, sizeof(id3v2Tag));
1000
	long file_len;
1001
	FILE *file;
1002
	void *ptr;
1003
1004
// check if an valid old id3v2 tag is present
1005
// In these two error-cases we don't know how big the tag is.
1006
	if( get_id3v2tag_raw (v2, filename) == 1
1007
		|| get_id3v2tag_raw (v2, filename) == 2 )
1008
		return(0);
1009
	
1010
	ptr =  malloc (4096);
1011
1012
// open file read/write
1013
	file = fopen (filename, "r+b");
1014
	if (!file)
1015
		return (1);
1016
1017
	fseek (file, 0, SEEK_END);
1018
	file_len = ftell (file);
1019
	if ( file_len < 11
1020
		|| v2->tag_size < 11 )
1021
		return (2);
1022
1023
// set anything but the header in tag to zero. I'll not really remove the tag,
1024
// because this would be much slower and if we write a new tag, this would mean we´d have to
1025
// rewrite the complete tag.
1026
/*
1027
	fseek (file, 10, SEEK_SET);
1028
	for (read = 0; read < v2->tag_size - 10; read++)
1029
		fputc (0, file);
1030
1031
*/
1032
    {
1033
        FILE *file = NULL;
1034
        FILE *tempfile = NULL;
1035
        char *tempfilename = NULL;
1036
        int read = 0;
1037
        char buf[4096];
1038
	    int error = 0;
1039
1040
        // Open a tempfile
1041
        error = 2;
1042
        tempfilename = malloc (strlen (filename) + 11);
1043
        sprintf (tempfilename, "%s%s", filename, ".tempXXXXX");
1044
        if( !(tempfile = fopen(tempfilename, "wb")) )
1045
        {
1046
            remove (tempfilename);
1047
            free (tempfilename);
1048
            goto done;
1049
        }
1050
1051
        // Write the tag to the tempfile.
1052
1053
        // Open the mp3file.
1054
        error = 4;
1055
        if( !(file = fopen(filename, "r+b")) )
1056
        {
1057
            fclose (file);
1058
            remove (tempfilename);
1059
            free (tempfilename);
1060
            goto done;
1061
        }
1062
        // skip the old tag (if one existed)
1063
        fseek (file, v2->tag_size + 10, SEEK_SET);
1064
1065
        // copy the rest of the file to the tempfile.
1066
        while ( !feof(file) )
1067
        {
1068
            error = 5;
1069
            read = fread (buf, 1, 4096, file);
1070
            if( fwrite (buf, 1, read, tempfile) != read
1071
                    && !feof (file) )
1072
            {
1073
                remove (tempfilename);
1074
                free (tempfilename);
1075
                fflush (tempfile);
1076
                fclose (tempfile);
1077
                fflush (file);
1078
                fclose (file);
1079
                goto done;
1080
            }
1081
        }
1082
1083
        fflush (file);
1084
        fclose (file);
1085
        fflush (tempfile);
1086
        fclose (tempfile);
1087
1088
        // rename the tempfile, so it is the mp3file.
1089
        rename (tempfilename, filename);
1090
        free (tempfilename);
1091
	}
1092
1093
done:
1094
	if (v2) free (v2);
1095
	if (ptr) free (ptr);
1096
	
1097
	return(0);
1098
}
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
int
1111
set_id3v2_tag (id3Tag *tag, char *filename)
1112
{
1113
	id3v2Tag *v2 = malloc (sizeof(id3v2Tag));
1114
	id3v2Frame *frame = NULL;
1115
	unsigned char *rawdata = NULL;
1116
	DLL *curframe = NULL;
1117
	int oldsize = 0;
1118
	char track[3];
1119
	int error = 0;
1120
1121
// Try to get the content of an old tag
1122
	error = 1;
1123
	memset (v2, 0, sizeof(id3v2Tag));
1124
	get_id3v2tag_raw (v2, filename);
1125
	
1126
	oldsize = v2->tag_size;
1127
1128
// If the old tag had an extheader, I'll add its size to my tag, because i don't plan to add it again.
1129
	if ( v2->has_extheader )
1130
	{
1131
		v2->padding_size += v2->extheader_size;
1132
		v2->has_extheader = FALSE;
1133
		v2->extheader_size = 0;
1134
	}
1135
	
1136
// first of all I'll generate a valid id3v2 tag struct out of the tag struct we got by the user.
1137
// Set the flags...
1138
	v2->unsync = FALSE;
1139
	v2->is_experimental = FALSE;
1140
	v2->crc_data_present = FALSE;
1141
	
1142
// Set the contentframes
1143
	frame_set (v2, "TIT2", tag->title);
1144
	frame_set (v2, "TPE1", tag->artist);
1145
	frame_set (v2, "TALB", tag->album);
1146
	frame_set (v2, "TYER", tag->year);
1147
	frame_set (v2, "COMM", tag->comment);
1148
	frame_set (v2, "TCON", tag->genre);
1149
    frame_set (v2, "TCOM", tag->composer);     // Composer
1150
    frame_set (v2, "TOPE", tag->orig_artist);  // TOPE Original artist(s)/performer(s)
1151
    frame_set (v2, "WCOM", tag->url);          // URL
1152
    frame_set (v2, "TENC", tag->enc_by);       // Encoded by
1153
	if ( atoi (tag->track) < 10 )
1154
		snprintf (track, 3, "0%i", atoi(tag->track));
1155
	else
1156
		snprintf (track, 3, "%i", atoi(tag->track));
1157
	frame_set (v2, "TRCK", track);
1158
	
1159
// Create a header in the raw data string
1160
	rawdata = calloc (1, v2->tag_size + 10);
1161
	create_header_raw (rawdata, v2);
1162
1163
// Create frames raw data.
1164
	create_frames_raw (rawdata, v2);
1165
	
1166
// is the new tag bigger than the old one? Then we'll have to completely rewrite the file...
1167
	if ( v2->tag_size > oldsize )
1168
	{
1169
		FILE *file = NULL;
1170
		FILE *tempfile = NULL;
1171
		char *tempfilename = NULL;
1172
		int read = 0;
1173
		char buf[4096];
1174
1175
// Open a tempfile
1176
		error = 2;
1177
		tempfilename = malloc (strlen (filename) + 11);
1178
		sprintf (tempfilename, "%s%s", filename, ".tempXXXXX");
1179
		if( !(tempfile = fopen(tempfilename, "wb")) )
1180
		{
1181
			remove (tempfilename);
1182
			free (tempfilename);
1183
			goto done;
1184
		}
1185
		
1186
// Write the tag to the tempfile.
1187
		error = 3;
1188
		fseek (tempfile, 0, SEEK_SET);
1189
		if( fwrite (rawdata, 1, v2->tag_size + 10, tempfile) < v2->tag_size )
1190
		{
1191
			fclose (tempfile);
1192
			remove (tempfilename);
1193
			free (tempfilename);
1194
			goto done;
1195
		}
1196
		
1197
// Open the mp3file.
1198
		error = 4;
1199
		if( !(file = fopen(filename, "r+b")) )
1200
		{
1201
			fclose (file);
1202
			remove (tempfilename);
1203
			free (tempfilename);
1204
			goto done;
1205
		}
1206
// skip the old tag (if one existed)
1207
		fseek (file, oldsize? oldsize + 10 : oldsize, SEEK_SET);
1208
		
1209
// copy the rest of the file to the tempfile.
1210
		while ( !feof(file) )
1211
		{
1212
			error = 5;
1213
			read = fread (buf, 1, 4096, file);
1214
			if( fwrite (buf, 1, read, tempfile) != read
1215
				&& !feof (file) )
1216
			{
1217
				remove (tempfilename);
1218
				free (tempfilename);
1219
				fflush (tempfile);
1220
				fclose (tempfile);
1221
				fflush (file);
1222
				fclose (file);
1223
				goto done;
1224
			}
1225
		}
1226
1227
		fflush (file);
1228
		fclose (file);
1229
		fflush (tempfile);
1230
		fclose (tempfile);
1231
		
1232
// rename the tempfile, so it is the mp3file.
1233
		rename (tempfilename, filename);
1234
		free (tempfilename);
1235
	}
1236
	else
1237
	{
1238
		FILE *file = NULL;
1239
		
1240
// If the old tag was bigger than the new one, we can simply overwrite it!
1241
// open.
1242
		error = 10;
1243
		if( !(file = fopen(filename, "r+b")) )
1244
			goto done;
1245
1246
// write.
1247
		error = 11;
1248
		fseek (file, 0, SEEK_SET);
1249
		if( fwrite (rawdata, 1, v2->tag_size + 10, file) < v2->tag_size )
1250
		{
1251
			fflush (file);
1252
			fclose (file);
1253
			goto done;
1254
		}
1255
		
1256
		fflush (file);
1257
		fclose (file);
1258
	}
1259
	
1260
	error = 0;
1261
	
1262
done:
1263
// Free all the stuff
1264
	curframe = v2->frames;
1265
	while ( curframe )
1266
	{
1267
		frame = (id3v2Frame *)curframe->data;
1268
		
1269
		free (frame->data);
1270
		free (frame);
1271
		
1272
		curframe = curframe->next;
1273
	}
1274
	dll_free (v2->frames);
1275
1276
	if ( rawdata != NULL )
1277
		free (rawdata);
1278
	free (v2);
1279
	return (error);
1280
}
(-)xmms-1.2.10.orig/Input/mpg123/mpg123.c (-2 / +11 lines)
Lines 607-614 Link Here
607
{									\
607
{									\
608
	id3frm = id3_get_frame( id3d, _tid, 1 );			\
608
	id3frm = id3_get_frame( id3d, _tid, 1 );			\
609
	if (id3frm) {							\
609
	if (id3frm) {							\
610
		txt = _tid == ID3_TCON ? id3_get_content(id3frm)	\
610
        if (_tid == ID3_COMM)                           \
611
		    : id3_get_text(id3frm);				\
611
            txt = id3_get_comm(id3frm);                          \
612
        else if (id3frm->fr_desc->fd_idstr[0] == 'W')        \
613
            txt = id3_get_url(id3frm);                   \
614
        else                                            \
615
            txt = _tid == ID3_TCON ? id3_get_content(id3frm)	\
616
		        : id3_get_text(id3frm);				\
612
		if(txt)							\
617
		if(txt)							\
613
		{							\
618
		{							\
614
			tlen = strlen(txt);				\
619
			tlen = strlen(txt);				\
Lines 644-649 Link Here
644
	ID3_SET_NUM	(ID3_TRCK, track_number);
649
	ID3_SET_NUM	(ID3_TRCK, track_number);
645
	ID3_SET		(ID3_COMM, comment);
650
	ID3_SET		(ID3_COMM, comment);
646
	ID3_SET		(ID3_TCON, genre);
651
	ID3_SET		(ID3_TCON, genre);
652
	ID3_SET		(ID3_TCOM, composer);
653
	ID3_SET		(ID3_TOPE, orig_artist);
654
	ID3_SET		(ID3_WCOM, url);
655
	ID3_SET		(ID3_TENC, encoded_by);
647
}
656
}
648
657
649
/*
658
/*
(-)xmms-1.2.10.orig/Input/mpg123/mpg123.h (+4 lines)
Lines 78-83 Link Here
78
	char genre[256];
78
	char genre[256];
79
	int year;
79
	int year;
80
	int track_number;
80
	int track_number;
81
    char composer[1024];
82
    char orig_artist[1024];
83
    char url[1024];
84
    char encoded_by[1024];
81
};
85
};
82
86
83
typedef struct
87
typedef struct

Return to bug 7555