3 #include <gdk/gdkkeysyms.h>
4 #include <gmpc/plugin.h>
5 #include <libmpd/libmpd.h>
8 #include "gmpc-mpddata-model-tagedit.h"
10 #define CONFIG_NAME "tagedit"
13 static void __save_myself(void);
14 /* The plugin structure */
18 GtkTreeRowReference
*te_ref
= NULL
;
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
));
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();
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
);
72 static mpd_Song
* get_song_from_file(const char *root
, const char *filename
)
76 mpd_Song
*song
= NULL
;
77 gchar
*url
= g_build_path(G_DIR_SEPARATOR_S
, root
, filename
,NULL
);
79 file
= taglib_file_new(url
);
84 song
->file
= g_strdup(filename
);
85 tag
= taglib_file_tag(file
);
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
);
111 static gboolean
__timeout_mpd_update(gchar
*url
)
113 printf("update: %s\n",url
);
114 mpd_database_update_dir(connection
, url
);
119 static void save_song_to_file(const char *root
, const mpd_Song
*song
)
124 gchar
*url
= g_build_path(G_DIR_SEPARATOR_S
, root
, song
->file
,NULL
);
125 file
= taglib_file_new(url
);
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
);
135 guint track
= (guint
) g_ascii_strtoll(song
->track
, NULL
, 10);
136 taglib_tag_set_track(tag
, track
);
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
);
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
)
166 if(i
->revert
) mpd_freeSong(i
->revert
);
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
));
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
);
182 GList
*iter
= g_list_first(selected
);
183 for(;iter
; iter
= g_list_next(iter
))
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
);
197 si
*i
= g_malloc0(sizeof(*i
));
198 data
= mpd_new_data_struct_append(data
);
199 data
->type
= MPD_DATA_TYPE_SONG
;
202 i
->revert
= mpd_songDup(data
->song
);
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
);
216 static int __song_list_option_menu ( GmpcMpdDataTreeview
*tree
, GtkMenu
*menu
)
219 char *entry_str
= cfg_get_single_value_as_string(config
, CONFIG_NAME
, "music_root");
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
);
231 static void browser_selection_changed(GtkTreeSelection
*selec
, gpointer data
)
233 GList
*selected
= gtk_tree_selection_get_selected_rows(selec
, &browser_model
);
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);
244 GList
*iter
= g_list_first(selected
);
245 for(;iter
; iter
= g_list_next(iter
))
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);
256 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries
[0]))) == 0)
257 gtk_entry_set_text(GTK_ENTRY(entries
[0]), song
->title
);
261 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries
[1]))) == 0)
262 gtk_entry_set_text(GTK_ENTRY(entries
[1]), song
->artist
);
266 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries
[2]))) == 0)
267 gtk_entry_set_text(GTK_ENTRY(entries
[2]), song
->album
);
271 if(strlen(gtk_entry_get_text(GTK_ENTRY(entries
[3]))) == 0)
272 gtk_entry_set_text(GTK_ENTRY(entries
[3]), song
->genre
);
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
);
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
);
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
);
305 GList
*iter
= g_list_first(selected
);
306 for(;iter
; iter
= g_list_next(iter
))
309 if(gtk_tree_model_get_iter(browser_model
, &titer
, iter
->data
))
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
;
332 GList
*selected
= gtk_tree_selection_get_selected_rows(gtk_tree_view_get_selection(GTK_TREE_VIEW(browser_tree
)), &browser_model
);
335 text
= gtk_entry_get_text(GTK_ENTRY(entry
));
339 value
= gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(entry
));
343 GList
*iter
= g_list_first(selected
);
344 for(;iter
; iter
= g_list_next(iter
))
347 if(gtk_tree_model_get_iter(browser_model
, &titer
, iter
->data
))
349 mpd_Song
*song
= NULL
;
351 gtk_tree_model_get(browser_model
, &titer
, MPDDATA_MODEL_COL_MPDSONG
, &song
,MPDDATA_MODEL_USERDATA
, &ud
, -1);
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)
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);
375 ud
->changed
|= (1<<1);
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);
387 ud
->changed
|= (1<<2);
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);
398 ud
->changed
|= (1<<3);
399 gtk_tree_model_row_changed(browser_model
, (GtkTreePath
*)iter
->data
, &titer
);
405 val
= (guint
)g_ascii_strtoll(song
->date
, NULL
, 10);
408 if(song
->date
) g_free(song
->date
);
410 song
->date
= g_strdup_printf("%i", value
);
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);
419 ud
->changed
|= (1<<4);
420 gtk_tree_model_row_changed(browser_model
, (GtkTreePath
*)iter
->data
, &titer
);
426 val
= (guint
)g_ascii_strtoll(song
->track
, NULL
, 10);
429 if(song
->track
) g_free(song
->track
);
431 song
->track
= g_strdup_printf("%i", value
);
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);
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");
457 if(root
&& gtk_tree_model_get_iter_first(browser_model
, &iter
))
460 mpd_Song
*song
= NULL
;
462 gtk_tree_model_get(browser_model
, &iter
, MPDDATA_MODEL_COL_MPDSONG
, &song
, MPDDATA_MODEL_USERDATA
, &ud
,-1);
465 /* check if song changed */
468 printf("saving: %s\n", song
->file
);
469 save_song_to_file(root
, song
);
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)
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
);
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
);
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
);
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
);
548 static void __browser_init ( )
550 GtkWidget
*sw
= NULL
, *label
;
551 GtkWidget
*table
= NULL
;
552 browser_box
= gtk_vbox_new(FALSE
, 6);
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
);
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));
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));
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));
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));
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
);
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
;
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",
647 PL3_CAT_ICON_ID
, "gtk-edit",
649 PL3_CAT_ICON_SIZE
,GTK_ICON_SIZE_DND
,-1);
651 * Clean up old row reference if it exists
655 gtk_tree_row_reference_free(te_ref
);
659 * create row reference
661 path
= gtk_tree_model_get_path(GTK_TREE_MODEL(playlist3_get_category_tree_store()), &iter
);
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
)
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()
685 g_object_unref(browser_box
);
689 g_object_unref(browser_model
);
690 browser_model
= NULL
;
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
)
705 /* Add the browser to the left pane, if there is none to begin with */
708 __browser_add(GTK_WIDGET(playlist3_get_category_tree_view()));
713 /* Remove it from the left pane */
714 GtkTreePath
*path
= gtk_tree_row_reference_get_path(te_ref
);
717 /* for a save of 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
);
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 */
734 GtkTreePath
*path
= gtk_tree_row_reference_get_path(te_ref
);
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
= {
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
= {
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
,
765 .browser
= &__browser
,
766 .set_enabled
= ___set_enabled
,
767 .get_enabled
= ___get_enabled