comparison src/madplug/tuple.c @ 2202:f76e846d53d9

updating TLEN frame returned
author Eugene Zagidullin <e.asphyx@gmail.com>
date Mon, 03 Dec 2007 01:26:57 +0300
parents src/madplug/tuples.c@df520f828dcf
children 13b8ab116b69
comparison
equal deleted inserted replaced
2201:df520f828dcf 2202:f76e846d53d9
1 /*
2 * mad plugin for audacious
3 * Copyright (C) 2005-2007 William Pitcock, Yoshiki Yazawa, Eugene Zagidullin
4 *
5 * Portions derived from xmms-mad:
6 * Copyright (C) 2001-2002 Sam Clegg - See COPYING
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; under version 2 of the License.
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 #include "config.h"
23
24 #include "plugin.h"
25 #include "tuple.h"
26 #include "input.h"
27
28 #include <math.h>
29 #include <string.h>
30
31 #include <glib.h>
32 #include <glib/gprintf.h>
33
34 #include <audacious/util.h>
35 #include <audacious/plugin.h>
36 #include <audacious/id3tag.h>
37
38 /* yaz */
39 #include <langinfo.h>
40
41 #define DEBUG
42
43 static void
44 update_id3_frame(struct id3_tag *tag, const char *frame_name, const char *data, int sjis)
45 {
46 int res;
47 struct id3_frame *frame;
48 union id3_field *field;
49 id3_ucs4_t *ucs4;
50
51 if (data == NULL)
52 return;
53
54 // printf ("updating id3: %s: %s\n", frame_name, data);
55
56 //
57 // An empty string removes the frame altogether.
58 //
59 if (strlen(data) == 0) {
60 while ((frame = id3_tag_findframe(tag, frame_name, 0))) {
61 #ifdef DEBUG
62 fprintf(stderr, "madplug: detachframe\n");
63 #endif
64 id3_tag_detachframe(tag, frame);
65 }
66 return;
67 }
68
69 frame = id3_tag_findframe(tag, frame_name, 0);
70 if (!frame) {
71 #ifdef DEBUG
72 printf("frame_new\n");
73 #endif
74 frame = id3_frame_new(frame_name);
75 id3_tag_attachframe(tag, frame);
76 }
77
78 // setup ucs4 string
79 if(sjis) {
80 ucs4 = id3_latin1_ucs4duplicate((id3_latin1_t *) data);
81 }
82 else {
83 ucs4 = id3_utf8_ucs4duplicate((id3_utf8_t *) data);
84 }
85
86 // set encoding
87 field = id3_frame_field(frame, 0);
88 id3_field_settextencoding(field, sjis ? ID3_FIELD_TEXTENCODING_ISO_8859_1 :
89 ID3_FIELD_TEXTENCODING_UTF_8);
90
91 // setup genre code
92 if (!strcmp(frame_name, ID3_FRAME_GENRE)) {
93 char *tmp;
94 int index = id3_genre_number(ucs4);
95 g_free(ucs4);
96
97 if(index == -1) { // unknown genre. remove TCON frame.
98 #ifdef DEBUG
99 fprintf(stderr, "madplug: remove genre frame\n");
100 #endif
101 id3_tag_detachframe(tag, frame);
102 }
103 else { // meaningful genre
104 tmp = g_strdup_printf("%d", index);
105 ucs4 = id3_latin1_ucs4duplicate((unsigned char *) tmp);
106 }
107
108 }
109
110 // write string
111 if (!strcmp(frame_name, ID3_FRAME_COMMENT)) {
112 field = id3_frame_field(frame, 3);
113 field->type = ID3_FIELD_TYPE_STRINGFULL;
114 res = id3_field_setfullstring(field, ucs4);
115 }
116 else {
117 field = id3_frame_field(frame, 1);
118 field->type = ID3_FIELD_TYPE_STRINGLIST;
119 res = id3_field_setstrings(field, 1, &ucs4);
120 }
121
122 if (res != 0)
123 g_print("error setting id3 field: %s\n", frame_name);
124 }
125
126 static void
127 update_id3_frame_from_tuple(struct id3_tag *id3tag, const char *field, Tuple *tuple, int fieldn, int sjis)
128 {
129 int val;
130 char *text, *text2;
131 const char *encoding = sjis ? "SJIS" : "UTF-8";
132
133 if(aud_tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_INT) {
134 val = aud_tuple_get_int(tuple, fieldn, NULL);
135 if(val > 0) {
136 text2 = g_strdup_printf("%d", val);
137 #ifdef DEBUG
138 fprintf(stderr, "madplug: updating field:\"%s\"=\"%s\", enc %s\n", field, text2, encoding);
139 #endif
140 update_id3_frame(id3tag, field, text2, 0);
141 g_free(text2);
142 } else {
143 update_id3_frame(id3tag, field, "", 0); /* will be detached */
144 }
145
146 } else if(aud_tuple_get_value_type(tuple, fieldn, NULL) == TUPLE_STRING) {
147 text = (char*)aud_tuple_get_string(tuple, fieldn, NULL);
148 text2 = g_convert(text, strlen(text), encoding, "UTF-8", NULL, NULL, NULL);
149 #ifdef DEBUG
150 fprintf(stderr, "madplug: updating field:\"%s\"=\"%s\", enc %s\n", field, text2, encoding);
151 #endif
152 update_id3_frame(id3tag, field, text2, sjis);
153 g_free(text2);
154 }
155 }
156
157 gboolean
158 audmad_update_song_tuple(Tuple *tuple, VFSFile *fd)
159 {
160 struct id3_file *id3file;
161 struct id3_tag *id3tag;
162 gchar *text;
163 struct mad_info_t songinfo;
164
165 if ((id3file = id3_file_vfsopen(fd, ID3_FILE_MODE_READWRITE)) == NULL) return FALSE;
166
167 id3tag = id3_file_tag(id3file);
168 if (!id3tag) {
169 #ifdef DEBUG
170 fprintf(stderr, "no id3tag\n. append new tag.\n");
171 #endif
172 id3tag = id3_tag_new();
173 id3_tag_clearframes(id3tag);
174 id3tag->options |= ID3_TAG_OPTION_APPENDEDTAG | ID3_TAG_OPTION_ID3V1;
175 }
176
177 id3_tag_options(id3tag, ID3_TAG_OPTION_ID3V1, ~0); /* enables id3v1. TODO: make id3v1 optional */
178
179 update_id3_frame_from_tuple(id3tag, ID3_FRAME_TITLE, tuple, FIELD_TITLE, audmad_config.sjis);
180 update_id3_frame_from_tuple(id3tag, ID3_FRAME_ARTIST, tuple, FIELD_ARTIST, audmad_config.sjis);
181 update_id3_frame_from_tuple(id3tag, ID3_FRAME_ALBUM, tuple, FIELD_ALBUM, audmad_config.sjis);
182 update_id3_frame_from_tuple(id3tag, ID3_FRAME_YEAR, tuple, FIELD_YEAR, audmad_config.sjis);
183 update_id3_frame_from_tuple(id3tag, ID3_FRAME_COMMENT, tuple, FIELD_COMMENT, audmad_config.sjis);
184 update_id3_frame_from_tuple(id3tag, ID3_FRAME_TRACK, tuple, FIELD_TRACK_NUMBER, audmad_config.sjis);
185 update_id3_frame_from_tuple(id3tag, ID3_FRAME_GENRE, tuple, FIELD_GENRE, audmad_config.sjis);
186
187 if(!id3_tag_findframe(id3tag, "TLEN", 0) && input_init(&songinfo, fd->uri, fd) && !songinfo.remote) {
188 #ifdef DEBUG
189 fprintf(stderr, "update TLEN frame\n");
190 #endif
191 songinfo.fileinfo_request = FALSE; /* we don't need to read tuple again */
192 input_get_info(&songinfo, FALSE);
193 text = g_strdup_printf("%ld", mad_timer_count(songinfo.duration, MAD_UNITS_MILLISECONDS));
194 #ifdef DEBUG
195 fprintf(stderr, "TLEN: \"%s\"\n", text);
196 #endif
197 update_id3_frame(id3tag, "TLEN", text, 0);
198 g_free(text);
199 input_term(&songinfo);
200 }
201
202 if (id3_file_update(id3file) != 0) return FALSE;
203
204 id3_file_close(id3file);
205 return TRUE;
206 }
207
208 /*#endif // !NOGUI
209
210 void audmad_get_file_info(char *fileurl)
211 {
212 #ifndef NOGUI
213 gchar *title;
214 gchar message[128];
215 static char const *const layer_str[3] = { "I", "II", "III" };
216 static char const *const mode_str[4] = {
217 ("single channel"), ("dual channel"), "joint stereo", "stereo"
218 };
219 gchar *tmp, *utf_filename;
220 gchar *realfn = NULL;
221 #ifdef DEBUG
222 {
223 tmp = aud_str_to_utf8(fileurl);
224 g_message("f: audmad_get_file_info: %s", tmp);
225 g_free(tmp);
226 tmp = NULL;
227 }
228 #endif
229
230 if(!aud_vfs_is_remote(fileurl) && !aud_vfs_file_test(fileurl, G_FILE_TEST_EXISTS)) {
231 return;
232 }
233
234 input_init(&info, fileurl, NULL);
235
236 if(audmad_is_remote(fileurl)) {
237 info.remote = TRUE;
238 if(aud_vfs_is_streaming(info.infile))
239 return; //file info dialog for remote streaming doesn't make sense.
240 }
241
242 realfn = g_filename_from_uri(fileurl, NULL, NULL);
243 utf_filename = aud_str_to_utf8(realfn ? realfn : fileurl);
244 g_free(realfn); realfn = NULL;
245 create_window();
246
247 info.fileinfo_request = TRUE;
248 input_get_info(&info, info.remote ? TRUE : FALSE);
249
250 tmp = g_path_get_basename(utf_filename);
251 title = g_strdup_printf(_("File Info - %s"), tmp);
252 g_free(tmp); tmp = NULL;
253 gtk_window_set_title(GTK_WINDOW(window), title);
254 g_free(title);
255
256 gtk_entry_set_text(GTK_ENTRY(filename_entry), utf_filename);
257 gtk_editable_set_position(GTK_EDITABLE(filename_entry), -1);
258
259 free(utf_filename);
260
261 id3_frame_to_entry(ID3_FRAME_ARTIST, GTK_ENTRY(artist_entry));
262 id3_frame_to_entry(ID3_FRAME_TITLE, GTK_ENTRY(title_entry));
263 id3_frame_to_entry(ID3_FRAME_ALBUM, GTK_ENTRY(album_entry));
264
265 // year
266 // id3_frame_to_entry (ID3_FRAME_YEAR, GTK_ENTRY (year_entry));
267 // to set year entry, we have to do manually because TYER is still used equally to TDRC.
268 gtk_entry_set_text(GTK_ENTRY(year_entry), "");
269 if (info.tag) {
270 gchar *text = NULL;
271 text = input_id3_get_string(info.tag, "TDRC");
272 if (!text)
273 text = input_id3_get_string(info.tag, "TYER");
274 if (text) {
275 gtk_entry_set_text(GTK_ENTRY(year_entry), text);
276 g_free(text);
277 }
278 }
279
280 id3_frame_to_entry(ID3_FRAME_TRACK, GTK_ENTRY(tracknum_entry));
281 id3_frame_to_entry(ID3_FRAME_COMMENT, GTK_ENTRY(comment_entry));
282 snprintf(message, 127, _("Layer %s"), layer_str[info.mpeg_layer - 1]);
283 gtk_label_set_text(GTK_LABEL(mpeg_level), message);
284 if (info.vbr) {
285 snprintf(message, 127, _("VBR (avg. %d kbps)"), info.bitrate / 1000);
286 }
287 else {
288 snprintf(message, 127, "%d kbps", info.bitrate / 1000);
289 }
290 gtk_label_set_text(GTK_LABEL(mpeg_bitrate), message);
291 snprintf(message, 127, _("%d Hz"), info.freq);
292 gtk_label_set_text(GTK_LABEL(mpeg_samplerate), message);
293 if (info.frames != -1) {
294 snprintf(message, 127, _("%d frames"), info.frames);
295 gtk_label_set_text(GTK_LABEL(mpeg_frames), message);
296 }
297 else {
298 gtk_label_set_text(GTK_LABEL(mpeg_frames), "");
299 }
300 gtk_label_set_text(GTK_LABEL(mpeg_flags), mode_str[info.mode]);
301 {
302 guint sec = mad_timer_count(info.duration, MAD_UNITS_SECONDS);
303 snprintf(message, 127, _("%d:%02d (%d seconds)"), sec /60 ,sec % 60, sec);
304 }
305 gtk_label_set_text(GTK_LABEL(mpeg_duration), message);
306
307 if (info.replaygain_album_str != NULL) {
308 snprintf(message, 127, _("RG_album=%4s (x%4.2f)"),
309 info.replaygain_album_str, info.replaygain_album_scale);
310 gtk_label_set_text(GTK_LABEL(mpeg_replaygain), message);
311 }
312 else
313 gtk_label_set_text(GTK_LABEL(mpeg_replaygain), "");
314
315 if (info.replaygain_track_str != NULL) {
316 snprintf(message, 127, _("RG_track=%4s (x%4.2f)"),
317 info.replaygain_track_str, info.replaygain_track_scale);
318 gtk_label_set_text(GTK_LABEL(mpeg_replaygain2), message);
319 }
320 else
321 gtk_label_set_text(GTK_LABEL(mpeg_replaygain2), "");
322
323 if (info.replaygain_album_peak_str != NULL) {
324 snprintf(message, 127, _("Peak album=%4s (%+5.3fdBFS)"),
325 info.replaygain_album_peak_str,
326 20 * log10(info.replaygain_album_peak));
327 gtk_label_set_text(GTK_LABEL(mpeg_replaygain3), message);
328 }
329 else
330 gtk_label_set_text(GTK_LABEL(mpeg_replaygain3), "");
331
332 if (info.replaygain_track_peak_str != NULL) {
333 snprintf(message, 127, _("Peak track=%4s (%+5.3fdBFS)"),
334 info.replaygain_track_peak_str,
335 20 * log10(info.replaygain_track_peak));
336 gtk_label_set_text(GTK_LABEL(mpeg_replaygain4), message);
337 }
338 else
339 gtk_label_set_text(GTK_LABEL(mpeg_replaygain3), "");
340
341 if (info.mp3gain_undo_str != NULL) {
342 snprintf(message, 127, _("mp3gain undo=%4s (%+5.3fdB)"),
343 info.mp3gain_undo_str, info.mp3gain_undo);
344 gtk_label_set_text(GTK_LABEL(mp3gain1), message);
345 }
346 else
347 gtk_label_set_text(GTK_LABEL(mp3gain1), "");
348
349 if (info.mp3gain_minmax_str != NULL) {
350 snprintf(message, 127, _("mp3gain minmax=%4s (max-min=%+6.3fdB)"),
351 info.mp3gain_minmax_str, info.mp3gain_minmax);
352 gtk_label_set_text(GTK_LABEL(mp3gain2), message);
353 }
354 else
355 gtk_label_set_text(GTK_LABEL(mp3gain2), "");
356
357 gtk_label_set_text(GTK_LABEL(mpeg_fileinfo), "");
358
359
360 // work out the index of the genre in the list
361 {
362 const id3_ucs4_t *string;
363 id3_ucs4_t *genre;
364 struct id3_frame *frame;
365 union id3_field *field;
366 frame = id3_tag_findframe(info.tag, ID3_FRAME_GENRE, 0);
367 if (frame) {
368 field = id3_frame_field(frame, 1);
369 string = id3_field_getstrings(field, 0);
370 genre = mad_parse_genre(string);
371 #ifdef DEBUG
372 if (genre) {
373 gchar *utf = (gchar *)id3_ucs4_utf8duplicate(genre);
374 g_print("genre = %s\n", utf);
375 g_print("genre num = %d\n", id3_genre_number(genre));
376 g_free(utf);
377 }
378 #endif
379 if (genre) {
380 gtk_list_select_item(GTK_LIST
381 (GTK_COMBO(genre_combo)->list),
382 id3_genre_number(genre)+1); //shift one for "Unknown".
383 g_free((void *)genre);
384 }
385 }
386 }
387
388 gtk_widget_set_sensitive(id3_frame, TRUE);
389
390 #endif // !NOGUI
391 }*/
392