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