00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021 #include <stdio.h>
00022
00023 #include <gdk/gdkkeysyms.h>
00024 #include <gtk/gtk.h>
00025
00026 #include <libaudcore/hook.h>
00027
00028 #include "config.h"
00029 #include "debug.h"
00030 #include "gtk-compat.h"
00031 #include "i18n.h"
00032 #include "misc.h"
00033 #include "output.h"
00034 #include "playback.h"
00035 #include "playlist.h"
00036 #include "plugin.h"
00037 #include "plugins.h"
00038 #include "preferences.h"
00039 #include "ui_preferences.h"
00040
00041 #ifdef USE_CHARDET
00042 #include <libguess.h>
00043 #endif
00044
00045 static void sw_volume_toggled (void);
00046
00047 enum CategoryViewCols {
00048 CATEGORY_VIEW_COL_ICON,
00049 CATEGORY_VIEW_COL_NAME,
00050 CATEGORY_VIEW_COL_ID,
00051 CATEGORY_VIEW_N_COLS
00052 };
00053
00054 typedef struct {
00055 const char *icon_path;
00056 const char *name;
00057 } Category;
00058
00059 typedef struct {
00060 const char *name;
00061 const char *tag;
00062 } TitleFieldTag;
00063
00064 static void * prefswin = NULL;
00065 static GtkWidget *filepopup_settings = NULL;
00066 static GtkWidget *category_treeview = NULL;
00067 static GtkWidget *category_notebook = NULL;
00068 GtkWidget *filepopupbutton = NULL;
00069
00070
00071 GtkWidget *filepopup_cover_name_include;
00072 GtkWidget *filepopup_cover_name_exclude;
00073 GtkWidget *filepopup_recurse;
00074 GtkWidget *filepopup_recurse_depth;
00075 GtkWidget *filepopup_recurse_depth_box;
00076 GtkWidget *filepopup_use_file_cover;
00077 GtkWidget *filepopup_showprogressbar;
00078 GtkWidget *filepopup_delay;
00079
00080
00081 GtkWidget *titlestring_entry;
00082 GtkWidget *filepopup_settings_button;
00083
00084 static Category categories[] = {
00085 {"audio.png", N_("Audio")},
00086 {"connectivity.png", N_("Network")},
00087 {"playlist.png", N_("Playlist")},
00088 {"plugins.png", N_("Plugins")},
00089 };
00090
00091 static int n_categories = G_N_ELEMENTS(categories);
00092
00093 static TitleFieldTag title_field_tags[] = {
00094 { N_("Artist") , "${artist}" },
00095 { N_("Album") , "${album}" },
00096 { N_("Title") , "${title}" },
00097 { N_("Tracknumber"), "${track-number}" },
00098 { N_("Genre") , "${genre}" },
00099 { N_("Filename") , "${file-name}" },
00100 { N_("Filepath") , "${file-path}" },
00101 { N_("Date") , "${date}" },
00102 { N_("Year") , "${year}" },
00103 { N_("Comment") , "${comment}" },
00104 { N_("Codec") , "${codec}" },
00105 { N_("Quality") , "${quality}" },
00106 };
00107 static const unsigned int n_title_field_tags = G_N_ELEMENTS(title_field_tags);
00108
00109 #ifdef USE_CHARDET
00110 static ComboBoxElements chardet_detector_presets[] = {
00111 {"", N_("None")},
00112 {GUESS_REGION_AR, N_("Arabic")},
00113 {GUESS_REGION_BL, N_("Baltic")},
00114 {GUESS_REGION_CN, N_("Chinese")},
00115 {GUESS_REGION_GR, N_("Greek")},
00116 {GUESS_REGION_HW, N_("Hebrew")},
00117 {GUESS_REGION_JP, N_("Japanese")},
00118 {GUESS_REGION_KR, N_("Korean")},
00119 {GUESS_REGION_PL, N_("Polish")},
00120 {GUESS_REGION_RU, N_("Russian")},
00121 {GUESS_REGION_TW, N_("Taiwanese")},
00122 {GUESS_REGION_TR, N_("Turkish")}};
00123 #endif
00124
00125 static ComboBoxElements bitdepth_elements[] = {
00126 { GINT_TO_POINTER(16), "16" },
00127 { GINT_TO_POINTER(24), "24" },
00128 { GINT_TO_POINTER(32), "32" },
00129 {GINT_TO_POINTER (0), "Floating point"},
00130 };
00131
00132 typedef struct {
00133 void *next;
00134 GtkWidget *container;
00135 const char * pg_name;
00136 const char * img_url;
00137 } CategoryQueueEntry;
00138
00139 CategoryQueueEntry *category_queue = NULL;
00140
00141 static void * create_output_plugin_box (void);
00142
00143 static PreferencesWidget rg_mode_widgets[] = {
00144 {WIDGET_CHK_BTN, N_("Album mode"), .cfg_type = VALUE_BOOLEAN, .cname = "replay_gain_album"}};
00145
00146 static PreferencesWidget audio_page_widgets[] = {
00147 {WIDGET_LABEL, N_("<b>Output Settings</b>")},
00148 {WIDGET_CUSTOM, .data = {.populate = create_output_plugin_box}},
00149 {WIDGET_COMBO_BOX, N_("Bit depth:"),
00150 .cfg_type = VALUE_INT, .cname = "output_bit_depth",
00151 .data = {.combo = {bitdepth_elements, G_N_ELEMENTS (bitdepth_elements), TRUE}}},
00152 {WIDGET_SPIN_BTN, N_("Buffer size:"),
00153 .cfg_type = VALUE_INT, .cname = "output_buffer_size",
00154 .data = {.spin_btn = {100, 10000, 1000, N_("ms")}}},
00155 {WIDGET_CHK_BTN, N_("Use software volume control (not recommended)"),
00156 .cfg_type = VALUE_BOOLEAN, .cname = "software_volume_control", .callback = sw_volume_toggled},
00157 {WIDGET_LABEL, N_("<b>Replay Gain</b>")},
00158 {WIDGET_CHK_BTN, N_("Enable Replay Gain"),
00159 .cfg_type = VALUE_BOOLEAN, .cname = "enable_replay_gain"},
00160 {WIDGET_BOX, .child = TRUE, .data = {.box = {rg_mode_widgets, G_N_ELEMENTS (rg_mode_widgets), TRUE}}},
00161 {WIDGET_CHK_BTN, N_("Prevent clipping (recommended)"), .child = TRUE,
00162 .cfg_type = VALUE_BOOLEAN, .cname = "enable_clipping_prevention"},
00163 {WIDGET_LABEL, N_("<b>Adjust Levels</b>"), .child = TRUE},
00164 {WIDGET_SPIN_BTN, N_("Amplify all files:"), .child = TRUE,
00165 .cfg_type = VALUE_FLOAT, .cname = "replay_gain_preamp",
00166 .data = {.spin_btn = {-15, 15, 0.1, N_("dB")}}},
00167 {WIDGET_SPIN_BTN, N_("Amplify untagged files:"), .child = TRUE,
00168 .cfg_type = VALUE_FLOAT, .cname = "default_gain",
00169 .data = {.spin_btn = {-15, 15, 0.1, N_("dB")}}}};
00170
00171 static PreferencesWidget proxy_host_port_elements[] = {
00172 {WIDGET_ENTRY, N_("Proxy hostname:"), .cfg_type = VALUE_STRING, .cname = "proxy_host"},
00173 {WIDGET_ENTRY, N_("Proxy port:"), .cfg_type = VALUE_STRING, .cname = "proxy_port"}};
00174
00175 static PreferencesWidget proxy_auth_elements[] = {
00176 {WIDGET_ENTRY, N_("Proxy username:"), .cfg_type = VALUE_STRING, .cname = "proxy_user"},
00177 {WIDGET_ENTRY, N_("Proxy password:"), .cfg_type = VALUE_STRING, .cname = "proxy_pass",
00178 .data = {.entry = {.password = TRUE}}}};
00179
00180 static PreferencesWidget connectivity_page_widgets[] = {
00181 {WIDGET_LABEL, N_("<b>Proxy Configuration</b>"), NULL, NULL, NULL, FALSE},
00182 {WIDGET_CHK_BTN, N_("Enable proxy usage"), .cfg_type = VALUE_BOOLEAN, .cname = "use_proxy"},
00183 {WIDGET_TABLE, .child = TRUE, .data = {.table = {proxy_host_port_elements,
00184 G_N_ELEMENTS (proxy_host_port_elements)}}},
00185 {WIDGET_CHK_BTN, N_("Use authentication with proxy"),
00186 .cfg_type = VALUE_BOOLEAN, .cname = "use_proxy_auth"},
00187 {WIDGET_TABLE, .child = TRUE, .data = {.table = {proxy_auth_elements,
00188 G_N_ELEMENTS (proxy_auth_elements)}}}
00189 };
00190
00191 static PreferencesWidget chardet_elements[] = {
00192 #ifdef USE_CHARDET
00193 {WIDGET_COMBO_BOX, N_("Auto character encoding detector for:"),
00194 .cfg_type = VALUE_STRING, .cname = "chardet_detector", .child = TRUE,
00195 .data = {.combo = {chardet_detector_presets,
00196 G_N_ELEMENTS (chardet_detector_presets), TRUE}}},
00197 #endif
00198 {WIDGET_ENTRY, N_("Fallback character encodings:"), .cfg_type = VALUE_STRING,
00199 .cname = "chardet_fallback", .child = TRUE}};
00200
00201 static PreferencesWidget playlist_page_widgets[] = {
00202 {WIDGET_LABEL, N_("<b>Behavior</b>"), NULL, NULL, NULL, FALSE},
00203 {WIDGET_CHK_BTN, N_("Continue playback on startup"),
00204 .cfg_type = VALUE_BOOLEAN, .cname = "resume_playback_on_startup"},
00205 {WIDGET_CHK_BTN, N_("Advance when the current song is deleted"),
00206 .cfg_type = VALUE_BOOLEAN, .cname = "advance_on_delete"},
00207 {WIDGET_CHK_BTN, N_("Clear the playlist when opening files"),
00208 .cfg_type = VALUE_BOOLEAN, .cname = "clear_playlist"},
00209 {WIDGET_CHK_BTN, N_("Open files in a temporary playlist"),
00210 .cfg_type = VALUE_BOOLEAN, .cname = "open_to_temporary"},
00211 {WIDGET_LABEL, N_("<b>Metadata</b>"), NULL, NULL, NULL, FALSE},
00212 {WIDGET_CHK_BTN, N_("Do not load metadata for songs until played"),
00213 .cfg_type = VALUE_BOOLEAN, .cname = "metadata_on_play",
00214 .callback = playlist_trigger_scan},
00215 {WIDGET_TABLE, .data = {.table = {chardet_elements,
00216 G_N_ELEMENTS (chardet_elements)}}}
00217 };
00218
00219 #define TITLESTRING_NPRESETS 6
00220
00221 static const char * const titlestring_presets[TITLESTRING_NPRESETS] = {
00222 "${title}",
00223 "${?artist:${artist} - }${title}",
00224 "${?artist:${artist} - }${?album:${album} - }${title}",
00225 "${?artist:${artist} - }${?album:${album} - }${?track-number:${track-number}. }${title}",
00226 "${?artist:${artist} }${?album:[ ${album} ] }${?artist:- }${?track-number:${track-number}. }${title}",
00227 "${?album:${album} - }${title}"};
00228
00229 static const char * const titlestring_preset_names[TITLESTRING_NPRESETS] = {
00230 N_("TITLE"),
00231 N_("ARTIST - TITLE"),
00232 N_("ARTIST - ALBUM - TITLE"),
00233 N_("ARTIST - ALBUM - TRACK. TITLE"),
00234 N_("ARTIST [ ALBUM ] - TRACK. TITLE"),
00235 N_("ALBUM - TITLE")};
00236
00237 static void prefswin_page_queue_destroy(CategoryQueueEntry *ent);
00238
00239 static void
00240 change_category(GtkNotebook * notebook,
00241 GtkTreeSelection * selection)
00242 {
00243 GtkTreeModel *model;
00244 GtkTreeIter iter;
00245 int index;
00246
00247 if (!gtk_tree_selection_get_selected(selection, &model, &iter))
00248 return;
00249
00250 gtk_tree_model_get(model, &iter, CATEGORY_VIEW_COL_ID, &index, -1);
00251 gtk_notebook_set_current_page(notebook, index);
00252 }
00253
00254 static void
00255 editable_insert_text(GtkEditable * editable,
00256 const char * text,
00257 int * pos)
00258 {
00259 gtk_editable_insert_text(editable, text, strlen(text), pos);
00260 }
00261
00262 static void
00263 titlestring_tag_menu_callback(GtkMenuItem * menuitem,
00264 gpointer data)
00265 {
00266 const char *separator = " - ";
00267 int item = GPOINTER_TO_INT(data);
00268 int pos;
00269
00270 pos = gtk_editable_get_position(GTK_EDITABLE(titlestring_entry));
00271
00272
00273 if (g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(titlestring_entry)), -1) > 0)
00274 editable_insert_text(GTK_EDITABLE(titlestring_entry), separator, &pos);
00275
00276 editable_insert_text(GTK_EDITABLE(titlestring_entry), _(title_field_tags[item].tag),
00277 &pos);
00278
00279 gtk_editable_set_position(GTK_EDITABLE(titlestring_entry), pos);
00280 }
00281
00282 static void
00283 on_titlestring_help_button_clicked(GtkButton * button,
00284 gpointer data)
00285 {
00286 GtkMenu * menu = data;
00287 gtk_menu_popup (menu, NULL, NULL, NULL, NULL, 0, GDK_CURRENT_TIME);
00288 }
00289
00290 static void update_titlestring_cbox (GtkComboBox * cbox, const char * format)
00291 {
00292 int preset;
00293 for (preset = 0; preset < TITLESTRING_NPRESETS; preset ++)
00294 {
00295 if (! strcmp (titlestring_presets[preset], format))
00296 break;
00297 }
00298
00299 if (gtk_combo_box_get_active (cbox) != preset)
00300 gtk_combo_box_set_active (cbox, preset);
00301 }
00302
00303 static void on_titlestring_entry_changed (GtkEntry * entry, GtkComboBox * cbox)
00304 {
00305 const char * format = gtk_entry_get_text (entry);
00306 set_string (NULL, "generic_title_format", format);
00307 update_titlestring_cbox (cbox, format);
00308 playlist_reformat_titles ();
00309 }
00310
00311 static void on_titlestring_cbox_changed (GtkComboBox * cbox, GtkEntry * entry)
00312 {
00313 int preset = gtk_combo_box_get_active (cbox);
00314 if (preset < TITLESTRING_NPRESETS)
00315 gtk_entry_set_text (entry, titlestring_presets[preset]);
00316 }
00317
00318 static void widget_set_bool (PreferencesWidget * widget, bool_t value)
00319 {
00320 g_return_if_fail (widget->cfg_type == VALUE_BOOLEAN);
00321
00322 if (widget->cfg)
00323 * (bool_t *) widget->cfg = value;
00324 else if (widget->cname)
00325 set_bool (widget->csect, widget->cname, value);
00326
00327 if (widget->callback)
00328 widget->callback ();
00329 }
00330
00331 static bool_t widget_get_bool (PreferencesWidget * widget)
00332 {
00333 g_return_val_if_fail (widget->cfg_type == VALUE_BOOLEAN, FALSE);
00334
00335 if (widget->cfg)
00336 return * (bool_t *) widget->cfg;
00337 else if (widget->cname)
00338 return get_bool (widget->csect, widget->cname);
00339 else
00340 return FALSE;
00341 }
00342
00343 static void widget_set_int (PreferencesWidget * widget, int value)
00344 {
00345 g_return_if_fail (widget->cfg_type == VALUE_INT);
00346
00347 if (widget->cfg)
00348 * (int *) widget->cfg = value;
00349 else if (widget->cname)
00350 set_int (widget->csect, widget->cname, value);
00351
00352 if (widget->callback)
00353 widget->callback ();
00354 }
00355
00356 static int widget_get_int (PreferencesWidget * widget)
00357 {
00358 g_return_val_if_fail (widget->cfg_type == VALUE_INT, 0);
00359
00360 if (widget->cfg)
00361 return * (int *) widget->cfg;
00362 else if (widget->cname)
00363 return get_int (widget->csect, widget->cname);
00364 else
00365 return 0;
00366 }
00367
00368 static void widget_set_double (PreferencesWidget * widget, double value)
00369 {
00370 g_return_if_fail (widget->cfg_type == VALUE_FLOAT);
00371
00372 if (widget->cfg)
00373 * (float *) widget->cfg = value;
00374 else if (widget->cname)
00375 set_double (widget->csect, widget->cname, value);
00376
00377 if (widget->callback)
00378 widget->callback ();
00379 }
00380
00381 static double widget_get_double (PreferencesWidget * widget)
00382 {
00383 g_return_val_if_fail (widget->cfg_type == VALUE_FLOAT, 0);
00384
00385 if (widget->cfg)
00386 return * (float *) widget->cfg;
00387 else if (widget->cname)
00388 return get_double (widget->csect, widget->cname);
00389 else
00390 return 0;
00391 }
00392
00393 static void widget_set_string (PreferencesWidget * widget, const char * value)
00394 {
00395 g_return_if_fail (widget->cfg_type == VALUE_STRING);
00396
00397 if (widget->cfg)
00398 {
00399 g_free (* (char * *) widget->cfg);
00400 * (char * *) widget->cfg = g_strdup (value);
00401 }
00402 else if (widget->cname)
00403 set_string (widget->csect, widget->cname, value);
00404
00405 if (widget->callback)
00406 widget->callback ();
00407 }
00408
00409 static char * widget_get_string (PreferencesWidget * widget)
00410 {
00411 g_return_val_if_fail (widget->cfg_type == VALUE_STRING, NULL);
00412
00413 if (widget->cfg)
00414 return g_strdup (* (char * *) widget->cfg);
00415 else if (widget->cname)
00416 return get_string (widget->csect, widget->cname);
00417 else
00418 return NULL;
00419 }
00420
00421 static void on_font_btn_font_set (GtkFontButton * button, PreferencesWidget * widget)
00422 {
00423 widget_set_string (widget, gtk_font_button_get_font_name (button));
00424 }
00425
00426 static void
00427 plugin_preferences_ok(GtkWidget *widget, PluginPreferences *settings)
00428 {
00429 if (settings->apply)
00430 settings->apply();
00431
00432 gtk_widget_destroy(GTK_WIDGET(settings->data));
00433 }
00434
00435 static void
00436 plugin_preferences_apply(GtkWidget *widget, PluginPreferences *settings)
00437 {
00438 if (settings->apply)
00439 settings->apply();
00440 }
00441
00442 static void
00443 plugin_preferences_cancel(GtkWidget *widget, PluginPreferences *settings)
00444 {
00445 if (settings->cancel)
00446 settings->cancel();
00447
00448 gtk_widget_destroy(GTK_WIDGET(settings->data));
00449 }
00450
00451 static void plugin_preferences_destroy(GtkWidget *widget, PluginPreferences *settings)
00452 {
00453 gtk_widget_destroy(widget);
00454
00455 if (settings->cleanup)
00456 settings->cleanup();
00457
00458 settings->data = NULL;
00459 }
00460
00461 void plugin_preferences_show (PluginPreferences * settings)
00462 {
00463 GtkWidget *window;
00464 GtkWidget *vbox, *bbox, *ok, *apply, *cancel;
00465
00466 if (settings->data != NULL) {
00467 gtk_widget_show(GTK_WIDGET(settings->data));
00468 return;
00469 }
00470
00471 if (settings->init)
00472 settings->init();
00473
00474 const char * d = settings->domain;
00475 if (! d)
00476 {
00477 printf ("WARNING: PluginPreferences window with title \"%s\" did not "
00478 "declare its gettext domain. Text may not be translated correctly.\n",
00479 settings->title);
00480 d = "audacious-plugins";
00481 }
00482
00483 window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00484 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG);
00485
00486 if (settings->title)
00487 gtk_window_set_title ((GtkWindow *) window, dgettext (d, settings->title));
00488
00489 gtk_container_set_border_width(GTK_CONTAINER(window), 10);
00490 g_signal_connect(G_OBJECT(window), "destroy",
00491 G_CALLBACK(plugin_preferences_destroy), settings);
00492
00493 vbox = gtk_vbox_new(FALSE, 10);
00494 create_widgets_with_domain ((GtkBox *) vbox, settings->prefs,
00495 settings->n_prefs, d);
00496 gtk_container_add(GTK_CONTAINER(window), vbox);
00497
00498 bbox = gtk_hbutton_box_new();
00499 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END);
00500 gtk_box_set_spacing(GTK_BOX(bbox), 5);
00501 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0);
00502
00503 ok = gtk_button_new_from_stock(GTK_STOCK_OK);
00504 g_signal_connect(G_OBJECT(ok), "clicked",
00505 G_CALLBACK(plugin_preferences_ok), settings);
00506 gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0);
00507 gtk_widget_set_can_default (ok, TRUE);
00508 gtk_widget_grab_default(ok);
00509
00510 apply = gtk_button_new_from_stock(GTK_STOCK_APPLY);
00511 g_signal_connect(G_OBJECT(apply), "clicked",
00512 G_CALLBACK(plugin_preferences_apply), settings);
00513 gtk_box_pack_start(GTK_BOX(bbox), apply, TRUE, TRUE, 0);
00514
00515 cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL);
00516 g_signal_connect(G_OBJECT(cancel), "clicked",
00517 G_CALLBACK(plugin_preferences_cancel), settings);
00518 gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0);
00519
00520 gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(prefswin));
00521 gtk_widget_show_all(window);
00522 settings->data = (gpointer)window;
00523 }
00524
00525 void plugin_preferences_cleanup (PluginPreferences * p)
00526 {
00527 if (p->data != NULL)
00528 {
00529 gtk_widget_destroy (p->data);
00530 p->data = NULL;
00531 }
00532 }
00533
00534 static void on_spin_btn_changed_int (GtkSpinButton * button, PreferencesWidget * widget)
00535 {
00536 widget_set_int (widget, gtk_spin_button_get_value_as_int (button));
00537 }
00538
00539 static void on_spin_btn_changed_float (GtkSpinButton * button, PreferencesWidget * widget)
00540 {
00541 widget_set_double (widget, gtk_spin_button_get_value (button));
00542 }
00543
00544 static void fill_category_list (GtkTreeView * treeview, GtkNotebook * notebook)
00545 {
00546 GtkListStore *store;
00547 GtkCellRenderer *renderer;
00548 GtkTreeViewColumn *column;
00549 GtkTreeSelection *selection;
00550 GtkTreeIter iter;
00551 GdkPixbuf *img;
00552 CategoryQueueEntry *qlist;
00553 int i;
00554
00555 column = gtk_tree_view_column_new();
00556 gtk_tree_view_column_set_title(column, _("Category"));
00557 gtk_tree_view_append_column(treeview, column);
00558 gtk_tree_view_column_set_spacing(column, 2);
00559
00560 renderer = gtk_cell_renderer_pixbuf_new();
00561 gtk_tree_view_column_pack_start(column, renderer, FALSE);
00562 gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", 0, NULL);
00563
00564 renderer = gtk_cell_renderer_text_new();
00565 gtk_tree_view_column_pack_start(column, renderer, FALSE);
00566 gtk_tree_view_column_set_attributes(column, renderer, "text", 1, NULL);
00567
00568 g_object_set ((GObject *) renderer, "wrap-width", 96, "wrap-mode",
00569 PANGO_WRAP_WORD_CHAR, NULL);
00570
00571 store = gtk_list_store_new(CATEGORY_VIEW_N_COLS,
00572 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT);
00573 gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store));
00574
00575 for (i = 0; i < n_categories; i ++)
00576 {
00577 char * path = g_strdup_printf ("%s/images/%s",
00578 get_path (AUD_PATH_DATA_DIR), categories[i].icon_path);
00579 img = gdk_pixbuf_new_from_file (path, NULL);
00580 g_free (path);
00581
00582 gtk_list_store_append(store, &iter);
00583 gtk_list_store_set(store, &iter,
00584 CATEGORY_VIEW_COL_ICON, img,
00585 CATEGORY_VIEW_COL_NAME,
00586 gettext(categories[i].name), CATEGORY_VIEW_COL_ID,
00587 i, -1);
00588 g_object_unref(img);
00589 }
00590
00591 selection = gtk_tree_view_get_selection(treeview);
00592
00593 g_signal_connect_swapped(selection, "changed",
00594 G_CALLBACK(change_category), notebook);
00595
00596
00597 category_treeview = GTK_WIDGET(treeview);
00598
00599
00600 for (qlist = category_queue; qlist != NULL; qlist = category_queue)
00601 {
00602 CategoryQueueEntry *ent = (CategoryQueueEntry *) qlist;
00603
00604 prefswin_page_new(ent->container, ent->pg_name, ent->img_url);
00605 prefswin_page_queue_destroy(ent);
00606 }
00607 }
00608
00609 static void on_show_filepopup_toggled (GtkToggleButton * button)
00610 {
00611 bool_t active = gtk_toggle_button_get_active (button);
00612 set_bool (NULL, "show_filepopup_for_tuple", active);
00613 gtk_widget_set_sensitive (filepopup_settings_button, active);
00614 }
00615
00616 static void on_filepopup_settings_clicked (void)
00617 {
00618 char * string = get_string (NULL, "cover_name_include");
00619 gtk_entry_set_text ((GtkEntry *) filepopup_cover_name_include, string);
00620 g_free (string);
00621
00622 string = get_string (NULL, "cover_name_exclude");
00623 gtk_entry_set_text ((GtkEntry *) filepopup_cover_name_exclude, string);
00624 g_free (string);
00625
00626 gtk_toggle_button_set_active ((GtkToggleButton *) filepopup_recurse,
00627 get_bool (NULL, "recurse_for_cover"));
00628 gtk_spin_button_set_value ((GtkSpinButton *) filepopup_recurse_depth,
00629 get_int (NULL, "recurse_for_cover_depth"));
00630 gtk_toggle_button_set_active ((GtkToggleButton *) filepopup_use_file_cover,
00631 get_bool (NULL, "use_file_cover"));
00632
00633 gtk_toggle_button_set_active ((GtkToggleButton *) filepopup_showprogressbar,
00634 get_bool (NULL, "filepopup_showprogressbar"));
00635 gtk_spin_button_set_value ((GtkSpinButton *) filepopup_delay,
00636 get_int (NULL, "filepopup_delay"));
00637
00638 gtk_widget_show (filepopup_settings);
00639 }
00640
00641 static void on_filepopup_ok_clicked (void)
00642 {
00643 set_string (NULL, "cover_name_include",
00644 gtk_entry_get_text ((GtkEntry *) filepopup_cover_name_include));
00645 set_string (NULL, "cover_name_exclude",
00646 gtk_entry_get_text ((GtkEntry *) filepopup_cover_name_exclude));
00647
00648 set_bool (NULL, "recurse_for_cover",
00649 gtk_toggle_button_get_active ((GtkToggleButton *) filepopup_recurse));
00650 set_int (NULL, "recurse_for_cover_depth",
00651 gtk_spin_button_get_value_as_int ((GtkSpinButton *) filepopup_recurse_depth));
00652 set_bool (NULL, "use_file_cover",
00653 gtk_toggle_button_get_active ((GtkToggleButton *) filepopup_use_file_cover));
00654
00655 set_bool (NULL, "filepopup_showprogressbar",
00656 gtk_toggle_button_get_active ((GtkToggleButton *) filepopup_showprogressbar));
00657 set_int (NULL, "filepopup_delay",
00658 gtk_spin_button_get_value_as_int ((GtkSpinButton *) filepopup_delay));
00659
00660 gtk_widget_hide (filepopup_settings);
00661 }
00662
00663 static void
00664 on_filepopup_cancel_clicked(GtkButton *button, gpointer data)
00665 {
00666 gtk_widget_hide(filepopup_settings);
00667 }
00668
00669 static void on_toggle_button_toggled (GtkToggleButton * button, PreferencesWidget * widget)
00670 {
00671 bool_t active = gtk_toggle_button_get_active (button);
00672 widget_set_bool (widget, active);
00673
00674 GtkWidget * child = g_object_get_data ((GObject *) button, "child");
00675 if (child)
00676 gtk_widget_set_sensitive (child, active);
00677 }
00678
00679 static void init_toggle_button (GtkWidget * button, PreferencesWidget * widget)
00680 {
00681 if (widget->cfg_type != VALUE_BOOLEAN)
00682 return;
00683
00684 gtk_toggle_button_set_active ((GtkToggleButton *) button, widget_get_bool (widget));
00685 g_signal_connect (button, "toggled", (GCallback) on_toggle_button_toggled, widget);
00686 }
00687
00688 static void on_entry_changed (GtkEntry * entry, PreferencesWidget * widget)
00689 {
00690 widget_set_string (widget, gtk_entry_get_text (entry));
00691 }
00692
00693 static void on_cbox_changed_int (GtkComboBox * combobox, PreferencesWidget * widget)
00694 {
00695 int position = gtk_combo_box_get_active (combobox);
00696 widget_set_int (widget, GPOINTER_TO_INT (widget->data.combo.elements[position].value));
00697 }
00698
00699 static void on_cbox_changed_string (GtkComboBox * combobox, PreferencesWidget * widget)
00700 {
00701 int position = gtk_combo_box_get_active (combobox);
00702 widget_set_string (widget, widget->data.combo.elements[position].value);
00703 }
00704
00705 static void fill_cbox (GtkWidget * combobox, PreferencesWidget * widget)
00706 {
00707 unsigned int i=0,index=0;
00708
00709 for (i = 0; i < widget->data.combo.n_elements; i ++)
00710 gtk_combo_box_text_append_text ((GtkComboBoxText *) combobox,
00711 _(widget->data.combo.elements[i].label));
00712
00713 if (widget->data.combo.enabled) {
00714 switch (widget->cfg_type) {
00715 case VALUE_INT:
00716 g_signal_connect(combobox, "changed",
00717 G_CALLBACK(on_cbox_changed_int), widget);
00718
00719 int ivalue = widget_get_int (widget);
00720
00721 for(i=0; i<widget->data.combo.n_elements; i++) {
00722 if (GPOINTER_TO_INT (widget->data.combo.elements[i].value) == ivalue)
00723 {
00724 index = i;
00725 break;
00726 }
00727 }
00728 break;
00729 case VALUE_STRING:
00730 g_signal_connect(combobox, "changed",
00731 G_CALLBACK(on_cbox_changed_string), widget);
00732
00733 char * value = widget_get_string (widget);
00734
00735 for(i=0; i<widget->data.combo.n_elements; i++) {
00736 if (value && ! strcmp ((char *) widget->data.combo.elements[i].value, value))
00737 {
00738 index = i;
00739 break;
00740 }
00741 }
00742
00743 g_free (value);
00744 break;
00745 default:
00746 break;
00747 }
00748 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), index);
00749 } else {
00750 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), -1);
00751 gtk_widget_set_sensitive(GTK_WIDGET(combobox), 0);
00752 }
00753 }
00754
00755 void
00756 create_filepopup_settings(void)
00757 {
00758 GtkWidget *vbox;
00759 GtkWidget *table;
00760
00761 GtkWidget *label_cover_retrieve;
00762 GtkWidget *label_cover_search;
00763 GtkWidget *label_exclude;
00764 GtkWidget *label_include;
00765 GtkWidget *label_search_depth;
00766 GtkWidget *label_misc;
00767 GtkWidget *label_delay;
00768
00769 GtkAdjustment *recurse_for_cover_depth_adj;
00770 GtkAdjustment *delay_adj;
00771 GtkWidget *alignment;
00772
00773 GtkWidget *hbox;
00774 GtkWidget *hbuttonbox;
00775 GtkWidget *btn_cancel;
00776 GtkWidget *btn_ok;
00777
00778 filepopup_settings = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00779 gtk_container_set_border_width(GTK_CONTAINER(filepopup_settings), 12);
00780 gtk_window_set_title(GTK_WINDOW(filepopup_settings), _("Popup Information Settings"));
00781 gtk_window_set_position(GTK_WINDOW(filepopup_settings), GTK_WIN_POS_CENTER_ON_PARENT);
00782 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(filepopup_settings), TRUE);
00783 gtk_window_set_type_hint(GTK_WINDOW(filepopup_settings), GDK_WINDOW_TYPE_HINT_DIALOG);
00784 gtk_window_set_transient_for(GTK_WINDOW(filepopup_settings), GTK_WINDOW(prefswin));
00785
00786 vbox = gtk_vbox_new(FALSE, 12);
00787 gtk_container_add(GTK_CONTAINER(filepopup_settings), vbox);
00788
00789 label_cover_retrieve = gtk_label_new(_("<b>Cover image retrieve</b>"));
00790 gtk_box_pack_start(GTK_BOX(vbox), label_cover_retrieve, FALSE, FALSE, 0);
00791 gtk_label_set_use_markup(GTK_LABEL(label_cover_retrieve), TRUE);
00792 gtk_misc_set_alignment(GTK_MISC(label_cover_retrieve), 0, 0.5);
00793
00794 label_cover_search = gtk_label_new(_("While searching for the album's cover, Audacious looks for certain words in the filename. You can specify those words in the lists below, separated using commas."));
00795 gtk_box_pack_start(GTK_BOX(vbox), label_cover_search, FALSE, FALSE, 0);
00796 gtk_label_set_line_wrap(GTK_LABEL(label_cover_search), TRUE);
00797 gtk_misc_set_alignment(GTK_MISC(label_cover_search), 0, 0);
00798 gtk_misc_set_padding(GTK_MISC(label_cover_search), 12, 0);
00799
00800 table = gtk_table_new(2, 2, FALSE);
00801 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
00802 gtk_table_set_row_spacings(GTK_TABLE(table), 4);
00803 gtk_table_set_col_spacings(GTK_TABLE(table), 4);
00804
00805 filepopup_cover_name_include = gtk_entry_new();
00806 gtk_table_attach(GTK_TABLE(table), filepopup_cover_name_include, 1, 2, 0, 1,
00807 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
00808 (GtkAttachOptions) (0), 0, 0);
00809 gtk_entry_set_activates_default(GTK_ENTRY(filepopup_cover_name_include), TRUE);
00810
00811 label_exclude = gtk_label_new(_("Exclude:"));
00812 gtk_table_attach(GTK_TABLE(table), label_exclude, 0, 1, 1, 2,
00813 (GtkAttachOptions) (0),
00814 (GtkAttachOptions) (0), 0, 0);
00815 gtk_misc_set_alignment(GTK_MISC(label_exclude), 0, 0.5);
00816 gtk_misc_set_padding(GTK_MISC(label_exclude), 12, 0);
00817
00818 label_include = gtk_label_new(_("Include:"));
00819 gtk_table_attach(GTK_TABLE(table), label_include, 0, 1, 0, 1,
00820 (GtkAttachOptions) (0),
00821 (GtkAttachOptions) (0), 0, 0);
00822 gtk_misc_set_alignment(GTK_MISC(label_include), 0, 0.5);
00823 gtk_misc_set_padding(GTK_MISC(label_include), 12, 0);
00824
00825 filepopup_cover_name_exclude = gtk_entry_new();
00826 gtk_table_attach(GTK_TABLE(table), filepopup_cover_name_exclude, 1, 2, 1, 2,
00827 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
00828 (GtkAttachOptions) (0), 0, 0);
00829 gtk_entry_set_activates_default(GTK_ENTRY(filepopup_cover_name_exclude), TRUE);
00830
00831 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00832 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
00833 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00834
00835 filepopup_recurse = gtk_check_button_new_with_mnemonic(_("Recursively search for cover"));
00836 gtk_container_add(GTK_CONTAINER(alignment), filepopup_recurse);
00837
00838 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00839 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
00840 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 45, 0);
00841
00842 filepopup_recurse_depth_box = gtk_hbox_new(FALSE, 0);
00843 gtk_container_add(GTK_CONTAINER(alignment), filepopup_recurse_depth_box);
00844
00845 label_search_depth = gtk_label_new(_("Search depth: "));
00846 gtk_box_pack_start(GTK_BOX(filepopup_recurse_depth_box), label_search_depth, TRUE, TRUE, 0);
00847 gtk_misc_set_padding(GTK_MISC(label_search_depth), 4, 0);
00848
00849 recurse_for_cover_depth_adj = (GtkAdjustment *) gtk_adjustment_new (0, 0,
00850 100, 1, 10, 0);
00851 filepopup_recurse_depth = gtk_spin_button_new(GTK_ADJUSTMENT(recurse_for_cover_depth_adj), 1, 0);
00852 gtk_box_pack_start(GTK_BOX(filepopup_recurse_depth_box), filepopup_recurse_depth, TRUE, TRUE, 0);
00853 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(filepopup_recurse_depth), TRUE);
00854
00855 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00856 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
00857 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00858
00859 filepopup_use_file_cover = gtk_check_button_new_with_mnemonic(_("Use per-file cover"));
00860 gtk_container_add(GTK_CONTAINER(alignment), filepopup_use_file_cover);
00861
00862 label_misc = gtk_label_new(_("<b>Miscellaneous</b>"));
00863 gtk_box_pack_start(GTK_BOX(vbox), label_misc, FALSE, FALSE, 0);
00864 gtk_label_set_use_markup(GTK_LABEL(label_misc), TRUE);
00865 gtk_misc_set_alignment(GTK_MISC(label_misc), 0, 0.5);
00866
00867 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00868 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
00869 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00870
00871 filepopup_showprogressbar = gtk_check_button_new_with_mnemonic(_("Show Progress bar for the current track"));
00872 gtk_container_add(GTK_CONTAINER(alignment), filepopup_showprogressbar);
00873
00874 alignment = gtk_alignment_new(0, 0.5, 1, 1);
00875 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
00876 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00877
00878 hbox = gtk_hbox_new(FALSE, 0);
00879 gtk_container_add(GTK_CONTAINER(alignment), hbox);
00880
00881 label_delay = gtk_label_new(_("Delay until filepopup comes up: "));
00882 gtk_box_pack_start(GTK_BOX(hbox), label_delay, TRUE, TRUE, 0);
00883 gtk_misc_set_alignment(GTK_MISC(label_delay), 0, 0.5);
00884 gtk_misc_set_padding(GTK_MISC(label_delay), 12, 0);
00885
00886 delay_adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 100, 1, 10, 0);
00887 filepopup_delay = gtk_spin_button_new(GTK_ADJUSTMENT(delay_adj), 1, 0);
00888 gtk_box_pack_start(GTK_BOX(hbox), filepopup_delay, TRUE, TRUE, 0);
00889 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(filepopup_delay), TRUE);
00890
00891 hbuttonbox = gtk_hbutton_box_new();
00892 gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, FALSE, 0);
00893 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_END);
00894 gtk_box_set_spacing(GTK_BOX(hbuttonbox), 6);
00895
00896 btn_cancel = gtk_button_new_from_stock("gtk-cancel");
00897 gtk_container_add(GTK_CONTAINER(hbuttonbox), btn_cancel);
00898
00899 btn_ok = gtk_button_new_from_stock("gtk-ok");
00900 gtk_container_add(GTK_CONTAINER(hbuttonbox), btn_ok);
00901 gtk_widget_set_can_default(btn_ok, TRUE);
00902
00903 g_signal_connect(G_OBJECT(filepopup_settings), "delete_event",
00904 G_CALLBACK(gtk_widget_hide_on_delete),
00905 NULL);
00906 g_signal_connect(G_OBJECT(btn_cancel), "clicked",
00907 G_CALLBACK(on_filepopup_cancel_clicked),
00908 NULL);
00909 g_signal_connect(G_OBJECT(btn_ok), "clicked",
00910 G_CALLBACK(on_filepopup_ok_clicked),
00911 NULL);
00912
00913 gtk_widget_grab_default(btn_ok);
00914 gtk_widget_show_all(vbox);
00915 }
00916
00917 static void create_spin_button (PreferencesWidget * widget, GtkWidget * *
00918 label_pre, GtkWidget * * spin_btn, GtkWidget * * label_past, const char *
00919 domain)
00920 {
00921 g_return_if_fail(widget->type == WIDGET_SPIN_BTN);
00922
00923 * label_pre = gtk_label_new (dgettext (domain, widget->label));
00924
00925 *spin_btn = gtk_spin_button_new_with_range(widget->data.spin_btn.min,
00926 widget->data.spin_btn.max,
00927 widget->data.spin_btn.step);
00928
00929
00930 if (widget->tooltip)
00931 gtk_widget_set_tooltip_text (* spin_btn, dgettext (domain,
00932 widget->tooltip));
00933
00934 if (widget->data.spin_btn.right_label) {
00935 * label_past = gtk_label_new (dgettext (domain,
00936 widget->data.spin_btn.right_label));
00937 }
00938
00939 switch (widget->cfg_type)
00940 {
00941 case VALUE_INT:
00942 gtk_spin_button_set_value ((GtkSpinButton *) * spin_btn, widget_get_int (widget));
00943 g_signal_connect (* spin_btn, "value_changed", (GCallback) on_spin_btn_changed_int, widget);
00944 break;
00945 case VALUE_FLOAT:
00946 gtk_spin_button_set_value ((GtkSpinButton *) * spin_btn, widget_get_double (widget));
00947 g_signal_connect (* spin_btn, "value_changed", (GCallback)
00948 on_spin_btn_changed_float, widget);
00949 break;
00950 default:
00951 break;
00952 }
00953 }
00954
00955 void create_font_btn (PreferencesWidget * widget, GtkWidget * * label,
00956 GtkWidget * * font_btn, const char * domain)
00957 {
00958 *font_btn = gtk_font_button_new();
00959 gtk_font_button_set_use_font(GTK_FONT_BUTTON(*font_btn), TRUE);
00960 gtk_font_button_set_use_size(GTK_FONT_BUTTON(*font_btn), TRUE);
00961 if (widget->label) {
00962 * label = gtk_label_new_with_mnemonic (dgettext (domain, widget->label));
00963 gtk_label_set_use_markup(GTK_LABEL(*label), TRUE);
00964 gtk_misc_set_alignment(GTK_MISC(*label), 1, 0.5);
00965 gtk_label_set_justify(GTK_LABEL(*label), GTK_JUSTIFY_RIGHT);
00966 gtk_label_set_mnemonic_widget(GTK_LABEL(*label), *font_btn);
00967 }
00968
00969 if (widget->data.font_btn.title)
00970 gtk_font_button_set_title (GTK_FONT_BUTTON (* font_btn),
00971 dgettext (domain, widget->data.font_btn.title));
00972
00973 char * name = widget_get_string (widget);
00974 if (name)
00975 {
00976 gtk_font_button_set_font_name ((GtkFontButton *) * font_btn, name);
00977 g_free (name);
00978 }
00979
00980 g_signal_connect (* font_btn, "font_set", (GCallback) on_font_btn_font_set, widget);
00981 }
00982
00983 static void create_entry (PreferencesWidget * widget, GtkWidget * * label,
00984 GtkWidget * * entry, const char * domain)
00985 {
00986 *entry = gtk_entry_new();
00987 gtk_entry_set_visibility(GTK_ENTRY(*entry), !widget->data.entry.password);
00988
00989 if (widget->label)
00990 * label = gtk_label_new (dgettext (domain, widget->label));
00991
00992 if (widget->tooltip)
00993 gtk_widget_set_tooltip_text (* entry, dgettext (domain, widget->tooltip));
00994
00995 if (widget->cfg_type == VALUE_STRING)
00996 {
00997 char * value = widget_get_string (widget);
00998 if (value)
00999 {
01000 gtk_entry_set_text ((GtkEntry *) * entry, value);
01001 g_free (value);
01002 }
01003
01004 g_signal_connect (* entry, "changed", (GCallback) on_entry_changed, widget);
01005 }
01006 }
01007
01008 static void create_label (PreferencesWidget * widget, GtkWidget * * label,
01009 GtkWidget * * icon, const char * domain)
01010 {
01011 if (widget->data.label.stock_id)
01012 *icon = gtk_image_new_from_stock(widget->data.label.stock_id, GTK_ICON_SIZE_BUTTON);
01013
01014 * label = gtk_label_new_with_mnemonic (dgettext (domain, widget->label));
01015 gtk_label_set_use_markup(GTK_LABEL(*label), TRUE);
01016
01017 if (widget->data.label.single_line == FALSE)
01018 gtk_label_set_line_wrap(GTK_LABEL(*label), TRUE);
01019
01020 gtk_misc_set_alignment(GTK_MISC(*label), 0, 0.5);
01021 }
01022
01023 static void create_cbox (PreferencesWidget * widget, GtkWidget * * label,
01024 GtkWidget * * combobox, const char * domain)
01025 {
01026 * combobox = gtk_combo_box_text_new ();
01027
01028 if (widget->label) {
01029 * label = gtk_label_new (dgettext (domain, widget->label));
01030 }
01031
01032 fill_cbox (* combobox, widget);
01033 }
01034
01035 static void fill_table (GtkWidget * table, PreferencesWidget * elements, int
01036 amt, const char * domain)
01037 {
01038 int x;
01039 GtkWidget *widget_left, *widget_middle, *widget_right;
01040 GtkAttachOptions middle_policy = (GtkAttachOptions) (0);
01041
01042 for (x = 0; x < amt; ++x) {
01043 widget_left = widget_middle = widget_right = NULL;
01044 switch (elements[x].type) {
01045 case WIDGET_SPIN_BTN:
01046 create_spin_button (& elements[x], & widget_left,
01047 & widget_middle, & widget_right, domain);
01048 middle_policy = (GtkAttachOptions) (GTK_FILL);
01049 break;
01050 case WIDGET_LABEL:
01051 create_label (& elements[x], & widget_middle, & widget_left,
01052 domain);
01053 middle_policy = (GtkAttachOptions) (GTK_FILL);
01054 break;
01055 case WIDGET_FONT_BTN:
01056 create_font_btn (& elements[x], & widget_left, & widget_middle,
01057 domain);
01058 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL);
01059 break;
01060 case WIDGET_ENTRY:
01061 create_entry (& elements[x], & widget_left, & widget_middle,
01062 domain);
01063 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL);
01064 break;
01065 case WIDGET_COMBO_BOX:
01066 create_cbox (& elements[x], & widget_left, & widget_middle,
01067 domain);
01068 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL);
01069 break;
01070 default:
01071 g_warning("Unsupported widget type %d in table", elements[x].type);
01072 }
01073
01074 if (widget_left)
01075 gtk_table_attach(GTK_TABLE (table), widget_left, 0, 1, x, x+1,
01076 (GtkAttachOptions) (0),
01077 (GtkAttachOptions) (0), 0, 0);
01078
01079 if (widget_middle)
01080 gtk_table_attach(GTK_TABLE(table), widget_middle, 1, widget_right ? 2 : 3, x, x+1,
01081 middle_policy,
01082 (GtkAttachOptions) (0), 4, 0);
01083
01084 if (widget_right)
01085 gtk_table_attach(GTK_TABLE(table), widget_right, 2, 3, x, x+1,
01086 (GtkAttachOptions) (0),
01087 (GtkAttachOptions) (0), 0, 0);
01088 }
01089 }
01090
01091
01092
01093 void create_widgets_with_domain (void * box, PreferencesWidget * widgets, int
01094 amt, const char * domain)
01095 {
01096 int x;
01097 GtkWidget *alignment = NULL, *widget = NULL;
01098 GtkWidget *child_box = NULL;
01099 GSList *radio_btn_group = NULL;
01100
01101 for (x = 0; x < amt; ++x) {
01102 if (widget && widgets[x].child)
01103 {
01104 if (!child_box) {
01105 child_box = gtk_vbox_new(FALSE, 0);
01106 g_object_set_data(G_OBJECT(widget), "child", child_box);
01107 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
01108 gtk_box_pack_start(box, alignment, FALSE, FALSE, 0);
01109 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
01110 gtk_container_add (GTK_CONTAINER (alignment), child_box);
01111
01112 if (GTK_IS_TOGGLE_BUTTON (widget))
01113 gtk_widget_set_sensitive (child_box, gtk_toggle_button_get_active ((GtkToggleButton *) widget));
01114 }
01115 } else
01116 child_box = NULL;
01117
01118 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
01119 gtk_alignment_set_padding ((GtkAlignment *) alignment, 6, 0, 12, 0);
01120 gtk_box_pack_start(child_box ? GTK_BOX(child_box) : box, alignment, FALSE, FALSE, 0);
01121
01122 if (radio_btn_group && widgets[x].type != WIDGET_RADIO_BTN)
01123 radio_btn_group = NULL;
01124
01125 switch(widgets[x].type) {
01126 case WIDGET_CHK_BTN:
01127 widget = gtk_check_button_new_with_mnemonic (dgettext (domain, widgets[x].label));
01128 init_toggle_button (widget, & widgets[x]);
01129 break;
01130 case WIDGET_LABEL:
01131 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 12, 0, 0, 0);
01132
01133 GtkWidget *label = NULL, *icon = NULL;
01134 create_label (& widgets[x], & label, & icon, domain);
01135
01136 if (icon == NULL)
01137 widget = label;
01138 else {
01139 widget = gtk_hbox_new(FALSE, 6);
01140 gtk_box_pack_start(GTK_BOX(widget), icon, FALSE, FALSE, 0);
01141 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01142 }
01143 break;
01144 case WIDGET_RADIO_BTN:
01145 widget = gtk_radio_button_new_with_mnemonic (radio_btn_group,
01146 dgettext (domain, widgets[x].label));
01147 radio_btn_group = gtk_radio_button_get_group ((GtkRadioButton *) widget);
01148 init_toggle_button (widget, & widgets[x]);
01149 break;
01150 case WIDGET_SPIN_BTN:
01151 widget = gtk_hbox_new(FALSE, 6);
01152
01153 GtkWidget *label_pre = NULL, *spin_btn = NULL, *label_past = NULL;
01154 create_spin_button (& widgets[x], & label_pre, & spin_btn,
01155 & label_past, domain);
01156
01157 if (label_pre)
01158 gtk_box_pack_start(GTK_BOX(widget), label_pre, FALSE, FALSE, 0);
01159 if (spin_btn)
01160 gtk_box_pack_start(GTK_BOX(widget), spin_btn, FALSE, FALSE, 0);
01161 if (label_past)
01162 gtk_box_pack_start(GTK_BOX(widget), label_past, FALSE, FALSE, 0);
01163
01164 break;
01165 case WIDGET_CUSTOM:
01166 if (widgets[x].data.populate)
01167 widget = widgets[x].data.populate();
01168 else
01169 widget = NULL;
01170
01171 break;
01172 case WIDGET_FONT_BTN:
01173 widget = gtk_hbox_new(FALSE, 6);
01174
01175 GtkWidget *font_btn = NULL;
01176 create_font_btn (& widgets[x], & label, & font_btn, domain);
01177
01178 if (label)
01179 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01180 if (font_btn)
01181 gtk_box_pack_start(GTK_BOX(widget), font_btn, FALSE, FALSE, 0);
01182 break;
01183 case WIDGET_TABLE:
01184 widget = gtk_table_new(widgets[x].data.table.rows, 3, FALSE);
01185 fill_table (widget, widgets[x].data.table.elem,
01186 widgets[x].data.table.rows, domain);
01187 gtk_table_set_row_spacings(GTK_TABLE(widget), 6);
01188 break;
01189 case WIDGET_ENTRY:
01190 widget = gtk_hbox_new(FALSE, 6);
01191
01192 GtkWidget *entry = NULL;
01193 create_entry (& widgets[x], & label, & entry, domain);
01194
01195 if (label)
01196 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01197 if (entry)
01198 gtk_box_pack_start(GTK_BOX(widget), entry, TRUE, TRUE, 0);
01199 break;
01200 case WIDGET_COMBO_BOX:
01201 widget = gtk_hbox_new(FALSE, 6);
01202
01203 GtkWidget *combo = NULL;
01204 create_cbox (& widgets[x], & label, & combo, domain);
01205
01206 if (label)
01207 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01208 if (combo)
01209 gtk_box_pack_start(GTK_BOX(widget), combo, FALSE, FALSE, 0);
01210 break;
01211 case WIDGET_BOX:
01212 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 0, 0);
01213
01214 if (widgets[x].data.box.horizontal) {
01215 widget = gtk_hbox_new(FALSE, 0);
01216 } else {
01217 widget = gtk_vbox_new(FALSE, 0);
01218 }
01219
01220 create_widgets_with_domain ((GtkBox *) widget,
01221 widgets[x].data.box.elem, widgets[x].data.box.n_elem, domain);
01222
01223 if (widgets[x].data.box.frame) {
01224 GtkWidget *tmp;
01225 tmp = widget;
01226
01227 widget = gtk_frame_new (dgettext (domain, widgets[x].label));
01228 gtk_container_add(GTK_CONTAINER(widget), tmp);
01229 }
01230 break;
01231 case WIDGET_NOTEBOOK:
01232 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
01233
01234 widget = gtk_notebook_new();
01235
01236 int i;
01237 for (i = 0; i<widgets[x].data.notebook.n_tabs; i++) {
01238 GtkWidget *vbox;
01239 vbox = gtk_vbox_new(FALSE, 5);
01240 create_widgets_with_domain ((GtkBox *) vbox,
01241 widgets[x].data.notebook.tabs[i].settings,
01242 widgets[x].data.notebook.tabs[i].n_settings, domain);
01243
01244 gtk_notebook_append_page (GTK_NOTEBOOK (widget), vbox,
01245 gtk_label_new (dgettext (domain,
01246 widgets[x].data.notebook.tabs[i].name)));
01247 }
01248 break;
01249 case WIDGET_SEPARATOR:
01250 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 6, 0, 0);
01251
01252 if (widgets[x].data.separator.horizontal == TRUE) {
01253 widget = gtk_hseparator_new();
01254 } else {
01255 widget = gtk_vseparator_new();
01256 }
01257 break;
01258 default:
01259 break;
01260 }
01261
01262 if (widget && !gtk_widget_get_parent(widget))
01263 gtk_container_add(GTK_CONTAINER(alignment), widget);
01264 if (widget && widgets[x].tooltip && widgets[x].type != WIDGET_SPIN_BTN)
01265 gtk_widget_set_tooltip_text (widget, dgettext (domain,
01266 widgets[x].tooltip));
01267 }
01268
01269 }
01270
01271 static GtkWidget *
01272 create_titlestring_tag_menu(void)
01273 {
01274 GtkWidget *titlestring_tag_menu, *menu_item;
01275 unsigned int i;
01276
01277 titlestring_tag_menu = gtk_menu_new();
01278 for(i = 0; i < n_title_field_tags; i++) {
01279 menu_item = gtk_menu_item_new_with_label(_(title_field_tags[i].name));
01280 gtk_menu_shell_append(GTK_MENU_SHELL(titlestring_tag_menu), menu_item);
01281 g_signal_connect(menu_item, "activate",
01282 G_CALLBACK(titlestring_tag_menu_callback),
01283 GINT_TO_POINTER(i));
01284 };
01285 gtk_widget_show_all(titlestring_tag_menu);
01286
01287 return titlestring_tag_menu;
01288 }
01289
01290 static void show_numbers_cb (GtkToggleButton * numbers, void * unused)
01291 {
01292 set_bool (NULL, "show_numbers_in_pl", gtk_toggle_button_get_active (numbers));
01293
01294 hook_call ("title change", NULL);
01295 }
01296
01297 static void leading_zero_cb (GtkToggleButton * leading)
01298 {
01299 set_bool (NULL, "leading_zero", gtk_toggle_button_get_active (leading));
01300
01301 hook_call ("title change", NULL);
01302 }
01303
01304 static void create_titlestring_widgets (GtkWidget * * cbox, GtkWidget * * entry)
01305 {
01306 * cbox = gtk_combo_box_text_new ();
01307 for (int i = 0; i < TITLESTRING_NPRESETS; i ++)
01308 gtk_combo_box_text_append_text ((GtkComboBoxText *) * cbox, _(titlestring_preset_names[i]));
01309 gtk_combo_box_text_append_text ((GtkComboBoxText *) * cbox, _("Custom"));
01310
01311 * entry = gtk_entry_new ();
01312
01313 char * format = get_string (NULL, "generic_title_format");
01314 update_titlestring_cbox ((GtkComboBox *) * cbox, format);
01315 gtk_entry_set_text ((GtkEntry *) * entry, format);
01316 g_free (format);
01317
01318 g_signal_connect (* cbox, "changed", (GCallback) on_titlestring_cbox_changed, * entry);
01319 g_signal_connect (* entry, "changed", (GCallback) on_titlestring_entry_changed, * cbox);
01320 }
01321
01322 static void
01323 create_playlist_category(void)
01324 {
01325 GtkWidget *vbox5;
01326 GtkWidget *alignment55;
01327 GtkWidget *label60;
01328 GtkWidget *alignment56;
01329 GtkWidget *table6;
01330 GtkWidget *titlestring_help_button;
01331 GtkWidget *image1;
01332 GtkWidget *label62;
01333 GtkWidget *label61;
01334 GtkWidget *alignment85;
01335 GtkWidget *label84;
01336 GtkWidget *alignment86;
01337 GtkWidget *hbox9;
01338 GtkWidget *vbox34;
01339 GtkWidget *image8;
01340 GtkWidget *titlestring_tag_menu = create_titlestring_tag_menu();
01341 GtkWidget * numbers_alignment, * numbers;
01342
01343 vbox5 = gtk_vbox_new (FALSE, 0);
01344 gtk_container_add ((GtkContainer *) category_notebook, vbox5);
01345
01346 create_widgets(GTK_BOX(vbox5), playlist_page_widgets, G_N_ELEMENTS(playlist_page_widgets));
01347
01348 alignment55 = gtk_alignment_new (0.5, 0.5, 1, 1);
01349 gtk_box_pack_start (GTK_BOX (vbox5), alignment55, FALSE, FALSE, 0);
01350 gtk_alignment_set_padding ((GtkAlignment *) alignment55, 12, 3, 0, 0);
01351
01352 label60 = gtk_label_new (_("<b>Song Display</b>"));
01353 gtk_container_add (GTK_CONTAINER (alignment55), label60);
01354 gtk_label_set_use_markup (GTK_LABEL (label60), TRUE);
01355 gtk_misc_set_alignment (GTK_MISC (label60), 0, 0.5);
01356
01357 numbers_alignment = gtk_alignment_new (0, 0, 0, 0);
01358 gtk_alignment_set_padding ((GtkAlignment *) numbers_alignment, 0, 0, 12, 0);
01359 gtk_box_pack_start ((GtkBox *) vbox5, numbers_alignment, 0, 0, 3);
01360
01361 numbers = gtk_check_button_new_with_label (_("Show song numbers"));
01362 gtk_toggle_button_set_active ((GtkToggleButton *) numbers,
01363 get_bool (NULL, "show_numbers_in_pl"));
01364 g_signal_connect ((GObject *) numbers, "toggled", (GCallback)
01365 show_numbers_cb, 0);
01366 gtk_container_add ((GtkContainer *) numbers_alignment, numbers);
01367
01368 numbers_alignment = gtk_alignment_new (0, 0, 0, 0);
01369 gtk_alignment_set_padding ((GtkAlignment *) numbers_alignment, 0, 0, 12, 0);
01370 gtk_box_pack_start ((GtkBox *) vbox5, numbers_alignment, 0, 0, 3);
01371
01372 numbers = gtk_check_button_new_with_label (_("Show leading zeroes (02:00 "
01373 "instead of 2:00)"));
01374 gtk_toggle_button_set_active ((GtkToggleButton *) numbers, get_bool (NULL, "leading_zero"));
01375 g_signal_connect ((GObject *) numbers, "toggled", (GCallback)
01376 leading_zero_cb, 0);
01377 gtk_container_add ((GtkContainer *) numbers_alignment, numbers);
01378
01379 alignment56 = gtk_alignment_new (0.5, 0.5, 1, 1);
01380 gtk_box_pack_start (GTK_BOX (vbox5), alignment56, FALSE, FALSE, 0);
01381 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment56), 0, 0, 12, 0);
01382
01383 table6 = gtk_table_new (2, 3, FALSE);
01384 gtk_container_add (GTK_CONTAINER (alignment56), table6);
01385 gtk_table_set_row_spacings (GTK_TABLE (table6), 4);
01386 gtk_table_set_col_spacings (GTK_TABLE (table6), 12);
01387
01388 titlestring_help_button = gtk_button_new ();
01389 gtk_table_attach (GTK_TABLE (table6), titlestring_help_button, 2, 3, 1, 2,
01390 (GtkAttachOptions) (0),
01391 (GtkAttachOptions) (0), 0, 0);
01392
01393 gtk_widget_set_can_focus (titlestring_help_button, FALSE);
01394 gtk_widget_set_tooltip_text (titlestring_help_button, _("Show information about titlestring format"));
01395 gtk_button_set_relief (GTK_BUTTON (titlestring_help_button), GTK_RELIEF_HALF);
01396 gtk_button_set_focus_on_click (GTK_BUTTON (titlestring_help_button), FALSE);
01397
01398 image1 = gtk_image_new_from_stock ("gtk-index", GTK_ICON_SIZE_BUTTON);
01399 gtk_container_add (GTK_CONTAINER (titlestring_help_button), image1);
01400
01401 GtkWidget * titlestring_cbox;
01402 create_titlestring_widgets (& titlestring_cbox, & titlestring_entry);
01403 gtk_table_attach (GTK_TABLE (table6), titlestring_cbox, 1, 3, 0, 1,
01404 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
01405 (GtkAttachOptions) (0), 0, 0);
01406 gtk_table_attach (GTK_TABLE (table6), titlestring_entry, 1, 2, 1, 2,
01407 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
01408 (GtkAttachOptions) (0), 0, 0);
01409
01410 label62 = gtk_label_new (_("Custom string:"));
01411 gtk_table_attach (GTK_TABLE (table6), label62, 0, 1, 1, 2,
01412 (GtkAttachOptions) (0),
01413 (GtkAttachOptions) (0), 0, 0);
01414 gtk_label_set_justify (GTK_LABEL (label62), GTK_JUSTIFY_RIGHT);
01415 gtk_misc_set_alignment (GTK_MISC (label62), 1, 0.5);
01416
01417 label61 = gtk_label_new (_("Title format:"));
01418 gtk_table_attach (GTK_TABLE (table6), label61, 0, 1, 0, 1,
01419 (GtkAttachOptions) (0),
01420 (GtkAttachOptions) (0), 0, 0);
01421 gtk_label_set_justify (GTK_LABEL (label61), GTK_JUSTIFY_RIGHT);
01422 gtk_misc_set_alignment (GTK_MISC (label61), 1, 0.5);
01423
01424 alignment85 = gtk_alignment_new (0.5, 0.5, 1, 1);
01425 gtk_box_pack_start (GTK_BOX (vbox5), alignment85, FALSE, FALSE, 0);
01426 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment85), 12, 12, 0, 0);
01427
01428 label84 = gtk_label_new (_("<b>Popup Information</b>"));
01429 gtk_container_add (GTK_CONTAINER (alignment85), label84);
01430 gtk_label_set_use_markup (GTK_LABEL (label84), TRUE);
01431 gtk_misc_set_alignment (GTK_MISC (label84), 0, 0.5);
01432
01433 alignment86 = gtk_alignment_new (0.5, 0.5, 1, 1);
01434 gtk_box_pack_start (GTK_BOX (vbox5), alignment86, FALSE, FALSE, 0);
01435 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment86), 0, 0, 12, 0);
01436
01437 hbox9 = gtk_hbox_new (FALSE, 12);
01438 gtk_container_add (GTK_CONTAINER (alignment86), hbox9);
01439
01440 vbox34 = gtk_vbox_new (FALSE, 0);
01441 gtk_box_pack_start (GTK_BOX (hbox9), vbox34, TRUE, TRUE, 0);
01442
01443 filepopupbutton = gtk_check_button_new_with_mnemonic (_("Show popup information for playlist entries"));
01444 gtk_widget_set_tooltip_text (filepopupbutton, _("Toggles popup information window for the pointed entry in the playlist. The window shows title of song, name of album, genre, year of publish, track number, track length, and artwork."));
01445 gtk_toggle_button_set_active ((GtkToggleButton *) filepopupbutton,
01446 get_bool (NULL, "show_filepopup_for_tuple"));
01447 gtk_box_pack_start ((GtkBox *) vbox34, filepopupbutton, TRUE, FALSE, 0);
01448
01449 filepopup_settings_button = gtk_button_new ();
01450 gtk_widget_set_sensitive (filepopup_settings_button,
01451 get_bool (NULL, "show_filepopup_for_tuple"));
01452 gtk_box_pack_start (GTK_BOX (hbox9), filepopup_settings_button, FALSE, FALSE, 0);
01453
01454 gtk_widget_set_can_focus (filepopup_settings_button, FALSE);
01455 gtk_widget_set_tooltip_text (filepopup_settings_button, _("Edit settings for popup information"));
01456 gtk_button_set_relief (GTK_BUTTON (filepopup_settings_button), GTK_RELIEF_HALF);
01457
01458 image8 = gtk_image_new_from_stock ("gtk-properties", GTK_ICON_SIZE_BUTTON);
01459 gtk_container_add (GTK_CONTAINER (filepopup_settings_button), image8);
01460
01461
01462
01463 g_signal_connect (filepopupbutton, "toggled",
01464 G_CALLBACK(on_show_filepopup_toggled),
01465 NULL);
01466 g_signal_connect(G_OBJECT(filepopup_settings_button), "clicked",
01467 G_CALLBACK(on_filepopup_settings_clicked),
01468 NULL);
01469
01470 g_signal_connect(titlestring_help_button, "clicked",
01471 G_CALLBACK(on_titlestring_help_button_clicked),
01472 titlestring_tag_menu);
01473
01474
01475 create_filepopup_settings();
01476 }
01477
01478 static GtkWidget * output_config_button, * output_about_button;
01479
01480 static bool_t output_enum_cb (PluginHandle * plugin, GList * * list)
01481 {
01482 * list = g_list_prepend (* list, plugin);
01483 return TRUE;
01484 }
01485
01486 static GList * output_get_list (void)
01487 {
01488 static GList * list = NULL;
01489
01490 if (list == NULL)
01491 {
01492 plugin_for_each (PLUGIN_TYPE_OUTPUT, (PluginForEachFunc) output_enum_cb,
01493 & list);
01494 list = g_list_reverse (list);
01495 }
01496
01497 return list;
01498 }
01499
01500 static void output_combo_update (GtkComboBox * combo)
01501 {
01502 PluginHandle * plugin = plugin_get_current (PLUGIN_TYPE_OUTPUT);
01503 gtk_combo_box_set_active (combo, g_list_index (output_get_list (), plugin));
01504 gtk_widget_set_sensitive (output_config_button, plugin_has_configure (plugin));
01505 gtk_widget_set_sensitive (output_about_button, plugin_has_about (plugin));
01506 }
01507
01508 static void output_combo_changed (GtkComboBox * combo)
01509 {
01510 PluginHandle * plugin = g_list_nth_data (output_get_list (),
01511 gtk_combo_box_get_active (combo));
01512 g_return_if_fail (plugin != NULL);
01513
01514 plugin_enable (plugin, TRUE);
01515 output_combo_update (combo);
01516 }
01517
01518 static void output_combo_fill (GtkComboBox * combo)
01519 {
01520 for (GList * node = output_get_list (); node != NULL; node = node->next)
01521 gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
01522 plugin_get_name (node->data));
01523 }
01524
01525 static void output_do_config (void)
01526 {
01527 OutputPlugin * op = plugin_get_header (output_plugin_get_current ());
01528 g_return_if_fail (op != NULL);
01529 if (op->configure != NULL)
01530 op->configure ();
01531 }
01532
01533 static void output_do_about (void)
01534 {
01535 OutputPlugin * op = plugin_get_header (output_plugin_get_current ());
01536 g_return_if_fail (op != NULL);
01537 if (op->about != NULL)
01538 op->about ();
01539 }
01540
01541 static void * create_output_plugin_box (void)
01542 {
01543 GtkWidget * hbox1 = gtk_hbox_new (FALSE, 6);
01544 gtk_box_pack_start ((GtkBox *) hbox1, gtk_label_new (_("Output plugin:")), FALSE, FALSE, 0);
01545
01546 GtkWidget * vbox = gtk_vbox_new (FALSE, 6);
01547 gtk_box_pack_start ((GtkBox *) hbox1, vbox, FALSE, FALSE, 0);
01548
01549 GtkWidget * hbox2 = gtk_hbox_new (FALSE, 6);
01550 gtk_box_pack_start ((GtkBox *) vbox, hbox2, FALSE, FALSE, 0);
01551
01552 GtkWidget * output_plugin_cbox = gtk_combo_box_text_new ();
01553 gtk_box_pack_start ((GtkBox *) hbox2, output_plugin_cbox, FALSE, FALSE, 0);
01554
01555 GtkWidget * hbox3 = gtk_hbox_new (FALSE, 6);
01556 gtk_box_pack_start ((GtkBox *) vbox, hbox3, FALSE, FALSE, 0);
01557
01558 output_config_button = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES);
01559 gtk_box_pack_start ((GtkBox *) hbox3, output_config_button, FALSE, FALSE, 0);
01560
01561 output_about_button = gtk_button_new_from_stock (GTK_STOCK_ABOUT);
01562 gtk_box_pack_start ((GtkBox *) hbox3, output_about_button, FALSE, FALSE, 0);
01563
01564 output_combo_fill ((GtkComboBox *) output_plugin_cbox);
01565 output_combo_update ((GtkComboBox *) output_plugin_cbox);
01566
01567 g_signal_connect (output_plugin_cbox, "changed", (GCallback) output_combo_changed, NULL);
01568 g_signal_connect (output_config_button, "clicked", (GCallback) output_do_config, NULL);
01569 g_signal_connect (output_about_button, "clicked", (GCallback) output_do_about, NULL);
01570
01571 return hbox1;
01572 }
01573
01574 static void create_audio_category (void)
01575 {
01576 GtkWidget * audio_page_vbox = gtk_vbox_new (FALSE, 0);
01577 create_widgets ((GtkBox *) audio_page_vbox, audio_page_widgets, G_N_ELEMENTS (audio_page_widgets));
01578 gtk_container_add ((GtkContainer *) category_notebook, audio_page_vbox);
01579 }
01580
01581 static void
01582 create_connectivity_category(void)
01583 {
01584 GtkWidget *connectivity_page_vbox;
01585 GtkWidget *vbox29;
01586
01587 connectivity_page_vbox = gtk_vbox_new (FALSE, 0);
01588 gtk_container_add (GTK_CONTAINER (category_notebook), connectivity_page_vbox);
01589
01590 vbox29 = gtk_vbox_new (FALSE, 0);
01591 gtk_box_pack_start (GTK_BOX (connectivity_page_vbox), vbox29, TRUE, TRUE, 0);
01592
01593 create_widgets(GTK_BOX(vbox29), connectivity_page_widgets, G_N_ELEMENTS(connectivity_page_widgets));
01594 }
01595
01596 static void create_plugin_category (void)
01597 {
01598 GtkWidget * notebook = gtk_notebook_new ();
01599 gtk_container_add ((GtkContainer *) category_notebook, notebook);
01600
01601 int types[] = {PLUGIN_TYPE_TRANSPORT, PLUGIN_TYPE_PLAYLIST,
01602 PLUGIN_TYPE_INPUT, PLUGIN_TYPE_EFFECT, PLUGIN_TYPE_VIS, PLUGIN_TYPE_GENERAL};
01603 const char * names[] = {N_("Transport"), N_("Playlist"), N_("Input"),
01604 N_("Effect"), N_("Visualization"), N_("General")};
01605
01606 for (int i = 0; i < G_N_ELEMENTS (types); i ++)
01607 gtk_notebook_append_page ((GtkNotebook *) notebook, plugin_view_new
01608 (types[i]), gtk_label_new (_(names[i])));
01609 }
01610
01611 static bool_t
01612 prefswin_destroy(GtkWidget *window, GdkEvent *event, gpointer data)
01613 {
01614 prefswin = NULL;
01615 category_notebook = NULL;
01616 gtk_widget_destroy(filepopup_settings);
01617 filepopup_settings = NULL;
01618 gtk_widget_destroy(window);
01619 return TRUE;
01620 }
01621
01622
01623 void * * create_prefs_window (void)
01624 {
01625 char *aud_version_string;
01626
01627 GtkWidget *vbox;
01628 GtkWidget *hbox1;
01629 GtkWidget *scrolledwindow6;
01630 GtkWidget *hseparator1;
01631 GtkWidget *hbox4;
01632 GtkWidget *audversionlabel;
01633 GtkWidget *prefswin_button_box;
01634 GtkWidget *hbox11;
01635 GtkWidget *image10;
01636 GtkWidget *close;
01637 GtkAccelGroup *accel_group;
01638
01639 accel_group = gtk_accel_group_new ();
01640
01641 prefswin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
01642 gtk_window_set_type_hint (GTK_WINDOW (prefswin), GDK_WINDOW_TYPE_HINT_DIALOG);
01643 gtk_container_set_border_width (GTK_CONTAINER (prefswin), 12);
01644 gtk_window_set_title (GTK_WINDOW (prefswin), _("Audacious Preferences"));
01645 gtk_window_set_position (GTK_WINDOW (prefswin), GTK_WIN_POS_CENTER);
01646 gtk_window_set_default_size (GTK_WINDOW (prefswin), 680, 400);
01647
01648 vbox = gtk_vbox_new (FALSE, 0);
01649 gtk_container_add (GTK_CONTAINER (prefswin), vbox);
01650
01651 hbox1 = gtk_hbox_new (FALSE, 8);
01652 gtk_box_pack_start (GTK_BOX (vbox), hbox1, TRUE, TRUE, 0);
01653
01654 scrolledwindow6 = gtk_scrolled_window_new (NULL, NULL);
01655 gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow6, FALSE, FALSE, 0);
01656 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow6), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
01657 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow6), GTK_SHADOW_IN);
01658
01659 category_treeview = gtk_tree_view_new ();
01660 gtk_container_add (GTK_CONTAINER (scrolledwindow6), category_treeview);
01661 gtk_widget_set_size_request (scrolledwindow6, 168, -1);
01662 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (category_treeview), FALSE);
01663
01664 category_notebook = gtk_notebook_new ();
01665 gtk_box_pack_start (GTK_BOX (hbox1), category_notebook, TRUE, TRUE, 0);
01666
01667 gtk_widget_set_can_focus (category_notebook, FALSE);
01668 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (category_notebook), FALSE);
01669 gtk_notebook_set_show_border (GTK_NOTEBOOK (category_notebook), FALSE);
01670 gtk_notebook_set_scrollable (GTK_NOTEBOOK (category_notebook), TRUE);
01671
01672 create_audio_category();
01673 create_connectivity_category();
01674 create_playlist_category();
01675 create_plugin_category();
01676
01677 hseparator1 = gtk_hseparator_new ();
01678 gtk_box_pack_start (GTK_BOX (vbox), hseparator1, FALSE, FALSE, 6);
01679
01680 hbox4 = gtk_hbox_new (FALSE, 0);
01681 gtk_box_pack_start (GTK_BOX (vbox), hbox4, FALSE, FALSE, 0);
01682
01683 audversionlabel = gtk_label_new ("");
01684 gtk_box_pack_start (GTK_BOX (hbox4), audversionlabel, FALSE, FALSE, 0);
01685 gtk_label_set_use_markup (GTK_LABEL (audversionlabel), TRUE);
01686
01687 prefswin_button_box = gtk_hbutton_box_new ();
01688 gtk_box_pack_start (GTK_BOX (hbox4), prefswin_button_box, TRUE, TRUE, 0);
01689 gtk_button_box_set_layout (GTK_BUTTON_BOX (prefswin_button_box), GTK_BUTTONBOX_END);
01690 gtk_box_set_spacing (GTK_BOX (prefswin_button_box), 6);
01691
01692 hbox11 = gtk_hbox_new (FALSE, 2);
01693
01694 image10 = gtk_image_new_from_stock ("gtk-refresh", GTK_ICON_SIZE_BUTTON);
01695 gtk_box_pack_start (GTK_BOX (hbox11), image10, FALSE, FALSE, 0);
01696
01697 close = gtk_button_new_from_stock ("gtk-close");
01698 gtk_container_add (GTK_CONTAINER (prefswin_button_box), close);
01699 gtk_widget_set_can_default(close, TRUE);
01700 gtk_widget_add_accelerator (close, "clicked", accel_group,
01701 GDK_Escape, (GdkModifierType) 0,
01702 GTK_ACCEL_VISIBLE);
01703
01704
01705 gtk_window_add_accel_group (GTK_WINDOW (prefswin), accel_group);
01706
01707
01708 g_signal_connect(G_OBJECT(prefswin), "delete_event",
01709 G_CALLBACK(prefswin_destroy),
01710 NULL);
01711 g_signal_connect_swapped(G_OBJECT(close), "clicked",
01712 G_CALLBACK(prefswin_destroy),
01713 prefswin);
01714
01715
01716 fill_category_list ((GtkTreeView *) category_treeview, (GtkNotebook *) category_notebook);
01717
01718
01719
01720 aud_version_string = g_strdup_printf
01721 ("<span size='small'>%s (%s)</span>", "Audacious " VERSION, BUILDSTAMP);
01722
01723 gtk_label_set_markup( GTK_LABEL(audversionlabel) , aud_version_string );
01724 g_free(aud_version_string);
01725 gtk_widget_show_all(vbox);
01726
01727 return & prefswin;
01728 }
01729
01730 void
01731 destroy_prefs_window(void)
01732 {
01733 prefswin_destroy(prefswin, NULL, NULL);
01734 }
01735
01736 void show_prefs_window (void)
01737 {
01738 if (! prefswin)
01739 create_prefs_window ();
01740
01741 gtk_window_present ((GtkWindow *) prefswin);
01742 }
01743
01744 void
01745 hide_prefs_window(void)
01746 {
01747 g_return_if_fail(prefswin);
01748 gtk_widget_hide(GTK_WIDGET(prefswin));
01749 }
01750
01751 static void prefswin_page_queue_new (GtkWidget * container, const char * name,
01752 const char * imgurl)
01753 {
01754 CategoryQueueEntry *ent = g_new0(CategoryQueueEntry, 1);
01755
01756 ent->container = container;
01757 ent->pg_name = name;
01758 ent->img_url = imgurl;
01759
01760 if (category_queue)
01761 ent->next = category_queue;
01762
01763 category_queue = ent;
01764 }
01765
01766 static void
01767 prefswin_page_queue_destroy(CategoryQueueEntry *ent)
01768 {
01769 category_queue = ent->next;
01770 g_free(ent);
01771 }
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783
01784
01785
01786 int prefswin_page_new (void * container, const char * name, const char *
01787 imgurl)
01788 {
01789 GtkTreeModel *model;
01790 GtkTreeIter iter;
01791 GdkPixbuf *img = NULL;
01792 GtkTreeView *treeview = GTK_TREE_VIEW(category_treeview);
01793 int id;
01794
01795 if (treeview == NULL || category_notebook == NULL)
01796 {
01797 prefswin_page_queue_new(container, name, imgurl);
01798 return -1;
01799 }
01800
01801 model = gtk_tree_view_get_model(treeview);
01802
01803 if (model == NULL)
01804 {
01805 prefswin_page_queue_new(container, name, imgurl);
01806 return -1;
01807 }
01808
01809
01810 gtk_widget_show(container);
01811 id = gtk_notebook_append_page(GTK_NOTEBOOK(category_notebook), container, NULL);
01812
01813 if (id == -1)
01814 return -1;
01815
01816 if (imgurl != NULL)
01817 img = gdk_pixbuf_new_from_file(imgurl, NULL);
01818
01819 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
01820 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
01821 CATEGORY_VIEW_COL_ICON, img,
01822 CATEGORY_VIEW_COL_NAME,
01823 name, CATEGORY_VIEW_COL_ID, id, -1);
01824
01825 if (img != NULL)
01826 g_object_unref(img);
01827
01828 return id;
01829 }
01830
01831 void
01832 prefswin_page_destroy(GtkWidget *container)
01833 {
01834 GtkTreeModel *model;
01835 GtkTreeIter iter;
01836 GtkTreeView *treeview = GTK_TREE_VIEW(category_treeview);
01837 bool_t ret;
01838 int id;
01839 int index = -1;
01840
01841 if (category_notebook == NULL || treeview == NULL || container == NULL)
01842 return;
01843
01844 id = gtk_notebook_page_num(GTK_NOTEBOOK(category_notebook), container);
01845
01846 if (id == -1)
01847 return;
01848
01849 gtk_notebook_remove_page(GTK_NOTEBOOK(category_notebook), id);
01850
01851 model = gtk_tree_view_get_model(treeview);
01852
01853 if (model == NULL)
01854 return;
01855
01856 ret = gtk_tree_model_get_iter_first(model, &iter);
01857
01858 while (ret == TRUE)
01859 {
01860 gtk_tree_model_get(model, &iter, CATEGORY_VIEW_COL_ID, &index, -1);
01861
01862 if (index == id)
01863 {
01864 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
01865 ret = gtk_tree_model_get_iter_first(model, &iter);
01866 continue;
01867 }
01868
01869 if (index > id)
01870 {
01871 index--;
01872 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CATEGORY_VIEW_COL_ID, index, -1);
01873 }
01874
01875 ret = gtk_tree_model_iter_next(model, &iter);
01876 }
01877 }
01878
01879 static void sw_volume_toggled (void)
01880 {
01881 int vol[2];
01882
01883 if (get_bool (NULL, "software_volume_control"))
01884 {
01885 vol[0] = get_int (NULL, "sw_volume_left");
01886 vol[1] = get_int (NULL, "sw_volume_right");
01887 }
01888 else
01889 playback_get_volume (& vol[0], & vol[1]);
01890
01891 hook_call ("volume set", vol);
01892 }