1 #include <config.h>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <errno.h>
6 #include <glib.h>
7 #include <glib/gi18n.h>
8 #include <gtk/gtk.h>
9 #include <gdk/gdkkeysyms.h>
10 #include <glade/glade.h>
11
12 #include "elist.h"
13 #include "gtk_util.h"
14 #include "mru.h"
15 #include "prefs.h"
16 #include "file_list.h"
17 #include "message_box.h"
18 #include "cursor.h"
19 #include "genre.h"
20 #include "mpeg_file.h"
21 #include "mpeg_edit_field.h"
22
23 #include "mpeg_edit.h"
24
25
26 /* widgets */
27 static GtkWindow *w_main = NULL;
28 static GtkNotebook *nb_edit = NULL;
29 static GtkNotebook *nb_id3 = NULL;
30 static GtkNotebook *nb_id3v1 = NULL;
31 static GtkNotebook *nb_id3v2 = NULL;
32 static GtkMenuItem *m_id3 = NULL;
33 static GtkCheckMenuItem *m_id3v2_view_simple = NULL;
34 static GtkCheckMenuItem *m_id3v2_view_advanced = NULL;
35 static GtkMenuItem *m_id3_copyv1tov2 = NULL;
36 static GtkMenuItem *m_id3_copyv2tov1 = NULL;
37 static GtkButton *b_write_tag = NULL;
38 static GtkButton *b_remove_tag = NULL;
39
40 static GtkButton *b_id3v1_create_tag = NULL;
41 static GtkEntry *ent_id3v1_title = NULL;
42 static GtkEntry *ent_id3v1_artist = NULL;
43 static GtkEntry *ent_id3v1_album = NULL;
44 static GtkEntry *ent_id3v1_year = NULL;
45 static GtkEntry *ent_id3v1_comment = NULL;
46 static GtkSpinButton *spin_id3v1_track = NULL;
47 static GtkCombo *combo_id3v1_genre = NULL;
48 static GtkLabel *lab_id3v1_title = NULL;
49 static GtkLabel *lab_id3v1_artist = NULL;
50 static GtkLabel *lab_id3v1_album = NULL;
51 static GtkLabel *lab_id3v1_year = NULL;
52 static GtkLabel *lab_id3v1_comment = NULL;
53 static GtkLabel *lab_id3v1_track = NULL;
54 static GtkLabel *lab_id3v1_genre = NULL;
55
56 static GtkButton *b_id3v2_create_tag = NULL;
57 static GtkEntry *ent_id3v2_title = NULL;
58 static GtkEntry *ent_id3v2_artist = NULL;
59 static GtkEntry *ent_id3v2_album = NULL;
60 static GtkEntry *ent_id3v2_year = NULL;
61 static GtkTextView *text_id3v2_comment = NULL;
62 static GtkEntry *ent_id3v2_track = NULL;
63 static GtkCombo *combo_id3v2_genre = NULL;
64 static GtkLabel *lab_id3v2_title = NULL;
65 static GtkLabel *lab_id3v2_artist = NULL;
66 static GtkLabel *lab_id3v2_album = NULL;
67 static GtkLabel *lab_id3v2_year = NULL;
68 static GtkLabel *lab_id3v2_comment = NULL;
69 static GtkLabel *lab_id3v2_track = NULL;
70 static GtkLabel *lab_id3v2_genre = NULL;
71 static GtkLabel *lab_id3v2_advanced = NULL;
72
73 static GtkTreeView *tv_id3v2_frames = NULL;
74 static GtkListStore *store_id3v2_frames = NULL;
75 static GtkButton *b_id3v2_add = NULL;
76 static GtkButton *b_id3v2_edit = NULL;
77 static GtkButton *b_id3v2_remove = NULL;
78
79 static GtkImage *img_id3v1_tab = NULL;
80 static GtkImage *img_id3v2_tab = NULL;
81 static GdkPixbuf *pix_graydot;
82 static GdkPixbuf *pix_greendot;
83
84
85 /* the various notebook tabs */
86 #define TAB_ID3_V1 0
87 #define TAB_ID3_V2 1
88 #define TAB_ID3V1_NOTAG 0
89 #define TAB_ID3V1_TAG 1
90 #define TAB_ID3V2_NOTAG 0
91 #define TAB_ID3V2_SIMPLE 1
92 #define TAB_ID3V2_ADVANCED 2
93
94 /* private data */
95 static int tab_edit_id3;
96 static gboolean changed_flag = TRUE;
97 static gboolean editable_flag = TRUE;
98 static gboolean ignore_changed_signals = FALSE;
99 static mpeg_file *file = NULL;
100
101 /* preferences */
102 static MRUList *genre_mru;
103 static int *current_tab;
104
105
106 /*** private functions ******************************************************/
107
tree_view_setup()108 static void tree_view_setup()
109 {
110 GtkTreeViewColumn *col;
111 GtkCellRenderer *renderer;
112
113 /* model */
114 store_id3v2_frames = gtk_list_store_new(3, G_TYPE_STRING, G_TYPE_STRING, G_TYPE_POINTER);
115
116 /* columns and renderers */
117 col = gtk_tree_view_column_new();
118 gtk_tree_view_column_set_title(col, _("Field"));
119 gtk_tree_view_append_column(tv_id3v2_frames, col);
120
121 renderer = gtk_cell_renderer_text_new();
122 g_object_set(renderer, "ypad", 0, NULL);
123 gtk_tree_view_column_pack_start(col, renderer, FALSE);
124 gtk_tree_view_column_add_attribute(col, renderer, "text", 0);
125
126 col = gtk_tree_view_column_new();
127 gtk_tree_view_column_set_title(col, _("Text"));
128 gtk_tree_view_append_column(tv_id3v2_frames, col);
129
130 renderer = gtk_cell_renderer_text_new();
131 g_object_set(renderer, "ypad", 0, NULL);
132 gtk_tree_view_column_pack_start(col, renderer, FALSE);
133 gtk_tree_view_column_add_attribute(col, renderer, "text", 1);
134
135 /* selection mode */
136 gtk_tree_selection_set_mode(gtk_tree_view_get_selection(tv_id3v2_frames),
137 GTK_SELECTION_SINGLE);
138 }
139
set_changed_flag(gboolean value)140 static void set_changed_flag(gboolean value)
141 {
142 if (changed_flag == value)
143 return;
144
145 changed_flag = value;
146 gtk_widget_set_sensitive(GTK_WIDGET(b_write_tag), value);
147 }
148
set_editable_flag(gboolean value)149 static void set_editable_flag(gboolean value)
150 {
151 if (editable_flag == value)
152 return;
153
154 editable_flag = value;
155 gtk_widget_set_sensitive(GTK_WIDGET(b_remove_tag), value);
156
157 /* v1 edit controls */
158 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v1_create_tag), value);
159 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v1_title), value);
160 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v1_title), value);
161 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v1_artist), value);
162 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v1_artist), value);
163 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v1_album), value);
164 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v1_album), value);
165 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v1_year), value);
166 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v1_year), value);
167 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v1_comment), value);
168 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v1_comment), value);
169 gtk_widget_set_sensitive(GTK_WIDGET(combo_id3v1_genre), value);
170 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v1_genre), value);
171 gtk_widget_set_sensitive(GTK_WIDGET(spin_id3v1_track), value);
172 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v1_track), value);
173 gtk_widget_set_sensitive(GTK_WIDGET(m_id3_copyv1tov2), value);
174
175 /* v2 simple edit controls */
176 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_create_tag), value);
177 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v2_title), value);
178 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v2_title), value);
179 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v2_artist), value);
180 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v2_artist), value);
181 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v2_album), value);
182 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v2_album), value);
183 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v2_year), value);
184 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v2_year), value);
185 gtk_widget_set_sensitive(GTK_WIDGET(text_id3v2_comment), value);
186 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v2_comment), value);
187 gtk_widget_set_sensitive(GTK_WIDGET(combo_id3v2_genre), value);
188 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v2_genre), value);
189 gtk_widget_set_sensitive(GTK_WIDGET(ent_id3v2_track), value);
190 gtk_widget_set_sensitive(GTK_WIDGET(lab_id3v2_track), value);
191 gtk_widget_set_sensitive(GTK_WIDGET(m_id3_copyv2tov1), value);
192
193 /* v2 advanced edit controls */
194 gtk_widget_set_sensitive(GTK_WIDGET(tv_id3v2_frames), value);
195 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_add), value);
196 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_edit), value);
197 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_remove), value);
198 }
199
update_form_v1()200 static void update_form_v1()
201 {
202 const gchar *str;
203
204 if (mpeg_file_has_tag_v(file, ID3TT_ID3V1)) {
205 gtk_notebook_set_page(nb_id3v1, TAB_ID3V1_TAG);
206
207 ignore_changed_signals = TRUE;
208 mpeg_file_get_field_v(file, ID3TT_ID3V1, AF_TITLE, &str);
209 gtk_entry_set_text(ent_id3v1_title, str);
210 mpeg_file_get_field_v(file, ID3TT_ID3V1, AF_ARTIST, &str);
211 gtk_entry_set_text(ent_id3v1_artist, str);
212 mpeg_file_get_field_v(file, ID3TT_ID3V1, AF_ALBUM, &str);
213 gtk_entry_set_text(ent_id3v1_album, str);
214 mpeg_file_get_field_v(file, ID3TT_ID3V1, AF_YEAR, &str);
215 gtk_entry_set_text(ent_id3v1_year, str);
216 mpeg_file_get_field_v(file, ID3TT_ID3V1, AF_COMMENT, &str);
217 gtk_entry_set_text(ent_id3v1_comment, str);
218 mpeg_file_get_field_v(file, ID3TT_ID3V1, AF_TRACK, &str);
219 gtk_spin_button_set_value(spin_id3v1_track, atoi(str));
220 mpeg_file_get_field_v(file, ID3TT_ID3V1, AF_GENRE, &str);
221 gtk_entry_set_text(GTK_ENTRY(combo_id3v1_genre->entry), str);
222 ignore_changed_signals = FALSE;
223 }
224 else {
225 gtk_notebook_set_page(nb_id3v1, TAB_ID3V1_NOTAG);
226 }
227
228 set_editable_flag(audio_file_is_editable((audio_file *)file));
229 }
230
update_form_v2()231 static void update_form_v2()
232 {
233 const gchar *str;
234
235 if (mpeg_file_has_tag_v(file, ID3TT_ID3V2)) {
236 gtk_notebook_set_page(nb_id3v2, *current_tab);
237
238 if (*current_tab == TAB_ID3V2_SIMPLE) {
239 int extra_fields;
240 ID3Frame **frames;
241 int nframes;
242 int i;
243
244 ignore_changed_signals = TRUE;
245 if (g_elist_length(genre_mru->list) > 0)
246 gtk_combo_set_popdown_strings(combo_id3v2_genre, GLIST(genre_mru->list));
247 mpeg_file_get_field_v(file, ID3TT_ID3V2, AF_TITLE, &str);
248 gtk_entry_set_text(ent_id3v2_title, str);
249 mpeg_file_get_field_v(file, ID3TT_ID3V2, AF_ARTIST, &str);
250 gtk_entry_set_text(ent_id3v2_artist, str);
251 mpeg_file_get_field_v(file, ID3TT_ID3V2, AF_ALBUM, &str);
252 gtk_entry_set_text(ent_id3v2_album, str);
253 mpeg_file_get_field_v(file, ID3TT_ID3V2, AF_YEAR, &str);
254 gtk_entry_set_text(ent_id3v2_year, str);
255 mpeg_file_get_field_v(file, ID3TT_ID3V2, AF_COMMENT, &str);
256 gtk_text_buffer_set_text(gtk_text_view_get_buffer(text_id3v2_comment), str, -1);
257 mpeg_file_get_field_v(file, ID3TT_ID3V2, AF_TRACK, &str);
258 gtk_entry_set_text(ent_id3v2_track, str);
259 mpeg_file_get_field_v(file, ID3TT_ID3V2, AF_GENRE, &str);
260 gtk_entry_set_text(GTK_ENTRY(combo_id3v2_genre->entry), str);
261 ignore_changed_signals = FALSE;
262
263 /* Show in the "Advanced" button label how many fields are not visible */
264 extra_fields = 0;
265 nframes = mpeg_file_get_frames(file, ID3TT_ID3V2, &frames);
266 for (i = 0; i < nframes; i++) {
267 gboolean is_simple;
268 mpeg_file_get_frame_info(ID3Frame_GetID(frames[i]), NULL, NULL, NULL, &is_simple);
269 if (!is_simple)
270 extra_fields++;
271 }
272
273 if (extra_fields > 0) {
274 char str[16];
275 snprintf(str, sizeof(str), _("Advanced (%i)"), extra_fields);
276 gtk_label_set_text(lab_id3v2_advanced, str);
277 }
278 else {
279 gtk_label_set_text(lab_id3v2_advanced, _("Advanced"));
280 }
281 }
282 else {
283 ID3Frame **frames;
284 int nframes;
285 int i;
286
287 nframes = mpeg_file_get_frames(file, ID3TT_ID3V2, &frames);
288
289 /* fill in the list */
290 gtk_tree_view_set_model(tv_id3v2_frames, NULL);
291 gtk_list_store_clear(store_id3v2_frames);
292
293 for (i = 0; i < nframes; i++) {
294 char short_desc[64];
295 const char *value;
296 const char *desc, *p;
297 GtkTreeIter iter;
298
299 mpeg_file_get_frame_info(ID3Frame_GetID(frames[i]), NULL, &desc, NULL, NULL);
300 p = strchr(desc, '/');
301 snprintf(short_desc, sizeof(short_desc), "%.*s", (p ? p-desc : sizeof(short_desc)), desc);
302
303 mpeg_file_get_frame_text(file, ID3TT_ID3V2, frames[i], &value);
304 if (value == NULL)
305 value = "[non-text field]";
306
307 gtk_list_store_append(store_id3v2_frames, &iter);
308 gtk_list_store_set(store_id3v2_frames, &iter,
309 0, short_desc,
310 1, value,
311 2, frames[i],
312 -1);
313 }
314 gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(store_id3v2_frames), 0, GTK_SORT_ASCENDING);
315
316 gtk_tree_view_set_model(tv_id3v2_frames, GTK_TREE_MODEL(store_id3v2_frames));
317
318 free(frames);
319
320 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_edit), FALSE);
321 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_remove), FALSE);
322 }
323 }
324 else {
325 gtk_notebook_set_page(nb_id3v2, TAB_ID3V2_NOTAG);
326 }
327
328 set_editable_flag(audio_file_is_editable((audio_file *)file));
329 }
330
update_tag_from_form_v1(int tag)331 static void update_tag_from_form_v1(int tag)
332 {
333 mpeg_file_set_field_v(file, tag, AF_TITLE, gtk_entry_get_text(ent_id3v1_title));
334 mpeg_file_set_field_v(file, tag, AF_ARTIST, gtk_entry_get_text(ent_id3v1_artist));
335 mpeg_file_set_field_v(file, tag, AF_ALBUM, gtk_entry_get_text(ent_id3v1_album));
336 mpeg_file_set_field_v(file, tag, AF_YEAR, gtk_entry_get_text(ent_id3v1_year));
337 mpeg_file_set_field_v(file, tag, AF_COMMENT, gtk_entry_get_text(ent_id3v1_comment));
338 mpeg_file_set_field_v(file, tag, AF_TRACK, gtk_entry_get_text(GTK_ENTRY(spin_id3v1_track)));
339 mpeg_file_set_field_v(file, tag, AF_GENRE, gtk_entry_get_text(GTK_ENTRY(combo_id3v1_genre->entry)));
340 }
341
update_tag_from_form_v2(int tag)342 static void update_tag_from_form_v2(int tag)
343 {
344 if (*current_tab == TAB_ID3V2_SIMPLE) {
345 GtkTextIter start, end;
346 gchar *temp;
347
348 mpeg_file_set_field_v(file, tag, AF_TITLE, gtk_entry_get_text(ent_id3v2_title));
349 mpeg_file_set_field_v(file, tag, AF_ARTIST, gtk_entry_get_text(ent_id3v2_artist));
350 mpeg_file_set_field_v(file, tag, AF_ALBUM, gtk_entry_get_text(ent_id3v2_album));
351 mpeg_file_set_field_v(file, tag, AF_YEAR, gtk_entry_get_text(ent_id3v2_year));
352 mpeg_file_set_field_v(file, tag, AF_TRACK, gtk_entry_get_text(ent_id3v2_track));
353 mpeg_file_set_field_v(file, tag, AF_GENRE, gtk_entry_get_text(GTK_ENTRY(combo_id3v2_genre->entry)));
354
355 gtk_text_buffer_get_bounds(gtk_text_view_get_buffer(text_id3v2_comment), &start, &end);
356 temp = gtk_text_buffer_get_text(gtk_text_view_get_buffer(text_id3v2_comment), &start, &end, FALSE);
357 mpeg_file_set_field_v(file, tag, AF_COMMENT, temp);
358 g_free(temp);
359 }
360 else {
361 /* Nothing to do here, advanced mode alters tag directly */
362 }
363 }
364
update_tag()365 static void update_tag()
366 {
367 if (mpeg_file_has_tag_v(file, ID3TT_ID3V1))
368 update_tag_from_form_v1(ID3TT_ID3V1);
369
370 if (mpeg_file_has_tag_v(file, ID3TT_ID3V2))
371 update_tag_from_form_v2(ID3TT_ID3V2);
372 }
373
update_tabs(gboolean allow_change)374 static void update_tabs(gboolean allow_change)
375 {
376 if (mpeg_file_has_tag_v(file, ID3TT_ID3V1)) {
377 gtk_image_set_from_pixbuf(img_id3v1_tab, pix_greendot);
378 gtk_widget_set_sensitive(GTK_WIDGET(m_id3_copyv1tov2), TRUE);
379 }
380 else {
381 gtk_image_set_from_pixbuf(img_id3v1_tab, pix_graydot);
382 gtk_widget_set_sensitive(GTK_WIDGET(m_id3_copyv1tov2), FALSE);
383 }
384
385 if (mpeg_file_has_tag_v(file, ID3TT_ID3V2)) {
386 gtk_image_set_from_pixbuf(img_id3v2_tab, pix_greendot);
387 gtk_widget_set_sensitive(GTK_WIDGET(m_id3_copyv2tov1), TRUE);
388 }
389 else {
390 gtk_image_set_from_pixbuf(img_id3v2_tab, pix_graydot);
391 gtk_widget_set_sensitive(GTK_WIDGET(m_id3_copyv2tov1), FALSE);
392 }
393
394 gtk_notebook_set_page(nb_edit, tab_edit_id3);
395 if (allow_change) {
396 if (mpeg_file_has_tag_v(file, ID3TT_ID3V2))
397 gtk_notebook_set_page(nb_id3, TAB_ID3_V2);
398 else
399 gtk_notebook_set_page(nb_id3, TAB_ID3_V1);
400 }
401 }
402
write_to_file()403 static void write_to_file()
404 {
405 int res;
406
407 cursor_set_wait();
408
409 if (mpeg_file_has_tag_v(file, ID3TT_ID3V2)) {
410 const char *genre = gtk_entry_get_text(GTK_ENTRY(combo_id3v2_genre->entry));
411 if (strcmp(genre, "") != 0)
412 mru_add(genre_mru, genre);
413 }
414
415 res = mpeg_file_write_changes(file);
416 if (res != AF_OK) {
417 char msg[512];
418 snprintf(msg, sizeof(msg),
419 _("Error saving file \"%s\":\n%s (%d)"),
420 file->name, strerror(errno), errno);
421 message_box(w_main, _("Error Saving File"), msg, 0, GTK_STOCK_OK, NULL);
422 }
423 else {
424 set_changed_flag(FALSE);
425 }
426
427 cursor_set_normal();
428 }
429
430
431 /*** UI callbacks ***********************************************************/
432
cb_id3_write_changes(GtkButton * button,gpointer user_data)433 void cb_id3_write_changes(GtkButton *button, gpointer user_data)
434 {
435 if (!file) {
436 g_warning("file is not open!");
437 return;
438 }
439
440 update_tag();
441 write_to_file();
442 }
443
cb_id3_remove_tag(GtkButton * button,gpointer user_data)444 void cb_id3_remove_tag(GtkButton *button, gpointer user_data)
445 {
446 if (!file) {
447 g_warning("file is not open!");
448 return;
449 }
450
451 if (gtk_notebook_get_current_page(nb_id3) == TAB_ID3_V1) {
452 mpeg_file_remove_tag_v(file, ID3TT_ID3V1);
453 update_form_v1();
454 }
455 else {
456 mpeg_file_remove_tag_v(file, ID3TT_ID3V2);
457 update_form_v2();
458 }
459
460 update_tabs(TRUE);
461 set_changed_flag(TRUE);
462 }
463
cb_id3v1_create_tag(GtkButton * button,gpointer user_data)464 void cb_id3v1_create_tag(GtkButton *button, gpointer user_data)
465 {
466 if (!file) {
467 g_warning("file is not open!");
468 return;
469 }
470
471 mpeg_file_create_tag_v(file, ID3TT_ID3V1);
472 set_changed_flag(TRUE);
473 update_form_v1();
474 update_tabs(FALSE);
475 }
476
cb_id3v2_create_tag(GtkButton * button,gpointer user_data)477 void cb_id3v2_create_tag(GtkButton *button, gpointer user_data)
478 {
479 if (!file) {
480 g_warning("file is not open!");
481 return;
482 }
483
484 mpeg_file_create_tag_v(file, ID3TT_ID3V2);
485 set_changed_flag(TRUE);
486 update_form_v2();
487 update_tabs(FALSE);
488 }
489
490 /* v1 and v2 simple mode callbacks */
cb_id3_tag_changed(GObject * obj,gpointer user_data)491 void cb_id3_tag_changed(GObject *obj, gpointer user_data)
492 {
493 if (!ignore_changed_signals)
494 set_changed_flag(TRUE);
495 }
496
cb_id3_keypress(GtkWidget * widget,GdkEventKey * event,gpointer user_data)497 gboolean cb_id3_keypress(GtkWidget *widget, GdkEventKey *event, gpointer user_data)
498 {
499 /* <return> saves the tag and advances to the next file */
500 if (event->keyval == GDK_Return) {
501 if (file && changed_flag) {
502 update_tag();
503 write_to_file();
504 }
505 fl_select_next_file();
506 return TRUE;
507 }
508
509 return FALSE;
510 }
511
512 /* v2 advanced mode callbacks */
cb_id3v2_frame_selection_changed(GtkTreeSelection * selection,gpointer data)513 void cb_id3v2_frame_selection_changed(GtkTreeSelection *selection, gpointer data)
514 {
515 if (gtk_tree_selection_count_selected_rows(selection) == 0) {
516 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_edit), FALSE);
517 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_remove), FALSE);
518 }
519 else {
520 GtkTreeModel *model;
521 GtkTreeIter iter;
522 ID3Frame *frame;
523 gboolean editable;
524
525 gtk_tree_view_get_first_selected(tv_id3v2_frames, &model, &iter);
526 gtk_tree_model_get(model, &iter, 2, &frame, -1);
527
528 mpeg_file_get_frame_info(ID3Frame_GetID(frame), NULL, NULL, &editable, NULL);
529
530 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_edit), editable);
531 gtk_widget_set_sensitive(GTK_WIDGET(b_id3v2_remove), TRUE);
532 }
533 }
534
cb_id3v2_add(GtkButton * button,gpointer user_data)535 void cb_id3v2_add(GtkButton *button, gpointer user_data)
536 {
537 if ( mpeg_editfld_create_frame(file, ID3TT_ID3V2) ) {
538 set_changed_flag(TRUE);
539 update_form_v2();
540 }
541 }
542
cb_id3v2_edit(GtkButton * button,gpointer user_data)543 void cb_id3v2_edit(GtkButton *button, gpointer user_data)
544 {
545 GtkTreeModel *model;
546 GtkTreeIter iter;
547
548 if (gtk_tree_view_get_first_selected(tv_id3v2_frames, &model, &iter)) {
549 ID3Frame *frame;
550 gboolean editable;
551
552 gtk_tree_model_get(model, &iter, 2, &frame, -1);
553
554 mpeg_file_get_frame_info(ID3Frame_GetID(frame), NULL, NULL, &editable, NULL);
555 if (!editable)
556 return;
557
558 if ( mpeg_editfld_edit_frame(file, ID3TT_ID3V2, frame) ) {
559 set_changed_flag(TRUE);
560 update_form_v2();
561 }
562 }
563 }
564
cb_id3v2_frame_row_activated(GtkTreeView * treeview,GtkTreePath * path,GtkTreeViewColumn * col,gpointer user_data)565 void cb_id3v2_frame_row_activated(GtkTreeView *treeview, GtkTreePath *path, GtkTreeViewColumn *col, gpointer user_data)
566 {
567 /* same as clicking the edit button */
568 cb_id3v2_edit(NULL, NULL);
569 }
570
cb_id3v2_remove(GtkButton * button,gpointer user_data)571 void cb_id3v2_remove(GtkButton *button, gpointer user_data)
572 {
573 GtkTreeModel *model;
574 GtkTreeIter iter;
575
576 if (gtk_tree_view_get_first_selected(tv_id3v2_frames, &model, &iter)) {
577 ID3Frame *frame;
578 gtk_tree_model_get(model, &iter, 2, &frame, -1);
579
580 mpeg_file_remove_frame(file, ID3TT_ID3V2, frame);
581 set_changed_flag(TRUE);
582 update_form_v2();
583 }
584 }
585
cb_id3v2_view_button(GtkButton * button,gpointer user_data)586 void cb_id3v2_view_button(GtkButton *button, gpointer user_data)
587 {
588 if (*current_tab == TAB_ID3V2_SIMPLE)
589 gtk_check_menu_item_set_active(m_id3v2_view_advanced, TRUE);
590 else if (*current_tab == TAB_ID3V2_ADVANCED)
591 gtk_check_menu_item_set_active(m_id3v2_view_simple, TRUE);
592 }
593
594 /* menu callbacks */
cb_id3v2_view_simple(GtkWidget * widget,GdkEvent * event)595 void cb_id3v2_view_simple(GtkWidget *widget, GdkEvent *event)
596 {
597 if (*current_tab == TAB_ID3V2_ADVANCED) {
598 *current_tab = TAB_ID3V2_SIMPLE;
599 if (gtk_notebook_get_current_page(nb_id3v2) != TAB_ID3V2_NOTAG) {
600 update_form_v2();
601 gtk_notebook_set_page(nb_id3v2, TAB_ID3V2_SIMPLE);
602 }
603 }
604 }
605
cb_id3v2_view_advanced(GtkWidget * widget,GdkEvent * event)606 void cb_id3v2_view_advanced(GtkWidget *widget, GdkEvent *event)
607 {
608 if (*current_tab == TAB_ID3V2_SIMPLE) {
609 update_tag_from_form_v2(ID3TT_ID3V2);
610
611 *current_tab = TAB_ID3V2_ADVANCED;
612 if (gtk_notebook_get_current_page(nb_id3v2) != TAB_ID3V2_NOTAG) {
613 update_form_v2();
614 gtk_notebook_set_page(nb_id3v2, TAB_ID3V2_ADVANCED);
615 }
616 }
617 }
618
cb_id3_copyv1tov2(GtkWidget * widget,GdkEvent * event)619 void cb_id3_copyv1tov2(GtkWidget *widget, GdkEvent *event)
620 {
621 if (!file) {
622 g_warning("file is not open!");
623 return;
624 }
625
626 if (!mpeg_file_has_tag_v(file, ID3TT_ID3V2))
627 mpeg_file_create_tag_v(file, ID3TT_ID3V2);
628
629 update_tag_from_form_v1(ID3TT_ID3V2);
630
631 set_changed_flag(TRUE);
632 update_form_v2();
633 update_tabs(FALSE);
634 }
635
cb_id3_copyv2tov1(GtkWidget * widget,GdkEvent * event)636 void cb_id3_copyv2tov1(GtkWidget *widget, GdkEvent *event)
637 {
638 if (!file) {
639 g_warning("file is not open!");
640 return;
641 }
642
643 if (!mpeg_file_has_tag_v(file, ID3TT_ID3V1))
644 mpeg_file_create_tag_v(file, ID3TT_ID3V1);
645
646 update_tag_from_form_v2(ID3TT_ID3V1);
647
648 set_changed_flag(TRUE);
649 update_form_v1();
650 update_tabs(FALSE);
651 }
652
653
654 /*** public functions *******************************************************/
655
mpeg_edit_load(mpeg_file * f)656 void mpeg_edit_load(mpeg_file *f)
657 {
658 gtk_widget_show(GTK_WIDGET(m_id3));
659
660 file = f;
661 set_changed_flag(FALSE);
662 update_form_v1();
663 update_form_v2();
664 update_tabs(TRUE);
665 }
666
667
mpeg_edit_unload()668 void mpeg_edit_unload()
669 {
670 if (changed_flag) {
671 int button;
672
673 button = message_box(w_main, _("Save Changes"),
674 _("ID3 Tag has been modified. Save changes?"), 1,
675 _("Discard"), GTK_STOCK_SAVE, NULL);
676 if (button == 1) {
677 /* save button was pressed */
678 update_tag();
679 write_to_file();
680 }
681 }
682
683 file = NULL;
684
685 if (GTK_IS_WIDGET(m_id3))
686 gtk_widget_hide(GTK_WIDGET(m_id3));
687 }
688
689
mpeg_edit_init(GladeXML * xml)690 void mpeg_edit_init(GladeXML *xml)
691 {
692 GEList *temp_list;
693 GEList *genre_list;
694 int default_tab = TAB_ID3V2_SIMPLE;
695
696 /* get the widgets from glade */
697 w_main = GTK_WINDOW(glade_xml_get_widget(xml, "w_main"));
698 nb_edit = GTK_NOTEBOOK(glade_xml_get_widget(xml, "nb_edit"));
699 nb_id3 = GTK_NOTEBOOK(glade_xml_get_widget(xml, "nb_id3"));
700 nb_id3v1 = GTK_NOTEBOOK(glade_xml_get_widget(xml, "nb_id3v1"));
701 nb_id3v2 = GTK_NOTEBOOK(glade_xml_get_widget(xml, "nb_id3v2"));
702 m_id3 = GTK_MENU_ITEM(glade_xml_get_widget(xml, "m_id3"));
703 m_id3v2_view_simple = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "m_id3v2_view_simple"));
704 m_id3v2_view_advanced = GTK_CHECK_MENU_ITEM(glade_xml_get_widget(xml, "m_id3v2_view_advanced"));
705 m_id3_copyv1tov2 = GTK_MENU_ITEM(glade_xml_get_widget(xml, "m_id3_copyv1tov2"));
706 m_id3_copyv2tov1 = GTK_MENU_ITEM(glade_xml_get_widget(xml, "m_id3_copyv2tov1"));
707 b_write_tag = GTK_BUTTON(glade_xml_get_widget(xml, "b_id3_write_tag"));
708 b_remove_tag = GTK_BUTTON(glade_xml_get_widget(xml, "b_id3_remove_tag"));
709
710 b_id3v1_create_tag = GTK_BUTTON(glade_xml_get_widget(xml, "b_id3v1_create_tag"));
711 ent_id3v1_title = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v1_title"));
712 ent_id3v1_artist = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v1_artist"));
713 ent_id3v1_album = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v1_album"));
714 ent_id3v1_year = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v1_year"));
715 ent_id3v1_comment = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v1_comment"));
716 spin_id3v1_track = GTK_SPIN_BUTTON(glade_xml_get_widget(xml, "spin_id3v1_track"));
717 combo_id3v1_genre = GTK_COMBO(glade_xml_get_widget(xml, "combo_id3v1_genre"));
718 lab_id3v1_title = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v1_title"));
719 lab_id3v1_artist = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v1_artist"));
720 lab_id3v1_album = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v1_album"));
721 lab_id3v1_year = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v1_year"));
722 lab_id3v1_comment = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v1_comment"));
723 lab_id3v1_track = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v1_track"));
724 lab_id3v1_genre = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v1_genre"));
725
726 b_id3v2_create_tag = GTK_BUTTON(glade_xml_get_widget(xml, "b_id3v2_create_tag"));
727 ent_id3v2_title = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v2_title"));
728 ent_id3v2_artist = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v2_artist"));
729 ent_id3v2_album = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v2_album"));
730 ent_id3v2_year = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v2_year"));
731 text_id3v2_comment = GTK_TEXT_VIEW(glade_xml_get_widget(xml, "text_id3v2_comment"));
732 ent_id3v2_track = GTK_ENTRY(glade_xml_get_widget(xml, "ent_id3v2_track"));
733 combo_id3v2_genre = GTK_COMBO(glade_xml_get_widget(xml, "combo_id3v2_genre"));
734 lab_id3v2_title = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_title"));
735 lab_id3v2_artist = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_artist"));
736 lab_id3v2_album = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_album"));
737 lab_id3v2_year = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_year"));
738 lab_id3v2_comment = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_comment"));
739 lab_id3v2_track = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_track"));
740 lab_id3v2_genre = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_genre"));
741 lab_id3v2_advanced = GTK_LABEL(glade_xml_get_widget(xml, "lab_id3v2_advanced"));
742
743 tv_id3v2_frames = GTK_TREE_VIEW(glade_xml_get_widget(xml, "tv_id3v2_frames"));
744 b_id3v2_add = GTK_BUTTON(glade_xml_get_widget(xml, "b_id3v2_add"));
745 b_id3v2_edit = GTK_BUTTON(glade_xml_get_widget(xml, "b_id3v2_edit"));
746 b_id3v2_remove = GTK_BUTTON(glade_xml_get_widget(xml, "b_id3v2_remove"));
747
748 img_id3v1_tab = GTK_IMAGE(glade_xml_get_widget(xml, "img_id3v1_tab"));
749 img_id3v2_tab = GTK_IMAGE(glade_xml_get_widget(xml, "img_id3v2_tab"));
750
751 /* additional widget setup */
752 gtk_editable_set_max_chars(GTK_EDITABLE(ent_id3v1_title), 30);
753 gtk_editable_set_max_chars(GTK_EDITABLE(ent_id3v1_artist), 30);
754 gtk_editable_set_max_chars(GTK_EDITABLE(ent_id3v1_album), 30);
755 gtk_editable_set_max_chars(GTK_EDITABLE(ent_id3v1_comment), 29);
756 gtk_editable_set_max_chars(GTK_EDITABLE(ent_id3v1_year), 4);
757
758 g_signal_connect(G_OBJECT(gtk_text_view_get_buffer(text_id3v2_comment)),
759 "changed", G_CALLBACK(cb_id3_tag_changed), NULL);
760
761 /* load the pixbufs */
762 pix_graydot = gdk_pixbuf_new_from_file(DATADIR"/graydot.png", NULL);
763 pix_greendot = gdk_pixbuf_new_from_file(DATADIR"/greendot.png", NULL);
764
765 /* set up the tree view */
766 tree_view_setup();
767 g_signal_connect(gtk_tree_view_get_selection(tv_id3v2_frames), "changed",
768 G_CALLBACK(cb_id3v2_frame_selection_changed), NULL);
769
770 /* find out which tab has the ID3 interface */
771 tab_edit_id3 = gtk_notebook_page_num(nb_edit, glade_xml_get_widget(xml, "cont_id3_edit"));
772
773 /* ID3v1 genre list */
774 temp_list = genre_create_list(TRUE);
775 g_elist_prepend(temp_list, "");
776 gtk_combo_set_popdown_strings(combo_id3v1_genre, GLIST(temp_list));
777 g_elist_free(temp_list);
778
779 /* ID3v2 genre list, from prefs */
780 temp_list = g_elist_new();
781 genre_list = pref_get_or_set("common_edit:genre_mru", PREF_STRING | PREF_LIST, temp_list);
782 g_elist_free_data(temp_list);
783 genre_mru = mru_new_from_list(50, genre_list);
784
785 /* current_tab, from prefs */
786 current_tab = pref_get_or_set("id3_edit:current_tab", PREF_INT, &default_tab);
787 if (*current_tab != TAB_ID3V2_SIMPLE && *current_tab != TAB_ID3V2_ADVANCED)
788 *current_tab = default_tab;
789
790 if (*current_tab == TAB_ID3V2_SIMPLE)
791 gtk_check_menu_item_set_active(m_id3v2_view_simple, TRUE);
792 else if (*current_tab == TAB_ID3V2_ADVANCED)
793 gtk_check_menu_item_set_active(m_id3v2_view_advanced, TRUE);
794 }
795
796