Put si strcuture in header in stead of defineing twice
[gmpc-tagedit.git] / src / plugin.c
blob8e9167501be8bbbe8e9867028748c54891c56ac6
1 #include <config.h>
2 #include <string.h>
3 #include <gdk/gdkkeysyms.h>
4 #include <gmpc/plugin.h>
5 #include <libmpd/libmpd.h>
6 #include <glib.h>
7 #include <tag_c.h>
8 #include "gmpc-mpddata-model-tagedit.h"
9 #include "tagedit.h"
10 #define CONFIG_NAME "tagedit"
13 static void __save_myself(void);
14 /* The plugin structure */
15 gmpcPlugin plugin;
18 GtkTreeRowReference *te_ref = NULL;
19 /**
20 * Preferences
22 static void music_dir_cover_art_enable_toggle(GtkWidget *wid)
24 int kk = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(wid));
25 cfg_set_single_value_as_int(config, CONFIG_NAME, "enable", kk);
27 static void info_entry_edited(GtkWidget *entry)
29 const char *str = gtk_entry_get_text(GTK_ENTRY(entry));
30 if(str)
32 cfg_set_single_value_as_string(config, CONFIG_NAME, "music_root",(char *)str);
36 static void __pref_destroy(GtkWidget *container)
38 gtk_widget_destroy(gtk_bin_get_child(GTK_BIN(container)));
40 static void __pref_construct(GtkWidget *container)
42 GtkWidget *enable_cg = gtk_check_button_new_with_mnemonic("_Enable mpd's music dir as cover art source");
43 GtkWidget *entry = NULL;
44 char *entry_str = cfg_get_single_value_as_string(config, CONFIG_NAME, "music_root");
45 GtkWidget *vbox = gtk_vbox_new(FALSE,6);
47 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(enable_cg),
48 cfg_get_single_value_as_int_with_default(config, CONFIG_NAME, "enable", TRUE));
50 g_signal_connect(G_OBJECT(enable_cg), "toggled", G_CALLBACK(music_dir_cover_art_enable_toggle), NULL);
51 gtk_box_pack_start(GTK_BOX(vbox), enable_cg, FALSE, FALSE, 0);
52 gtk_container_add(GTK_CONTAINER(container), vbox);
54 entry = gtk_entry_new();
55 if(entry_str)
57 gtk_entry_set_text(GTK_ENTRY(entry), entry_str);
58 cfg_free_string(entry_str);
60 gtk_box_pack_start(GTK_BOX(vbox), gtk_label_new("Music Root:"), FALSE, FALSE,0);
61 gtk_box_pack_start(GTK_BOX(vbox), entry, FALSE, FALSE,0);
62 g_signal_connect(G_OBJECT(entry), "changed", G_CALLBACK(info_entry_edited), NULL);
64 gtk_widget_show_all(container);
68 /**
69 * Taglib functions
72 static mpd_Song * get_song_from_file(const char *root, const char *filename)
74 TagLib_File *file;
75 TagLib_Tag *tag;
76 mpd_Song *song = NULL;
77 gchar *url = g_build_path(G_DIR_SEPARATOR_S, root, filename,NULL);
79 file = taglib_file_new(url);
80 if(file)
82 char *a = NULL;
83 song = mpd_newSong();
84 song->file = g_strdup(filename);
85 tag = taglib_file_tag(file);
86 if(tag)
88 if((a = taglib_tag_title(tag)) && a[0] != '\0')
89 song->title = g_strdup(a);
90 if((a = taglib_tag_album(tag)) && a[0] != '\0')
91 song->album = g_strdup(a);
92 if((a = taglib_tag_artist(tag)) && a[0] != '\0')
93 song->artist = g_strdup(a);
94 if(taglib_tag_track(tag) > 0)
95 song->track = g_strdup_printf("%i", taglib_tag_track(tag));
96 if((a = taglib_tag_genre(tag)) && a[0] != '\0')
97 song->genre = g_strdup(a);
98 if((a = taglib_tag_comment(tag)) && a[0] != '\0')
99 song->comment = g_strdup(a);
100 if(taglib_tag_year(tag) > 0)
101 song->date = g_strdup_printf("%i", taglib_tag_year(tag));
104 taglib_tag_free_strings();
106 taglib_file_free(file);
108 g_free(url);
109 return song;
111 static gboolean __timeout_mpd_update(gchar *url)
113 printf("update: %s\n",url);
114 mpd_database_update_dir(connection, url);
116 return FALSE;
119 static void save_song_to_file(const char *root, const mpd_Song *song)
121 TagLib_File *file;
122 TagLib_Tag *tag;
124 gchar *url = g_build_path(G_DIR_SEPARATOR_S, root, song->file,NULL);
125 file = taglib_file_new(url);
126 if(file)
128 tag = taglib_file_tag(file);
129 if(song->title) taglib_tag_set_title(tag, song->title);
130 if(song->artist) taglib_tag_set_artist(tag, song->artist);
131 if(song->album) taglib_tag_set_album(tag, song->album);
132 if(song->genre) taglib_tag_set_genre(tag, song->genre);
133 if(song->comment) taglib_tag_set_comment(tag, song->comment);
134 if(song->track){
135 guint track = (guint) g_ascii_strtoll(song->track, NULL, 10);
136 taglib_tag_set_track(tag, track);
138 if(song->date){
139 guint year = (guint) g_ascii_strtoll(song->date, NULL, 10);
140 taglib_tag_set_year(tag, year);
142 taglib_file_save(file);
143 taglib_tag_free_strings();
144 taglib_file_free(file);
145 g_timeout_add_seconds_full(G_PRIORITY_DEFAULT ,1, (GSourceFunc)__timeout_mpd_update, g_strdup(song->file), g_free);
148 g_free(url);
155 * Browser View
157 static GtkWidget *browser_box = NULL;
158 static GtkWidget *browser_tree = NULL;
159 static GtkTreeModel *browser_model = NULL;
160 static GtkWidget *entries[7];
161 static gulong signal_entries[7];
163 static void free_si(si *i)
165 printf("free si\n");
166 if(i->revert) mpd_freeSong(i->revert);
167 g_free(i);
169 static void queue_selected_songs_for_edit(GtkMenuItem *item, GmpcMpdDataTreeview *tree)
171 char *root = cfg_get_single_value_as_string(config, CONFIG_NAME, "music_root");
172 MpdData *data = NULL;
173 GList *selected = NULL;
174 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(tree));
175 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(tree));
176 if(!browser_model)
177 browser_model = (GtkTreeModel *)gmpc_mpddata_model_tagedit_new();
178 data = gmpc_mpddata_model_steal_mpd_data(GMPC_MPDDATA_MODEL(browser_model));
179 selected = gtk_tree_selection_get_selected_rows(selection, &model);
180 if(selected)
182 GList *iter = g_list_first(selected);
183 for(;iter; iter = g_list_next(iter))
185 GtkTreeIter titer;
187 if(gtk_tree_model_get_iter(model, &titer, iter->data))
189 mpd_Song *song = NULL;
190 gtk_tree_model_get(model, &titer, MPDDATA_MODEL_COL_MPDSONG, &song, -1);
191 if(song && song->file)
193 mpd_Song *edited = get_song_from_file(root, song->file);
194 printf("adding: %s\n", song->file);
195 if(edited)
197 si *i = g_malloc0(sizeof(*i));
198 data = mpd_new_data_struct_append(data);
199 data->type = MPD_DATA_TYPE_SONG;
200 data->song = edited;
201 i->changed = 0;
202 i->revert = mpd_songDup(data->song);
203 data->userdata =i;
204 data->freefunc = free_si;
209 g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
210 g_list_free (selected);
212 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(browser_model),data);
213 g_free(root);
216 static int __song_list_option_menu ( GmpcMpdDataTreeview *tree, GtkMenu *menu)
218 GtkWidget *item;
219 char *entry_str = cfg_get_single_value_as_string(config, CONFIG_NAME, "music_root");
220 if(entry_str)
222 item = gtk_image_menu_item_new_with_label("Queue songs for tag edit");
223 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
224 gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
225 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
226 g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(queue_selected_songs_for_edit), tree);
227 g_free(entry_str);
229 return 1;
231 static void browser_selection_changed(GtkTreeSelection *selec, gpointer data)
233 GList *selected = gtk_tree_selection_get_selected_rows(selec, &browser_model);
234 int i =0;
235 for(i=0;i< 6;i++)
237 if(signal_entries[i])
238 g_signal_handler_block(G_OBJECT(entries[i]), signal_entries[i]);
239 if(i<4) gtk_entry_set_text(GTK_ENTRY(entries[i]), "");
240 else gtk_spin_button_set_value(GTK_SPIN_BUTTON(entries[i]), 0.0);
242 if(selected)
244 GList *iter = g_list_first(selected);
245 for(;iter; iter = g_list_next(iter))
247 GtkTreeIter titer;
248 if(gtk_tree_model_get_iter(browser_model, &titer, iter->data))
250 mpd_Song *song = NULL;
251 gtk_tree_model_get(browser_model, &titer, MPDDATA_MODEL_COL_MPDSONG, &song, -1);
252 if(song)
254 if(song->title)
256 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries[0]))) == 0)
257 gtk_entry_set_text(GTK_ENTRY(entries[0]), song->title);
259 if(song->artist)
261 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries[1]))) == 0)
262 gtk_entry_set_text(GTK_ENTRY(entries[1]), song->artist);
264 if(song->album)
266 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries[2]))) == 0)
267 gtk_entry_set_text(GTK_ENTRY(entries[2]), song->album);
269 if(song->genre)
271 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries[3]))) == 0)
272 gtk_entry_set_text(GTK_ENTRY(entries[3]), song->genre);
274 if(song->date)
276 guint year = (guint) g_ascii_strtoll(song->date, NULL, 10);
277 if(year && gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(entries[4])) == 0)
278 gtk_spin_button_set_value(GTK_SPIN_BUTTON(entries[4]), (gdouble) year);
280 if(song->track)
282 guint track = (guint) g_ascii_strtoll(song->track, NULL, 10);
283 if(track && gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(entries[5])) == 0)
284 gtk_spin_button_set_value(GTK_SPIN_BUTTON(entries[5]), (gdouble) track);
290 g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
291 g_list_free (selected);
293 for(i=0;i<6;i++)
295 if(signal_entries[i])
296 g_signal_handler_unblock(G_OBJECT(entries[i]), signal_entries[i]);
299 static void __revert_selected(GtkWidget *button, gpointer data)
301 GtkTreeSelection *selec = gtk_tree_view_get_selection(GTK_TREE_VIEW(browser_tree));
302 GList *selected = gtk_tree_selection_get_selected_rows(selec, &browser_model);
303 if(selected)
305 GList *iter = g_list_first(selected);
306 for(;iter; iter = g_list_next(iter))
308 GtkTreeIter titer;
309 if(gtk_tree_model_get_iter(browser_model, &titer, iter->data))
311 si *ud = NULL;
312 mpd_Song *song = NULL;
313 gtk_tree_model_get(browser_model, &titer, MPDDATA_MODEL_COL_MPDSONG, &song, MPDDATA_MODEL_USERDATA, &ud,-1);
314 gmpc_mpddata_model_tagedit_revert_song(browser_model, &titer);
318 g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
319 g_list_free (selected);
321 browser_selection_changed(selec, NULL);
326 static void __field_changed(GtkWidget *entry, gpointer data)
328 int id = GPOINTER_TO_INT(data);
330 const gchar *text = NULL;
331 gint value = 0;
332 GList *selected = gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(browser_tree)), &browser_model);
333 if(id < 4)
335 text = gtk_entry_get_text(GTK_ENTRY(entry));
337 else if (id < 6)
339 value = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(entry));
341 if(selected)
343 GList *iter = g_list_first(selected);
344 for(;iter; iter = g_list_next(iter))
346 GtkTreeIter titer;
347 if(gtk_tree_model_get_iter(browser_model, &titer, iter->data))
349 mpd_Song *song = NULL;
350 si *ud = NULL;
351 gtk_tree_model_get(browser_model, &titer, MPDDATA_MODEL_COL_MPDSONG, &song,MPDDATA_MODEL_USERDATA, &ud, -1);
352 if(song)
354 if(id == 0) {
355 if(song->title == NULL || strcmp(song->title, text) != 0)
357 if(song->title) g_free(song->title);
358 song->title = g_strdup(text);
359 gtk_tree_model_row_changed(browser_model, (GtkTreePath *)iter->data, &titer);
360 if(ud->revert->title && strcmp(text, ud->revert->title) == 0)
361 ud->changed &= ~1;
362 else
363 ud->changed |= 1;
366 else if(id == 1) {
367 if(song->artist == NULL || strcmp(song->artist, text) != 0)
369 if(song->artist) g_free(song->artist);
370 song->artist = g_strdup(text);
371 gtk_tree_model_row_changed(browser_model, (GtkTreePath *)iter->data, &titer);
372 if(ud->revert->artist && strcmp(text, ud->revert->artist) == 0)
373 ud->changed &= ~(1<<1);
374 else
375 ud->changed |= (1<<1);
378 else if(id == 2) {
379 if(song->album == NULL || strcmp(song->album, text) != 0)
381 if(song->album) g_free(song->album);
382 song->album = g_strdup(text);
383 gtk_tree_model_row_changed(browser_model, (GtkTreePath *)iter->data, &titer);
384 if(ud->revert->album && strcmp(text, ud->revert->album) == 0)
385 ud->changed &= ~(1<<2);
386 else
387 ud->changed |= (1<<2);
390 else if(id == 3) {
391 if(song->genre == NULL || strcmp(song->genre, text) != 0)
393 if(song->genre) g_free(song->genre);
394 song->genre = g_strdup(text);
395 if(ud->revert->genre && strcmp(text, ud->revert->genre) == 0)
396 ud->changed &= ~(1<<3);
397 else
398 ud->changed |= (1<<3);
399 gtk_tree_model_row_changed(browser_model, (GtkTreePath *)iter->data, &titer);
402 else if (id == 4) {
403 guint val = 0;
404 if(song->date)
405 val = (guint)g_ascii_strtoll(song->date, NULL, 10);
406 if(val != value)
408 if(song->date ) g_free(song->date );
409 if(value > 0)
410 song->date = g_strdup_printf("%i", value);
411 else
412 song->date = NULL;
415 if(ud->revert->date == NULL && song->date == NULL) ud->changed &= ~(1<<4);
416 else if(ud->revert->date && song->date && strcmp(song->date, ud->revert->date) == 0)
417 ud->changed &= ~(1<<4);
418 else
419 ud->changed |= (1<<4);
420 gtk_tree_model_row_changed(browser_model, (GtkTreePath *)iter->data, &titer);
423 else if (id == 5) {
424 guint val = 0;
425 if(song->track)
426 val = (guint)g_ascii_strtoll(song->track, NULL, 10);
427 if(val != value)
429 if(song->track) g_free(song->track);
430 if(value > 0)
431 song->track = g_strdup_printf("%i", value);
432 else
433 song->track = NULL;
434 if(song->track == NULL && ud->revert->track == NULL)
435 ud->changed &= ~(1<<5);
436 else if(ud->revert->track && song->track && strcmp(song->track, ud->revert->track) == 0)
437 ud->changed &= ~(1<<5);
438 else
439 ud->changed |= (1<<5);
440 gtk_tree_model_row_changed(browser_model, (GtkTreePath *)iter->data, &titer);
445 printf("changed: %i-%i\n", id, ud->changed);
448 g_list_foreach (selected, (GFunc)gtk_tree_path_free, NULL);
449 g_list_free (selected);
453 static void save_all(GtkWidget *button, gpointer data)
455 char *root = cfg_get_single_value_as_string(config, CONFIG_NAME, "music_root");
456 GtkTreeIter iter;
457 if(root && gtk_tree_model_get_iter_first(browser_model, &iter))
460 mpd_Song *song = NULL;
461 si *ud = NULL;
462 gtk_tree_model_get(browser_model, &iter, MPDDATA_MODEL_COL_MPDSONG, &song, MPDDATA_MODEL_USERDATA, &ud,-1);
463 if(song)
465 /* check if song changed */
466 if(ud->changed > 0)
468 printf("saving: %s\n", song->file);
469 save_song_to_file(root, song);
470 ud->changed = 0;
473 }while(gtk_tree_model_iter_next(browser_model, &iter));
475 if(root)g_free(root);
477 static void clear_all(GtkWidget *button, gpointer data)
479 gmpc_mpddata_model_set_mpd_data(GMPC_MPDDATA_MODEL(browser_model), NULL);
482 static void __edit_columns(void)
484 gmpc_mpddata_treeview_edit_columns(GMPC_MPDDATA_TREEVIEW(browser_tree));
486 static int __button_release_event(GtkTreeView *tree, GdkEventButton *event)
488 if(event->button == 3)
490 /* del, crop */
491 GtkWidget *item;
492 GtkWidget *menu = gtk_menu_new();
493 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(browser_tree));
494 if(gtk_tree_selection_count_selected_rows(selection) == 1)
496 item = gtk_image_menu_item_new_with_label(("Revert changes"));
497 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
498 gtk_image_new_from_stock(GTK_STOCK_REVERT_TO_SAVED, GTK_ICON_SIZE_MENU));
499 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
500 g_signal_connect(G_OBJECT(item), "activate",
501 G_CALLBACK(__revert_selected), NULL);
503 item = gtk_image_menu_item_new_with_label(("Edit Columns"));
504 gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item),
505 gtk_image_new_from_stock(GTK_STOCK_EDIT, GTK_ICON_SIZE_MENU));
506 gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
507 g_signal_connect(G_OBJECT(item), "activate",
508 G_CALLBACK(__edit_columns), NULL);
510 gtk_widget_show_all(menu);
511 gtk_menu_popup(GTK_MENU(menu), NULL, NULL,NULL, NULL,0, event->time);
512 return TRUE;
514 return FALSE;
517 static int __key_release_event(GtkWidget *box , GdkEventKey *event, gpointer data)
519 if(event->keyval == GDK_Page_Up||event->keyval == GDK_Page_Down)
521 GtkTreeSelection *selection = gtk_tree_view_get_selection(GTK_TREE_VIEW(browser_tree));
522 if(gtk_tree_selection_count_selected_rows(selection) == 1)
524 GList *list = gtk_tree_selection_get_selected_rows(selection, &browser_model);
525 if(list)
527 GtkTreePath *path = list->data;
528 if(event->keyval == GDK_Page_Up)
530 if(gtk_tree_path_prev(path)){
531 gtk_tree_selection_unselect_all(selection);
532 gtk_tree_selection_select_path(selection, path);
534 }else{
535 gtk_tree_path_next(path);
536 gtk_tree_selection_unselect_all(selection);
537 gtk_tree_selection_select_path(selection, path);
540 g_list_foreach (list, (GFunc)gtk_tree_path_free, NULL);
541 g_list_free (list);
543 return TRUE;
545 return FALSE;
548 static void __browser_init ( )
550 GtkWidget *sw = NULL, *label;
551 GtkWidget *table = NULL;
552 browser_box = gtk_vbox_new(FALSE, 6);
553 if(!browser_model)
554 browser_model = (GtkTreeModel *)gmpc_mpddata_model_tagedit_new();
555 sw = gtk_scrolled_window_new(NULL, NULL);
556 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC,GTK_POLICY_AUTOMATIC);
557 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw), GTK_SHADOW_ETCHED_IN);
558 browser_tree = gmpc_mpddata_treeview_new(CONFIG_NAME, TRUE, browser_model);
559 gmpc_mpddata_treeview_enable_click_fix(GMPC_MPDDATA_TREEVIEW(browser_tree));
560 gtk_container_add(GTK_CONTAINER(sw), browser_tree);
561 gtk_box_pack_start(GTK_BOX(browser_box), sw, TRUE, TRUE,0);
563 g_signal_connect(G_OBJECT(gtk_tree_view_get_selection(GTK_TREE_VIEW(browser_tree))),
564 "changed", G_CALLBACK(browser_selection_changed), NULL);
565 /** Add all the fill in fields */
566 table = gtk_table_new(4,6,FALSE);
567 /* title */
568 label = gtk_label_new("Title:");
569 gtk_misc_set_alignment(GTK_MISC(label), 1.0,0.5);
570 gtk_table_attach(GTK_TABLE(table),label, 0,1,0,1,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
571 entries[0] = gtk_entry_new();
572 gtk_table_attach(GTK_TABLE(table),entries[0], 1,2,0,1,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
573 signal_entries[0] = g_signal_connect(G_OBJECT(entries[0]), "changed", G_CALLBACK(__field_changed), GINT_TO_POINTER(0));
574 /* artist */
575 label = gtk_label_new("Artist:");
576 gtk_misc_set_alignment(GTK_MISC(label), 1.0,0.5);
577 gtk_table_attach(GTK_TABLE(table),label, 0,1,1,2,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
578 entries[1] = gtk_entry_new();
579 gtk_table_attach(GTK_TABLE(table),entries[1], 1,2,1,2,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
580 signal_entries[1] = g_signal_connect(G_OBJECT(entries[1]), "changed", G_CALLBACK(__field_changed), GINT_TO_POINTER(1));
581 /* album */
582 label = gtk_label_new("Album:");
583 gtk_misc_set_alignment(GTK_MISC(label), 1.0,0.5);
584 gtk_table_attach(GTK_TABLE(table),label, 0,1,2,3,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
585 entries[2] = gtk_entry_new();
586 gtk_table_attach(GTK_TABLE(table),entries[2], 1,2,2,3,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
587 signal_entries[2] = g_signal_connect(G_OBJECT(entries[2]), "changed", G_CALLBACK(__field_changed), GINT_TO_POINTER(2));
588 /* album */
589 label = gtk_label_new("Genre:");
590 gtk_misc_set_alignment(GTK_MISC(label), 1.0,0.5);
591 gtk_table_attach(GTK_TABLE(table),label, 0,1,3,4,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
592 entries[3] = gtk_entry_new();
593 gtk_table_attach(GTK_TABLE(table),entries[3], 1,2,3,4,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
594 signal_entries[3] = g_signal_connect(G_OBJECT(entries[3]), "changed", G_CALLBACK(__field_changed), GINT_TO_POINTER(3));
595 /* album */
596 label = gtk_label_new("Year:");
597 gtk_misc_set_alignment(GTK_MISC(label), 1.0,0.5);
598 gtk_table_attach(GTK_TABLE(table),label, 3,4,0,1,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
599 entries[4] = gtk_spin_button_new_with_range(0, 3000,1);
600 gtk_table_attach(GTK_TABLE(table),entries[4], 4,5,0,1,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
601 signal_entries[4] = g_signal_connect(G_OBJECT(entries[4]), "value-changed", G_CALLBACK(__field_changed), GINT_TO_POINTER(4));
602 g_signal_connect(G_OBJECT(entries[4]), "key-press-event", G_CALLBACK(__key_release_event), NULL);
603 /* album */
604 label = gtk_label_new("Track:");
605 gtk_misc_set_alignment(GTK_MISC(label), 1.0,0.5);
606 gtk_table_attach(GTK_TABLE(table),label, 3,4,1,2,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
607 entries[5] = gtk_spin_button_new_with_range(0, 3000,1);
608 gtk_table_attach(GTK_TABLE(table),entries[5], 4,5,1,2,GTK_EXPAND|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
609 signal_entries[5] = g_signal_connect(G_OBJECT(entries[5]), "value-changed", G_CALLBACK(__field_changed), GINT_TO_POINTER(5));
611 g_signal_connect(G_OBJECT(entries[5]), "key-press-event", G_CALLBACK(__key_release_event), NULL);
615 label = gtk_button_new_from_stock(GTK_STOCK_SAVE);
616 gtk_table_attach(GTK_TABLE(table),label, 5,6,2,3,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
617 g_signal_connect(G_OBJECT(label), "clicked", G_CALLBACK(save_all), NULL);
619 label = gtk_button_new_with_label("Clear tag queue");
620 gtk_button_set_image(GTK_BUTTON(label), gtk_image_new_from_stock(GTK_STOCK_CLEAR, GTK_ICON_SIZE_BUTTON));
621 gtk_table_attach(GTK_TABLE(table),label, 4,5,2,3,GTK_SHRINK|GTK_FILL, GTK_SHRINK|GTK_FILL, 0,0);
622 g_signal_connect(G_OBJECT(label), "clicked", G_CALLBACK(clear_all), NULL);
624 gtk_box_pack_start(GTK_BOX(browser_box), table, FALSE, TRUE,0);
626 g_signal_connect(G_OBJECT(browser_tree), "button-release-event", G_CALLBACK(__button_release_event), NULL);
628 g_signal_connect(G_OBJECT(browser_box), "key-press-event", G_CALLBACK(__key_release_event), NULL);
629 gtk_widget_show_all(browser_box);
630 g_object_ref(browser_box);
632 static void __browser_add ( GtkWidget *cat_tree)
634 GtkTreePath *path = NULL;
635 GtkTreeIter iter;
636 GtkListStore *pl3_tree = (GtkListStore *)gtk_tree_view_get_model(GTK_TREE_VIEW(cat_tree));
637 gint pos = cfg_get_single_value_as_int_with_default(config, CONFIG_NAME,"position",20);
639 if(!cfg_get_single_value_as_int_with_default(config, CONFIG_NAME, "enable", TRUE)) return;
641 debug_printf(DEBUG_INFO,"Adding at position: %i", pos);
642 playlist3_insert_browser(&iter, pos);
643 gtk_list_store_set(GTK_LIST_STORE(pl3_tree), &iter,
644 PL3_CAT_TYPE, plugin.id,
645 PL3_CAT_TITLE, "Tag editor",
646 PL3_CAT_INT_ID, "",
647 PL3_CAT_ICON_ID, "gtk-edit",
648 PL3_CAT_PROC, TRUE,
649 PL3_CAT_ICON_SIZE,GTK_ICON_SIZE_DND,-1);
651 * Clean up old row reference if it exists
653 if (te_ref)
655 gtk_tree_row_reference_free(te_ref);
656 te_ref = NULL;
659 * create row reference
661 path = gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter);
662 if (path)
664 te_ref = gtk_tree_row_reference_new(GTK_TREE_MODEL(playlist3_get_category_tree_store()), path);
665 gtk_tree_path_free(path);
669 static void __browser_selected (GtkWidget *container)
671 if(browser_box == NULL)
673 __browser_init();
675 gtk_container_add(GTK_CONTAINER(container), browser_box);
677 static void __browser_unselected ( GtkWidget *container)
679 gtk_container_remove(GTK_CONTAINER(container), gtk_bin_get_child(GTK_BIN(container)));
682 static void __destroy()
684 if(browser_box) {
685 g_object_unref(browser_box);
686 browser_box = NULL;
688 if(browser_model){
689 g_object_unref(browser_model);
690 browser_model = NULL;
695 * Get/Set enabled
697 static int ___get_enabled()
699 return cfg_get_single_value_as_int_with_default(config, CONFIG_NAME, "enable", TRUE);
701 static void ___set_enabled(int enabled)
703 if(enabled)
705 /* Add the browser to the left pane, if there is none to begin with */
706 if(te_ref == NULL)
708 __browser_add(GTK_WIDGET(playlist3_get_category_tree_view()));
711 else if (te_ref)
713 /* Remove it from the left pane */
714 GtkTreePath *path = gtk_tree_row_reference_get_path(te_ref);
715 if (path){
716 GtkTreeIter iter;
717 /* for a save of myself */
718 __save_myself();
719 if (gtk_tree_model_get_iter(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter, path)){
720 gtk_list_store_remove(playlist3_get_category_tree_store(), &iter);
722 gtk_tree_path_free(path);
723 gtk_tree_row_reference_free(te_ref);
724 te_ref = NULL;
727 cfg_set_single_value_as_int(config, CONFIG_NAME, "enable", enabled);
729 static void __save_myself(void)
731 /* Save the position in the left tree */
732 if (te_ref)
734 GtkTreePath *path = gtk_tree_row_reference_get_path(te_ref);
735 if(path)
737 gint *indices = gtk_tree_path_get_indices(path);
738 debug_printf(DEBUG_INFO,"Saving myself '%s' to position: %i\n",plugin.name, indices[0]);
739 cfg_set_single_value_as_int(config, CONFIG_NAME,"position",indices[0]);
740 gtk_tree_path_free(path);
744 int plugin_api_version = PLUGIN_API_VERSION;
746 gmpcPlBrowserPlugin __browser = {
747 /* browser */
748 .add = __browser_add,
749 .selected = __browser_selected,
750 .unselected = __browser_unselected,
751 .song_list_option_menu = __song_list_option_menu
753 gmpcPrefPlugin __pref = {
754 .construct = __pref_construct,
755 .destroy = __pref_destroy
757 gmpcPlugin plugin = {
758 .name = "Tag Edit",
759 .version = {PLUGIN_MAJOR_VERSION,PLUGIN_MINOR_VERSION,PLUGIN_MICRO_VERSION},
760 .plugin_type = GMPC_PLUGIN_PL_BROWSER,
762 .save_yourself = __save_myself,
763 .destroy = __destroy,
764 .pref = &__pref,
765 .browser = &__browser,
766 .set_enabled = ___set_enabled,
767 .get_enabled = ___get_enabled