00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021 #include <stdio.h>
00022
00023 #include <gdk/gdkkeysyms.h>
00024 #include <gtk/gtk.h>
00025
00026 #include <libaudcore/hook.h>
00027
00028 #include "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 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
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
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
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
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
00550 category_treeview = GTK_WIDGET(treeview);
00551
00552
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
01164
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) {
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:
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
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
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
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
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
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
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
01915 on_category_treeview_realize ((GtkTreeView *) category_treeview,
01916 (GtkNotebook *) category_notebook);
01917
01918
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));
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
01974
01975
01976
01977
01978
01979
01980
01981
01982
01983
01984
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
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 }