1 /*
2 |  Copyright (C) 2007 Maia Kozheva <sikon at users sourceforge net>
3 |  Part of the gtkpod project.
4 |
5 |  URL: http://www.gtkpod.org/
6 |  URL: http://gtkpod.sourceforge.net/
7 |
8 |  This program is free software; you can redistribute it and/or modify
9 |  it under the terms of the GNU General Public License as published by
10 |  the Free Software Foundation; either version 2 of the License, or
11 |  (at your option) any later version.
12 |
13 |  This program is distributed in the hope that it will be useful,
14 |  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 |  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 |  GNU General Public License for more details.
17 |
18 |  You should have received a copy of the GNU General Public License
19 |  along with this program; if not, write to the Free Software
20 |  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 |
22 |  iTunes and iPod are trademarks of Apple
23 |
24 |  This product is not supported/written/published by Apple!
25 */
26 
27 #ifdef HAVE_CONFIG_H
28 #  include <config.h>
29 #endif
30 
31 #include <glib.h>
32 #include <gtk/gtk.h>
33 #include <string.h>
34 #include "charset.h"
35 #include "misc.h"
36 #include "help.h"
37 #include "prefs.h"
38 #include "display_coverart.h"
39 #include "sort_window.h"
40 
41 /*
42 	Begin types
43 */
44 typedef struct _ind_string
45 {
46 	gint index;
47 	const gchar *string;
48 } ind_string;
49 
50 ind_string toolbar_styles[] = {
51 	{ -1, N_("Hide") },
52 	{ GTK_TOOLBAR_ICONS, N_("Icons only") },
53 	{ GTK_TOOLBAR_TEXT, N_("Text only") },
54 	{ GTK_TOOLBAR_BOTH, N_("Text under icons") },
55 	{ GTK_TOOLBAR_BOTH_HORIZ, N_("Text beside icons") },
56 	{ -1, NULL }
57 };
58 
59 #define IND_STRING_END(x, i) ((x)[i].string == NULL)
60 #define COUNTOF(x) (sizeof(x) / sizeof((x)[0]))
61 
62 /*
63 	Begin data
64 
65 	0: checkbox glade ID
66 	1: preference
67 	2: dependency glade IDs, comma-separated
68 */
69 const gchar *checkbox_map[][3] = {
70 	/* Display tab */
71 	{ "filter_tabs_top", "filter_tabs_top", NULL },
72 	{ "horizontal_scrollbar", "horizontal_scrollbar", NULL },
73 	{ "group_compilations", "group_compilations", NULL },
74 	{ "display_tooltips", "display_tooltips_main", NULL },
75 	/* Music tab */
76 	{ "background_transfer", "file_convert_background_transfer", NULL },
77 	{ "add_subfolders", "add_recursively", NULL },
78 	{ "allow_duplicates", "!sha1", NULL },
79 	{ "delete_missing", "sync_delete_tracks", NULL },
80 	{ "update_existing_track", "update_existing", NULL },
81 	{ "include_neverplayed", "not_played_track", NULL },
82 	/* Metadata tab */
83 	{ "read_tags", "readtags", NULL },
84 	{ "parse_filename_tags", "parsetags", "customize_tags" },
85 	{ "last_resort_tags", NULL, "tag_title,tag_artist,tag_album,tag_composer,tag_genre" },
86 	{ "write_tags", "id3_write", "tag_encoding,write_tags_legacy" },
87 	{ "write_tags_legacy", "!id3_write_id3v24", NULL },
88 	{ "mass_modify_tags", "multi_edit", NULL },
89 	{ "read_coverart", "coverart_apic", NULL },
90 	{ "template_coverart", "coverart_file", "customize_coverart" },
91 	{ "generate_video_thumbnails", "video_thumbnailer", "customize_video_thumbnailer" },
92 	/* Feedback tab */
93 	{ "confirm_del_tracks", NULL, "confirm_from_ipod,confirm_from_hdd,confirm_from_db" },
94 	{ "confirm_from_ipod", "delete_ipod", NULL },
95 	{ "confirm_from_hdd", "delete_local_file", NULL },
96 	{ "confirm_from_db", "delete_database", NULL },
97 	{ "confirm_del_pl", "delete_file", NULL },
98 	{ "confirm_del_sync", "sync_confirm_delete", NULL },
99 	{ "msg_startup", "startup_messages", NULL },
100 	{ "msg_duplicates", "show_duplicates", NULL },
101 	{ "msg_results", "sync_show_summary", NULL },
102 	{ "msg_updated", "show_updated", NULL },
103 	{ "msg_unupdated", "show_non_updated", NULL },
104 };
105 
106 const gchar *conv_checkbox_map[][3] = {
107 	{ "convert_ogg", "convert_ogg", NULL },
108 	{ "convert_flac", "convert_flac", NULL },
109 	{ "convert_mp3", "convert_mp3", NULL },
110 	{ "convert_aac", "convert_m4a", NULL },
111 	{ "convert_wav", "convert_wav", NULL },
112 	{ "display_conversion_log", "", NULL },
113 };
114 
115 ind_string tag_checkbox_map[] = {
116 	{ 0, "tag_title" },
117 	{ 1, "tag_artist" },
118 	{ 2, "tag_album" },
119 	{ 3, "tag_genre" },
120 	{ 4, "tag_composer" },
121 };
122 
123 const gchar *conv_scripts[] = {
124 	"convert-2mp3.sh",
125 	"convert-2m4a.sh",
126 };
127 
128 ind_string conv_paths[] = {
129 	{ -1, "path_conv_ogg" },
130     { -1, "path_conv_flac" },
131     { TARGET_FORMAT_AAC, "path_conv_m4a" },
132     { TARGET_FORMAT_MP3, "path_conv_mp3" },
133     { -1, "path_conv_wav" },
134 };
135 
136 static GladeXML *prefs_xml = NULL;
137 static GtkWidget *prefs_dialog = NULL;
138 static TempPrefs *temp_prefs = NULL;
139 
140 /*
141 	Convenience functions
142 */
combo_box_clear(GtkComboBox * combo)143 void combo_box_clear (GtkComboBox *combo)
144 {
145 	GtkListStore *store;
146 	GtkTreeModel *model = gtk_combo_box_get_model (combo);
147 	g_return_if_fail (GTK_IS_LIST_STORE (model));
148 	store = GTK_LIST_STORE (model);
149 	gtk_list_store_clear (store);
150 }
151 
ind_string_find(ind_string * array,gint index)152 gint ind_string_find(ind_string *array, gint index)
153 {
154 	gint i;
155 
156 	for(i = 0; !IND_STRING_END(array, i); i++)
157 	{
158 		if(array[i].index == index)
159 			return i;
160 	}
161 
162 	return -1;
163 }
164 
ind_string_fill_combo(ind_string * array,GtkComboBox * combo)165 void ind_string_fill_combo (ind_string *array, GtkComboBox *combo)
166 {
167 	gint i;
168 	combo_box_clear(combo);
169 
170 	for (i = 0; !IND_STRING_END(array, i); i++)
171 	{
172 		gtk_combo_box_append_text(combo, gettext(array[i].string));
173 	}
174 }
175 
update_checkbox_deps(GtkToggleButton * checkbox,const gchar * deps)176 void update_checkbox_deps (GtkToggleButton *checkbox, const gchar *deps)
177 {
178 	/* Enable or disable dependent checkboxes */
179 	GladeXML *xml = GLADE_XML (g_object_get_data (G_OBJECT (checkbox), "xml"));
180 	gboolean active = gtk_toggle_button_get_active (checkbox);
181 	gchar **deparray;
182 	int i;
183 
184 	if(!xml || !deps)
185 		return;
186 
187 	deparray = g_strsplit (deps, ",", 0);
188 
189 	for(i = 0; deparray[i]; i++)
190 	{
191 		GtkWidget *dep = gtkpod_xml_get_widget (xml, deparray[i]);
192 		gtk_widget_set_sensitive (dep, active);
193 	}
194 
195 	g_strfreev (deparray);
196 }
197 
init_checkbox(GtkToggleButton * checkbox,GladeXML * xml,const gchar * pref,const gchar * deps)198 static void init_checkbox (GtkToggleButton *checkbox, GladeXML *xml, const gchar *pref, const gchar *deps)
199 {
200 	g_object_set_data(G_OBJECT(checkbox), "pref", (gchar *) pref);
201 	g_object_set_data(G_OBJECT(checkbox), "deps", (gchar *) deps);
202 	g_object_set_data(G_OBJECT(checkbox), "xml", xml);
203 
204 	if(pref)
205 	{
206 		if(pref[0] == '!')		/* Checkbox is !preference */
207 			gtk_toggle_button_set_active(checkbox, !prefs_get_int(pref + 1));
208 		else
209 			gtk_toggle_button_set_active(checkbox, prefs_get_int(pref));
210 	}
211 
212 	update_checkbox_deps (checkbox, deps);
213 }
214 
column_tree_sort(GtkTreeModel * model,GtkTreeIter * a,GtkTreeIter * b,gpointer user_data)215 static gint column_tree_sort (GtkTreeModel *model,
216 							  GtkTreeIter *a,
217 							  GtkTreeIter *b,
218 							  gpointer user_data)
219 {
220     gchar *str1, *str2;
221     gint result;
222 
223     gtk_tree_model_get (model, a, 0, &str1, -1);
224     gtk_tree_model_get (model, b, 0, &str2, -1);
225     result = g_utf8_collate (str1, str2);
226 
227     g_free (str1);
228     g_free (str2);
229     return result;
230 }
231 
setup_column_tree(GtkTreeView * treeview,gboolean list_visible)232 static void setup_column_tree (GtkTreeView *treeview, gboolean list_visible)
233 {
234     GtkListStore *store;
235     GtkTreeIter iter;
236     GtkTreeViewColumn *column;
237     GtkCellRenderer *renderer;
238     gint i;
239 
240 	/* Delete any existing columns first */
241 	while (TRUE)
242 	{
243 		column = gtk_tree_view_get_column (treeview, 0);
244 
245 		if (!column)
246 			break;
247 
248 		gtk_tree_view_remove_column (treeview, column);
249 	}
250 
251     store = gtk_list_store_new (2, G_TYPE_STRING, G_TYPE_INT);
252     column = gtk_tree_view_column_new ();
253     renderer = gtk_cell_renderer_text_new ();
254 
255 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
256     gtk_tree_view_column_set_attributes (column, renderer, "text", 0, NULL);
257 
258     gtk_tree_view_append_column (treeview, column);
259     gtk_tree_view_set_model (treeview, GTK_TREE_MODEL (store));
260 
261     g_object_unref (G_OBJECT (store));
262 
263     for (i = 0; i < TM_NUM_COLUMNS; i++)
264     {
265 		gint visible = prefs_get_int_index("col_visible", i);
266 
267 		if ((!list_visible && visible) || (list_visible && !visible))
268 			continue;
269 
270 		gtk_list_store_append (store, &iter);
271 		gtk_list_store_set(store, &iter,
272 				   0, gettext (get_tm_string (i)),
273 				   1, i, -1);
274     }
275 
276 	if(!list_visible)
277 	{
278 		/* Sort invisible columns */
279 		gtk_tree_sortable_set_default_sort_func (GTK_TREE_SORTABLE (store),
280 							 column_tree_sort,
281 							 NULL,
282 							 NULL);
283 
284 		gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE (store),
285 						  GTK_TREE_SORTABLE_DEFAULT_SORT_COLUMN_ID,
286 						  GTK_SORT_ASCENDING);
287 	}
288 }
289 
tree_get_current_iter(GtkTreeView * view,GtkTreeIter * iter)290 static gboolean tree_get_current_iter (GtkTreeView *view, GtkTreeIter *iter)
291 {
292 	GtkTreeModel *model = gtk_tree_view_get_model (view);
293 	GtkTreePath *path;
294 
295 	gtk_tree_view_get_cursor (view, &path, NULL);
296 
297 	if (!path)
298 		return FALSE;
299 
300 	gtk_tree_model_get_iter (model, iter, path);
301 	gtk_tree_path_free (path);
302 
303 	return TRUE;
304 }
305 
306 /*
307 	Disconnects all signals connected to a GtkWidget.
308 	The "data" paremeter is ignored.
309 */
disconnect_signals_internal(GtkWidget * widget,gpointer data)310 static void disconnect_signals_internal (GtkWidget *widget, gpointer data)
311 {
312 	GType type;
313 
314 	for (type = G_TYPE_FROM_INSTANCE (widget);
315 		 type && type != GTK_TYPE_OBJECT && type != GTK_TYPE_WIDGET;
316 		 type = g_type_parent (type))
317 	{
318 		guint i;
319 		guint n_ids;
320 		guint *ids;
321 
322 		ids = g_signal_list_ids (type, &n_ids);
323 
324 		for (i = 0; i < n_ids; i++)
325 		{
326 			gint handler;
327 
328 			while (TRUE)
329 			{
330 				handler = g_signal_handler_find (widget, G_SIGNAL_MATCH_ID, ids[i], 0, NULL, NULL, NULL);
331 
332 				if (!handler)
333 					break;
334 
335 				g_signal_handler_disconnect (widget, handler);
336 			}
337 		}
338 	}
339 }
340 
disconnect_all_internal(GtkWidget * widget,gpointer data)341 static void disconnect_all_internal (GtkWidget *widget, gpointer data)
342 {
343 	disconnect_signals_internal (widget, NULL);
344 
345 	if (GTK_IS_CONTAINER (widget))
346 	{
347 		gtk_container_foreach (GTK_CONTAINER (widget), disconnect_all_internal, NULL);
348 	}
349 }
350 
351 /*
352 	Recursively disconnects all signals connected to a GtkWidget and its children.
353 */
disconnect_all(GtkWidget * widget)354 static void disconnect_all (GtkWidget *widget)
355 {
356 	disconnect_all_internal (widget, NULL);
357 }
358 
359 /*
360 	Real functions
361 */
setup_prefs_dlg(GladeXML * xml,GtkWidget * dlg)362 void setup_prefs_dlg (GladeXML *xml, GtkWidget *dlg)
363 {
364 	gint i;
365 	GtkWidget *toolbar_style_combo = gtkpod_xml_get_widget (xml, "toolbar_style");
366 	GtkWidget *skip_track_update_radio = gtkpod_xml_get_widget (xml, "skip_track_update");
367 	GtkWidget *filter_tabs_bottom_radio = gtkpod_xml_get_widget (xml, "filter_tabs_bottom");
368 	GtkWidget *coverart_bgcolorselect_button = gtkpod_xml_get_widget (xml, "coverart_display_bg_button");
369 	GtkWidget *coverart_fgcolorselect_button = gtkpod_xml_get_widget (xml, "coverart_display_fg_button");
370 	GdkColor *color;
371 
372 	/* Display */
373 
374 	/* Toolbar */
375 	ind_string_fill_combo(toolbar_styles, GTK_COMBO_BOX (toolbar_style_combo));
376 
377 	if (!prefs_get_int("display_toolbar"))
378 	{
379 		gtk_combo_box_set_active(GTK_COMBO_BOX (toolbar_style_combo),
380 								 ind_string_find(toolbar_styles, -1));
381 	}
382 	else
383 	{
384 		gint style = prefs_get_int("toolbar_style");
385 		gint index = ind_string_find(toolbar_styles, style);
386 
387 		gtk_combo_box_set_active(GTK_COMBO_BOX (toolbar_style_combo), index);
388 	}
389 	/* End toolbar */
390 
391 	/* Columns */
392 	setup_column_tree (GTK_TREE_VIEW (gtkpod_xml_get_widget (xml, "displayed_columns")), TRUE);
393 
394 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtkpod_xml_get_widget (xml, "filter_tabs_count")),
395 							   prefs_get_int("sort_tab_num"));
396 
397 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtkpod_xml_get_widget (xml, "agp_track_count")),
398 							   prefs_get_int("misc_track_nr"));
399 
400 	/* Check boxes */
401 	for (i = 0; i < COUNTOF(checkbox_map); i++)
402 	{
403 		init_checkbox (GTK_TOGGLE_BUTTON (gtkpod_xml_get_widget (xml, checkbox_map[i][0])),
404 					   xml, checkbox_map[i][1], checkbox_map[i][2]);
405 	}
406 
407 	for (i = 0; i < COUNTOF(tag_checkbox_map); i++)
408 	{
409 		GtkWidget *widget = gtkpod_xml_get_widget (xml, tag_checkbox_map[i].string);
410 		g_object_set_data (G_OBJECT (widget), "index", &tag_checkbox_map[i].index);
411 
412 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget),
413 									  prefs_get_int_index ("tag_autoset", tag_checkbox_map[i].index));
414 	}
415 
416 	if(!prefs_get_int("update_existing"))
417 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (skip_track_update_radio), TRUE);
418 
419 	if(!prefs_get_int("filter_tabs_top"))
420 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (filter_tabs_bottom_radio), TRUE);
421 
422 	color = coverart_get_background_display_color();
423 	gtk_color_button_set_color (GTK_COLOR_BUTTON(coverart_bgcolorselect_button), color);
424 	g_free (color);
425 
426 	color = coverart_get_foreground_display_color();
427 	gtk_color_button_set_color (GTK_COLOR_BUTTON(coverart_fgcolorselect_button), color);
428 	g_free (color);
429 
430 	gtk_combo_box_set_active (GTK_COMBO_BOX (gtkpod_xml_get_widget (xml, "target_format")),
431 							  prefs_get_int ("conversion_target_format"));
432 }
433 
434 /*
435 	glade callback
436 */
open_prefs_dlg()437 G_MODULE_EXPORT void open_prefs_dlg ()
438 {
439 	if(prefs_dialog)
440 	{
441 		gtk_window_present(GTK_WINDOW(prefs_dialog));
442 		return;
443 	}
444 
445     temp_prefs = temp_prefs_create();
446 	temp_prefs_copy_prefs (temp_prefs);
447 
448 	prefs_xml = gtkpod_xml_new (xml_file, "prefs_dialog");
449 	prefs_dialog = gtkpod_xml_get_widget (prefs_xml, "prefs_dialog");
450 
451 	setup_prefs_dlg(prefs_xml, prefs_dialog);
452 	/*
453 		This is after setup because we don't want on_changed signals to fire
454 		during setup
455 	*/
456 	glade_xml_signal_autoconnect (prefs_xml);
457 	gtk_widget_show(prefs_dialog);
458 }
459 
460 /*
461 	glade callback
462 */
on_prefs_dialog_help()463 G_MODULE_EXPORT void on_prefs_dialog_help ()
464 {
465 	gtkpod_open_help_context ("gtkpod");
466 }
467 
468 /*
469 	glade callback
470 */
on_prefs_dialog_close()471 G_MODULE_EXPORT void on_prefs_dialog_close ()
472 {
473 	if (!prefs_dialog)
474 		return;
475 
476 	gtk_widget_destroy(prefs_dialog);
477 	g_object_unref(prefs_xml);
478     temp_prefs_destroy(temp_prefs);
479 
480 	prefs_dialog = NULL;
481 	prefs_xml = NULL;
482 	temp_prefs = NULL;
483 }
484 
485 /*
486 	glade callback
487 */
on_prefs_dialog_revert()488 G_MODULE_EXPORT void on_prefs_dialog_revert ()
489 {
490 	disconnect_all (prefs_dialog);
491     temp_prefs_apply (temp_prefs);
492 	setup_prefs_dlg (prefs_xml, prefs_dialog);
493 	glade_xml_signal_autoconnect (prefs_xml);
494 
495 	/* Apply all */
496 	tm_store_col_order ();
497 
498 	tm_show_preferred_columns();
499 	st_show_visible();
500 	display_show_hide_tooltips();
501 	display_show_hide_toolbar();
502 
503 	file_convert_prefs_changed ();
504 }
505 
506 /*
507 	glade callback
508 */
on_filter_tabs_count_value_changed(GtkSpinButton * sender,gpointer e)509 G_MODULE_EXPORT void on_filter_tabs_count_value_changed (GtkSpinButton *sender, gpointer e)
510 {
511     gint num = gtk_spin_button_get_value_as_int (sender);
512 
513 	/* Update the number of filter tabs */
514     prefs_set_int ("sort_tab_num", num);
515 	st_show_visible();
516 }
517 
518 /*
519 	glade callback
520 */
on_agp_track_count_value_changed(GtkSpinButton * sender,gpointer e)521 G_MODULE_EXPORT void on_agp_track_count_value_changed (GtkSpinButton *sender, gpointer e)
522 {
523     gint num = gtk_spin_button_get_value_as_int (sender);
524     prefs_set_int ("misc_track_nr", num);
525 }
526 
527 /*
528 	glade callback
529 */
on_toolbar_style_changed(GtkComboBox * sender,gpointer e)530 G_MODULE_EXPORT void on_toolbar_style_changed (GtkComboBox *sender, gpointer e)
531 {
532 	gint index = toolbar_styles[gtk_combo_box_get_active(sender)].index;
533 
534 	if (index == -1)
535 	{
536 		prefs_set_int ("display_toolbar", 0);
537 	}
538 	else
539 	{
540 		prefs_set_int ("display_toolbar", 1);
541 		prefs_set_int ("toolbar_style", index);
542 	}
543 
544 	display_show_hide_toolbar ();
545 }
546 
547 /*
548 	generic glade callback, used by many checkboxes
549 */
on_simple_checkbox_toggled(GtkToggleButton * sender,gpointer e)550 G_MODULE_EXPORT void on_simple_checkbox_toggled (GtkToggleButton *sender, gpointer e)
551 {
552 	gboolean active = gtk_toggle_button_get_active (sender);
553 	gchar *pref = (gchar *) g_object_get_data (G_OBJECT(sender), "pref");
554 	gchar *deps = (gchar *) g_object_get_data (G_OBJECT(sender), "deps");
555 
556 	if(pref)
557 	{
558 		if(pref[0] == '!')		/* Checkbox is !preference */
559 			prefs_set_int(pref + 1, !active);
560 		else
561 			prefs_set_int(pref, active);
562 	}
563 
564 	update_checkbox_deps (sender, deps);
565 }
566 
567 /*
568 	glade callback
569 */
on_tag_checkbox_toggled(GtkToggleButton * sender,gpointer e)570 G_MODULE_EXPORT void on_tag_checkbox_toggled (GtkToggleButton *sender, gpointer e)
571 {
572 	gint index = *(gint *) g_object_get_data (G_OBJECT(sender), "index");
573 	prefs_set_int_index ("tag_autoset", index, gtk_toggle_button_get_active (sender));
574 }
575 
576 /*
577 	glade callback
578 */
on_browse_button_clicked(GtkButton * sender,gpointer e)579 G_MODULE_EXPORT void on_browse_button_clicked (GtkButton *sender, gpointer e)
580 {
581 	GtkWidget *dialog;
582 	gchar *base, *args, *path;
583 	const gchar *space, *current;
584 	GtkEntry *entry = GTK_ENTRY (g_object_get_data (G_OBJECT (sender), "entry"));
585 
586 	g_return_if_fail (entry);
587 
588 	dialog = gtk_file_chooser_dialog_new (_("Browse"),
589 										  GTK_WINDOW (gtk_widget_get_toplevel (GTK_WIDGET (sender))),
590 										  GTK_FILE_CHOOSER_ACTION_OPEN,
591 										  GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
592 										  GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
593 										  NULL);
594 
595 
596 	current = gtk_entry_get_text (entry);
597 	/* separate filename from command line arguments */
598 	space = strchr (current, ' ');
599 	if (space)
600 	{
601 	    base = g_strndup (current, space-current);
602 	    args = g_strdup (space);
603 	}
604 	else
605 	{
606 	    base = g_strdup (current);
607 	    args = NULL;
608 	}
609 
610 	path = g_find_program_in_path (base);
611 
612 	if (path)
613 	{
614 	    gtk_file_chooser_set_filename (GTK_FILE_CHOOSER (dialog), path);
615 	}
616 	else
617 	{
618 	    gchar *dir = g_path_get_dirname (base);
619 	    if (dir)
620 	    {
621 		if (g_file_test (dir, G_FILE_TEST_IS_DIR) && g_path_is_absolute (dir))
622 		{
623 		    gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
624 							 dir);
625 		}
626 	    }
627 	    g_free (dir);
628 	}
629 
630 	if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_ACCEPT)
631 	{
632 	    gchar *filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
633 	    if (args)
634 	    {  /* add args to filename */
635 		gchar *new = g_strdup_printf ("%s%s", filename, args);
636 		gtk_entry_set_text (entry, new);
637 		g_free (new);
638 	    }
639 	    else
640 	    {
641 		gtk_entry_set_text (entry, filename);
642 	    }
643 	    g_free (filename);
644 	}
645 
646 	gtk_widget_destroy (GTK_WIDGET (dialog));
647 
648 	g_free (base);
649 	g_free (path);
650 	g_free (args);
651 }
652 
653 /*
654 	glade callback
655 */
on_group_compilations_toggled(GtkToggleButton * sender,gpointer e)656 G_MODULE_EXPORT void on_group_compilations_toggled (GtkToggleButton *sender, gpointer e)
657 {
658 	gboolean active = gtk_toggle_button_get_active (sender);
659 
660 	prefs_set_int ("group_compilations", active);
661 	st_show_visible();
662 }
663 
664 /*
665 	glade callback
666 */
on_display_tooltips_toggled(GtkToggleButton * sender,gpointer e)667 G_MODULE_EXPORT void on_display_tooltips_toggled (GtkToggleButton *sender, gpointer e)
668 {
669 	gboolean active = gtk_toggle_button_get_active (sender);
670 
671 	prefs_set_int ("display_tooltips", active);
672 	display_show_hide_tooltips ();
673 }
674 
675 /*
676 	glade callback
677 */
on_filter_tabs_top_toggled(GtkToggleButton * sender,gpointer e)678 G_MODULE_EXPORT void on_filter_tabs_top_toggled (GtkToggleButton *sender, gpointer e)
679 {
680 	gboolean active = gtk_toggle_button_get_active (sender);
681 
682 	prefs_set_int ("filter_tabs_top", active);
683 	st_update_paned_position ();
684 }
685 
686 /*
687 	glade callback
688 */
on_horizontal_scrollbar_toggled(GtkToggleButton * sender,gpointer e)689 G_MODULE_EXPORT void on_horizontal_scrollbar_toggled (GtkToggleButton *sender, gpointer e)
690 {
691 	gboolean active = gtk_toggle_button_get_active (sender);
692 
693 	prefs_set_int ("horizontal_scrollbar", active);
694 	tm_show_preferred_columns ();
695 }
696 
697 /*
698 	glade callback
699 */
on_column_add_clicked(GtkButton * sender,gpointer e)700 G_MODULE_EXPORT void on_column_add_clicked (GtkButton *sender, gpointer e)
701 {
702 	gint i;
703 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_columns_dialog");
704 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_columns_dialog");
705 	GtkTreeView *view = GTK_TREE_VIEW (gtkpod_xml_get_widget (xml, "available_columns"));
706 	GtkTreeModel *model;
707 	GtkTreeIter iter;
708 
709 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
710 	setup_column_tree (view, FALSE);
711 
712 	/* User pressed Cancel */
713 	if(!gtk_dialog_run (GTK_DIALOG (dlg)))
714 	{
715 		gtk_widget_destroy (dlg);
716 		g_object_unref (xml);
717 		return;
718 	}
719 
720 	/* User pressed Add */
721 	model = gtk_tree_view_get_model (view);
722 	tree_get_current_iter (view, &iter);
723 	gtk_tree_model_get (model, &iter, 1, &i, -1);
724 
725 	gtk_widget_destroy (dlg);
726 	g_object_unref (xml);
727 
728 	view = GTK_TREE_VIEW (gtkpod_xml_get_widget (prefs_xml, "displayed_columns"));
729 	model = gtk_tree_view_get_model (view);
730 
731 	gtk_list_store_append (GTK_LIST_STORE (model), &iter);
732 	gtk_list_store_set(GTK_LIST_STORE (model), &iter,
733 			   0, gettext (get_tm_string (i)),
734 			   1, i, -1);
735 
736 	prefs_set_int_index ("col_visible", i, TRUE);
737 	tm_store_col_order ();
738 	tm_show_preferred_columns ();
739 }
740 
741 /*
742 	glade callback
743 */
on_column_remove_clicked(GtkButton * sender,gpointer e)744 G_MODULE_EXPORT void on_column_remove_clicked (GtkButton *sender, gpointer e)
745 {
746 	gint i;
747 	GtkTreeView *view = GTK_TREE_VIEW (gtkpod_xml_get_widget (prefs_xml, "displayed_columns"));
748 	GtkTreeModel *model = gtk_tree_view_get_model (view);
749 	GtkTreeIter iter;
750 
751 	if(!tree_get_current_iter (view, &iter) || !gtk_list_store_iter_is_valid (GTK_LIST_STORE (model), &iter))
752 		return;
753 
754 	gtk_tree_model_get (model, &iter, 1, &i, -1);
755 	gtk_list_store_remove (GTK_LIST_STORE (model), &iter);
756 
757 	prefs_set_int_index ("col_visible", i, FALSE);
758 	tm_store_col_order ();
759 	tm_show_preferred_columns ();
760 }
761 
762 /*
763 	glade callback
764 */
on_unsetdeps_checkbox_toggled(GtkToggleButton * sender,gpointer e)765 G_MODULE_EXPORT void on_unsetdeps_checkbox_toggled (GtkToggleButton *sender, gpointer e)
766 {
767 	GladeXML *xml = GLADE_XML (g_object_get_data (G_OBJECT(sender), "xml"));
768 
769 	if(xml && !gtk_toggle_button_get_active (sender))
770 	{
771 		int i;
772 		const gchar *deps = (gchar *) g_object_get_data (G_OBJECT(sender), "deps");
773 		gchar **deparray = g_strsplit (deps, ",", 0);
774 
775 		for(i = 0; deparray[i]; i++)
776 		{
777 			GtkWidget *dep = gtkpod_xml_get_widget (xml, deparray[i]);
778 			gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dep), FALSE);
779 		}
780 		g_strfreev (deparray);
781 	}
782 
783 	/* and then call the default handler */
784 	on_simple_checkbox_toggled (sender, e);
785 }
786 
787 /*
788 	glade callback
789 */
on_coverart_dialog_bg_color_set(GtkColorButton * widget,gpointer user_data)790 G_MODULE_EXPORT void on_coverart_dialog_bg_color_set (GtkColorButton *widget, gpointer user_data)
791 {
792 	GdkColor color;
793 	gtk_color_button_get_color (widget, &color);
794 	gchar *hexstring = g_strdup_printf("#%02X%02X%02X",
795 									   color.red >> 8,
796 									   color.green >> 8,
797 									   color.blue >> 8);
798 
799 	prefs_set_string ("coverart_display_bg_color", hexstring);
800 	g_free (hexstring);
801 	coverart_display_update (FALSE);
802 }
803 
804 /*
805 	glade callback
806 */
on_coverart_dialog_fg_color_set(GtkColorButton * widget,gpointer user_data)807 G_MODULE_EXPORT void on_coverart_dialog_fg_color_set (GtkColorButton *widget, gpointer user_data)
808 {
809 	GdkColor color;
810 	gtk_color_button_get_color (widget, &color);
811 	gchar *hexstring = g_strdup_printf("#%02X%02X%02X",
812 									   color.red >> 8,
813 									   color.green >> 8,
814 									   color.blue >> 8);
815 
816 	prefs_set_string ("coverart_display_fg_color", hexstring);
817 	g_free (hexstring);
818 	coverart_display_update (FALSE);
819 }
820 
821 /*
822 	glade callback
823 */
open_encoding_dialog(GtkButton * sender,gpointer e)824 G_MODULE_EXPORT void open_encoding_dialog (GtkButton *sender, gpointer e)
825 {
826 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_encoding_dialog");
827 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_encoding_dialog");
828 	GtkWidget *combo = gtkpod_xml_get_widget (xml, "encoding_combo");
829 
830 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
831 
832 	init_checkbox (GTK_TOGGLE_BUTTON (gtkpod_xml_get_widget (xml, "use_encoding_for_update")),
833 				   xml, "update_charset", NULL);
834 
835 	init_checkbox (GTK_TOGGLE_BUTTON (gtkpod_xml_get_widget (xml, "use_encoding_for_writing")),
836 				   xml, "write_charset", NULL);
837 
838 	charset_init_combo_box (GTK_COMBO_BOX (combo));
839 	glade_xml_signal_autoconnect (xml);
840 	gtk_dialog_run (GTK_DIALOG (dlg));
841 	gtk_widget_destroy (dlg);
842 	g_object_unref (xml);
843 }
844 
845 /*
846 	glade callback
847 */
on_encoding_combo_changed(GtkComboBox * sender,gpointer e)848 G_MODULE_EXPORT void on_encoding_combo_changed (GtkComboBox *sender, gpointer e)
849 {
850 	gchar *description = gtk_combo_box_get_active_text (sender);
851 	gchar *charset = charset_from_description (description);
852 
853 	prefs_set_string ("charset", charset);
854 	g_free (charset);
855 }
856 
857 /*
858 	glade callback
859 */
on_customize_tags_clicked(GtkButton * sender,gpointer e)860 G_MODULE_EXPORT void on_customize_tags_clicked (GtkButton *sender, gpointer e)
861 {
862 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_tag_parse_dialog");
863 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_tag_parse_dialog");
864 	gchar *temp = prefs_get_string("parsetags_template");
865 
866 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
867 
868 	if(temp)
869 	{
870 		gtk_entry_set_text (GTK_ENTRY (gtkpod_xml_get_widget (xml, "filename_pattern")),
871 							temp);
872 
873 		g_free (temp);
874 	}
875 
876 	init_checkbox (GTK_TOGGLE_BUTTON (gtkpod_xml_get_widget (xml, "overwrite_tags")),
877 				   xml, "parsetags_overwrite", NULL);
878 
879 	glade_xml_signal_autoconnect (xml);
880 	gtk_dialog_run (GTK_DIALOG (dlg));
881 	gtk_widget_destroy (dlg);
882 	g_object_unref (xml);
883 }
884 
885 /*
886 	glade callback
887 */
on_filename_pattern_changed(GtkEditable * sender,gpointer e)888 G_MODULE_EXPORT void on_filename_pattern_changed (GtkEditable *sender, gpointer e)
889 {
890 	prefs_set_string ("parsetags_template", gtk_entry_get_text (GTK_ENTRY (sender)));
891 }
892 
893 /*
894 	glade callback
895 */
on_customize_coverart_clicked(GtkButton * sender,gpointer e)896 G_MODULE_EXPORT void on_customize_coverart_clicked (GtkButton *sender, gpointer e)
897 {
898 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_coverart_dialog");
899 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_coverart_dialog");
900 	gchar *temp = prefs_get_string("coverart_template");
901 
902 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
903 
904 	if(temp)
905 	{
906 		gtk_entry_set_text (GTK_ENTRY (gtkpod_xml_get_widget (xml, "coverart_pattern")),
907 							temp);
908 
909 		g_free (temp);
910 	}
911 
912 	glade_xml_signal_autoconnect (xml);
913 	gtk_dialog_run (GTK_DIALOG (dlg));
914 	gtk_widget_destroy (dlg);
915 	g_object_unref (xml);
916 }
917 
918 /*
919 	glade callback
920 */
on_customize_video_thumbnailer_clicked(GtkButton * sender,gpointer e)921 G_MODULE_EXPORT void on_customize_video_thumbnailer_clicked (GtkButton *sender, gpointer e)
922 {
923 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_video_thumbnailer_dialog");
924 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_video_thumbnailer_dialog");
925 	gchar *temp = prefs_get_string("video_thumbnailer_prog");
926 
927 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
928 
929 	if(temp)
930 	{
931 		gtk_entry_set_text (GTK_ENTRY (gtkpod_xml_get_widget (xml, "video_thumbnailer")),
932 							temp);
933 
934 		g_free (temp);
935 	}
936 
937 	glade_xml_signal_autoconnect (xml);
938 	gtk_dialog_run (GTK_DIALOG (dlg));
939 	gtk_widget_destroy (dlg);
940 	g_object_unref (xml);
941 }
942 
943 
944 /*
945 	glade callback
946 */
on_coverart_pattern_changed(GtkEditable * sender,gpointer e)947 G_MODULE_EXPORT void on_coverart_pattern_changed (GtkEditable *sender, gpointer e)
948 {
949 	prefs_set_string ("coverart_template", gtk_entry_get_text (GTK_ENTRY (sender)));
950 }
951 
952 /*
953 	glade callback
954 */
on_video_thumbnailer_changed(GtkEditable * sender,gpointer e)955 G_MODULE_EXPORT void on_video_thumbnailer_changed (GtkEditable *sender, gpointer e)
956 {
957 	prefs_set_string ("video_thumbnailer_prog", gtk_entry_get_text (GTK_ENTRY (sender)));
958 }
959 
960 /*
961 	glade callback
962 */
on_exclusions_clicked(GtkButton * sender,gpointer e)963 G_MODULE_EXPORT void on_exclusions_clicked (GtkButton *sender, gpointer e)
964 {
965 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_exclusions_dialog");
966 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_exclusions_dialog");
967 	GtkWidget *tree = gtkpod_xml_get_widget (xml, "exclusion_list");
968 	GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
969     GtkTreeViewColumn *column = gtk_tree_view_column_new ();
970     GtkCellRenderer *renderer = gtk_cell_renderer_text_new ();
971 	gchar *temp = prefs_get_string("exclude_file_mask");
972 
973 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
974 
975 	if (temp)
976 	{
977 		gint i;
978 		gchar **masks = g_strsplit (temp, ";", 0);
979 		GtkTreeIter iter;
980 
981 		g_free (temp);
982 
983 		for (i = 0; masks[i]; i++)
984 		{
985 			gtk_list_store_append (store, &iter);
986 			gtk_list_store_set(store, &iter, 0, masks[i], -1);
987 		}
988 
989 		g_strfreev (masks);
990 	}
991 
992 	gtk_tree_view_column_pack_start (column, renderer, TRUE);
993     gtk_tree_view_column_set_attributes (column, renderer, "text", 0, NULL);
994     gtk_tree_view_append_column (GTK_TREE_VIEW (tree), column);
995 	gtk_tree_view_set_model (GTK_TREE_VIEW (tree), GTK_TREE_MODEL (store));
996 	g_object_unref (store);
997 
998 	g_object_set_data (G_OBJECT (gtkpod_xml_get_widget (xml, "add_exclusion")),
999 					   "xml", xml);
1000 
1001 	g_object_set_data (G_OBJECT (gtkpod_xml_get_widget (xml, "remove_exclusion")),
1002 					   "xml", xml);
1003 
1004 	glade_xml_signal_autoconnect (xml);
1005 	gtk_dialog_run (GTK_DIALOG (dlg));
1006 	gtk_widget_destroy (dlg);
1007 	g_object_unref (xml);
1008 }
1009 
update_exclusions(GtkListStore * store)1010 static void update_exclusions (GtkListStore *store)
1011 {
1012 	GtkTreeModel *model = GTK_TREE_MODEL (store);
1013 	gint rows = gtk_tree_model_iter_n_children (model, NULL);
1014 	gchar **array = g_new (gchar *, rows + 1);
1015 	gchar *temp;
1016 	gint i;
1017 	GtkTreeIter iter;
1018 
1019 	array[rows] = NULL;
1020 
1021 	for (i = 0; i < rows; i++)
1022 	{
1023 		gtk_tree_model_iter_nth_child (model, &iter, NULL, i);
1024 		gtk_tree_model_get (model, &iter, 0, array + i, -1);
1025 	}
1026 
1027 	temp = g_strjoinv (";", array);
1028 	prefs_set_string ("exclude_file_mask", temp);
1029 	g_free (temp);
1030 	g_strfreev (array);
1031 }
1032 
1033 /*
1034 	glade callback
1035 */
on_add_exclusion_clicked(GtkButton * sender,gpointer e)1036 G_MODULE_EXPORT void on_add_exclusion_clicked (GtkButton *sender, gpointer e)
1037 {
1038 	GladeXML *xml = GLADE_XML (g_object_get_data (G_OBJECT (sender), "xml"));
1039 	GtkWidget *tree = gtkpod_xml_get_widget (xml, "exclusion_list");
1040 	GtkWidget *entry = gtkpod_xml_get_widget (xml, "new_exclusion");
1041 	const gchar *text = gtk_entry_get_text (GTK_ENTRY (entry));
1042 
1043 	if (text && text[0])
1044 	{
1045 		GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree)));
1046 		GtkTreeIter iter;
1047 
1048 		gtk_list_store_append (store, &iter);
1049 		gtk_list_store_set(store, &iter, 0, text, -1);
1050 		gtk_entry_set_text (GTK_ENTRY (entry), "");
1051 
1052 		update_exclusions (store);
1053 	}
1054 }
1055 
1056 /*
1057 	glade callback
1058 */
on_remove_exclusion_clicked(GtkButton * sender,gpointer e)1059 G_MODULE_EXPORT void on_remove_exclusion_clicked (GtkButton *sender, gpointer e)
1060 {
1061 	GladeXML *xml = GLADE_XML (g_object_get_data (G_OBJECT (sender), "xml"));
1062 	GtkWidget *tree = gtkpod_xml_get_widget (xml, "exclusion_list");
1063 	GtkListStore *store = GTK_LIST_STORE (gtk_tree_view_get_model (GTK_TREE_VIEW (tree)));
1064 		GtkTreeIter iter;
1065 
1066 	if(!tree_get_current_iter (GTK_TREE_VIEW (tree), &iter) || gtk_list_store_iter_is_valid (store, &iter))
1067 	{
1068 		gtk_list_store_remove (store, &iter);
1069 		update_exclusions (store);
1070 	}
1071 }
1072 
1073 /*
1074 	glade callback
1075 */
on_mserv_settings_clicked(GtkButton * sender,gpointer e)1076 G_MODULE_EXPORT void on_mserv_settings_clicked (GtkButton *sender, gpointer e)
1077 {
1078 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_mserv_dialog");
1079 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_mserv_dialog");
1080 	gchar *temp = prefs_get_string ("mserv_username");
1081 
1082 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
1083 
1084 	if(temp)
1085 	{
1086 		gtk_entry_set_text (GTK_ENTRY (gtkpod_xml_get_widget (xml, "mserv_username")),
1087 							temp);
1088 
1089 		g_free (temp);
1090 	}
1091 
1092 	temp = prefs_get_string ("path_mserv_music_root");
1093 
1094 	if(temp)
1095 	{
1096 		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gtkpod_xml_get_widget (xml, "music_root")),
1097 											 temp);
1098 
1099 		g_free (temp);
1100 	}
1101 
1102 	temp = prefs_get_string ("path_mserv_trackinfo_root");
1103 
1104 	if(temp)
1105 	{
1106 		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gtkpod_xml_get_widget (xml, "mserv_root")),
1107 											 temp);
1108 
1109 		g_free (temp);
1110 	}
1111 
1112 	init_checkbox (GTK_TOGGLE_BUTTON (gtkpod_xml_get_widget (xml, "use_mserv")),
1113 				   xml, "mserv_use", "mserv_settings_frame");
1114 
1115 	init_checkbox (GTK_TOGGLE_BUTTON (gtkpod_xml_get_widget (xml, "report_mserv_problems")),
1116 				   xml, "mserv_report_probs", NULL);
1117 
1118 	glade_xml_signal_autoconnect (xml);
1119 	gtk_dialog_run (GTK_DIALOG (dlg));
1120 	gtk_widget_destroy (dlg);
1121 	g_object_unref (xml);
1122 }
1123 
1124 /*
1125 	glade callback
1126 */
on_mserv_username_changed(GtkEditable * sender,gpointer e)1127 G_MODULE_EXPORT void on_mserv_username_changed (GtkEditable *sender, gpointer e)
1128 {
1129 	prefs_set_string ("mserv_username", gtk_entry_get_text (GTK_ENTRY (sender)));
1130 }
1131 
1132 /*
1133 	glade callback
1134 */
on_music_root_current_folder_changed(GtkFileChooser * sender,gpointer e)1135 G_MODULE_EXPORT void on_music_root_current_folder_changed (GtkFileChooser *sender, gpointer e)
1136 {
1137 	prefs_set_string ("path_mserv_music_root",
1138 					  gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (sender)));
1139 }
1140 
1141 /*
1142 	glade callback
1143 */
on_mserv_root_current_folder_changed(GtkFileChooser * sender,gpointer e)1144 G_MODULE_EXPORT void on_mserv_root_current_folder_changed (GtkFileChooser *sender, gpointer e)
1145 {
1146 	prefs_set_string ("path_mserv_trackinfo_root",
1147 					  gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (sender)));
1148 }
1149 
cmd_setup_widget(GladeXML * xml,const gchar * entry_name,const gchar * envname,const gchar * browse_name)1150 static void cmd_setup_widget (GladeXML *xml, const gchar *entry_name, const gchar *envname, const gchar *browse_name)
1151 {
1152     GtkWidget *entry = gtkpod_xml_get_widget (xml, entry_name);
1153     gchar *temp = prefs_get_string (envname);
1154     if (!temp)
1155     {
1156 	temp = g_strdup ("");
1157     }
1158     gtk_entry_set_text (GTK_ENTRY (entry), temp);
1159     g_free (temp);
1160 
1161     g_object_set_data (G_OBJECT (entry), "envname", (gpointer)envname);
1162     g_object_set_data (G_OBJECT (gtkpod_xml_get_widget (xml, browse_name)),
1163 		       "entry", entry);
1164 }
1165 
1166 
1167 /*
1168 	glade callback
1169 */
on_commands_clicked(GtkButton * sender,gpointer e)1170 G_MODULE_EXPORT void on_commands_clicked (GtkButton *sender, gpointer e)
1171 {
1172 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_commands_dialog");
1173 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_commands_dialog");
1174 
1175 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
1176 
1177 	cmd_setup_widget (xml, "cmd_playnow", "path_play_now", "browse_playnow");
1178 	cmd_setup_widget (xml, "cmd_enqueue", "path_play_enqueue", "browse_enqueue");
1179 	cmd_setup_widget (xml, "cmd_mp3gain", "path_mp3gain", "browse_mp3gain");
1180 	cmd_setup_widget (xml, "cmd_aacgain", "path_aacgain", "browse_aacgain");
1181 
1182 	glade_xml_signal_autoconnect (xml);
1183 	gtk_dialog_run (GTK_DIALOG (dlg));
1184 	gtk_widget_destroy (dlg);
1185 	g_object_unref (xml);
1186 }
1187 
1188 /*
1189 	glade callback
1190 */
on_cmd_entry_changed(GtkEditable * sender,gpointer e)1191 G_MODULE_EXPORT void on_cmd_entry_changed (GtkEditable *sender, gpointer e)
1192 {
1193     const gchar *envname = g_object_get_data (G_OBJECT (sender), "envname");
1194 
1195     prefs_set_string (envname, gtk_entry_get_text (GTK_ENTRY (sender)));
1196 }
1197 
1198 /*
1199 	glade callback
1200 */
on_conversion_settings_clicked(GtkButton * sender,gpointer e)1201 G_MODULE_EXPORT void on_conversion_settings_clicked (GtkButton *sender, gpointer e)
1202 {
1203 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_conversion_dialog");
1204 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_conversion_dialog");
1205 	gchar *temp = prefs_get_string ("file_convert_cachedir");
1206 	gint i;
1207 
1208 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
1209 
1210 	if(temp)
1211 	{
1212 		gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (gtkpod_xml_get_widget (xml, "cache_folder")),
1213 											 temp);
1214 
1215 		g_free (temp);
1216 	}
1217 
1218 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtkpod_xml_get_widget (xml, "bg_threads")),
1219 							   prefs_get_int("file_convert_max_threads_num"));
1220 
1221 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtkpod_xml_get_widget (xml, "cache_size")),
1222 							   prefs_get_int("file_convert_maxdirsize"));
1223 
1224 	for (i = 0; i < COUNTOF(conv_checkbox_map); i++)
1225 	{
1226 		init_checkbox (GTK_TOGGLE_BUTTON (gtkpod_xml_get_widget (xml, conv_checkbox_map[i][0])),
1227 					   xml, conv_checkbox_map[i][1], conv_checkbox_map[i][2]);
1228 	}
1229 
1230 	glade_xml_signal_autoconnect (xml);
1231 	gtk_dialog_run (GTK_DIALOG (dlg));
1232 	gtk_widget_destroy (dlg);
1233 	g_object_unref (xml);
1234 	file_convert_prefs_changed ();
1235 }
1236 
1237 /*
1238 	glade callback
1239 */
on_cache_folder_current_folder_changed(GtkFileChooser * sender,gpointer e)1240 G_MODULE_EXPORT void on_cache_folder_current_folder_changed (GtkFileChooser *sender, gpointer e)
1241 {
1242 	prefs_set_string ("file_convert_cachedir",
1243 					  gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (sender)));
1244 }
1245 
1246 /*
1247 	glade callback
1248 */
on_bg_threads_value_changed(GtkSpinButton * sender,gpointer e)1249 G_MODULE_EXPORT void on_bg_threads_value_changed (GtkSpinButton *sender, gpointer e)
1250 {
1251     prefs_set_int ("file_convert_max_threads_num", gtk_spin_button_get_value_as_int (sender));
1252 }
1253 
1254 /*
1255 	glade callback
1256 */
on_cache_size_value_changed(GtkSpinButton * sender,gpointer e)1257 G_MODULE_EXPORT void on_cache_size_value_changed (GtkSpinButton *sender, gpointer e)
1258 {
1259     prefs_set_int ("file_convert_maxdirsize", gtk_spin_button_get_value_as_int (sender));
1260 }
1261 
1262 /*
1263 	glade callback
1264 */
on_target_format_changed(GtkComboBox * sender,gpointer e)1265 G_MODULE_EXPORT void on_target_format_changed (GtkComboBox *sender, gpointer e)
1266 {
1267 	gint index = gtk_combo_box_get_active (sender);
1268 	gchar *script = g_build_filename (SCRIPTDIR, conv_scripts[index], NULL);
1269 	gint i;
1270 
1271 	for (i = 0; i < COUNTOF (conv_paths); i++)
1272 	{
1273 		if (conv_paths[i].index == index)
1274 		{
1275 			/*
1276 				The source format is the same as the target format -
1277 				we set "null conversion" without touching the boolean preference
1278 			*/
1279 			prefs_set_string (conv_paths[i].string, "");
1280 		}
1281 		else
1282 			prefs_set_string (conv_paths[i].string, script);
1283 	}
1284 
1285 	prefs_set_int ("conversion_target_format", index);
1286 	g_free (script);
1287 	file_convert_prefs_changed ();
1288 }
1289 
1290 /*
1291 	glade callback
1292 */
on_sorting_button_clicked(GtkButton * sender,gpointer e)1293 G_MODULE_EXPORT void on_sorting_button_clicked (GtkButton *sender, gpointer e)
1294 {
1295 	sort_window_create ();
1296 }
1297 
1298 /*
1299 	glade callback
1300 */
on_replaygain_clicked(GtkButton * sender,gpointer e)1301 G_MODULE_EXPORT void on_replaygain_clicked (GtkButton *sender, gpointer e)
1302 {
1303 	GladeXML *xml = gtkpod_xml_new (xml_file, "prefs_replaygain_dialog");
1304 	GtkWidget *dlg = gtkpod_xml_get_widget (xml, "prefs_replaygain_dialog");
1305 	GtkWidget *mode_album_radio = gtkpod_xml_get_widget (xml, "mode_album");
1306 	GtkWidget *mode_track_radio = gtkpod_xml_get_widget (xml, "mode_track");
1307 
1308 	gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefs_dialog));
1309 
1310 	gtk_spin_button_set_value (GTK_SPIN_BUTTON (gtkpod_xml_get_widget (xml, "replaygain_offset")), prefs_get_int("replaygain_offset"));
1311 
1312 	if(prefs_get_int("replaygain_mode_album_priority"))
1313 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_album_radio), TRUE);
1314 	else
1315 		gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (mode_track_radio), TRUE);
1316 
1317 	glade_xml_signal_autoconnect (xml);
1318 	gtk_dialog_run (GTK_DIALOG (dlg));
1319 	gtk_widget_destroy (dlg);
1320 	g_object_unref (xml);
1321 }
1322 
1323 /*
1324 	glade callback
1325 */
on_replaygain_mode_album_toggled(GtkToggleButton * sender,gpointer e)1326 G_MODULE_EXPORT void on_replaygain_mode_album_toggled (GtkToggleButton *sender, gpointer e)
1327 {
1328 	gboolean active = gtk_toggle_button_get_active (sender);
1329 
1330 	prefs_set_int ("replaygain_mode_album_priority", active);
1331 }
1332 
1333 /*
1334 	glade callback
1335 */
on_replaygain_offset_value_changed(GtkSpinButton * sender,gpointer e)1336 G_MODULE_EXPORT void on_replaygain_offset_value_changed (GtkSpinButton *sender, gpointer e)
1337 {
1338     prefs_set_int ("replaygain_offset", gtk_spin_button_get_value_as_int (sender));
1339 }
1340