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 window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 00401 gtk_window_set_type_hint(GTK_WINDOW(window), GDK_WINDOW_TYPE_HINT_DIALOG); 00402 gtk_window_set_title(GTK_WINDOW(window), _(settings->title)); 00403 gtk_container_set_border_width(GTK_CONTAINER(window), 10); 00404 00405 g_signal_connect(G_OBJECT(window), "destroy", 00406 G_CALLBACK(plugin_preferences_destroy), settings); 00407 00408 vbox = gtk_vbox_new(FALSE, 10); 00409 create_widgets(GTK_BOX(vbox), settings->prefs, settings->n_prefs); 00410 gtk_container_add(GTK_CONTAINER(window), vbox); 00411 00412 bbox = gtk_hbutton_box_new(); 00413 gtk_button_box_set_layout(GTK_BUTTON_BOX(bbox), GTK_BUTTONBOX_END); 00414 gtk_box_set_spacing(GTK_BOX(bbox), 5); 00415 gtk_box_pack_start(GTK_BOX(vbox), bbox, FALSE, FALSE, 0); 00416 00417 ok = gtk_button_new_from_stock(GTK_STOCK_OK); 00418 g_signal_connect(G_OBJECT(ok), "clicked", 00419 G_CALLBACK(plugin_preferences_ok), settings); 00420 gtk_box_pack_start(GTK_BOX(bbox), ok, TRUE, TRUE, 0); 00421 gtk_widget_set_can_default (ok, TRUE); 00422 gtk_widget_grab_default(ok); 00423 00424 apply = gtk_button_new_from_stock(GTK_STOCK_APPLY); 00425 g_signal_connect(G_OBJECT(apply), "clicked", 00426 G_CALLBACK(plugin_preferences_apply), settings); 00427 gtk_box_pack_start(GTK_BOX(bbox), apply, TRUE, TRUE, 0); 00428 00429 cancel = gtk_button_new_from_stock(GTK_STOCK_CANCEL); 00430 g_signal_connect(G_OBJECT(cancel), "clicked", 00431 G_CALLBACK(plugin_preferences_cancel), settings); 00432 gtk_box_pack_start(GTK_BOX(bbox), cancel, TRUE, TRUE, 0); 00433 00434 gtk_window_set_transient_for(GTK_WINDOW(window), GTK_WINDOW(prefswin)); 00435 gtk_widget_show_all(window); 00436 settings->data = (gpointer)window; 00437 } 00438 00439 void plugin_preferences_cleanup (PluginPreferences * p) 00440 { 00441 if (p->data != NULL) 00442 { 00443 gtk_widget_destroy (p->data); 00444 p->data = NULL; 00445 } 00446 } 00447 00448 static void 00449 on_output_plugin_bufsize_realize(GtkSpinButton *button, 00450 gpointer data) 00451 { 00452 gtk_spin_button_set_value(button, cfg.output_buffer_size); 00453 } 00454 00455 static void 00456 on_output_plugin_bufsize_value_changed(GtkSpinButton *button, 00457 gpointer data) 00458 { 00459 cfg.output_buffer_size = gtk_spin_button_get_value_as_int(button); 00460 } 00461 00462 static void 00463 on_spin_btn_realize_gint(GtkSpinButton *button, gint *cfg) 00464 { 00465 gtk_spin_button_set_value(button, *cfg); 00466 } 00467 00468 static void 00469 on_spin_btn_changed_gint(GtkSpinButton *button, gint *cfg) 00470 { 00471 *cfg = gtk_spin_button_get_value_as_int(button); 00472 } 00473 00474 static void 00475 on_spin_btn_realize_gfloat(GtkSpinButton *button, gfloat *cfg) 00476 { 00477 gtk_spin_button_set_value(button, (gdouble) *cfg); 00478 } 00479 00480 static void 00481 on_spin_btn_changed_gfloat(GtkSpinButton *button, gfloat *cfg) 00482 { 00483 *cfg = (gfloat) gtk_spin_button_get_value(button); 00484 } 00485 00486 00487 static void 00488 on_category_treeview_realize(GtkTreeView * treeview, 00489 GtkNotebook * notebook) 00490 { 00491 GtkListStore *store; 00492 GtkCellRenderer *renderer; 00493 GtkTreeViewColumn *column; 00494 GtkTreeSelection *selection; 00495 GtkTreeIter iter; 00496 GdkPixbuf *img; 00497 CategoryQueueEntry *qlist; 00498 gint i; 00499 00500 column = gtk_tree_view_column_new(); 00501 gtk_tree_view_column_set_title(column, _("Category")); 00502 gtk_tree_view_append_column(treeview, column); 00503 gtk_tree_view_column_set_spacing(column, 2); 00504 00505 renderer = gtk_cell_renderer_pixbuf_new(); 00506 gtk_tree_view_column_pack_start(column, renderer, FALSE); 00507 gtk_tree_view_column_set_attributes(column, renderer, "pixbuf", 0, NULL); 00508 00509 renderer = gtk_cell_renderer_text_new(); 00510 gtk_tree_view_column_pack_start(column, renderer, FALSE); 00511 gtk_tree_view_column_set_attributes(column, renderer, "text", 1, NULL); 00512 00513 gint width, height; 00514 gtk_widget_get_size_request(GTK_WIDGET(treeview), &width, &height); 00515 g_object_set(G_OBJECT(renderer), "wrap-width", width - 64 - 24, "wrap-mode", 00516 PANGO_WRAP_WORD_CHAR, NULL); 00517 00518 store = gtk_list_store_new(CATEGORY_VIEW_N_COLS, 00519 GDK_TYPE_PIXBUF, G_TYPE_STRING, G_TYPE_INT); 00520 gtk_tree_view_set_model(treeview, GTK_TREE_MODEL(store)); 00521 00522 for (i = 0; i < n_categories; i ++) 00523 { 00524 gchar * path = g_strdup_printf ("%s/images/%s", 00525 get_path (AUD_PATH_DATA_DIR), categories[i].icon_path); 00526 img = gdk_pixbuf_new_from_file (path, NULL); 00527 g_free (path); 00528 00529 gtk_list_store_append(store, &iter); 00530 gtk_list_store_set(store, &iter, 00531 CATEGORY_VIEW_COL_ICON, img, 00532 CATEGORY_VIEW_COL_NAME, 00533 gettext(categories[i].name), CATEGORY_VIEW_COL_ID, 00534 i, -1); 00535 g_object_unref(img); 00536 } 00537 00538 selection = gtk_tree_view_get_selection(treeview); 00539 00540 g_signal_connect_swapped(selection, "changed", 00541 G_CALLBACK(change_category), notebook); 00542 00543 /* mark the treeview widget as available to third party plugins */ 00544 category_treeview = GTK_WIDGET(treeview); 00545 00546 /* prefswin_page_queue_destroy already pops the queue forward for us. */ 00547 for (qlist = category_queue; qlist != NULL; qlist = category_queue) 00548 { 00549 CategoryQueueEntry *ent = (CategoryQueueEntry *) qlist; 00550 00551 prefswin_page_new(ent->container, ent->pg_name, ent->img_url); 00552 prefswin_page_queue_destroy(ent); 00553 } 00554 } 00555 00556 static void 00557 on_show_filepopup_for_tuple_realize(GtkToggleButton * button, gpointer data) 00558 { 00559 gtk_toggle_button_set_active(button, cfg.show_filepopup_for_tuple); 00560 filepopupbutton = GTK_WIDGET(button); 00561 00562 gtk_widget_set_sensitive(filepopup_for_tuple_settings_button, cfg.show_filepopup_for_tuple); 00563 } 00564 00565 static void 00566 on_show_filepopup_for_tuple_toggled(GtkToggleButton * button, gpointer data) 00567 { 00568 cfg.show_filepopup_for_tuple = gtk_toggle_button_get_active(button); 00569 00570 gtk_widget_set_sensitive(filepopup_for_tuple_settings_button, cfg.show_filepopup_for_tuple); 00571 } 00572 00573 static void 00574 on_recurse_for_cover_toggled(GtkToggleButton *button, gpointer data) 00575 { 00576 gtk_widget_set_sensitive(GTK_WIDGET(data), 00577 gtk_toggle_button_get_active(button)); 00578 } 00579 00580 static void 00581 on_filepopup_for_tuple_settings_clicked(GtkButton *button, gpointer data) 00582 { 00583 gtk_entry_set_text(GTK_ENTRY(filepopup_settings_cover_name_include), cfg.cover_name_include); 00584 gtk_entry_set_text(GTK_ENTRY(filepopup_settings_cover_name_exclude), cfg.cover_name_exclude); 00585 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filepopup_settings_recurse_for_cover), cfg.recurse_for_cover); 00586 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filepopup_settings_recurse_for_cover_depth), cfg.recurse_for_cover_depth); 00587 on_recurse_for_cover_toggled(GTK_TOGGLE_BUTTON(filepopup_settings_recurse_for_cover), filepopup_settings_recurse_for_cover_depth_box); 00588 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filepopup_settings_use_file_cover), cfg.use_file_cover); 00589 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(filepopup_settings_showprogressbar), cfg.filepopup_showprogressbar); 00590 gtk_spin_button_set_value(GTK_SPIN_BUTTON(filepopup_settings_delay), cfg.filepopup_delay); 00591 00592 gtk_widget_show(filepopup_settings); 00593 } 00594 00595 static void 00596 on_filepopup_settings_ok_clicked(GtkButton *button, gpointer data) 00597 { 00598 g_free(cfg.cover_name_include); 00599 cfg.cover_name_include = g_strdup(gtk_entry_get_text(GTK_ENTRY(filepopup_settings_cover_name_include))); 00600 00601 g_free(cfg.cover_name_exclude); 00602 cfg.cover_name_exclude = g_strdup(gtk_entry_get_text(GTK_ENTRY(filepopup_settings_cover_name_exclude))); 00603 00604 cfg.recurse_for_cover = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filepopup_settings_recurse_for_cover)); 00605 cfg.recurse_for_cover_depth = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filepopup_settings_recurse_for_cover_depth)); 00606 cfg.use_file_cover = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filepopup_settings_use_file_cover)); 00607 cfg.filepopup_showprogressbar = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(filepopup_settings_showprogressbar)); 00608 cfg.filepopup_delay = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(filepopup_settings_delay)); 00609 00610 gtk_widget_hide(filepopup_settings); 00611 } 00612 00613 static void 00614 on_filepopup_settings_cancel_clicked(GtkButton *button, gpointer data) 00615 { 00616 gtk_widget_hide(filepopup_settings); 00617 } 00618 00619 static void 00620 on_toggle_button_toggled(GtkToggleButton * button, gboolean *cfg) 00621 { 00622 *cfg = gtk_toggle_button_get_active(button); 00623 void (*callback) (void) = g_object_get_data(G_OBJECT(button), "callback"); 00624 if (callback != NULL) callback(); 00625 GtkWidget *child = g_object_get_data(G_OBJECT(button), "child"); 00626 if (child) gtk_widget_set_sensitive(GTK_WIDGET(child), *cfg); 00627 } 00628 00629 static void 00630 on_toggle_button_realize(GtkToggleButton * button, gboolean *cfg) 00631 { 00632 gtk_toggle_button_set_active(button, cfg ? *cfg : FALSE); 00633 GtkWidget *child = g_object_get_data(G_OBJECT(button), "child"); 00634 if (child) gtk_widget_set_sensitive(GTK_WIDGET(child), cfg ? *cfg : FALSE); 00635 } 00636 00637 static void 00638 on_toggle_button_cfg_toggled(GtkToggleButton *button, gchar *cfg) 00639 { 00640 g_return_if_fail(cfg != NULL); 00641 00642 mcs_handle_t *db; 00643 gboolean ret = gtk_toggle_button_get_active(button); 00644 00645 db = cfg_db_open(); 00646 cfg_db_set_bool(db, NULL, cfg, ret); 00647 cfg_db_close(db); 00648 } 00649 00650 static void 00651 on_toggle_button_cfg_realize(GtkToggleButton *button, gchar *cfg) 00652 { 00653 mcs_handle_t *db; 00654 gboolean ret; 00655 00656 g_return_if_fail(cfg != NULL); 00657 00658 db = cfg_db_open(); 00659 00660 if (cfg_db_get_bool(db, NULL, cfg, &ret) != FALSE) 00661 gtk_toggle_button_set_active(button, ret); 00662 00663 cfg_db_close(db); 00664 } 00665 00666 static void 00667 on_entry_realize(GtkEntry *entry, gchar **cfg) 00668 { 00669 g_return_if_fail(cfg != NULL); 00670 00671 if (*cfg) 00672 gtk_entry_set_text(entry, *cfg); 00673 } 00674 00675 static void 00676 on_entry_changed(GtkEntry *entry, gchar **cfg) 00677 { 00678 void (*callback) (void) = g_object_get_data(G_OBJECT(entry), "callback"); 00679 const gchar *ret; 00680 00681 g_return_if_fail(cfg != NULL); 00682 00683 g_free(*cfg); 00684 00685 ret = gtk_entry_get_text(entry); 00686 00687 if (ret == NULL) 00688 *cfg = g_strdup(""); 00689 else 00690 *cfg = g_strdup(ret); 00691 00692 if (callback != NULL) callback(); 00693 } 00694 00695 static void 00696 on_entry_cfg_realize(GtkEntry *entry, gchar *cfg) 00697 { 00698 mcs_handle_t *db; 00699 gchar *ret; 00700 00701 g_return_if_fail(cfg != NULL); 00702 00703 db = cfg_db_open(); 00704 00705 if (cfg_db_get_string(db, NULL, cfg, &ret) != FALSE) 00706 gtk_entry_set_text(entry, ret); 00707 00708 cfg_db_close(db); 00709 } 00710 00711 static void 00712 on_entry_cfg_changed(GtkEntry *entry, gchar *cfg) 00713 { 00714 mcs_handle_t *db; 00715 gchar *ret = g_strdup(gtk_entry_get_text(entry)); 00716 00717 g_return_if_fail(cfg != NULL); 00718 00719 db = cfg_db_open(); 00720 cfg_db_set_string(db, NULL, cfg, ret); 00721 cfg_db_close(db); 00722 00723 g_free(ret); 00724 } 00725 00726 static void 00727 on_cbox_changed_int(GtkComboBox * combobox, PreferencesWidget *widget) 00728 { 00729 gint position = 0; 00730 00731 position = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox)); 00732 *((gint *)widget->cfg) = GPOINTER_TO_INT(widget->data.combo.elements[position].value); 00733 } 00734 00735 static void 00736 on_cbox_changed_string(GtkComboBox * combobox, PreferencesWidget *widget) 00737 { 00738 gint position = 0; 00739 00740 position = gtk_combo_box_get_active(GTK_COMBO_BOX(combobox)); 00741 00742 g_free(*((gchar **)widget->cfg)); 00743 00744 *((gchar **)widget->cfg) = g_strdup(widget->data.combo.elements[position].value); 00745 } 00746 00747 static void on_cbox_realize (GtkWidget * combobox, PreferencesWidget * widget) 00748 { 00749 guint i=0,index=0; 00750 00751 for (i = 0; i < widget->data.combo.n_elements; i ++) 00752 gtk_combo_box_text_append_text ((GtkComboBoxText *) combobox, 00753 _(widget->data.combo.elements[i].label)); 00754 00755 if (widget->data.combo.enabled) { 00756 switch (widget->cfg_type) { 00757 case VALUE_INT: 00758 g_signal_connect(combobox, "changed", 00759 G_CALLBACK(on_cbox_changed_int), widget); 00760 for(i=0; i<widget->data.combo.n_elements; i++) { 00761 if (GPOINTER_TO_INT(widget->data.combo.elements[i].value) == *((gint *) widget->cfg)) { 00762 index = i; 00763 break; 00764 } 00765 } 00766 break; 00767 case VALUE_STRING: 00768 g_signal_connect(combobox, "changed", 00769 G_CALLBACK(on_cbox_changed_string), widget); 00770 for(i=0; i<widget->data.combo.n_elements; i++) { 00771 if(!strcmp((gchar *)widget->data.combo.elements[i].value, *((gchar **)widget->cfg))) { 00772 index = i; 00773 break; 00774 } 00775 } 00776 break; 00777 case VALUE_NULL: 00778 break; 00779 default: 00780 g_warning("Unhandled cbox value type"); 00781 break; 00782 } 00783 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), index); 00784 } else { 00785 gtk_combo_box_set_active(GTK_COMBO_BOX(combobox), -1); 00786 gtk_widget_set_sensitive(GTK_WIDGET(combobox), 0); 00787 } 00788 } 00789 00790 void 00791 create_filepopup_settings(void) 00792 { 00793 GtkWidget *vbox; 00794 GtkWidget *table; 00795 00796 GtkWidget *label_cover_retrieve; 00797 GtkWidget *label_cover_search; 00798 GtkWidget *label_exclude; 00799 GtkWidget *label_include; 00800 GtkWidget *label_search_depth; 00801 GtkWidget *label_misc; 00802 GtkWidget *label_delay; 00803 00804 GtkAdjustment *recurse_for_cover_depth_adj; 00805 GtkAdjustment *delay_adj; 00806 GtkWidget *alignment; 00807 00808 GtkWidget *hbox; 00809 GtkWidget *hbuttonbox; 00810 GtkWidget *btn_cancel; 00811 GtkWidget *btn_ok; 00812 00813 filepopup_settings = gtk_window_new(GTK_WINDOW_TOPLEVEL); 00814 gtk_container_set_border_width(GTK_CONTAINER(filepopup_settings), 12); 00815 gtk_window_set_title(GTK_WINDOW(filepopup_settings), _("Popup Information Settings")); 00816 gtk_window_set_position(GTK_WINDOW(filepopup_settings), GTK_WIN_POS_CENTER_ON_PARENT); 00817 gtk_window_set_skip_taskbar_hint(GTK_WINDOW(filepopup_settings), TRUE); 00818 gtk_window_set_type_hint(GTK_WINDOW(filepopup_settings), GDK_WINDOW_TYPE_HINT_DIALOG); 00819 gtk_window_set_transient_for(GTK_WINDOW(filepopup_settings), GTK_WINDOW(prefswin)); 00820 00821 vbox = gtk_vbox_new(FALSE, 12); 00822 gtk_container_add(GTK_CONTAINER(filepopup_settings), vbox); 00823 00824 label_cover_retrieve = gtk_label_new(_("<b>Cover image retrieve</b>")); 00825 gtk_box_pack_start(GTK_BOX(vbox), label_cover_retrieve, FALSE, FALSE, 0); 00826 gtk_label_set_use_markup(GTK_LABEL(label_cover_retrieve), TRUE); 00827 gtk_misc_set_alignment(GTK_MISC(label_cover_retrieve), 0, 0.5); 00828 00829 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.")); 00830 gtk_box_pack_start(GTK_BOX(vbox), label_cover_search, FALSE, FALSE, 0); 00831 gtk_label_set_line_wrap(GTK_LABEL(label_cover_search), TRUE); 00832 gtk_misc_set_alignment(GTK_MISC(label_cover_search), 0, 0); 00833 gtk_misc_set_padding(GTK_MISC(label_cover_search), 12, 0); 00834 00835 table = gtk_table_new(2, 2, FALSE); 00836 gtk_box_pack_start(GTK_BOX(vbox), table, FALSE, FALSE, 0); 00837 gtk_table_set_row_spacings(GTK_TABLE(table), 4); 00838 gtk_table_set_col_spacings(GTK_TABLE(table), 4); 00839 00840 filepopup_settings_cover_name_include = gtk_entry_new(); 00841 gtk_table_attach(GTK_TABLE(table), filepopup_settings_cover_name_include, 1, 2, 0, 1, 00842 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 00843 (GtkAttachOptions) (0), 0, 0); 00844 gtk_entry_set_activates_default(GTK_ENTRY(filepopup_settings_cover_name_include), TRUE); 00845 00846 label_exclude = gtk_label_new(_("Exclude:")); 00847 gtk_table_attach(GTK_TABLE(table), label_exclude, 0, 1, 1, 2, 00848 (GtkAttachOptions) (0), 00849 (GtkAttachOptions) (0), 0, 0); 00850 gtk_misc_set_alignment(GTK_MISC(label_exclude), 0, 0.5); 00851 gtk_misc_set_padding(GTK_MISC(label_exclude), 12, 0); 00852 00853 label_include = gtk_label_new(_("Include:")); 00854 gtk_table_attach(GTK_TABLE(table), label_include, 0, 1, 0, 1, 00855 (GtkAttachOptions) (0), 00856 (GtkAttachOptions) (0), 0, 0); 00857 gtk_misc_set_alignment(GTK_MISC(label_include), 0, 0.5); 00858 gtk_misc_set_padding(GTK_MISC(label_include), 12, 0); 00859 00860 filepopup_settings_cover_name_exclude = gtk_entry_new(); 00861 gtk_table_attach(GTK_TABLE(table), filepopup_settings_cover_name_exclude, 1, 2, 1, 2, 00862 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 00863 (GtkAttachOptions) (0), 0, 0); 00864 gtk_entry_set_activates_default(GTK_ENTRY(filepopup_settings_cover_name_exclude), TRUE); 00865 00866 alignment = gtk_alignment_new(0.5, 0.5, 1, 1); 00867 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0); 00868 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0); 00869 00870 filepopup_settings_recurse_for_cover = gtk_check_button_new_with_mnemonic(_("Recursively search for cover")); 00871 gtk_container_add(GTK_CONTAINER(alignment), filepopup_settings_recurse_for_cover); 00872 00873 alignment = gtk_alignment_new(0.5, 0.5, 1, 1); 00874 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0); 00875 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 45, 0); 00876 00877 filepopup_settings_recurse_for_cover_depth_box = gtk_hbox_new(FALSE, 0); 00878 gtk_container_add(GTK_CONTAINER(alignment), filepopup_settings_recurse_for_cover_depth_box); 00879 00880 label_search_depth = gtk_label_new(_("Search depth: ")); 00881 gtk_box_pack_start(GTK_BOX(filepopup_settings_recurse_for_cover_depth_box), label_search_depth, TRUE, TRUE, 0); 00882 gtk_misc_set_padding(GTK_MISC(label_search_depth), 4, 0); 00883 00884 recurse_for_cover_depth_adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 00885 100, 1, 10, 0); 00886 filepopup_settings_recurse_for_cover_depth = gtk_spin_button_new(GTK_ADJUSTMENT(recurse_for_cover_depth_adj), 1, 0); 00887 gtk_box_pack_start(GTK_BOX(filepopup_settings_recurse_for_cover_depth_box), filepopup_settings_recurse_for_cover_depth, TRUE, TRUE, 0); 00888 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(filepopup_settings_recurse_for_cover_depth), TRUE); 00889 00890 alignment = gtk_alignment_new(0.5, 0.5, 1, 1); 00891 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0); 00892 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0); 00893 00894 filepopup_settings_use_file_cover = gtk_check_button_new_with_mnemonic(_("Use per-file cover")); 00895 gtk_container_add(GTK_CONTAINER(alignment), filepopup_settings_use_file_cover); 00896 00897 label_misc = gtk_label_new(_("<b>Miscellaneous</b>")); 00898 gtk_box_pack_start(GTK_BOX(vbox), label_misc, FALSE, FALSE, 0); 00899 gtk_label_set_use_markup(GTK_LABEL(label_misc), TRUE); 00900 gtk_misc_set_alignment(GTK_MISC(label_misc), 0, 0.5); 00901 00902 alignment = gtk_alignment_new(0.5, 0.5, 1, 1); 00903 gtk_box_pack_start(GTK_BOX(vbox), alignment, FALSE, FALSE, 0); 00904 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0); 00905 00906 filepopup_settings_showprogressbar = gtk_check_button_new_with_mnemonic(_("Show Progress bar for the current track")); 00907 gtk_container_add(GTK_CONTAINER(alignment), filepopup_settings_showprogressbar); 00908 00909 alignment = gtk_alignment_new(0, 0.5, 1, 1); 00910 gtk_box_pack_start(GTK_BOX(vbox), alignment, TRUE, TRUE, 0); 00911 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0); 00912 00913 hbox = gtk_hbox_new(FALSE, 0); 00914 gtk_container_add(GTK_CONTAINER(alignment), hbox); 00915 00916 label_delay = gtk_label_new(_("Delay until filepopup comes up: ")); 00917 gtk_box_pack_start(GTK_BOX(hbox), label_delay, TRUE, TRUE, 0); 00918 gtk_misc_set_alignment(GTK_MISC(label_delay), 0, 0.5); 00919 gtk_misc_set_padding(GTK_MISC(label_delay), 12, 0); 00920 00921 delay_adj = (GtkAdjustment *) gtk_adjustment_new (0, 0, 100, 1, 10, 0); 00922 filepopup_settings_delay = gtk_spin_button_new(GTK_ADJUSTMENT(delay_adj), 1, 0); 00923 gtk_box_pack_start(GTK_BOX(hbox), filepopup_settings_delay, TRUE, TRUE, 0); 00924 gtk_spin_button_set_numeric(GTK_SPIN_BUTTON(filepopup_settings_delay), TRUE); 00925 00926 hbuttonbox = gtk_hbutton_box_new(); 00927 gtk_box_pack_start(GTK_BOX(vbox), hbuttonbox, FALSE, FALSE, 0); 00928 gtk_button_box_set_layout(GTK_BUTTON_BOX(hbuttonbox), GTK_BUTTONBOX_END); 00929 gtk_box_set_spacing(GTK_BOX(hbuttonbox), 6); 00930 00931 btn_cancel = gtk_button_new_from_stock("gtk-cancel"); 00932 gtk_container_add(GTK_CONTAINER(hbuttonbox), btn_cancel); 00933 00934 btn_ok = gtk_button_new_from_stock("gtk-ok"); 00935 gtk_container_add(GTK_CONTAINER(hbuttonbox), btn_ok); 00936 gtk_widget_set_can_default(btn_ok, TRUE); 00937 00938 g_signal_connect(G_OBJECT(filepopup_settings), "delete_event", 00939 G_CALLBACK(gtk_widget_hide_on_delete), 00940 NULL); 00941 g_signal_connect(G_OBJECT(btn_cancel), "clicked", 00942 G_CALLBACK(on_filepopup_settings_cancel_clicked), 00943 NULL); 00944 g_signal_connect(G_OBJECT(btn_ok), "clicked", 00945 G_CALLBACK(on_filepopup_settings_ok_clicked), 00946 NULL); 00947 g_signal_connect(G_OBJECT(filepopup_settings_recurse_for_cover), "toggled", 00948 G_CALLBACK(on_recurse_for_cover_toggled), 00949 filepopup_settings_recurse_for_cover_depth_box); 00950 00951 gtk_widget_grab_default(btn_ok); 00952 gtk_widget_show_all(vbox); 00953 } 00954 00955 static void create_spin_button (PreferencesWidget * widget, GtkWidget * * 00956 label_pre, GtkWidget * * spin_btn, GtkWidget * * label_past, const gchar * 00957 domain) 00958 { 00959 g_return_if_fail(widget->type == WIDGET_SPIN_BTN); 00960 00961 * label_pre = gtk_label_new (dgettext (domain, widget->label)); 00962 gtk_misc_set_alignment(GTK_MISC(*label_pre), 0, 0.5); 00963 gtk_misc_set_padding(GTK_MISC(*label_pre), 4, 0); 00964 00965 *spin_btn = gtk_spin_button_new_with_range(widget->data.spin_btn.min, 00966 widget->data.spin_btn.max, 00967 widget->data.spin_btn.step); 00968 00969 00970 if (widget->tooltip) 00971 gtk_widget_set_tooltip_text (* spin_btn, dgettext (domain, 00972 widget->tooltip)); 00973 00974 if (widget->data.spin_btn.right_label) { 00975 * label_past = gtk_label_new (dgettext (domain, 00976 widget->data.spin_btn.right_label)); 00977 gtk_misc_set_alignment(GTK_MISC(*label_past), 0, 0.5); 00978 gtk_misc_set_padding(GTK_MISC(*label_past), 4, 0); 00979 } 00980 00981 switch (widget->cfg_type) { 00982 case VALUE_INT: 00983 g_signal_connect(G_OBJECT(*spin_btn), "value_changed", 00984 G_CALLBACK(on_spin_btn_changed_gint), 00985 widget->cfg); 00986 g_signal_connect(G_OBJECT(*spin_btn), "realize", 00987 G_CALLBACK(on_spin_btn_realize_gint), 00988 widget->cfg); 00989 break; 00990 case VALUE_FLOAT: 00991 g_signal_connect(G_OBJECT(*spin_btn), "value_changed", 00992 G_CALLBACK(on_spin_btn_changed_gfloat), 00993 widget->cfg); 00994 g_signal_connect(G_OBJECT(*spin_btn), "realize", 00995 G_CALLBACK(on_spin_btn_realize_gfloat), 00996 widget->cfg); 00997 break; 00998 case VALUE_NULL: 00999 break; 01000 default: 01001 g_warning("Unsupported value type for spin button"); 01002 } 01003 } 01004 01005 void create_font_btn (PreferencesWidget * widget, GtkWidget * * label, 01006 GtkWidget * * font_btn, const gchar * domain) 01007 { 01008 *font_btn = gtk_font_button_new(); 01009 gtk_font_button_set_use_font(GTK_FONT_BUTTON(*font_btn), TRUE); 01010 gtk_font_button_set_use_size(GTK_FONT_BUTTON(*font_btn), TRUE); 01011 if (widget->label) { 01012 * label = gtk_label_new_with_mnemonic (dgettext (domain, widget->label)); 01013 gtk_label_set_use_markup(GTK_LABEL(*label), TRUE); 01014 gtk_misc_set_alignment(GTK_MISC(*label), 1, 0.5); 01015 gtk_label_set_justify(GTK_LABEL(*label), GTK_JUSTIFY_RIGHT); 01016 gtk_label_set_mnemonic_widget(GTK_LABEL(*label), *font_btn); 01017 } 01018 01019 if (widget->data.font_btn.title) 01020 gtk_font_button_set_title (GTK_FONT_BUTTON (* font_btn), 01021 dgettext (domain, widget->data.font_btn.title)); 01022 01023 g_object_set_data ((GObject *) (* font_btn), "callback", (void *) 01024 widget->callback); 01025 01026 g_signal_connect(G_OBJECT(*font_btn), "font_set", 01027 G_CALLBACK(on_font_btn_font_set), 01028 (gchar**)widget->cfg); 01029 g_signal_connect(G_OBJECT(*font_btn), "realize", 01030 G_CALLBACK(on_font_btn_realize), 01031 (gchar**)widget->cfg); 01032 } 01033 01034 static void create_entry (PreferencesWidget * widget, GtkWidget * * label, 01035 GtkWidget * * entry, const gchar * domain) 01036 { 01037 *entry = gtk_entry_new(); 01038 gtk_entry_set_visibility(GTK_ENTRY(*entry), !widget->data.entry.password); 01039 01040 if (widget->label) 01041 * label = gtk_label_new (dgettext (domain, widget->label)); 01042 01043 if (widget->tooltip) 01044 gtk_widget_set_tooltip_text (* entry, dgettext (domain, widget->tooltip)); 01045 01046 g_object_set_data ((GObject *) (* entry), "callback", (void *) 01047 widget->callback); 01048 01049 switch (widget->cfg_type) { 01050 case VALUE_STRING: 01051 g_signal_connect(G_OBJECT(*entry), "realize", 01052 G_CALLBACK(on_entry_realize), 01053 widget->cfg); 01054 g_signal_connect(G_OBJECT(*entry), "changed", 01055 G_CALLBACK(on_entry_changed), 01056 widget->cfg); 01057 break; 01058 case VALUE_CFG_STRING: 01059 g_signal_connect(G_OBJECT(*entry), "realize", 01060 G_CALLBACK(on_entry_cfg_realize), 01061 widget->cfg); 01062 g_signal_connect(G_OBJECT(*entry), "changed", 01063 G_CALLBACK(on_entry_cfg_changed), 01064 widget->cfg); 01065 break; 01066 default: 01067 g_warning("Unhandled entry value type %d", widget->cfg_type); 01068 } 01069 } 01070 01071 static void create_label (PreferencesWidget * widget, GtkWidget * * label, 01072 GtkWidget * * icon, const gchar * domain) 01073 { 01074 if (widget->data.label.stock_id) 01075 *icon = gtk_image_new_from_stock(widget->data.label.stock_id, GTK_ICON_SIZE_BUTTON); 01076 01077 * label = gtk_label_new_with_mnemonic (dgettext (domain, widget->label)); 01078 gtk_label_set_use_markup(GTK_LABEL(*label), TRUE); 01079 01080 if (widget->data.label.single_line == FALSE) 01081 gtk_label_set_line_wrap(GTK_LABEL(*label), TRUE); 01082 01083 gtk_misc_set_alignment(GTK_MISC(*label), 0, 0.5); 01084 } 01085 01086 static void create_cbox (PreferencesWidget * widget, GtkWidget * * label, 01087 GtkWidget * * combobox, const gchar * domain) 01088 { 01089 * combobox = gtk_combo_box_text_new (); 01090 01091 if (widget->label) { 01092 * label = gtk_label_new (dgettext (domain, widget->label)); 01093 gtk_misc_set_alignment(GTK_MISC(*label), 1, 0.5); 01094 } 01095 01096 g_signal_connect_after(G_OBJECT(*combobox), "realize", 01097 G_CALLBACK(on_cbox_realize), 01098 widget); 01099 } 01100 01101 static void fill_table (GtkWidget * table, PreferencesWidget * elements, gint 01102 amt, const gchar * domain) 01103 { 01104 gint x; 01105 GtkWidget *widget_left, *widget_middle, *widget_right; 01106 GtkAttachOptions middle_policy = (GtkAttachOptions) (0); 01107 01108 for (x = 0; x < amt; ++x) { 01109 widget_left = widget_middle = widget_right = NULL; 01110 switch (elements[x].type) { 01111 case WIDGET_SPIN_BTN: 01112 create_spin_button (& elements[x], & widget_left, 01113 & widget_middle, & widget_right, domain); 01114 middle_policy = (GtkAttachOptions) (GTK_FILL); 01115 break; 01116 case WIDGET_LABEL: 01117 create_label (& elements[x], & widget_middle, & widget_left, 01118 domain); 01119 middle_policy = (GtkAttachOptions) (GTK_FILL); 01120 break; 01121 case WIDGET_FONT_BTN: 01122 create_font_btn (& elements[x], & widget_left, & widget_middle, 01123 domain); 01124 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL); 01125 break; 01126 case WIDGET_ENTRY: 01127 create_entry (& elements[x], & widget_left, & widget_middle, 01128 domain); 01129 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL); 01130 break; 01131 case WIDGET_COMBO_BOX: 01132 create_cbox (& elements[x], & widget_left, & widget_middle, 01133 domain); 01134 middle_policy = (GtkAttachOptions) (GTK_EXPAND | GTK_FILL); 01135 break; 01136 default: 01137 g_warning("Unsupported widget type %d in table", elements[x].type); 01138 } 01139 01140 if (widget_left) 01141 gtk_table_attach(GTK_TABLE (table), widget_left, 0, 1, x, x+1, 01142 (GtkAttachOptions) (0), 01143 (GtkAttachOptions) (0), 0, 0); 01144 01145 if (widget_middle) 01146 gtk_table_attach(GTK_TABLE(table), widget_middle, 1, widget_right ? 2 : 3, x, x+1, 01147 middle_policy, 01148 (GtkAttachOptions) (0), 4, 0); 01149 01150 if (widget_right) 01151 gtk_table_attach(GTK_TABLE(table), widget_right, 2, 3, x, x+1, 01152 (GtkAttachOptions) (0), 01153 (GtkAttachOptions) (0), 0, 0); 01154 } 01155 } 01156 01157 /* void create_widgets_with_domain (GtkBox * box, PreferencesWidget * widgets, 01158 gint amt, const gchar * domain) */ 01159 void create_widgets_with_domain (void * box, PreferencesWidget * widgets, gint 01160 amt, const gchar * domain) 01161 { 01162 gint x; 01163 GtkWidget *alignment = NULL, *widget = NULL; 01164 GtkWidget *child_box = NULL; 01165 GSList *radio_btn_group = NULL; 01166 01167 for (x = 0; x < amt; ++x) { 01168 if (widgets[x].child) { /* perhaps this logic can be better */ 01169 if (!child_box) { 01170 child_box = gtk_vbox_new(FALSE, 0); 01171 g_object_set_data(G_OBJECT(widget), "child", child_box); 01172 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); 01173 gtk_box_pack_start(box, alignment, FALSE, FALSE, 0); 01174 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 24, 0); 01175 gtk_container_add (GTK_CONTAINER (alignment), child_box); 01176 } 01177 } else 01178 child_box = NULL; 01179 01180 alignment = gtk_alignment_new (0.5, 0.5, 1, 1); 01181 gtk_box_pack_start(child_box ? GTK_BOX(child_box) : box, alignment, FALSE, FALSE, 0); 01182 01183 if (radio_btn_group && widgets[x].type != WIDGET_RADIO_BTN) 01184 radio_btn_group = NULL; 01185 01186 switch(widgets[x].type) { 01187 case WIDGET_CHK_BTN: 01188 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0); 01189 widget = gtk_check_button_new_with_mnemonic (dgettext (domain, 01190 widgets[x].label)); 01191 g_object_set_data ((GObject *) widget, "callback", 01192 (void *) widgets[x].callback); 01193 01194 if (widgets[x].cfg_type == VALUE_CFG_BOOLEAN) { 01195 g_signal_connect(G_OBJECT(widget), "toggled", 01196 G_CALLBACK(on_toggle_button_cfg_toggled), 01197 widgets[x].cfg); 01198 g_signal_connect(G_OBJECT(widget), "realize", 01199 G_CALLBACK(on_toggle_button_cfg_realize), 01200 widgets[x].cfg); 01201 } else { 01202 if (widgets[x].cfg) { 01203 g_signal_connect(G_OBJECT(widget), "toggled", 01204 G_CALLBACK(on_toggle_button_toggled), 01205 widgets[x].cfg); 01206 } else { 01207 gtk_widget_set_sensitive(widget, FALSE); 01208 } 01209 g_signal_connect(G_OBJECT(widget), "realize", 01210 G_CALLBACK(on_toggle_button_realize), 01211 widgets[x].cfg); 01212 } 01213 break; 01214 case WIDGET_LABEL: 01215 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 12, 6, 0, 0); 01216 01217 GtkWidget *label = NULL, *icon = NULL; 01218 create_label (& widgets[x], & label, & icon, domain); 01219 01220 if (icon == NULL) 01221 widget = label; 01222 else { 01223 widget = gtk_hbox_new(FALSE, 6); 01224 gtk_box_pack_start(GTK_BOX(widget), icon, FALSE, FALSE, 0); 01225 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0); 01226 } 01227 break; 01228 case WIDGET_RADIO_BTN: 01229 gtk_alignment_set_padding(GTK_ALIGNMENT(alignment), 0, 0, 12, 0); 01230 widget = gtk_radio_button_new_with_mnemonic (radio_btn_group, 01231 dgettext (domain, widgets[x].label)); 01232 radio_btn_group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (widget)); 01233 g_signal_connect(G_OBJECT(widget), "toggled", 01234 G_CALLBACK(on_toggle_button_toggled), 01235 widgets[x].cfg); 01236 g_signal_connect(G_OBJECT(widget), "realize", 01237 G_CALLBACK(on_toggle_button_realize), 01238 widgets[x].cfg); 01239 break; 01240 case WIDGET_SPIN_BTN: 01241 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 12, 0); 01242 01243 widget = gtk_hbox_new(FALSE, 6); 01244 01245 GtkWidget *label_pre = NULL, *spin_btn = NULL, *label_past = NULL; 01246 create_spin_button (& widgets[x], & label_pre, & spin_btn, 01247 & label_past, domain); 01248 01249 if (label_pre) 01250 gtk_box_pack_start(GTK_BOX(widget), label_pre, FALSE, FALSE, 0); 01251 if (spin_btn) 01252 gtk_box_pack_start(GTK_BOX(widget), spin_btn, FALSE, FALSE, 0); 01253 if (label_past) 01254 gtk_box_pack_start(GTK_BOX(widget), label_past, FALSE, FALSE, 0); 01255 01256 break; 01257 case WIDGET_CUSTOM: /* custom widget. --nenolod */ 01258 if (widgets[x].data.populate) 01259 widget = widgets[x].data.populate(); 01260 else 01261 widget = NULL; 01262 01263 break; 01264 case WIDGET_FONT_BTN: 01265 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0); 01266 01267 widget = gtk_hbox_new(FALSE, 6); 01268 01269 GtkWidget *font_btn = NULL; 01270 create_font_btn (& widgets[x], & label, & font_btn, domain); 01271 01272 if (label) 01273 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0); 01274 if (font_btn) 01275 gtk_box_pack_start(GTK_BOX(widget), font_btn, FALSE, FALSE, 0); 01276 break; 01277 case WIDGET_TABLE: 01278 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0); 01279 01280 widget = gtk_table_new(widgets[x].data.table.rows, 3, FALSE); 01281 fill_table (widget, widgets[x].data.table.elem, 01282 widgets[x].data.table.rows, domain); 01283 gtk_table_set_row_spacings(GTK_TABLE(widget), 6); 01284 break; 01285 case WIDGET_ENTRY: 01286 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 0, 6, 12); 01287 01288 widget = gtk_hbox_new(FALSE, 6); 01289 01290 GtkWidget *entry = NULL; 01291 create_entry (& widgets[x], & label, & entry, domain); 01292 01293 if (label) 01294 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0); 01295 if (entry) 01296 gtk_box_pack_start(GTK_BOX(widget), entry, TRUE, TRUE, 0); 01297 break; 01298 case WIDGET_COMBO_BOX: 01299 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 12, 0); 01300 01301 widget = gtk_hbox_new(FALSE, 10); 01302 01303 GtkWidget *combo = NULL; 01304 create_cbox (& widgets[x], & label, & combo, domain); 01305 01306 if (label) 01307 gtk_box_pack_start(GTK_BOX(widget), label, FALSE, FALSE, 0); 01308 if (combo) 01309 gtk_box_pack_start(GTK_BOX(widget), combo, FALSE, FALSE, 0); 01310 break; 01311 case WIDGET_BOX: 01312 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 3, 0); 01313 01314 if (widgets[x].data.box.horizontal) { 01315 widget = gtk_hbox_new(FALSE, 0); 01316 } else { 01317 widget = gtk_vbox_new(FALSE, 0); 01318 } 01319 01320 create_widgets(GTK_BOX(widget), widgets[x].data.box.elem, widgets[x].data.box.n_elem); 01321 01322 if (widgets[x].data.box.frame) { 01323 GtkWidget *tmp; 01324 tmp = widget; 01325 01326 widget = gtk_frame_new (dgettext (domain, widgets[x].label)); 01327 gtk_container_add(GTK_CONTAINER(widget), tmp); 01328 } 01329 break; 01330 case WIDGET_NOTEBOOK: 01331 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 0, 0, 3, 0); 01332 01333 widget = gtk_notebook_new(); 01334 01335 gint i; 01336 for (i = 0; i<widgets[x].data.notebook.n_tabs; i++) { 01337 GtkWidget *vbox; 01338 vbox = gtk_vbox_new(FALSE, 5); 01339 create_widgets(GTK_BOX(vbox), widgets[x].data.notebook.tabs[i].settings, widgets[x].data.notebook.tabs[i].n_settings); 01340 01341 gtk_notebook_append_page (GTK_NOTEBOOK (widget), vbox, 01342 gtk_label_new (dgettext (domain, 01343 widgets[x].data.notebook.tabs[i].name))); 01344 } 01345 break; 01346 case WIDGET_SEPARATOR: 01347 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment), 6, 6, 0, 0); 01348 01349 if (widgets[x].data.separator.horizontal == TRUE) { 01350 widget = gtk_hseparator_new(); 01351 } else { 01352 widget = gtk_vseparator_new(); 01353 } 01354 break; 01355 default: 01356 /* shouldn't ever happen - expect things to break */ 01357 g_error("This shouldn't ever happen - expect things to break."); 01358 continue; 01359 } 01360 01361 if (widget && !gtk_widget_get_parent(widget)) 01362 gtk_container_add(GTK_CONTAINER(alignment), widget); 01363 if (widget && widgets[x].tooltip && widgets[x].type != WIDGET_SPIN_BTN) 01364 gtk_widget_set_tooltip_text (widget, dgettext (domain, 01365 widgets[x].tooltip)); 01366 } 01367 01368 } 01369 01370 static GtkWidget * 01371 create_titlestring_tag_menu(void) 01372 { 01373 GtkWidget *titlestring_tag_menu, *menu_item; 01374 guint i; 01375 01376 titlestring_tag_menu = gtk_menu_new(); 01377 for(i = 0; i < n_title_field_tags; i++) { 01378 menu_item = gtk_menu_item_new_with_label(_(title_field_tags[i].name)); 01379 gtk_menu_shell_append(GTK_MENU_SHELL(titlestring_tag_menu), menu_item); 01380 g_signal_connect(menu_item, "activate", 01381 G_CALLBACK(titlestring_tag_menu_callback), 01382 GINT_TO_POINTER(i)); 01383 }; 01384 gtk_widget_show_all(titlestring_tag_menu); 01385 01386 return titlestring_tag_menu; 01387 } 01388 01389 static void 01390 create_replay_gain_category(void) 01391 { 01392 GtkWidget *rg_page_vbox; 01393 GtkWidget *widgets_vbox; 01394 01395 rg_page_vbox = gtk_vbox_new (FALSE, 0); 01396 gtk_container_add (GTK_CONTAINER (category_notebook), rg_page_vbox); 01397 01398 widgets_vbox = gtk_vbox_new (FALSE, 0); 01399 create_widgets(GTK_BOX(widgets_vbox), replay_gain_page_widgets, G_N_ELEMENTS(replay_gain_page_widgets)); 01400 gtk_box_pack_start (GTK_BOX (rg_page_vbox), widgets_vbox, TRUE, TRUE, 0); 01401 } 01402 01403 static void show_numbers_cb (GtkToggleButton * numbers, void * unused) 01404 { 01405 cfg.show_numbers_in_pl = gtk_toggle_button_get_active (numbers); 01406 01407 hook_call ("title change", NULL); 01408 01409 /* trigger playlist update */ 01410 gchar * t = g_strdup (playlist_get_title (playlist_get_active ())); 01411 playlist_set_title (playlist_get_active (), t); 01412 g_free (t); 01413 } 01414 01415 static void leading_zero_cb (GtkToggleButton * leading) 01416 { 01417 cfg.leading_zero = gtk_toggle_button_get_active (leading); 01418 01419 hook_call ("title change", NULL); 01420 01421 /* trigger playlist update */ 01422 gchar * t = g_strdup (playlist_get_title (playlist_get_active ())); 01423 playlist_set_title (playlist_get_active (), t); 01424 g_free (t); 01425 } 01426 01427 static void 01428 create_playlist_category(void) 01429 { 01430 GtkWidget *vbox5; 01431 GtkWidget *alignment55; 01432 GtkWidget *label60; 01433 GtkWidget *alignment56; 01434 GtkWidget *table6; 01435 GtkWidget *titlestring_help_button; 01436 GtkWidget *image1; 01437 GtkWidget *titlestring_cbox; 01438 GtkWidget *label62; 01439 GtkWidget *label61; 01440 GtkWidget *alignment85; 01441 GtkWidget *label84; 01442 GtkWidget *alignment86; 01443 GtkWidget *hbox9; 01444 GtkWidget *vbox34; 01445 GtkWidget *checkbutton10; 01446 GtkWidget *image8; 01447 GtkWidget *titlestring_tag_menu = create_titlestring_tag_menu(); 01448 GtkWidget * numbers_alignment, * numbers; 01449 01450 vbox5 = gtk_vbox_new (FALSE, 0); 01451 gtk_container_add ((GtkContainer *) category_notebook, vbox5); 01452 01453 create_widgets(GTK_BOX(vbox5), playlist_page_widgets, G_N_ELEMENTS(playlist_page_widgets)); 01454 01455 alignment55 = gtk_alignment_new (0.5, 0.5, 1, 1); 01456 gtk_box_pack_start (GTK_BOX (vbox5), alignment55, FALSE, FALSE, 0); 01457 gtk_alignment_set_padding ((GtkAlignment *) alignment55, 12, 3, 0, 0); 01458 01459 label60 = gtk_label_new (_("<b>Song Display</b>")); 01460 gtk_container_add (GTK_CONTAINER (alignment55), label60); 01461 gtk_label_set_use_markup (GTK_LABEL (label60), TRUE); 01462 gtk_misc_set_alignment (GTK_MISC (label60), 0, 0.5); 01463 01464 numbers_alignment = gtk_alignment_new (0, 0, 0, 0); 01465 gtk_alignment_set_padding ((GtkAlignment *) numbers_alignment, 0, 0, 12, 0); 01466 gtk_box_pack_start ((GtkBox *) vbox5, numbers_alignment, 0, 0, 3); 01467 01468 numbers = gtk_check_button_new_with_label (_("Show song numbers")); 01469 gtk_toggle_button_set_active ((GtkToggleButton *) numbers, 01470 cfg.show_numbers_in_pl); 01471 g_signal_connect ((GObject *) numbers, "toggled", (GCallback) 01472 show_numbers_cb, 0); 01473 gtk_container_add ((GtkContainer *) numbers_alignment, numbers); 01474 01475 numbers_alignment = gtk_alignment_new (0, 0, 0, 0); 01476 gtk_alignment_set_padding ((GtkAlignment *) numbers_alignment, 0, 0, 12, 0); 01477 gtk_box_pack_start ((GtkBox *) vbox5, numbers_alignment, 0, 0, 3); 01478 01479 numbers = gtk_check_button_new_with_label (_("Show leading zeroes (02:00 " 01480 "instead of 2:00)")); 01481 gtk_toggle_button_set_active ((GtkToggleButton *) numbers, cfg.leading_zero); 01482 g_signal_connect ((GObject *) numbers, "toggled", (GCallback) 01483 leading_zero_cb, 0); 01484 gtk_container_add ((GtkContainer *) numbers_alignment, numbers); 01485 01486 alignment56 = gtk_alignment_new (0.5, 0.5, 1, 1); 01487 gtk_box_pack_start (GTK_BOX (vbox5), alignment56, FALSE, FALSE, 0); 01488 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment56), 0, 0, 12, 0); 01489 01490 table6 = gtk_table_new (2, 3, FALSE); 01491 gtk_container_add (GTK_CONTAINER (alignment56), table6); 01492 gtk_table_set_row_spacings (GTK_TABLE (table6), 4); 01493 gtk_table_set_col_spacings (GTK_TABLE (table6), 12); 01494 01495 titlestring_help_button = gtk_button_new (); 01496 gtk_table_attach (GTK_TABLE (table6), titlestring_help_button, 2, 3, 1, 2, 01497 (GtkAttachOptions) (0), 01498 (GtkAttachOptions) (0), 0, 0); 01499 01500 gtk_widget_set_can_focus (titlestring_help_button, FALSE); 01501 gtk_widget_set_tooltip_text (titlestring_help_button, _("Show information about titlestring format")); 01502 gtk_button_set_relief (GTK_BUTTON (titlestring_help_button), GTK_RELIEF_HALF); 01503 gtk_button_set_focus_on_click (GTK_BUTTON (titlestring_help_button), FALSE); 01504 01505 image1 = gtk_image_new_from_stock ("gtk-index", GTK_ICON_SIZE_BUTTON); 01506 gtk_container_add (GTK_CONTAINER (titlestring_help_button), image1); 01507 01508 titlestring_cbox = gtk_combo_box_text_new (); 01509 01510 gtk_table_attach (GTK_TABLE (table6), titlestring_cbox, 1, 3, 0, 1, 01511 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 01512 (GtkAttachOptions) (0), 0, 0); 01513 01514 gtk_combo_box_text_append_text ((GtkComboBoxText *) titlestring_cbox, _("TITLE")); 01515 gtk_combo_box_text_append_text ((GtkComboBoxText *) titlestring_cbox, _("ARTIST - TITLE")); 01516 gtk_combo_box_text_append_text ((GtkComboBoxText *) titlestring_cbox, _("ARTIST - ALBUM - TITLE")); 01517 gtk_combo_box_text_append_text ((GtkComboBoxText *) titlestring_cbox, _("ARTIST - ALBUM - TRACK. TITLE")); 01518 gtk_combo_box_text_append_text ((GtkComboBoxText *) titlestring_cbox, _("ARTIST [ ALBUM ] - TRACK. TITLE")); 01519 gtk_combo_box_text_append_text ((GtkComboBoxText *) titlestring_cbox, _("ALBUM - TITLE")); 01520 gtk_combo_box_text_append_text ((GtkComboBoxText *) titlestring_cbox, _("Custom")); 01521 01522 titlestring_entry = gtk_entry_new (); 01523 gtk_table_attach (GTK_TABLE (table6), titlestring_entry, 1, 2, 1, 2, 01524 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 01525 (GtkAttachOptions) (0), 0, 0); 01526 01527 label62 = gtk_label_new (_("Custom string:")); 01528 gtk_table_attach (GTK_TABLE (table6), label62, 0, 1, 1, 2, 01529 (GtkAttachOptions) (0), 01530 (GtkAttachOptions) (0), 0, 0); 01531 gtk_label_set_justify (GTK_LABEL (label62), GTK_JUSTIFY_RIGHT); 01532 gtk_misc_set_alignment (GTK_MISC (label62), 1, 0.5); 01533 01534 label61 = gtk_label_new (_("Title format:")); 01535 gtk_table_attach (GTK_TABLE (table6), label61, 0, 1, 0, 1, 01536 (GtkAttachOptions) (0), 01537 (GtkAttachOptions) (0), 0, 0); 01538 gtk_label_set_justify (GTK_LABEL (label61), GTK_JUSTIFY_RIGHT); 01539 gtk_misc_set_alignment (GTK_MISC (label61), 1, 0.5); 01540 01541 alignment85 = gtk_alignment_new (0.5, 0.5, 1, 1); 01542 gtk_box_pack_start (GTK_BOX (vbox5), alignment85, FALSE, FALSE, 0); 01543 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment85), 12, 12, 0, 0); 01544 01545 label84 = gtk_label_new (_("<b>Popup Information</b>")); 01546 gtk_container_add (GTK_CONTAINER (alignment85), label84); 01547 gtk_label_set_use_markup (GTK_LABEL (label84), TRUE); 01548 gtk_misc_set_alignment (GTK_MISC (label84), 0, 0.5); 01549 01550 alignment86 = gtk_alignment_new (0.5, 0.5, 1, 1); 01551 gtk_box_pack_start (GTK_BOX (vbox5), alignment86, FALSE, FALSE, 0); 01552 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment86), 0, 0, 12, 0); 01553 01554 hbox9 = gtk_hbox_new (FALSE, 12); 01555 gtk_container_add (GTK_CONTAINER (alignment86), hbox9); 01556 01557 vbox34 = gtk_vbox_new (FALSE, 0); 01558 gtk_box_pack_start (GTK_BOX (hbox9), vbox34, TRUE, TRUE, 0); 01559 01560 checkbutton10 = gtk_check_button_new_with_mnemonic (_("Show popup information for playlist entries")); 01561 gtk_box_pack_start (GTK_BOX (vbox34), checkbutton10, TRUE, FALSE, 0); 01562 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.")); 01563 01564 filepopup_for_tuple_settings_button = gtk_button_new (); 01565 gtk_box_pack_start (GTK_BOX (hbox9), filepopup_for_tuple_settings_button, FALSE, FALSE, 0); 01566 01567 gtk_widget_set_can_focus (filepopup_for_tuple_settings_button, FALSE); 01568 gtk_widget_set_tooltip_text (filepopup_for_tuple_settings_button, _("Edit settings for popup information")); 01569 gtk_button_set_relief (GTK_BUTTON (filepopup_for_tuple_settings_button), GTK_RELIEF_HALF); 01570 01571 image8 = gtk_image_new_from_stock ("gtk-properties", GTK_ICON_SIZE_BUTTON); 01572 gtk_container_add (GTK_CONTAINER (filepopup_for_tuple_settings_button), image8); 01573 01574 01575 01576 g_signal_connect(G_OBJECT(checkbutton10), "toggled", 01577 G_CALLBACK(on_show_filepopup_for_tuple_toggled), 01578 NULL); 01579 g_signal_connect_after(G_OBJECT(checkbutton10), "realize", 01580 G_CALLBACK(on_show_filepopup_for_tuple_realize), 01581 NULL); 01582 g_signal_connect(G_OBJECT(filepopup_for_tuple_settings_button), "clicked", 01583 G_CALLBACK(on_filepopup_for_tuple_settings_clicked), 01584 NULL); 01585 01586 g_signal_connect(titlestring_cbox, "realize", 01587 G_CALLBACK(on_titlestring_cbox_realize), 01588 titlestring_entry); 01589 g_signal_connect(titlestring_cbox, "changed", 01590 G_CALLBACK(on_titlestring_cbox_changed), 01591 titlestring_entry); 01592 01593 g_signal_connect(titlestring_cbox, "changed", 01594 G_CALLBACK(on_titlestring_cbox_changed), 01595 titlestring_help_button); 01596 g_signal_connect(titlestring_help_button, "clicked", 01597 G_CALLBACK(on_titlestring_help_button_clicked), 01598 titlestring_tag_menu); 01599 01600 g_signal_connect(G_OBJECT(titlestring_entry), "changed", 01601 G_CALLBACK(on_titlestring_entry_changed), 01602 NULL); 01603 g_signal_connect_after(G_OBJECT(titlestring_entry), "realize", 01604 G_CALLBACK(on_titlestring_entry_realize), 01605 NULL); 01606 01607 01608 01609 /* Create window for filepopup settings */ 01610 create_filepopup_settings(); 01611 } 01612 01613 static GtkWidget * output_config_button, * output_about_button; 01614 01615 static gboolean output_enum_cb (PluginHandle * plugin, GList * * list) 01616 { 01617 * list = g_list_prepend (* list, plugin); 01618 return TRUE; 01619 } 01620 01621 static GList * output_get_list (void) 01622 { 01623 static GList * list = NULL; 01624 01625 if (list == NULL) 01626 { 01627 plugin_for_each (PLUGIN_TYPE_OUTPUT, (PluginForEachFunc) output_enum_cb, 01628 & list); 01629 list = g_list_reverse (list); 01630 } 01631 01632 return list; 01633 } 01634 01635 static void output_combo_update (GtkComboBox * combo) 01636 { 01637 PluginHandle * plugin = plugin_get_current (PLUGIN_TYPE_OUTPUT); 01638 gtk_combo_box_set_active (combo, g_list_index (output_get_list (), plugin)); 01639 gtk_widget_set_sensitive (output_config_button, plugin_has_configure (plugin)); 01640 gtk_widget_set_sensitive (output_about_button, plugin_has_about (plugin)); 01641 } 01642 01643 static void output_combo_changed (GtkComboBox * combo) 01644 { 01645 PluginHandle * plugin = g_list_nth_data (output_get_list (), 01646 gtk_combo_box_get_active (combo)); 01647 g_return_if_fail (plugin != NULL); 01648 01649 plugin_enable (plugin, TRUE); 01650 output_combo_update (combo); 01651 } 01652 01653 static void output_combo_fill (GtkComboBox * combo) 01654 { 01655 for (GList * node = output_get_list (); node != NULL; node = node->next) 01656 gtk_combo_box_text_append_text ((GtkComboBoxText *) combo, 01657 plugin_get_name (node->data)); 01658 } 01659 01660 static void output_do_config (void) 01661 { 01662 OutputPlugin * op = plugin_get_header (output_plugin_get_current ()); 01663 g_return_if_fail (op != NULL); 01664 if (op->configure != NULL) 01665 op->configure (); 01666 } 01667 01668 static void output_do_about (void) 01669 { 01670 OutputPlugin * op = plugin_get_header (output_plugin_get_current ()); 01671 g_return_if_fail (op != NULL); 01672 if (op->about != NULL) 01673 op->about (); 01674 } 01675 01676 static void 01677 create_audio_category(void) 01678 { 01679 GtkWidget *audio_page_vbox; 01680 GtkWidget *alignment74; 01681 GtkWidget *label77; 01682 GtkWidget *alignment73; 01683 GtkWidget *vbox33; 01684 GtkWidget *table11; 01685 GtkWidget *label79; 01686 GtkAdjustment * output_plugin_bufsize_adj; 01687 GtkWidget *output_plugin_bufsize; 01688 GtkWidget *output_plugin_cbox; 01689 GtkWidget *label78; 01690 01691 audio_page_vbox = gtk_vbox_new (FALSE, 0); 01692 gtk_container_add (GTK_CONTAINER (category_notebook), audio_page_vbox); 01693 01694 alignment74 = gtk_alignment_new (0.5, 0.5, 1, 1); 01695 gtk_box_pack_start (GTK_BOX (audio_page_vbox), alignment74, FALSE, FALSE, 0); 01696 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment74), 0, 12, 0, 0); 01697 01698 label77 = gtk_label_new (_("<b>Audio System</b>")); 01699 gtk_container_add (GTK_CONTAINER (alignment74), label77); 01700 gtk_label_set_use_markup (GTK_LABEL (label77), TRUE); 01701 gtk_misc_set_alignment (GTK_MISC (label77), 0, 0.5); 01702 01703 alignment73 = gtk_alignment_new (0.5, 0.5, 1, 1); 01704 gtk_box_pack_start (GTK_BOX (audio_page_vbox), alignment73, FALSE, FALSE, 0); 01705 gtk_alignment_set_padding (GTK_ALIGNMENT (alignment73), 0, 6, 12, 0); 01706 01707 vbox33 = gtk_vbox_new (FALSE, 0); 01708 gtk_container_add (GTK_CONTAINER (alignment73), vbox33); 01709 01710 table11 = gtk_table_new (3, 2, FALSE); 01711 gtk_box_pack_start (GTK_BOX (vbox33), table11, FALSE, FALSE, 0); 01712 gtk_table_set_row_spacings (GTK_TABLE (table11), 6); 01713 gtk_table_set_col_spacings (GTK_TABLE (table11), 6); 01714 01715 label79 = gtk_label_new (_("Buffer size:")); 01716 gtk_table_attach (GTK_TABLE (table11), label79, 0, 1, 1, 2, 01717 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 01718 (GtkAttachOptions) (0), 0, 0); 01719 gtk_misc_set_alignment (GTK_MISC (label79), 1, 0.5); 01720 01721 output_plugin_bufsize_adj = (GtkAdjustment *) gtk_adjustment_new (0, 100, 01722 10000, 100, 1000, 0); 01723 output_plugin_bufsize = gtk_spin_button_new (GTK_ADJUSTMENT (output_plugin_bufsize_adj), 100, 0); 01724 gtk_table_attach (GTK_TABLE (table11), output_plugin_bufsize, 1, 2, 1, 2, 01725 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 01726 (GtkAttachOptions) (0), 0, 0); 01727 01728 output_plugin_cbox = gtk_combo_box_text_new (); 01729 01730 gtk_table_attach (GTK_TABLE (table11), output_plugin_cbox, 1, 2, 0, 1, 01731 (GtkAttachOptions) (GTK_EXPAND | GTK_FILL), 01732 (GtkAttachOptions) (0), 0, 0); 01733 01734 label78 = gtk_label_new (_("Current output plugin:")); 01735 gtk_table_attach (GTK_TABLE (table11), label78, 0, 1, 0, 1, 01736 (GtkAttachOptions) (0), 01737 (GtkAttachOptions) (0), 0, 0); 01738 gtk_misc_set_alignment (GTK_MISC (label78), 0, 0.5); 01739 01740 GtkWidget * hbox = gtk_hbox_new (FALSE, 6); 01741 gtk_box_pack_start ((GtkBox *) audio_page_vbox, hbox, FALSE, FALSE, 0); 01742 01743 output_config_button = gtk_button_new_from_stock (GTK_STOCK_PREFERENCES); 01744 output_about_button = gtk_button_new_from_stock (GTK_STOCK_ABOUT); 01745 01746 gtk_box_pack_end ((GtkBox *) hbox, output_about_button, FALSE, FALSE, 0); 01747 gtk_box_pack_end ((GtkBox *) hbox, output_config_button, FALSE, FALSE, 0); 01748 01749 create_widgets(GTK_BOX(audio_page_vbox), audio_page_widgets, G_N_ELEMENTS(audio_page_widgets)); 01750 01751 output_combo_fill ((GtkComboBox *) output_plugin_cbox); 01752 output_combo_update ((GtkComboBox *) output_plugin_cbox); 01753 g_signal_connect (output_plugin_cbox, "changed", (GCallback) 01754 output_combo_changed, NULL); 01755 g_signal_connect (output_config_button, "clicked", (GCallback) 01756 output_do_config, NULL); 01757 g_signal_connect (output_about_button, "clicked", (GCallback) 01758 output_do_about, NULL); 01759 01760 g_signal_connect(G_OBJECT(output_plugin_bufsize), "value_changed", 01761 G_CALLBACK(on_output_plugin_bufsize_value_changed), 01762 NULL); 01763 g_signal_connect_after(G_OBJECT(output_plugin_bufsize), "realize", 01764 G_CALLBACK(on_output_plugin_bufsize_realize), 01765 NULL); 01766 } 01767 01768 static void 01769 create_connectivity_category(void) 01770 { 01771 GtkWidget *connectivity_page_vbox; 01772 GtkWidget *vbox29; 01773 01774 connectivity_page_vbox = gtk_vbox_new (FALSE, 0); 01775 gtk_container_add (GTK_CONTAINER (category_notebook), connectivity_page_vbox); 01776 01777 vbox29 = gtk_vbox_new (FALSE, 0); 01778 gtk_box_pack_start (GTK_BOX (connectivity_page_vbox), vbox29, TRUE, TRUE, 0); 01779 01780 create_widgets(GTK_BOX(vbox29), connectivity_page_widgets, G_N_ELEMENTS(connectivity_page_widgets)); 01781 } 01782 01783 static void create_plugin_category (void) 01784 { 01785 GtkWidget * notebook = gtk_notebook_new (); 01786 gtk_container_add ((GtkContainer *) category_notebook, notebook); 01787 01788 gint types[] = {PLUGIN_TYPE_TRANSPORT, PLUGIN_TYPE_PLAYLIST, 01789 PLUGIN_TYPE_INPUT, PLUGIN_TYPE_EFFECT, PLUGIN_TYPE_VIS, PLUGIN_TYPE_GENERAL}; 01790 const gchar * names[] = {N_("Transport"), N_("Playlist"), N_("Input"), 01791 N_("Effect"), N_("Visualization"), N_("General")}; 01792 01793 for (gint i = 0; i < G_N_ELEMENTS (types); i ++) 01794 gtk_notebook_append_page ((GtkNotebook *) notebook, plugin_view_new 01795 (types[i]), gtk_label_new (_(names[i]))); 01796 } 01797 01798 static gboolean 01799 prefswin_destroy(GtkWidget *window, GdkEvent *event, gpointer data) 01800 { 01801 prefswin = NULL; 01802 category_notebook = NULL; 01803 gtk_widget_destroy(filepopup_settings); 01804 filepopup_settings = NULL; 01805 gtk_widget_destroy(window); 01806 return TRUE; 01807 } 01808 01809 /* GtkWidget * * create_prefs_window (void) */ 01810 void * * create_prefs_window (void) 01811 { 01812 gchar *aud_version_string; 01813 01814 GtkWidget *vbox; 01815 GtkWidget *hbox1; 01816 GtkWidget *scrolledwindow6; 01817 GtkWidget *hseparator1; 01818 GtkWidget *hbox4; 01819 GtkWidget *audversionlabel; 01820 GtkWidget *prefswin_button_box; 01821 GtkWidget *hbox11; 01822 GtkWidget *image10; 01823 GtkWidget *close; 01824 GtkAccelGroup *accel_group; 01825 01826 accel_group = gtk_accel_group_new (); 01827 01828 prefswin = gtk_window_new (GTK_WINDOW_TOPLEVEL); 01829 gtk_window_set_type_hint (GTK_WINDOW (prefswin), GDK_WINDOW_TYPE_HINT_DIALOG); 01830 gtk_container_set_border_width (GTK_CONTAINER (prefswin), 12); 01831 gtk_window_set_title (GTK_WINDOW (prefswin), _("Audacious Preferences")); 01832 gtk_window_set_position (GTK_WINDOW (prefswin), GTK_WIN_POS_CENTER); 01833 gtk_window_set_default_size (GTK_WINDOW (prefswin), 680, 400); 01834 01835 vbox = gtk_vbox_new (FALSE, 0); 01836 gtk_container_add (GTK_CONTAINER (prefswin), vbox); 01837 01838 hbox1 = gtk_hbox_new (FALSE, 8); 01839 gtk_box_pack_start (GTK_BOX (vbox), hbox1, TRUE, TRUE, 0); 01840 01841 scrolledwindow6 = gtk_scrolled_window_new (NULL, NULL); 01842 gtk_box_pack_start (GTK_BOX (hbox1), scrolledwindow6, TRUE, TRUE, 0); 01843 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolledwindow6), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 01844 gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolledwindow6), GTK_SHADOW_IN); 01845 01846 category_treeview = gtk_tree_view_new (); 01847 gtk_container_add (GTK_CONTAINER (scrolledwindow6), category_treeview); 01848 gtk_widget_set_size_request (category_treeview, 172, -1); 01849 gtk_tree_view_set_headers_visible (GTK_TREE_VIEW (category_treeview), FALSE); 01850 01851 category_notebook = gtk_notebook_new (); 01852 gtk_box_pack_start (GTK_BOX (hbox1), category_notebook, TRUE, TRUE, 0); 01853 01854 gtk_widget_set_can_focus (category_notebook, FALSE); 01855 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (category_notebook), FALSE); 01856 gtk_notebook_set_show_border (GTK_NOTEBOOK (category_notebook), FALSE); 01857 gtk_notebook_set_scrollable (GTK_NOTEBOOK (category_notebook), TRUE); 01858 01859 01860 01861 create_audio_category(); 01862 create_replay_gain_category(); 01863 create_connectivity_category(); 01864 create_playlist_category(); 01865 create_plugin_category(); 01866 01867 hseparator1 = gtk_hseparator_new (); 01868 gtk_box_pack_start (GTK_BOX (vbox), hseparator1, FALSE, FALSE, 6); 01869 01870 hbox4 = gtk_hbox_new (FALSE, 0); 01871 gtk_box_pack_start (GTK_BOX (vbox), hbox4, FALSE, FALSE, 0); 01872 01873 audversionlabel = gtk_label_new (""); 01874 gtk_box_pack_start (GTK_BOX (hbox4), audversionlabel, FALSE, FALSE, 0); 01875 gtk_label_set_use_markup (GTK_LABEL (audversionlabel), TRUE); 01876 01877 prefswin_button_box = gtk_hbutton_box_new (); 01878 gtk_box_pack_start (GTK_BOX (hbox4), prefswin_button_box, TRUE, TRUE, 0); 01879 gtk_button_box_set_layout (GTK_BUTTON_BOX (prefswin_button_box), GTK_BUTTONBOX_END); 01880 gtk_box_set_spacing (GTK_BOX (prefswin_button_box), 6); 01881 01882 hbox11 = gtk_hbox_new (FALSE, 2); 01883 01884 image10 = gtk_image_new_from_stock ("gtk-refresh", GTK_ICON_SIZE_BUTTON); 01885 gtk_box_pack_start (GTK_BOX (hbox11), image10, FALSE, FALSE, 0); 01886 01887 close = gtk_button_new_from_stock ("gtk-close"); 01888 gtk_container_add (GTK_CONTAINER (prefswin_button_box), close); 01889 gtk_widget_set_can_default(close, TRUE); 01890 gtk_widget_add_accelerator (close, "clicked", accel_group, 01891 GDK_Escape, (GdkModifierType) 0, 01892 GTK_ACCEL_VISIBLE); 01893 01894 01895 gtk_window_add_accel_group (GTK_WINDOW (prefswin), accel_group); 01896 01897 /* connect signals */ 01898 g_signal_connect(G_OBJECT(prefswin), "delete_event", 01899 G_CALLBACK(prefswin_destroy), 01900 NULL); 01901 g_signal_connect_swapped(G_OBJECT(close), "clicked", 01902 G_CALLBACK(prefswin_destroy), 01903 prefswin); 01904 01905 /* create category view */ 01906 on_category_treeview_realize ((GtkTreeView *) category_treeview, 01907 (GtkNotebook *) category_notebook); 01908 01909 /* audacious version label */ 01910 01911 aud_version_string = g_strdup_printf 01912 ("<span size='small'>%s (%s)</span>", "Audacious " PACKAGE_VERSION, 01913 BUILDSTAMP); 01914 01915 gtk_label_set_markup( GTK_LABEL(audversionlabel) , aud_version_string ); 01916 g_free(aud_version_string); 01917 gtk_widget_show_all(vbox); 01918 01919 return & prefswin; 01920 } 01921 01922 void 01923 destroy_prefs_window(void) 01924 { 01925 prefswin_destroy(prefswin, NULL, NULL); 01926 } 01927 01928 void 01929 show_prefs_window(void) 01930 { 01931 gtk_window_present(GTK_WINDOW(prefswin)); /* show or raise prefs window */ 01932 } 01933 01934 void 01935 hide_prefs_window(void) 01936 { 01937 g_return_if_fail(prefswin); 01938 gtk_widget_hide(GTK_WIDGET(prefswin)); 01939 } 01940 01941 static void prefswin_page_queue_new (GtkWidget * container, const gchar * name, 01942 const gchar * imgurl) 01943 { 01944 CategoryQueueEntry *ent = g_new0(CategoryQueueEntry, 1); 01945 01946 ent->container = container; 01947 ent->pg_name = name; 01948 ent->img_url = imgurl; 01949 01950 if (category_queue) 01951 ent->next = category_queue; 01952 01953 category_queue = ent; 01954 } 01955 01956 static void 01957 prefswin_page_queue_destroy(CategoryQueueEntry *ent) 01958 { 01959 category_queue = ent->next; 01960 g_free(ent); 01961 } 01962 01963 /* 01964 * Public APIs for adding new pages to the prefs window. 01965 * 01966 * Basically, the concept here is that third party components can register themselves in the root 01967 * preferences window. 01968 * 01969 * From a usability standpoint this makes the application look more "united", instead of cluttered 01970 * and malorganised. Hopefully this option will be used further in the future. 01971 * 01972 * - nenolod 01973 */ 01974 /* gint prefswin_page_new (GtkWidget * container, const gchar * name, 01975 const gchar * imgurl) */ 01976 gint prefswin_page_new (void * container, const gchar * name, const gchar * 01977 imgurl) 01978 { 01979 GtkTreeModel *model; 01980 GtkTreeIter iter; 01981 GdkPixbuf *img = NULL; 01982 GtkTreeView *treeview = GTK_TREE_VIEW(category_treeview); 01983 gint id; 01984 01985 if (treeview == NULL || category_notebook == NULL) 01986 { 01987 prefswin_page_queue_new(container, name, imgurl); 01988 return -1; 01989 } 01990 01991 model = gtk_tree_view_get_model(treeview); 01992 01993 if (model == NULL) 01994 { 01995 prefswin_page_queue_new(container, name, imgurl); 01996 return -1; 01997 } 01998 01999 /* Make sure the widgets are visible. */ 02000 gtk_widget_show(container); 02001 id = gtk_notebook_append_page(GTK_NOTEBOOK(category_notebook), container, NULL); 02002 02003 if (id == -1) 02004 return -1; 02005 02006 if (imgurl != NULL) 02007 img = gdk_pixbuf_new_from_file(imgurl, NULL); 02008 02009 gtk_list_store_append(GTK_LIST_STORE(model), &iter); 02010 gtk_list_store_set(GTK_LIST_STORE(model), &iter, 02011 CATEGORY_VIEW_COL_ICON, img, 02012 CATEGORY_VIEW_COL_NAME, 02013 name, CATEGORY_VIEW_COL_ID, id, -1); 02014 02015 if (img != NULL) 02016 g_object_unref(img); 02017 02018 return id; 02019 } 02020 02021 void 02022 prefswin_page_destroy(GtkWidget *container) 02023 { 02024 GtkTreeModel *model; 02025 GtkTreeIter iter; 02026 GtkTreeView *treeview = GTK_TREE_VIEW(category_treeview); 02027 gboolean ret; 02028 gint id; 02029 gint index = -1; 02030 02031 if (category_notebook == NULL || treeview == NULL || container == NULL) 02032 return; 02033 02034 id = gtk_notebook_page_num(GTK_NOTEBOOK(category_notebook), container); 02035 02036 if (id == -1) 02037 return; 02038 02039 gtk_notebook_remove_page(GTK_NOTEBOOK(category_notebook), id); 02040 02041 model = gtk_tree_view_get_model(treeview); 02042 02043 if (model == NULL) 02044 return; 02045 02046 ret = gtk_tree_model_get_iter_first(model, &iter); 02047 02048 while (ret == TRUE) 02049 { 02050 gtk_tree_model_get(model, &iter, CATEGORY_VIEW_COL_ID, &index, -1); 02051 02052 if (index == id) 02053 { 02054 gtk_list_store_remove(GTK_LIST_STORE(model), &iter); 02055 ret = gtk_tree_model_get_iter_first(model, &iter); 02056 continue; 02057 } 02058 02059 if (index > id) 02060 { 02061 index--; 02062 gtk_list_store_set(GTK_LIST_STORE(model), &iter, CATEGORY_VIEW_COL_ID, index, -1); 02063 } 02064 02065 ret = gtk_tree_model_iter_next(model, &iter); 02066 } 02067 } 02068 02069 static void sw_volume_toggled (void) 02070 { 02071 gint vol[2]; 02072 02073 if (cfg.software_volume_control) 02074 { 02075 vol[0] = cfg.sw_volume_left; 02076 vol[1] = cfg.sw_volume_right; 02077 } 02078 else 02079 playback_get_volume (& vol[0], & vol[1]); 02080 02081 hook_call ("volume set", vol); 02082 }