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