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, const char * domain)
00706 {
00707 for (int i = 0; i < widget->data.combo.n_elements; i ++)
00708 gtk_combo_box_text_append_text ((GtkComboBoxText *) combobox,
00709 dgettext (domain, widget->data.combo.elements[i].label));
00710
00711 switch (widget->cfg_type)
00712 {
00713 case VALUE_INT:;
00714 int ivalue = widget_get_int (widget);
00715
00716 for (int i = 0; i < widget->data.combo.n_elements; i++)
00717 {
00718 if (GPOINTER_TO_INT (widget->data.combo.elements[i].value) == ivalue)
00719 {
00720 gtk_combo_box_set_active ((GtkComboBox *) combobox, i);
00721 break;
00722 }
00723 }
00724
00725 g_signal_connect (combobox, "changed", (GCallback) on_cbox_changed_int, (void *) widget);
00726 break;
00727
00728 case VALUE_STRING:;
00729 char * value = widget_get_string (widget);
00730
00731 for(int i = 0; i < widget->data.combo.n_elements; i++)
00732 {
00733 if (value && ! strcmp (widget->data.combo.elements[i].value, value))
00734 {
00735 gtk_combo_box_set_active ((GtkComboBox *) combobox, i);
00736 break;
00737 }
00738 }
00739
00740 g_free (value);
00741
00742 g_signal_connect (combobox, "changed", (GCallback) on_cbox_changed_string, (void *) widget);
00743 break;
00744
00745 default:
00746 break;
00747 }
00748 }
00749
00750 void
00751 create_filepopup_settings(void)
00752 {
00753 GtkWidget *vbox;
00754 GtkWidget *table;
00755
00756 GtkWidget *label_cover_retrieve;
00757 GtkWidget *label_cover_search;
00758 GtkWidget *label_exclude;
00759 GtkWidget *label_include;
00760 GtkWidget *label_search_depth;
00761 GtkWidget *label_misc;
00762 GtkWidget *label_delay;
00763
00764 GtkAdjustment *recurse_for_cover_depth_adj;
00765 GtkAdjustment *delay_adj;
00766 GtkWidget *alignment;
00767
00768 GtkWidget *hbox;
00769 GtkWidget *hbuttonbox;
00770 GtkWidget *btn_cancel;
00771 GtkWidget *btn_ok;
00772
00773 filepopup_settings = gtk_window_new(GTK_WINDOW_TOPLEVEL);
00774 gtk_container_set_border_width(GTK_CONTAINER(filepopup_settings), 12);
00775 gtk_window_set_title(GTK_WINDOW(filepopup_settings), _("Popup Information Settings"));
00776 gtk_window_set_position(GTK_WINDOW(filepopup_settings), GTK_WIN_POS_CENTER_ON_PARENT);
00777 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(filepopup_settings), TRUE);
00778 gtk_window_set_type_hint(GTK_WINDOW(filepopup_settings), GDK_WINDOW_TYPE_HINT_DIALOG);
00779 gtk_window_set_transient_for(GTK_WINDOW(filepopup_settings), GTK_WINDOW(prefswin));
00780
00781 vbox = gtk_vbox_new(FALSE, 12);
00782 gtk_container_add(GTK_CONTAINER(filepopup_settings), vbox);
00783
00784 label_cover_retrieve = gtk_label_new(_("<b>Cover image retrieve</b>"));
00785 gtk_box_pack_start(GTK_BOX(vbox), label_cover_retrieve, FALSE, FALSE, 0);
00786 gtk_label_set_use_markup(GTK_LABEL(label_cover_retrieve), TRUE);
00787 gtk_misc_set_alignment(GTK_MISC(label_cover_retrieve), 0, 0.5);
00788
00789 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."));
00790 gtk_box_pack_start(GTK_BOX(vbox), label_cover_search, FALSE, FALSE, 0);
00791 gtk_label_set_line_wrap(GTK_LABEL(label_cover_search), TRUE);
00792 gtk_misc_set_alignment(GTK_MISC(label_cover_search), 0, 0);
00793 gtk_misc_set_padding(GTK_MISC(label_cover_search), 12, 0);
00794
00795 table = gtk_table_new(2, 2, FALSE);
00796 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0);
00797 gtk_table_set_row_spacings(GTK_TABLE(table), 4);
00798 gtk_table_set_col_spacings(GTK_TABLE(table), 4);
00799
00800 filepopup_cover_name_include = gtk_entry_new();
00801 gtk_table_attach(GTK_TABLE(table), filepopup_cover_name_include, 1, 2, 0, 1,
00802 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
00803 (GtkAttachOptions) (0), 0, 0);
00804 gtk_entry_set_activates_default(GTK_ENTRY(filepopup_cover_name_include), TRUE);
00805
00806 label_exclude = gtk_label_new(_("Exclude:"));
00807 gtk_table_attach(GTK_TABLE(table), label_exclude, 0, 1, 1, 2,
00808 (GtkAttachOptions) (0),
00809 (GtkAttachOptions) (0), 0, 0);
00810 gtk_misc_set_alignment(GTK_MISC(label_exclude), 0, 0.5);
00811 gtk_misc_set_padding(GTK_MISC(label_exclude), 12, 0);
00812
00813 label_include = gtk_label_new(_("Include:"));
00814 gtk_table_attach(GTK_TABLE(table), label_include, 0, 1, 0, 1,
00815 (GtkAttachOptions) (0),
00816 (GtkAttachOptions) (0), 0, 0);
00817 gtk_misc_set_alignment(GTK_MISC(label_include), 0, 0.5);
00818 gtk_misc_set_padding(GTK_MISC(label_include), 12, 0);
00819
00820 filepopup_cover_name_exclude = gtk_entry_new();
00821 gtk_table_attach(GTK_TABLE(table), filepopup_cover_name_exclude, 1, 2, 1, 2,
00822 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
00823 (GtkAttachOptions) (0), 0, 0);
00824 gtk_entry_set_activates_default(GTK_ENTRY(filepopup_cover_name_exclude), TRUE);
00825
00826 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00827 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
00828 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00829
00830 filepopup_recurse = gtk_check_button_new_with_mnemonic(_("Recursively search for cover"));
00831 gtk_container_add(GTK_CONTAINER(alignment), filepopup_recurse);
00832
00833 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00834 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
00835 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 45, 0);
00836
00837 filepopup_recurse_depth_box = gtk_hbox_new(FALSE, 0);
00838 gtk_container_add(GTK_CONTAINER(alignment), filepopup_recurse_depth_box);
00839
00840 label_search_depth = gtk_label_new(_("Search depth: "));
00841 gtk_box_pack_start(GTK_BOX(filepopup_recurse_depth_box), label_search_depth, TRUE, TRUE, 0);
00842 gtk_misc_set_padding(GTK_MISC(label_search_depth), 4, 0);
00843
00844 recurse_for_cover_depth_adj = (GtkAdjustment *) gtk_adjustment_new (0, 0,
00845 100, 1, 10, 0);
00846 filepopup_recurse_depth = gtk_spin_button_new(GTK_ADJUSTMENT(recurse_for_cover_depth_adj), 1, 0);
00847 gtk_box_pack_start(GTK_BOX(filepopup_recurse_depth_box), filepopup_recurse_depth, TRUE, TRUE, 0);
00848 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(filepopup_recurse_depth), TRUE);
00849
00850 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00851 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
00852 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00853
00854 filepopup_use_file_cover = gtk_check_button_new_with_mnemonic(_("Use per-file cover"));
00855 gtk_container_add(GTK_CONTAINER(alignment), filepopup_use_file_cover);
00856
00857 label_misc = gtk_label_new(_("<b>Miscellaneous</b>"));
00858 gtk_box_pack_start(GTK_BOX(vbox), label_misc, FALSE, FALSE, 0);
00859 gtk_label_set_use_markup(GTK_LABEL(label_misc), TRUE);
00860 gtk_misc_set_alignment(GTK_MISC(label_misc), 0, 0.5);
00861
00862 alignment = gtk_alignment_new(0.5, 0.5, 1, 1);
00863 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0);
00864 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00865
00866 filepopup_showprogressbar = gtk_check_button_new_with_mnemonic(_("Show Progress bar for the current track"));
00867 gtk_container_add(GTK_CONTAINER(alignment), filepopup_showprogressbar);
00868
00869 alignment = gtk_alignment_new(0, 0.5, 1, 1);
00870 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0);
00871 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0);
00872
00873 hbox = gtk_hbox_new(FALSE, 0);
00874 gtk_container_add(GTK_CONTAINER(alignment), hbox);
00875
00876 label_delay = gtk_label_new(_("Delay until filepopup comes up: "));
00877 gtk_box_pack_start(GTK_BOX(hbox), label_delay, TRUE, TRUE, 0);
00878 gtk_misc_set_alignment(GTK_MISC(label_delay), 0, 0.5);
00879 gtk_misc_set_padding(GTK_MISC(label_delay), 12, 0);
00880
00881 delay_adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 100, 1, 10, 0);
00882 filepopup_delay = gtk_spin_button_new(GTK_ADJUSTMENT(delay_adj), 1, 0);
00883 gtk_box_pack_start(GTK_BOX(hbox), filepopup_delay, TRUE, TRUE, 0);
00884 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(filepopup_delay), TRUE);
00885
00886 hbuttonbox = gtk_hbutton_box_new();
00887 gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, FALSE, 0);
00888 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_END);
00889 gtk_box_set_spacing(GTK_BOX(hbuttonbox), 6);
00890
00891 btn_cancel = gtk_button_new_from_stock("gtk-cancel");
00892 gtk_container_add(GTK_CONTAINER(hbuttonbox), btn_cancel);
00893
00894 btn_ok = gtk_button_new_from_stock("gtk-ok");
00895 gtk_container_add(GTK_CONTAINER(hbuttonbox), btn_ok);
00896 gtk_widget_set_can_default(btn_ok, TRUE);
00897
00898 g_signal_connect(G_OBJECT(filepopup_settings), "delete_event",
00899 G_CALLBACK(gtk_widget_hide_on_delete),
00900 NULL);
00901 g_signal_connect(G_OBJECT(btn_cancel), "clicked",
00902 G_CALLBACK(on_filepopup_cancel_clicked),
00903 NULL);
00904 g_signal_connect(G_OBJECT(btn_ok), "clicked",
00905 G_CALLBACK(on_filepopup_ok_clicked),
00906 NULL);
00907
00908 gtk_widget_grab_default(btn_ok);
00909 gtk_widget_show_all(vbox);
00910 }
00911
00912 static void create_spin_button (PreferencesWidget * widget, GtkWidget * *
00913 label_pre, GtkWidget * * spin_btn, GtkWidget * * label_past, const char *
00914 domain)
00915 {
00916 g_return_if_fail(widget->type == WIDGET_SPIN_BTN);
00917
00918 * label_pre = gtk_label_new (dgettext (domain, widget->label));
00919
00920 *spin_btn = gtk_spin_button_new_with_range(widget->data.spin_btn.min,
00921 widget->data.spin_btn.max,
00922 widget->data.spin_btn.step);
00923
00924
00925 if (widget->tooltip)
00926 gtk_widget_set_tooltip_text (* spin_btn, dgettext (domain,
00927 widget->tooltip));
00928
00929 if (widget->data.spin_btn.right_label) {
00930 * label_past = gtk_label_new (dgettext (domain,
00931 widget->data.spin_btn.right_label));
00932 }
00933
00934 switch (widget->cfg_type)
00935 {
00936 case VALUE_INT:
00937 gtk_spin_button_set_value ((GtkSpinButton *) * spin_btn, widget_get_int (widget));
00938 g_signal_connect (* spin_btn, "value_changed", (GCallback) on_spin_btn_changed_int, widget);
00939 break;
00940 case VALUE_FLOAT:
00941 gtk_spin_button_set_value ((GtkSpinButton *) * spin_btn, widget_get_double (widget));
00942 g_signal_connect (* spin_btn, "value_changed", (GCallback)
00943 on_spin_btn_changed_float, widget);
00944 break;
00945 default:
00946 break;
00947 }
00948 }
00949
00950 void create_font_btn (PreferencesWidget * widget, GtkWidget * * label,
00951 GtkWidget * * font_btn, const char * domain)
00952 {
00953 *font_btn = gtk_font_button_new();
00954 gtk_font_button_set_use_font(GTK_FONT_BUTTON(*font_btn), TRUE);
00955 gtk_font_button_set_use_size(GTK_FONT_BUTTON(*font_btn), TRUE);
00956 if (widget->label) {
00957 * label = gtk_label_new_with_mnemonic (dgettext (domain, widget->label));
00958 gtk_label_set_use_markup(GTK_LABEL(*label), TRUE);
00959 gtk_misc_set_alignment(GTK_MISC(*label), 1, 0.5);
00960 gtk_label_set_justify(GTK_LABEL(*label), GTK_JUSTIFY_RIGHT);
00961 gtk_label_set_mnemonic_widget(GTK_LABEL(*label), *font_btn);
00962 }
00963
00964 if (widget->data.font_btn.title)
00965 gtk_font_button_set_title (GTK_FONT_BUTTON (* font_btn),
00966 dgettext (domain, widget->data.font_btn.title));
00967
00968 char * name = widget_get_string (widget);
00969 if (name)
00970 {
00971 gtk_font_button_set_font_name ((GtkFontButton *) * font_btn, name);
00972 g_free (name);
00973 }
00974
00975 g_signal_connect (* font_btn, "font_set", (GCallback) on_font_btn_font_set, widget);
00976 }
00977
00978 static void create_entry (PreferencesWidget * widget, GtkWidget * * label,
00979 GtkWidget * * entry, const char * domain)
00980 {
00981 *entry = gtk_entry_new();
00982 gtk_entry_set_visibility(GTK_ENTRY(*entry), !widget->data.entry.password);
00983
00984 if (widget->label)
00985 * label = gtk_label_new (dgettext (domain, widget->label));
00986
00987 if (widget->tooltip)
00988 gtk_widget_set_tooltip_text (* entry, dgettext (domain, widget->tooltip));
00989
00990 if (widget->cfg_type == VALUE_STRING)
00991 {
00992 char * value = widget_get_string (widget);
00993 if (value)
00994 {
00995 gtk_entry_set_text ((GtkEntry *) * entry, value);
00996 g_free (value);
00997 }
00998
00999 g_signal_connect (* entry, "changed", (GCallback) on_entry_changed, widget);
01000 }
01001 }
01002
01003 static void create_label (PreferencesWidget * widget, GtkWidget * * label,
01004 GtkWidget * * icon, const char * domain)
01005 {
01006 if (widget->data.label.stock_id)
01007 *icon = gtk_image_new_from_stock(widget->data.label.stock_id, GTK_ICON_SIZE_BUTTON);
01008
01009 * label = gtk_label_new_with_mnemonic (dgettext (domain, widget->label));
01010 gtk_label_set_use_markup(GTK_LABEL(*label), TRUE);
01011
01012 if (widget->data.label.single_line == FALSE)
01013 gtk_label_set_line_wrap(GTK_LABEL(*label), TRUE);
01014
01015 gtk_misc_set_alignment(GTK_MISC(*label), 0, 0.5);
01016 }
01017
01018 static void create_cbox (PreferencesWidget * widget, GtkWidget * * label,
01019 GtkWidget * * combobox, const char * domain)
01020 {
01021 * combobox = gtk_combo_box_text_new ();
01022
01023 if (widget->label) {
01024 * label = gtk_label_new (dgettext (domain, widget->label));
01025 }
01026
01027 fill_cbox (* combobox, widget, domain);
01028 }
01029
01030 static void fill_table (GtkWidget * table, PreferencesWidget * elements, int
01031 amt, const char * domain)
01032 {
01033 int x;
01034 GtkWidget *widget_left, *widget_middle, *widget_right;
01035 GtkAttachOptions middle_policy = (GtkAttachOptions) (0);
01036
01037 for (x = 0; x < amt; ++x) {
01038 widget_left = widget_middle = widget_right = NULL;
01039 switch (elements[x].type) {
01040 case WIDGET_SPIN_BTN:
01041 create_spin_button (& elements[x], & widget_left,
01042 & widget_middle, & widget_right, domain);
01043 middle_policy = (GtkAttachOptions) (GTK_FILL);
01044 break;
01045 case WIDGET_LABEL:
01046 create_label (& elements[x], & widget_middle, & widget_left,
01047 domain);
01048 middle_policy = (GtkAttachOptions) (GTK_FILL);
01049 break;
01050 case WIDGET_FONT_BTN:
01051 create_font_btn (& elements[x], & widget_left, & widget_middle,
01052 domain);
01053 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL);
01054 break;
01055 case WIDGET_ENTRY:
01056 create_entry (& elements[x], & widget_left, & widget_middle,
01057 domain);
01058 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL);
01059 break;
01060 case WIDGET_COMBO_BOX:
01061 create_cbox (& elements[x], & widget_left, & widget_middle,
01062 domain);
01063 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL);
01064 break;
01065 default:
01066 g_warning("Unsupported widget type %d in table", elements[x].type);
01067 }
01068
01069 if (widget_left)
01070 gtk_table_attach(GTK_TABLE (table), widget_left, 0, 1, x, x+1,
01071 (GtkAttachOptions) (0),
01072 (GtkAttachOptions) (0), 0, 0);
01073
01074 if (widget_middle)
01075 gtk_table_attach(GTK_TABLE(table), widget_middle, 1, widget_right ? 2 : 3, x, x+1,
01076 middle_policy,
01077 (GtkAttachOptions) (0), 4, 0);
01078
01079 if (widget_right)
01080 gtk_table_attach(GTK_TABLE(table), widget_right, 2, 3, x, x+1,
01081 (GtkAttachOptions) (0),
01082 (GtkAttachOptions) (0), 0, 0);
01083 }
01084 }
01085
01086
01087
01088 void create_widgets_with_domain (void * box, PreferencesWidget * widgets, int
01089 amt, const char * domain)
01090 {
01091 int x;
01092 GtkWidget *alignment = NULL, *widget = NULL;
01093 GtkWidget *child_box = NULL;
01094 GSList *radio_btn_group = NULL;
01095
01096 for (x = 0; x < amt; ++x) {
01097 if (widget && widgets[x].child)
01098 {
01099 if (!child_box) {
01100 child_box = gtk_vbox_new(FALSE, 0);
01101 g_object_set_data(G_OBJECT(widget), "child", child_box);
01102 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
01103 gtk_box_pack_start(box, alignment, FALSE, FALSE, 0);
01104 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0);
01105 gtk_container_add (GTK_CONTAINER (alignment), child_box);
01106
01107 if (GTK_IS_TOGGLE_BUTTON (widget))
01108 gtk_widget_set_sensitive (child_box, gtk_toggle_button_get_active ((GtkToggleButton *) widget));
01109 }
01110 } else
01111 child_box = NULL;
01112
01113 alignment = gtk_alignment_new (0.5, 0.5, 1, 1);
01114 gtk_alignment_set_padding ((GtkAlignment *) alignment, 6, 0, 12, 0);
01115 gtk_box_pack_start(child_box ? GTK_BOX(child_box) : box, alignment, FALSE, FALSE, 0);
01116
01117 if (radio_btn_group && widgets[x].type != WIDGET_RADIO_BTN)
01118 radio_btn_group = NULL;
01119
01120 switch(widgets[x].type) {
01121 case WIDGET_CHK_BTN:
01122 widget = gtk_check_button_new_with_mnemonic (dgettext (domain, widgets[x].label));
01123 init_toggle_button (widget, & widgets[x]);
01124 break;
01125 case WIDGET_LABEL:
01126 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 12, 0, 0, 0);
01127
01128 GtkWidget *label = NULL, *icon = NULL;
01129 create_label (& widgets[x], & label, & icon, domain);
01130
01131 if (icon == NULL)
01132 widget = label;
01133 else {
01134 widget = gtk_hbox_new(FALSE, 6);
01135 gtk_box_pack_start(GTK_BOX(widget), icon, FALSE, FALSE, 0);
01136 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01137 }
01138 break;
01139 case WIDGET_RADIO_BTN:
01140 widget = gtk_radio_button_new_with_mnemonic (radio_btn_group,
01141 dgettext (domain, widgets[x].label));
01142 radio_btn_group = gtk_radio_button_get_group ((GtkRadioButton *) widget);
01143 init_toggle_button (widget, & widgets[x]);
01144 break;
01145 case WIDGET_SPIN_BTN:
01146 widget = gtk_hbox_new(FALSE, 6);
01147
01148 GtkWidget *label_pre = NULL, *spin_btn = NULL, *label_past = NULL;
01149 create_spin_button (& widgets[x], & label_pre, & spin_btn,
01150 & label_past, domain);
01151
01152 if (label_pre)
01153 gtk_box_pack_start(GTK_BOX(widget), label_pre, FALSE, FALSE, 0);
01154 if (spin_btn)
01155 gtk_box_pack_start(GTK_BOX(widget), spin_btn, FALSE, FALSE, 0);
01156 if (label_past)
01157 gtk_box_pack_start(GTK_BOX(widget), label_past, FALSE, FALSE, 0);
01158
01159 break;
01160 case WIDGET_CUSTOM:
01161 if (widgets[x].data.populate)
01162 widget = widgets[x].data.populate();
01163 else
01164 widget = NULL;
01165
01166 break;
01167 case WIDGET_FONT_BTN:
01168 widget = gtk_hbox_new(FALSE, 6);
01169
01170 GtkWidget *font_btn = NULL;
01171 create_font_btn (& widgets[x], & label, & font_btn, domain);
01172
01173 if (label)
01174 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01175 if (font_btn)
01176 gtk_box_pack_start(GTK_BOX(widget), font_btn, FALSE, FALSE, 0);
01177 break;
01178 case WIDGET_TABLE:
01179 widget = gtk_table_new(widgets[x].data.table.rows, 3, FALSE);
01180 fill_table (widget, widgets[x].data.table.elem,
01181 widgets[x].data.table.rows, domain);
01182 gtk_table_set_row_spacings(GTK_TABLE(widget), 6);
01183 break;
01184 case WIDGET_ENTRY:
01185 widget = gtk_hbox_new(FALSE, 6);
01186
01187 GtkWidget *entry = NULL;
01188 create_entry (& widgets[x], & label, & entry, domain);
01189
01190 if (label)
01191 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01192 if (entry)
01193 gtk_box_pack_start(GTK_BOX(widget), entry, TRUE, TRUE, 0);
01194 break;
01195 case WIDGET_COMBO_BOX:
01196 widget = gtk_hbox_new(FALSE, 6);
01197
01198 GtkWidget *combo = NULL;
01199 create_cbox (& widgets[x], & label, & combo, domain);
01200
01201 if (label)
01202 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0);
01203 if (combo)
01204 gtk_box_pack_start(GTK_BOX(widget), combo, FALSE, FALSE, 0);
01205 break;
01206 case WIDGET_BOX:
01207 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 0, 0);
01208
01209 if (widgets[x].data.box.horizontal) {
01210 widget = gtk_hbox_new(FALSE, 0);
01211 } else {
01212 widget = gtk_vbox_new(FALSE, 0);
01213 }
01214
01215 create_widgets_with_domain ((GtkBox *) widget,
01216 widgets[x].data.box.elem, widgets[x].data.box.n_elem, domain);
01217
01218 if (widgets[x].data.box.frame) {
01219 GtkWidget *tmp;
01220 tmp = widget;
01221
01222 widget = gtk_frame_new (dgettext (domain, widgets[x].label));
01223 gtk_container_add(GTK_CONTAINER(widget), tmp);
01224 }
01225 break;
01226 case WIDGET_NOTEBOOK:
01227 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 0, 0);
01228
01229 widget = gtk_notebook_new();
01230
01231 int i;
01232 for (i = 0; i<widgets[x].data.notebook.n_tabs; i++) {
01233 GtkWidget *vbox;
01234 vbox = gtk_vbox_new(FALSE, 5);
01235 create_widgets_with_domain ((GtkBox *) vbox,
01236 widgets[x].data.notebook.tabs[i].settings,
01237 widgets[x].data.notebook.tabs[i].n_settings, domain);
01238
01239 gtk_notebook_append_page (GTK_NOTEBOOK (widget), vbox,
01240 gtk_label_new (dgettext (domain,
01241 widgets[x].data.notebook.tabs[i].name)));
01242 }
01243 break;
01244 case WIDGET_SEPARATOR:
01245 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 6, 0, 0);
01246
01247 if (widgets[x].data.separator.horizontal == TRUE) {
01248 widget = gtk_hseparator_new();
01249 } else {
01250 widget = gtk_vseparator_new();
01251 }
01252 break;
01253 default:
01254 break;
01255 }
01256
01257 if (widget && !gtk_widget_get_parent(widget))
01258 gtk_container_add(GTK_CONTAINER(alignment), widget);
01259 if (widget && widgets[x].tooltip && widgets[x].type != WIDGET_SPIN_BTN)
01260 gtk_widget_set_tooltip_text (widget, dgettext (domain,
01261 widgets[x].tooltip));
01262 }
01263
01264 }
01265
01266 static GtkWidget *
01267 create_titlestring_tag_menu(void)
01268 {
01269 GtkWidget *titlestring_tag_menu, *menu_item;
01270 unsigned int i;
01271
01272 titlestring_tag_menu = gtk_menu_new();
01273 for(i = 0; i < n_title_field_tags; i++) {
01274 menu_item = gtk_menu_item_new_with_label(_(title_field_tags[i].name));
01275 gtk_menu_shell_append(GTK_MENU_SHELL(titlestring_tag_menu), menu_item);
01276 g_signal_connect(menu_item, "activate",
01277 G_CALLBACK(titlestring_tag_menu_callback),
01278 GINT_TO_POINTER(i));
01279 };
01280 gtk_widget_show_all(titlestring_tag_menu);
01281
01282 return titlestring_tag_menu;
01283 }
01284
01285 static void show_numbers_cb (GtkToggleButton * numbers, void * unused)
01286 {
01287 set_bool (NULL, "show_numbers_in_pl", gtk_toggle_button_get_active (numbers));
01288 playlist_reformat_titles ();
01289 hook_call ("title change", NULL);
01290 }
01291
01292 static void leading_zero_cb (GtkToggleButton * leading)
01293 {
01294 set_bool (NULL, "leading_zero", gtk_toggle_button_get_active (leading));
01295 playlist_reformat_titles ();
01296 hook_call ("title change", NULL);
01297 }
01298
01299 static void create_titlestring_widgets (GtkWidget * * cbox, GtkWidget * * entry)
01300 {
01301 * cbox = gtk_combo_box_text_new ();
01302 for (int i = 0; i < TITLESTRING_NPRESETS; i ++)
01303 gtk_combo_box_text_append_text ((GtkComboBoxText *) * cbox, _(titlestring_preset_names[i]));
01304 gtk_combo_box_text_append_text ((GtkComboBoxText *) * cbox, _("Custom"));
01305
01306 * entry = gtk_entry_new ();
01307
01308 char * format = get_string (NULL, "generic_title_format");
01309 update_titlestring_cbox ((GtkComboBox *) * cbox, format);
01310 gtk_entry_set_text ((GtkEntry *) * entry, format);
01311 g_free (format);
01312
01313 g_signal_connect (* cbox, "changed", (GCallback) on_titlestring_cbox_changed, * entry);
01314 g_signal_connect (* entry, "changed", (GCallback) on_titlestring_entry_changed, * cbox);
01315 }
01316
01317 static void
01318 create_playlist_category(void)
01319 {
01320 GtkWidget *vbox5;
01321 GtkWidget *alignment55;
01322 GtkWidget *label60;
01323 GtkWidget *alignment56;
01324 GtkWidget *table6;
01325 GtkWidget *titlestring_help_button;
01326 GtkWidget *image1;
01327 GtkWidget *label62;
01328 GtkWidget *label61;
01329 GtkWidget *alignment85;
01330 GtkWidget *label84;
01331 GtkWidget *alignment86;
01332 GtkWidget *hbox9;
01333 GtkWidget *vbox34;
01334 GtkWidget *image8;
01335 GtkWidget *titlestring_tag_menu = create_titlestring_tag_menu();
01336 GtkWidget * numbers_alignment, * numbers;
01337
01338 vbox5 = gtk_vbox_new (FALSE, 0);
01339 gtk_container_add ((GtkContainer *) category_notebook, vbox5);
01340
01341 create_widgets(GTK_BOX(vbox5), playlist_page_widgets, G_N_ELEMENTS(playlist_page_widgets));
01342
01343 alignment55 = gtk_alignment_new (0.5, 0.5, 1, 1);
01344 gtk_box_pack_start (GTK_BOX (vbox5), alignment55, FALSE, FALSE, 0);
01345 gtk_alignment_set_padding ((GtkAlignment *) alignment55, 12, 3, 0, 0);
01346
01347 label60 = gtk_label_new (_("<b>Song Display</b>"));
01348 gtk_container_add (GTK_CONTAINER (alignment55), label60);
01349 gtk_label_set_use_markup (GTK_LABEL (label60), TRUE);
01350 gtk_misc_set_alignment (GTK_MISC (label60), 0, 0.5);
01351
01352 numbers_alignment = gtk_alignment_new (0, 0, 0, 0);
01353 gtk_alignment_set_padding ((GtkAlignment *) numbers_alignment, 0, 0, 12, 0);
01354 gtk_box_pack_start ((GtkBox *) vbox5, numbers_alignment, 0, 0, 3);
01355
01356 numbers = gtk_check_button_new_with_label (_("Show song numbers"));
01357 gtk_toggle_button_set_active ((GtkToggleButton *) numbers,
01358 get_bool (NULL, "show_numbers_in_pl"));
01359 g_signal_connect ((GObject *) numbers, "toggled", (GCallback)
01360 show_numbers_cb, 0);
01361 gtk_container_add ((GtkContainer *) numbers_alignment, numbers);
01362
01363 numbers_alignment = gtk_alignment_new (0, 0, 0, 0);
01364 gtk_alignment_set_padding ((GtkAlignment *) numbers_alignment, 0, 0, 12, 0);
01365 gtk_box_pack_start ((GtkBox *) vbox5, numbers_alignment, 0, 0, 3);
01366
01367 numbers = gtk_check_button_new_with_label (_("Show leading zeroes (02:00 "
01368 "instead of 2:00)"));
01369 gtk_toggle_button_set_active ((GtkToggleButton *) numbers, get_bool (NULL, "leading_zero"));
01370 g_signal_connect ((GObject *) numbers, "toggled", (GCallback)
01371 leading_zero_cb, 0);
01372 gtk_container_add ((GtkContainer *) numbers_alignment, numbers);
01373
01374 alignment56 = gtk_alignment_new (0.5, 0.5, 1, 1);
01375 gtk_box_pack_start (GTK_BOX (vbox5), alignment56, FALSE, FALSE, 0);
01376 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment56), 0, 0, 12, 0);
01377
01378 table6 = gtk_table_new (2, 3, FALSE);
01379 gtk_container_add (GTK_CONTAINER (alignment56), table6);
01380 gtk_table_set_row_spacings (GTK_TABLE (table6), 4);
01381 gtk_table_set_col_spacings (GTK_TABLE (table6), 12);
01382
01383 titlestring_help_button = gtk_button_new ();
01384 gtk_table_attach (GTK_TABLE (table6), titlestring_help_button, 2, 3, 1, 2,
01385 (GtkAttachOptions) (0),
01386 (GtkAttachOptions) (0), 0, 0);
01387
01388 gtk_widget_set_can_focus (titlestring_help_button, FALSE);
01389 gtk_widget_set_tooltip_text (titlestring_help_button, _("Show information about titlestring format"));
01390 gtk_button_set_relief (GTK_BUTTON (titlestring_help_button), GTK_RELIEF_HALF);
01391 gtk_button_set_focus_on_click (GTK_BUTTON (titlestring_help_button), FALSE);
01392
01393 image1 = gtk_image_new_from_stock ("gtk-index", GTK_ICON_SIZE_BUTTON);
01394 gtk_container_add (GTK_CONTAINER (titlestring_help_button), image1);
01395
01396 GtkWidget * titlestring_cbox;
01397 create_titlestring_widgets (& titlestring_cbox, & titlestring_entry);
01398 gtk_table_attach (GTK_TABLE (table6), titlestring_cbox, 1, 3, 0, 1,
01399 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
01400 (GtkAttachOptions) (0), 0, 0);
01401 gtk_table_attach (GTK_TABLE (table6), titlestring_entry, 1, 2, 1, 2,
01402 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
01403 (GtkAttachOptions) (0), 0, 0);
01404
01405 label62 = gtk_label_new (_("Custom string:"));
01406 gtk_table_attach (GTK_TABLE (table6), label62, 0, 1, 1, 2,
01407 (GtkAttachOptions) (0),
01408 (GtkAttachOptions) (0), 0, 0);
01409 gtk_label_set_justify (GTK_LABEL (label62), GTK_JUSTIFY_RIGHT);
01410 gtk_misc_set_alignment (GTK_MISC (label62), 1, 0.5);
01411
01412 label61 = gtk_label_new (_("Title format:"));
01413 gtk_table_attach (GTK_TABLE (table6), label61, 0, 1, 0, 1,
01414 (GtkAttachOptions) (0),
01415 (GtkAttachOptions) (0), 0, 0);
01416 gtk_label_set_justify (GTK_LABEL (label61), GTK_JUSTIFY_RIGHT);
01417 gtk_misc_set_alignment (GTK_MISC (label61), 1, 0.5);
01418
01419 alignment85 = gtk_alignment_new (0.5, 0.5, 1, 1);
01420 gtk_box_pack_start (GTK_BOX (vbox5), alignment85, FALSE, FALSE, 0);
01421 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment85), 12, 12, 0, 0);
01422
01423 label84 = gtk_label_new (_("<b>Popup Information</b>"));
01424 gtk_container_add (GTK_CONTAINER (alignment85), label84);
01425 gtk_label_set_use_markup (GTK_LABEL (label84), TRUE);
01426 gtk_misc_set_alignment (GTK_MISC (label84), 0, 0.5);
01427
01428 alignment86 = gtk_alignment_new (0.5, 0.5, 1, 1);
01429 gtk_box_pack_start (GTK_BOX (vbox5), alignment86, FALSE, FALSE, 0);
01430 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment86), 0, 0, 12, 0);
01431
01432 hbox9 = gtk_hbox_new (FALSE, 12);
01433 gtk_container_add (GTK_CONTAINER (alignment86), hbox9);
01434
01435 vbox34 = gtk_vbox_new (FALSE, 0);
01436 gtk_box_pack_start (GTK_BOX (hbox9), vbox34, TRUE, TRUE, 0);
01437
01438 filepopupbutton = gtk_check_button_new_with_mnemonic (_("Show popup information for playlist entries"));
01439 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."));
01440 gtk_toggle_button_set_active ((GtkToggleButton *) filepopupbutton,
01441 get_bool (NULL, "show_filepopup_for_tuple"));
01442 gtk_box_pack_start ((GtkBox *) vbox34, filepopupbutton, TRUE, FALSE, 0);
01443
01444 filepopup_settings_button = gtk_button_new ();
01445 gtk_widget_set_sensitive (filepopup_settings_button,
01446 get_bool (NULL, "show_filepopup_for_tuple"));
01447 gtk_box_pack_start (GTK_BOX (hbox9), filepopup_settings_button, FALSE, FALSE, 0);
01448
01449 gtk_widget_set_can_focus (filepopup_settings_button, FALSE);
01450 gtk_widget_set_tooltip_text (filepopup_settings_button, _("Edit settings for popup information"));
01451 gtk_button_set_relief (GTK_BUTTON (filepopup_settings_button), GTK_RELIEF_HALF);
01452
01453 image8 = gtk_image_new_from_stock ("gtk-properties", GTK_ICON_SIZE_BUTTON);
01454 gtk_container_add (GTK_CONTAINER (filepopup_settings_button), image8);
01455
01456
01457
01458 g_signal_connect (filepopupbutton, "toggled",
01459 G_CALLBACK(on_show_filepopup_toggled),
01460 NULL);
01461 g_signal_connect(G_OBJECT(filepopup_settings_button), "clicked",
01462 G_CALLBACK(on_filepopup_settings_clicked),
01463 NULL);
01464
01465 g_signal_connect(titlestring_help_button, "clicked",
01466 G_CALLBACK(on_titlestring_help_button_clicked),
01467 titlestring_tag_menu);
01468
01469
01470 create_filepopup_settings();
01471 }
01472
01473 static GtkWidget * output_config_button, * output_about_button;
01474
01475 static bool_t output_enum_cb (PluginHandle * plugin, GList * * list)
01476 {
01477 * list = g_list_prepend (* list, plugin);
01478 return TRUE;
01479 }
01480
01481 static GList * output_get_list (void)
01482 {
01483 static GList * list = NULL;
01484
01485 if (list == NULL)
01486 {
01487 plugin_for_each (PLUGIN_TYPE_OUTPUT, (PluginForEachFunc) output_enum_cb,
01488 & list);
01489 list = g_list_reverse (list);
01490 }
01491
01492 return list;
01493 }
01494
01495 static void output_combo_update (GtkComboBox * combo)
01496 {
01497 PluginHandle * plugin = plugin_get_current (PLUGIN_TYPE_OUTPUT);
01498 gtk_combo_box_set_active (combo, g_list_index (output_get_list (), plugin));
01499 gtk_widget_set_sensitive (output_config_button, plugin_has_configure (plugin));
01500 gtk_widget_set_sensitive (output_about_button, plugin_has_about (plugin));
01501 }
01502
01503 static void output_combo_changed (GtkComboBox * combo)
01504 {
01505 PluginHandle * plugin = g_list_nth_data (output_get_list (),
01506 gtk_combo_box_get_active (combo));
01507 g_return_if_fail (plugin != NULL);
01508
01509 plugin_enable (plugin, TRUE);
01510 output_combo_update (combo);
01511 }
01512
01513 static void output_combo_fill (GtkComboBox * combo)
01514 {
01515 for (GList * node = output_get_list (); node != NULL; node = node->next)
01516 gtk_combo_box_text_append_text ((GtkComboBoxText *) combo,
01517 plugin_get_name (node->data));
01518 }
01519
01520 static void output_do_config (void)
01521 {
01522 OutputPlugin * op = plugin_get_header (output_plugin_get_current ());
01523 g_return_if_fail (op != NULL);
01524 if (op->configure != NULL)
01525 op->configure ();
01526 else if (op->settings != NULL)
01527 plugin_preferences_show (op->settings);
01528 }
01529
01530 static void output_do_about (void)
01531 {
01532 OutputPlugin * op = plugin_get_header (output_plugin_get_current ());
01533 g_return_if_fail (op != NULL);
01534 if (op->about != NULL)
01535 op->about ();
01536 }
01537
01538 static void * create_output_plugin_box (void)
01539 {
01540 GtkWidget * hbox1 = gtk_hbox_new (FALSE, 6);
01541 gtk_box_pack_start ((GtkBox *) hbox1, gtk_label_new (_("Output plugin:")), FALSE, FALSE, 0);
01542
01543 GtkWidget * vbox = gtk_vbox_new (FALSE, 6);
01544 gtk_box_pack_start ((GtkBox *) hbox1, vbox, FALSE, FALSE, 0);
01545
01546 GtkWidget * hbox2 = gtk_hbox_new (FALSE, 6);
01547 gtk_box_pack_start ((GtkBox *) vbox, hbox2, FALSE, FALSE, 0);
01548
01549 GtkWidget * output_plugin_cbox = gtk_combo_box_text_new ();
01550 gtk_box_pack_start ((GtkBox *) hbox2, output_plugin_cbox, FALSE, FALSE, 0);
01551
01552 GtkWidget * hbox3 = gtk_hbox_new (FALSE, 6);
01553 gtk_box_pack_start ((GtkBox *) vbox, hbox3, FALSE, FALSE, 0);
01554
01555 output_config_button = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES);
01556 gtk_box_pack_start ((GtkBox *) hbox3, output_config_button, FALSE, FALSE, 0);
01557
01558 output_about_button = gtk_button_new_from_stock (GTK_STOCK_ABOUT);
01559 gtk_box_pack_start ((GtkBox *) hbox3, output_about_button, FALSE, FALSE, 0);
01560
01561 output_combo_fill ((GtkComboBox *) output_plugin_cbox);
01562 output_combo_update ((GtkComboBox *) output_plugin_cbox);
01563
01564 g_signal_connect (output_plugin_cbox, "changed", (GCallback) output_combo_changed, NULL);
01565 g_signal_connect (output_config_button, "clicked", (GCallback) output_do_config, NULL);
01566 g_signal_connect (output_about_button, "clicked", (GCallback) output_do_about, NULL);
01567
01568 return hbox1;
01569 }
01570
01571 static void create_audio_category (void)
01572 {
01573 GtkWidget * audio_page_vbox = gtk_vbox_new (FALSE, 0);
01574 create_widgets ((GtkBox *) audio_page_vbox, audio_page_widgets, G_N_ELEMENTS (audio_page_widgets));
01575 gtk_container_add ((GtkContainer *) category_notebook, audio_page_vbox);
01576 }
01577
01578 static void
01579 create_connectivity_category(void)
01580 {
01581 GtkWidget *connectivity_page_vbox;
01582 GtkWidget *vbox29;
01583
01584 connectivity_page_vbox = gtk_vbox_new (FALSE, 0);
01585 gtk_container_add (GTK_CONTAINER (category_notebook), connectivity_page_vbox);
01586
01587 vbox29 = gtk_vbox_new (FALSE, 0);
01588 gtk_box_pack_start (GTK_BOX (connectivity_page_vbox), vbox29, TRUE, TRUE, 0);
01589
01590 create_widgets(GTK_BOX(vbox29), connectivity_page_widgets, G_N_ELEMENTS(connectivity_page_widgets));
01591 }
01592
01593 static void create_plugin_category (void)
01594 {
01595 GtkWidget * notebook = gtk_notebook_new ();
01596 gtk_container_add ((GtkContainer *) category_notebook, notebook);
01597
01598 int types[] = {PLUGIN_TYPE_TRANSPORT, PLUGIN_TYPE_PLAYLIST,
01599 PLUGIN_TYPE_INPUT, PLUGIN_TYPE_EFFECT, PLUGIN_TYPE_VIS, PLUGIN_TYPE_GENERAL};
01600 const char * names[] = {N_("Transport"), N_("Playlist"), N_("Input"),
01601 N_("Effect"), N_("Visualization"), N_("General")};
01602
01603 for (int i = 0; i < G_N_ELEMENTS (types); i ++)
01604 gtk_notebook_append_page ((GtkNotebook *) notebook, plugin_view_new
01605 (types[i]), gtk_label_new (_(names[i])));
01606 }
01607
01608 static bool_t
01609 prefswin_destroy(GtkWidget *window, GdkEvent *event, gpointer data)
01610 {
01611 prefswin = NULL;
01612 category_notebook = NULL;
01613 gtk_widget_destroy(filepopup_settings);
01614 filepopup_settings = NULL;
01615 gtk_widget_destroy(window);
01616 return TRUE;
01617 }
01618
01619
01620 void * * create_prefs_window (void)
01621 {
01622 char *aud_version_string;
01623
01624 GtkWidget *vbox;
01625 GtkWidget *hbox1;
01626 GtkWidget *scrolledwindow6;
01627 GtkWidget *hseparator1;
01628 GtkWidget *hbox4;
01629 GtkWidget *audversionlabel;
01630 GtkWidget *prefswin_button_box;
01631 GtkWidget *hbox11;
01632 GtkWidget *image10;
01633 GtkWidget *close;
01634 GtkAccelGroup *accel_group;
01635
01636 accel_group = gtk_accel_group_new ();
01637
01638 prefswin = gtk_window_new (GTK_WINDOW_TOPLEVEL);
01639 gtk_window_set_type_hint (GTK_WINDOW (prefswin), GDK_WINDOW_TYPE_HINT_DIALOG);
01640 gtk_container_set_border_width (GTK_CONTAINER (prefswin), 12);
01641 gtk_window_set_title (GTK_WINDOW (prefswin), _("Audacious Preferences"));
01642 gtk_window_set_position (GTK_WINDOW (prefswin), GTK_WIN_POS_CENTER);
01643 gtk_window_set_default_size (GTK_WINDOW (prefswin), 680, 400);
01644
01645 vbox = gtk_vbox_new (FALSE, 0);
01646 gtk_container_add (GTK_CONTAINER (prefswin), vbox);
01647
01648 hbox1 = gtk_hbox_new (FALSE, 8);
01649 gtk_box_pack_start (GTK_BOX (vbox), hbox1, TRUE, TRUE, 0);
01650
01651 scrolledwindow6 = gtk_scrolled_window_new (NULL, NULL);
01652 gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow6, FALSE, FALSE, 0);
01653 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow6), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
01654 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow6), GTK_SHADOW_IN);
01655
01656 category_treeview = gtk_tree_view_new ();
01657 gtk_container_add (GTK_CONTAINER (scrolledwindow6), category_treeview);
01658 gtk_widget_set_size_request (scrolledwindow6, 168, -1);
01659 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (category_treeview), FALSE);
01660
01661 category_notebook = gtk_notebook_new ();
01662 gtk_box_pack_start (GTK_BOX (hbox1), category_notebook, TRUE, TRUE, 0);
01663
01664 gtk_widget_set_can_focus (category_notebook, FALSE);
01665 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (category_notebook), FALSE);
01666 gtk_notebook_set_show_border (GTK_NOTEBOOK (category_notebook), FALSE);
01667 gtk_notebook_set_scrollable (GTK_NOTEBOOK (category_notebook), TRUE);
01668
01669 create_audio_category();
01670 create_connectivity_category();
01671 create_playlist_category();
01672 create_plugin_category();
01673
01674 hseparator1 = gtk_hseparator_new ();
01675 gtk_box_pack_start (GTK_BOX (vbox), hseparator1, FALSE, FALSE, 6);
01676
01677 hbox4 = gtk_hbox_new (FALSE, 0);
01678 gtk_box_pack_start (GTK_BOX (vbox), hbox4, FALSE, FALSE, 0);
01679
01680 audversionlabel = gtk_label_new ("");
01681 gtk_box_pack_start (GTK_BOX (hbox4), audversionlabel, FALSE, FALSE, 0);
01682 gtk_label_set_use_markup (GTK_LABEL (audversionlabel), TRUE);
01683
01684 prefswin_button_box = gtk_hbutton_box_new ();
01685 gtk_box_pack_start (GTK_BOX (hbox4), prefswin_button_box, TRUE, TRUE, 0);
01686 gtk_button_box_set_layout (GTK_BUTTON_BOX (prefswin_button_box), GTK_BUTTONBOX_END);
01687 gtk_box_set_spacing (GTK_BOX (prefswin_button_box), 6);
01688
01689 hbox11 = gtk_hbox_new (FALSE, 2);
01690
01691 image10 = gtk_image_new_from_stock ("gtk-refresh", GTK_ICON_SIZE_BUTTON);
01692 gtk_box_pack_start (GTK_BOX (hbox11), image10, FALSE, FALSE, 0);
01693
01694 close = gtk_button_new_from_stock ("gtk-close");
01695 gtk_container_add (GTK_CONTAINER (prefswin_button_box), close);
01696 gtk_widget_set_can_default(close, TRUE);
01697 gtk_widget_add_accelerator (close, "clicked", accel_group,
01698 GDK_Escape, (GdkModifierType) 0,
01699 GTK_ACCEL_VISIBLE);
01700
01701
01702 gtk_window_add_accel_group (GTK_WINDOW (prefswin), accel_group);
01703
01704
01705 g_signal_connect(G_OBJECT(prefswin), "delete_event",
01706 G_CALLBACK(prefswin_destroy),
01707 NULL);
01708 g_signal_connect_swapped(G_OBJECT(close), "clicked",
01709 G_CALLBACK(prefswin_destroy),
01710 prefswin);
01711
01712
01713 fill_category_list ((GtkTreeView *) category_treeview, (GtkNotebook *) category_notebook);
01714
01715
01716
01717 aud_version_string = g_strdup_printf
01718 ("<span size='small'>%s (%s)</span>", "Audacious " VERSION, BUILDSTAMP);
01719
01720 gtk_label_set_markup( GTK_LABEL(audversionlabel) , aud_version_string );
01721 g_free(aud_version_string);
01722 gtk_widget_show_all(vbox);
01723
01724 return & prefswin;
01725 }
01726
01727 void
01728 destroy_prefs_window(void)
01729 {
01730 prefswin_destroy(prefswin, NULL, NULL);
01731 }
01732
01733 void show_prefs_window (void)
01734 {
01735 if (! prefswin)
01736 create_prefs_window ();
01737
01738 gtk_window_present ((GtkWindow *) prefswin);
01739 }
01740
01741 void
01742 hide_prefs_window(void)
01743 {
01744 g_return_if_fail(prefswin);
01745 gtk_widget_hide(GTK_WIDGET(prefswin));
01746 }
01747
01748 static void prefswin_page_queue_new (GtkWidget * container, const char * name,
01749 const char * imgurl)
01750 {
01751 CategoryQueueEntry *ent = g_new0(CategoryQueueEntry, 1);
01752
01753 ent->container = container;
01754 ent->pg_name = name;
01755 ent->img_url = imgurl;
01756
01757 if (category_queue)
01758 ent->next = category_queue;
01759
01760 category_queue = ent;
01761 }
01762
01763 static void
01764 prefswin_page_queue_destroy(CategoryQueueEntry *ent)
01765 {
01766 category_queue = ent->next;
01767 g_free(ent);
01768 }
01769
01770
01771
01772
01773
01774
01775
01776
01777
01778
01779
01780
01781
01782
01783 int prefswin_page_new (void * container, const char * name, const char *
01784 imgurl)
01785 {
01786 GtkTreeModel *model;
01787 GtkTreeIter iter;
01788 GdkPixbuf *img = NULL;
01789 GtkTreeView *treeview = GTK_TREE_VIEW(category_treeview);
01790 int id;
01791
01792 if (treeview == NULL || category_notebook == NULL)
01793 {
01794 prefswin_page_queue_new(container, name, imgurl);
01795 return -1;
01796 }
01797
01798 model = gtk_tree_view_get_model(treeview);
01799
01800 if (model == NULL)
01801 {
01802 prefswin_page_queue_new(container, name, imgurl);
01803 return -1;
01804 }
01805
01806
01807 gtk_widget_show(container);
01808 id = gtk_notebook_append_page(GTK_NOTEBOOK(category_notebook), container, NULL);
01809
01810 if (id == -1)
01811 return -1;
01812
01813 if (imgurl != NULL)
01814 img = gdk_pixbuf_new_from_file(imgurl, NULL);
01815
01816 gtk_list_store_append(GTK_LIST_STORE(model), &iter);
01817 gtk_list_store_set(GTK_LIST_STORE(model), &iter,
01818 CATEGORY_VIEW_COL_ICON, img,
01819 CATEGORY_VIEW_COL_NAME,
01820 name, CATEGORY_VIEW_COL_ID, id, -1);
01821
01822 if (img != NULL)
01823 g_object_unref(img);
01824
01825 return id;
01826 }
01827
01828 void
01829 prefswin_page_destroy(GtkWidget *container)
01830 {
01831 GtkTreeModel *model;
01832 GtkTreeIter iter;
01833 GtkTreeView *treeview = GTK_TREE_VIEW(category_treeview);
01834 bool_t ret;
01835 int id;
01836 int index = -1;
01837
01838 if (category_notebook == NULL || treeview == NULL || container == NULL)
01839 return;
01840
01841 id = gtk_notebook_page_num(GTK_NOTEBOOK(category_notebook), container);
01842
01843 if (id == -1)
01844 return;
01845
01846 gtk_notebook_remove_page(GTK_NOTEBOOK(category_notebook), id);
01847
01848 model = gtk_tree_view_get_model(treeview);
01849
01850 if (model == NULL)
01851 return;
01852
01853 ret = gtk_tree_model_get_iter_first(model, &iter);
01854
01855 while (ret == TRUE)
01856 {
01857 gtk_tree_model_get(model, &iter, CATEGORY_VIEW_COL_ID, &index, -1);
01858
01859 if (index == id)
01860 {
01861 gtk_list_store_remove(GTK_LIST_STORE(model), &iter);
01862 ret = gtk_tree_model_get_iter_first(model, &iter);
01863 continue;
01864 }
01865
01866 if (index > id)
01867 {
01868 index--;
01869 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CATEGORY_VIEW_COL_ID, index, -1);
01870 }
01871
01872 ret = gtk_tree_model_iter_next(model, &iter);
01873 }
01874 }
01875
01876 static void sw_volume_toggled (void)
01877 {
01878 int vol[2];
01879
01880 if (get_bool (NULL, "software_volume_control"))
01881 {
01882 vol[0] = get_int (NULL, "sw_volume_left");
01883 vol[1] = get_int (NULL, "sw_volume_right");
01884 }
01885 else
01886 playback_get_volume (& vol[0], & vol[1]);
01887
01888 hook_call ("volume set", vol);
01889 }