1 /*
2     DeaDBeeF -- the music player
3     Copyright (C) 2009-2015 Alexey Yakovenko and other contributors
4 
5     This software is provided 'as-is', without any express or implied
6     warranty.  In no event will the authors be held liable for any damages
7     arising from the use of this software.
8 
9     Permission is granted to anyone to use this software for any purpose,
10     including commercial applications, and to alter it and redistribute it
11     freely, subject to the following restrictions:
12 
13     1. The origin of this software must not be misrepresented; you must not
14      claim that you wrote the original software. If you use this software
15      in a product, an acknowledgment in the product documentation would be
16      appreciated but is not required.
17 
18     2. Altered source versions must be plainly marked as such, and must not be
19      misrepresented as being the original software.
20 
21     3. This notice may not be removed or altered from any source distribution.
22 */
23 
24 #ifdef HAVE_CONFIG_H
25 #  include <config.h>
26 #endif
27 #include <gtk/gtk.h>
28 #include <string.h>
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <gdk/gdkkeysyms.h>
32 #include "../../gettext.h"
33 #include "gtkui.h"
34 #include "support.h"
35 #include "interface.h"
36 #include "callbacks.h"
37 #include "drawing.h"
38 #include "eq.h"
39 #include "ddblistview.h"
40 #include "pluginconf.h"
41 #include "dspconfig.h"
42 #include "wingeom.h"
43 #include "hotkeys.h"
44 
45 #define GLADE_HOOKUP_OBJECT(component,widget,name) \
46   g_object_set_data_full (G_OBJECT (component), name, \
47     g_object_ref (G_OBJECT (widget)), (GDestroyNotify) g_object_unref)
48 
49 #define GLADE_HOOKUP_OBJECT_NO_REF(component,widget,name) \
50   g_object_set_data (G_OBJECT (component), name, widget)
51 
52 static GtkWidget *prefwin;
53 
54 static char alsa_device_names[100][64];
55 static int num_alsa_devices;
56 
57 static void
gtk_enum_sound_callback(const char * name,const char * desc,void * userdata)58 gtk_enum_sound_callback (const char *name, const char *desc, void *userdata) {
59     if (num_alsa_devices >= 100) {
60         fprintf (stderr, "wtf!! more than 100 alsa devices??\n");
61         return;
62     }
63     GtkComboBox *combobox = GTK_COMBO_BOX (userdata);
64     gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combobox), desc);
65 
66     deadbeef->conf_lock ();
67     if (!strcmp (deadbeef->conf_get_str_fast ("alsa_soundcard", "default"), name)) {
68         gtk_combo_box_set_active (combobox, num_alsa_devices);
69     }
70     deadbeef->conf_unlock ();
71 
72     strncpy (alsa_device_names[num_alsa_devices], name, 63);
73     alsa_device_names[num_alsa_devices][63] = 0;
74     num_alsa_devices++;
75 }
76 
77 void
preferences_fill_soundcards(void)78 preferences_fill_soundcards (void) {
79     if (!prefwin) {
80         return;
81     }
82     GtkComboBox *combobox = GTK_COMBO_BOX (lookup_widget (prefwin, "pref_soundcard"));
83     GtkTreeModel *mdl = gtk_combo_box_get_model (combobox);
84     gtk_list_store_clear (GTK_LIST_STORE (mdl));
85 
86     gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combobox), _("Default Audio Device"));
87 
88     deadbeef->conf_lock ();
89     const char *s = deadbeef->conf_get_str_fast ("alsa_soundcard", "default");
90     if (!strcmp (s, "default")) {
91         gtk_combo_box_set_active (combobox, 0);
92     }
93     deadbeef->conf_unlock ();
94 
95     num_alsa_devices = 1;
96     strcpy (alsa_device_names[0], "default");
97     if (deadbeef->get_output ()->enum_soundcards) {
98         deadbeef->get_output ()->enum_soundcards (gtk_enum_sound_callback, combobox);
99         gtk_widget_set_sensitive (GTK_WIDGET (combobox), TRUE);
100     }
101     else {
102         gtk_widget_set_sensitive (GTK_WIDGET (combobox), FALSE);
103     }
104 }
105 
106 void
prefwin_init_theme_colors(void)107 prefwin_init_theme_colors (void) {
108     GdkColor clr;
109     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "bar_background")), (gtkui_get_bar_background_color (&clr), &clr));
110     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "bar_foreground")), (gtkui_get_bar_foreground_color (&clr), &clr));
111     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "tabstrip_dark")), (gtkui_get_tabstrip_dark_color (&clr), &clr));
112     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "tabstrip_mid")), (gtkui_get_tabstrip_mid_color (&clr), &clr));
113     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "tabstrip_light")), (gtkui_get_tabstrip_light_color (&clr), &clr));
114     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "tabstrip_base")), (gtkui_get_tabstrip_base_color (&clr), &clr));
115     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "tabstrip_text")), (gtkui_get_tabstrip_text_color (&clr), &clr));
116     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "tabstrip_playing_text")), (gtkui_get_tabstrip_playing_text_color (&clr), &clr));
117     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "tabstrip_selected_text")), (gtkui_get_tabstrip_selected_text_color (&clr), &clr));
118     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_even_row")), (gtkui_get_listview_even_row_color (&clr), &clr));
119     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_odd_row")), (gtkui_get_listview_odd_row_color (&clr), &clr));
120     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_selected_row")), (gtkui_get_listview_selection_color (&clr), &clr));
121     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_text")), (gtkui_get_listview_text_color (&clr), &clr));
122     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_selected_text")), (gtkui_get_listview_selected_text_color (&clr), &clr));
123     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_playing_text")), (gtkui_get_listview_playing_text_color (&clr), &clr));
124     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_group_text")), (gtkui_get_listview_group_text_color (&clr), &clr));
125     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_column_text")), (gtkui_get_listview_column_text_color (&clr), &clr));
126     gtk_color_button_set_color (GTK_COLOR_BUTTON (lookup_widget (prefwin, "listview_cursor")), (gtkui_get_listview_cursor_color (&clr), &clr));
127 }
128 
129 static void
unescape_forward_slash(const char * src,char * dst,int size)130 unescape_forward_slash (const char *src, char *dst, int size) {
131     char *start = dst;
132     while (*src) {
133         if (dst - start >= size - 1) {
134             break;
135         }
136         if (*src == '\\' && *(src+1) == '/') {
137             src++;
138         }
139         *dst++ = *src++;
140     }
141     *dst = 0;
142 }
143 
144 void
gtkui_run_preferences_dlg(void)145 gtkui_run_preferences_dlg (void) {
146     if (prefwin) {
147         return;
148     }
149     deadbeef->conf_lock ();
150     GtkWidget *w = prefwin = create_prefwin ();
151     gtk_window_set_transient_for (GTK_WINDOW (w), GTK_WINDOW (mainwin));
152 
153     GtkComboBox *combobox = NULL;
154 
155     // output plugin selection
156     combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_output_plugin"));
157 
158     const char *outplugname = deadbeef->conf_get_str_fast ("output_plugin", "ALSA output plugin");
159     DB_output_t **out_plugs = deadbeef->plug_get_output_list ();
160     for (int i = 0; out_plugs[i]; i++) {
161         gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combobox), out_plugs[i]->plugin.name);
162         if (!strcmp (outplugname, out_plugs[i]->plugin.name)) {
163             gtk_combo_box_set_active (combobox, i);
164         }
165     }
166 
167     // soundcard (output device) selection
168     preferences_fill_soundcards ();
169 
170     g_signal_connect ((gpointer) combobox, "changed",
171             G_CALLBACK (on_pref_output_plugin_changed),
172             NULL);
173     GtkWidget *pref_soundcard = lookup_widget (prefwin, "pref_soundcard");
174     g_signal_connect ((gpointer) pref_soundcard, "changed",
175             G_CALLBACK (on_pref_soundcard_changed),
176             NULL);
177 
178     // replaygain_mode
179     combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_replaygain_mode"));
180     gtk_combo_box_set_active (combobox, deadbeef->conf_get_int ("replaygain_mode", 0));
181 
182     // replaygain_scale
183     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_replaygain_scale")), deadbeef->conf_get_int ("replaygain_scale", 1));
184 
185     // replaygain_preamp
186     gtk_range_set_value (GTK_RANGE (lookup_widget (w, "replaygain_preamp")), deadbeef->conf_get_int ("replaygain_preamp", 0));
187 
188     // global_preamp
189     gtk_range_set_value (GTK_RANGE (lookup_widget (w, "global_preamp")), deadbeef->conf_get_int ("global_preamp", 0));
190 
191     // 8_to_16
192     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "convert8to16")), deadbeef->conf_get_int ("streamer.8_to_16", 1));
193 
194     // 16_to_24
195     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "convert16to24")), deadbeef->conf_get_int ("streamer.16_to_24", 0));
196 
197     // dsp
198     dsp_setup_init (prefwin);
199 
200     // close_send_to_tray
201     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_close_send_to_tray")), deadbeef->conf_get_int ("close_send_to_tray", 0));
202 
203     // hide tray icon
204     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "hide_tray_icon")), deadbeef->conf_get_int ("gtkui.hide_tray_icon", 0));
205 
206     // mmb_delete_playlist
207     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "mmb_delete_playlist")), deadbeef->conf_get_int ("gtkui.mmb_delete_playlist", 1));
208 
209     // hide_delete_from_disk
210     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "hide_delete_from_disk")), deadbeef->conf_get_int ("gtkui.hide_remove_from_disk", 0));
211 
212     // auto-rename playlist from folder name
213     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "auto_name_playlist_from_folder")), deadbeef->conf_get_int ("gtkui.name_playlist_from_folder", 1));
214 
215     // refresh rate
216     int val = deadbeef->conf_get_int ("gtkui.refresh_rate", 10);
217     gtk_range_set_value (GTK_RANGE (lookup_widget (w, "gui_fps")), val);
218 
219     // add from archives
220     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "ignore_archives")), deadbeef->conf_get_int ("ignore_archives", 1));
221 
222     // reset autostop
223     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "reset_autostop")), deadbeef->conf_get_int ("playlist.stop_after_current_reset", 0));
224 
225     // reset album autostop
226     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "reset_autostopalbum")), deadbeef->conf_get_int ("playlist.stop_after_album_reset", 0));
227 
228     // titlebar text
229     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "titlebar_format_playing")), deadbeef->conf_get_str_fast ("gtkui.titlebar_playing_tf", gtkui_default_titlebar_playing));
230     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "titlebar_format_stopped")), deadbeef->conf_get_str_fast ("gtkui.titlebar_stopped_tf", gtkui_default_titlebar_stopped));
231 
232     // cli playlist
233     int active = deadbeef->conf_get_int ("cli_add_to_specific_playlist", 1);
234     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "cli_add_to_playlist")), active);
235     gtk_widget_set_sensitive (lookup_widget (prefwin, "cli_playlist_name"), active);
236     gtk_entry_set_text (GTK_ENTRY (lookup_widget (prefwin, "cli_playlist_name")), deadbeef->conf_get_str_fast ("cli_add_playlist_name", "Default"));
237 
238     // resume last session
239     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "resume_last_session")), deadbeef->conf_get_int ("resume_last_session", 0));
240 
241     // enable shift-jis recoding
242     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "enable_shift_jis_recoding")), deadbeef->conf_get_int ("junk.enable_shift_jis_detection", 0));
243 
244     // enable cp1251 recoding
245     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "enable_cp1251_recoding")), deadbeef->conf_get_int ("junk.enable_cp1251_detection", 1));
246 
247     // enable cp936 recoding
248     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "enable_cp936_recoding")), deadbeef->conf_get_int ("junk.enable_cp936_detection", 0));
249 
250     // enable auto-sizing of columns
251     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "auto_size_columns")), deadbeef->conf_get_int ("gtkui.autoresize_columns", 0));
252 
253     // fill gui plugin list
254     combobox = GTK_COMBO_BOX (lookup_widget (w, "gui_plugin"));
255     const char **names = deadbeef->plug_get_gui_names ();
256     for (int i = 0; names[i]; i++) {
257         gtk_combo_box_text_append_text (GTK_COMBO_BOX_TEXT (combobox), names[i]);
258         if (!strcmp (names[i], deadbeef->conf_get_str_fast ("gui_plugin", "GTK2"))) {
259             gtk_combo_box_set_active (combobox, i);
260         }
261     }
262 
263     // override bar colors
264     int override = deadbeef->conf_get_int ("gtkui.override_bar_colors", 0);
265     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "override_bar_colors")), override);
266     gtk_widget_set_sensitive (lookup_widget (prefwin, "bar_colors_group"), override);
267 
268     // override tabstrip colors
269     override = deadbeef->conf_get_int ("gtkui.override_tabstrip_colors", 0);
270     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "override_tabstrip_colors")), override);
271     gtk_widget_set_sensitive (lookup_widget (prefwin, "tabstrip_colors_group"), override);
272 
273     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "tabstrip_playing_bold")), deadbeef->conf_get_int ("gtkui.tabstrip_embolden_playing", 0));
274     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "tabstrip_playing_italic")), deadbeef->conf_get_int ("gtkui.tabstrip_italic_playing", 0));
275     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "tabstrip_selected_bold")), deadbeef->conf_get_int ("gtkui.tabstrip_embolden_selected", 0));
276     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "tabstrip_selected_italic")), deadbeef->conf_get_int ("gtkui.tabstrip_italic_selected", 0));
277 
278     // get default gtk font
279     GtkStyle *style = gtk_widget_get_style (mainwin);
280     const char *gtk_style_font = pango_font_description_to_string (style->font_desc);
281 
282     gtk_font_button_set_font_name (GTK_FONT_BUTTON (lookup_widget (w, "tabstrip_text_font")), deadbeef->conf_get_str_fast ("gtkui.font.tabstrip_text", gtk_style_font));
283 
284     // override listview colors
285     override = deadbeef->conf_get_int ("gtkui.override_listview_colors", 0);
286     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (prefwin, "override_listview_colors")), override);
287     gtk_widget_set_sensitive (lookup_widget (prefwin, "listview_colors_group"), override);
288 
289     // embolden/italic listview text
290     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "listview_selected_text_bold")), deadbeef->conf_get_int ("gtkui.embolden_selected_tracks", 0));
291     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "listview_selected_text_italic")), deadbeef->conf_get_int ("gtkui.italic_selected_tracks", 0));
292     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "listview_playing_text_bold")), deadbeef->conf_get_int ("gtkui.embolden_current_track", 0));
293     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "listview_playing_text_italic")), deadbeef->conf_get_int ("gtkui.italic_current_track", 0));
294 
295     gtk_font_button_set_font_name (GTK_FONT_BUTTON (lookup_widget (w, "listview_text_font")), deadbeef->conf_get_str_fast ("gtkui.font.listview_text", gtk_style_font));
296     gtk_font_button_set_font_name (GTK_FONT_BUTTON (lookup_widget (w, "listview_group_text_font")), deadbeef->conf_get_str_fast ("gtkui.font.listview_group_text", gtk_style_font));
297     gtk_font_button_set_font_name (GTK_FONT_BUTTON (lookup_widget (w, "listview_column_text_font")), deadbeef->conf_get_str_fast ("gtkui.font.listview_column_text", gtk_style_font));
298 
299     // colors
300     prefwin_init_theme_colors ();
301 
302     // network
303     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (lookup_widget (w, "pref_network_enableproxy")), deadbeef->conf_get_int ("network.proxy", 0));
304     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "pref_network_proxyaddress")), deadbeef->conf_get_str_fast ("network.proxy.address", ""));
305     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "pref_network_proxyport")), deadbeef->conf_get_str_fast ("network.proxy.port", "8080"));
306     combobox = GTK_COMBO_BOX (lookup_widget (w, "pref_network_proxytype"));
307     const char *type = deadbeef->conf_get_str_fast ("network.proxy.type", "HTTP");
308     if (!strcasecmp (type, "HTTP")) {
309         gtk_combo_box_set_active (combobox, 0);
310     }
311     else if (!strcasecmp (type, "HTTP_1_0")) {
312         gtk_combo_box_set_active (combobox, 1);
313     }
314     else if (!strcasecmp (type, "SOCKS4")) {
315         gtk_combo_box_set_active (combobox, 2);
316     }
317     else if (!strcasecmp (type, "SOCKS5")) {
318         gtk_combo_box_set_active (combobox, 3);
319     }
320     else if (!strcasecmp (type, "SOCKS4A")) {
321         gtk_combo_box_set_active (combobox, 4);
322     }
323     else if (!strcasecmp (type, "SOCKS5_HOSTNAME")) {
324         gtk_combo_box_set_active (combobox, 5);
325     }
326     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "proxyuser")), deadbeef->conf_get_str_fast ("network.proxy.username", ""));
327     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "proxypassword")), deadbeef->conf_get_str_fast ("network.proxy.password", ""));
328 
329     char ua[100];
330     deadbeef->conf_get_str ("network.http_user_agent", "deadbeef", ua, sizeof (ua));
331     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "useragent")), ua);
332 
333     // list of plugins
334     GtkTreeView *tree = GTK_TREE_VIEW (lookup_widget (w, "pref_pluginlist"));
335     GtkCellRenderer *rend_text = gtk_cell_renderer_text_new ();
336 #if 0
337     GtkCellRenderer *rend_toggle = gtk_cell_renderer_toggle_new ();
338     GtkListStore *store = gtk_list_store_new (3, G_TYPE_BOOLEAN, G_TYPE_STRING, G_TYPE_BOOLEAN);
339     g_signal_connect ((gpointer)rend_toggle, "toggled",
340             G_CALLBACK (on_plugin_active_toggled),
341             store);
342     GtkTreeViewColumn *col1 = gtk_tree_view_column_new_with_attributes ("Active", rend_toggle, "active", 0, "activatable", 2, NULL);
343     GtkTreeViewColumn *col2 = gtk_tree_view_column_new_with_attributes ("Title", rend_text, "text", 1, NULL);
344     gtk_tree_view_append_column (tree, col1);
345     gtk_tree_view_append_column (tree, col2);
346     DB_plugin_t **plugins = deadbeef->plug_get_list ();
347     int i;
348     for (i = 0; plugins[i]; i++) {
349         GtkTreeIter it;
350         gtk_list_store_append (store, &it);
351         gtk_list_store_set (store, &it, 0, plugins[i]->inactive ? FALSE : TRUE, 1, plugins[i]->name, 2, plugins[i]->nostop ? FALSE : TRUE, -1);
352     }
353 #else
354     GtkListStore *store = gtk_list_store_new (1, G_TYPE_STRING);
355     GtkTreeViewColumn *col2 = gtk_tree_view_column_new_with_attributes (_("Title"), rend_text, "text", 0, NULL);
356     gtk_tree_view_append_column (tree, col2);
357     DB_plugin_t **plugins = deadbeef->plug_get_list ();
358     int i;
359     for (i = 0; plugins[i]; i++) {
360         GtkTreeIter it;
361         gtk_list_store_append (store, &it);
362         gtk_list_store_set (store, &it, 0, plugins[i]->name, -1);
363     }
364 #endif
365     gtk_tree_view_set_model (tree, GTK_TREE_MODEL (store));
366 
367     gtk_widget_set_sensitive (lookup_widget (prefwin, "configure_plugin"), FALSE);
368 
369     // hotkeys
370     prefwin_init_hotkeys (prefwin);
371 
372     deadbeef->conf_unlock ();
373     for (;;) {
374         gtk_dialog_run (GTK_DIALOG (prefwin));
375         if (gtkui_hotkeys_changed) {
376             GtkWidget *dlg = gtk_message_dialog_new (GTK_WINDOW (prefwin), GTK_DIALOG_MODAL, GTK_MESSAGE_WARNING, GTK_BUTTONS_YES_NO, _("You modified the hotkeys settings, but didn't save your changes."));
377             gtk_window_set_transient_for (GTK_WINDOW (dlg), GTK_WINDOW (prefwin));
378             gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dlg), _("Are you sure you want to continue without saving?"));
379             gtk_window_set_title (GTK_WINDOW (dlg), _("Warning"));
380             int response = gtk_dialog_run (GTK_DIALOG (dlg));
381             gtk_widget_destroy (dlg);
382             if (response == GTK_RESPONSE_YES) {
383                 break;
384             }
385         }
386         else {
387             break;
388         }
389     }
390     dsp_setup_free ();
391     gtk_widget_destroy (prefwin);
392     deadbeef->conf_save ();
393     prefwin = NULL;
394 }
395 
396 void
on_pref_soundcard_changed(GtkComboBox * combobox,gpointer user_data)397 on_pref_soundcard_changed              (GtkComboBox     *combobox,
398                                         gpointer         user_data)
399 {
400     int active = gtk_combo_box_get_active (combobox);
401     if (active >= 0 && active < num_alsa_devices) {
402         deadbeef->conf_lock ();
403         const char *soundcard = deadbeef->conf_get_str_fast ("alsa_soundcard", "default");
404         if (strcmp (soundcard, alsa_device_names[active])) {
405             deadbeef->conf_set_str ("alsa_soundcard", alsa_device_names[active]);
406             deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
407         }
408         deadbeef->conf_unlock ();
409     }
410 }
411 
412 void
on_pref_output_plugin_changed(GtkComboBox * combobox,gpointer user_data)413 on_pref_output_plugin_changed          (GtkComboBox     *combobox,
414                                         gpointer         user_data)
415 {
416     int active = gtk_combo_box_get_active (combobox);
417 
418     DB_output_t **out_plugs = deadbeef->plug_get_output_list ();
419     DB_output_t *prev = NULL;
420     DB_output_t *new = NULL;
421 
422     deadbeef->conf_lock ();
423     const char *outplugname = deadbeef->conf_get_str_fast ("output_plugin", "ALSA output plugin");
424     for (int i = 0; out_plugs[i]; i++) {
425         if (!strcmp (out_plugs[i]->plugin.name, outplugname)) {
426             prev = out_plugs[i];
427         }
428         if (i == active) {
429             new = out_plugs[i];
430         }
431     }
432     deadbeef->conf_unlock ();
433 
434     if (!new) {
435         fprintf (stderr, "failed to find output plugin selected in preferences window\n");
436     }
437     else {
438         if (prev != new) {
439             deadbeef->conf_set_str ("output_plugin", new->plugin.name);
440             deadbeef->sendmessage (DB_EV_REINIT_SOUND, 0, 0, 0);
441         }
442     }
443 }
444 
445 void
on_pref_replaygain_mode_changed(GtkComboBox * combobox,gpointer user_data)446 on_pref_replaygain_mode_changed        (GtkComboBox     *combobox,
447                                         gpointer         user_data)
448 {
449     int active = gtk_combo_box_get_active (combobox);
450     deadbeef->conf_set_int ("replaygain_mode", active == -1 ? 0 : active);
451     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
452 }
453 
454 void
on_pref_replaygain_scale_clicked(GtkButton * button,gpointer user_data)455 on_pref_replaygain_scale_clicked       (GtkButton       *button,
456                                         gpointer         user_data)
457 {
458     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
459     deadbeef->conf_set_int ("replaygain_scale", active);
460     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
461 }
462 
463 void
on_replaygain_preamp_value_changed(GtkRange * range,gpointer user_data)464 on_replaygain_preamp_value_changed     (GtkRange        *range,
465                                         gpointer         user_data)
466 {
467     float val = gtk_range_get_value (range);
468     deadbeef->conf_set_float ("replaygain_preamp", val);
469     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
470 }
471 
472 void
on_global_preamp_value_changed(GtkRange * range,gpointer user_data)473 on_global_preamp_value_changed     (GtkRange        *range,
474                                     gpointer         user_data)
475 {
476     float val = gtk_range_get_value (range);
477     deadbeef->conf_set_float ("global_preamp", val);
478     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
479 }
480 
481 void
on_pref_close_send_to_tray_clicked(GtkButton * button,gpointer user_data)482 on_pref_close_send_to_tray_clicked     (GtkButton       *button,
483                                         gpointer         user_data)
484 {
485     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
486     deadbeef->conf_set_int ("close_send_to_tray", active);
487     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
488 }
489 
490 void
on_hide_tray_icon_toggled(GtkToggleButton * togglebutton,gpointer user_data)491 on_hide_tray_icon_toggled              (GtkToggleButton *togglebutton,
492                                         gpointer         user_data)
493 {
494     int active = gtk_toggle_button_get_active (togglebutton);
495     deadbeef->conf_set_int ("gtkui.hide_tray_icon", active);
496     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
497 }
498 
499 void
on_mmb_delete_playlist_toggled(GtkToggleButton * togglebutton,gpointer user_data)500 on_mmb_delete_playlist_toggled         (GtkToggleButton *togglebutton,
501                                         gpointer         user_data)
502 {
503     deadbeef->conf_set_int ("gtkui.mmb_delete_playlist", gtk_toggle_button_get_active (togglebutton));
504 }
505 
506 void
on_pref_pluginlist_cursor_changed(GtkTreeView * treeview,gpointer user_data)507 on_pref_pluginlist_cursor_changed      (GtkTreeView     *treeview,
508                                         gpointer         user_data)
509 {
510     GtkTreePath *path;
511     GtkTreeViewColumn *col;
512     gtk_tree_view_get_cursor (treeview, &path, &col);
513     if (!path || !col) {
514         // reset
515         return;
516     }
517     int *indices = gtk_tree_path_get_indices (path);
518     DB_plugin_t **plugins = deadbeef->plug_get_list ();
519     DB_plugin_t *p = plugins[*indices];
520     g_free (indices);
521     assert (p);
522     GtkWidget *w = prefwin;
523     assert (w);
524 
525     char s[20];
526     snprintf (s, sizeof (s), "%d.%d", p->version_major, p->version_minor);
527     gtk_entry_set_text (GTK_ENTRY (lookup_widget (w, "plug_version")), s);
528 
529     if (p->descr) {
530         GtkTextView *tv = GTK_TEXT_VIEW (lookup_widget (w, "plug_description"));
531 
532         GtkTextBuffer *buffer = gtk_text_buffer_new (NULL);
533 
534         gtk_text_buffer_set_text (buffer, p->descr, strlen(p->descr));
535         gtk_text_view_set_buffer (GTK_TEXT_VIEW (tv), buffer);
536         g_object_unref (buffer);
537     }
538 
539     GtkWidget *link = lookup_widget (w, "weblink");
540     if (p->website) {
541         gtk_link_button_set_uri (GTK_LINK_BUTTON(link), p->website);
542         gtk_widget_set_sensitive (link, TRUE);
543     }
544     else {
545         gtk_link_button_set_uri (GTK_LINK_BUTTON(link), "");
546         gtk_widget_set_sensitive (link, FALSE);
547     }
548 
549     GtkWidget *cpr = lookup_widget (w, "plug_copyright");
550     if (p->copyright) {
551         gtk_widget_set_sensitive (cpr, TRUE);
552     }
553     else {
554         gtk_widget_set_sensitive (cpr, FALSE);
555     }
556 
557     gtk_widget_set_sensitive (lookup_widget (prefwin, "configure_plugin"), p->configdialog ? TRUE : FALSE);
558 }
559 
560 void
gtkui_conf_get_str(const char * key,char * value,int len,const char * def)561 gtkui_conf_get_str (const char *key, char *value, int len, const char *def) {
562     deadbeef->conf_get_str (key, def, value, len);
563 }
564 
565 void
on_configure_plugin_clicked(GtkButton * button,gpointer user_data)566 on_configure_plugin_clicked            (GtkButton       *button,
567                                         gpointer         user_data)
568 {
569     GtkWidget *w = prefwin;
570     GtkTreeView *treeview = GTK_TREE_VIEW (lookup_widget (w, "pref_pluginlist"));
571     GtkTreePath *path;
572     GtkTreeViewColumn *col;
573     gtk_tree_view_get_cursor (treeview, &path, &col);
574     if (!path || !col) {
575         // reset
576         return;
577     }
578     int *indices = gtk_tree_path_get_indices (path);
579     DB_plugin_t **plugins = deadbeef->plug_get_list ();
580     DB_plugin_t *p = plugins[*indices];
581     if (p->configdialog) {
582         ddb_dialog_t conf = {
583             .title = p->name,
584             .layout = p->configdialog,
585             .set_param = deadbeef->conf_set_str,
586             .get_param = gtkui_conf_get_str,
587         };
588         gtkui_run_dialog (prefwin, &conf, 0, NULL, NULL);
589     }
590 }
591 
592 static void
color_set_helper(GtkColorButton * colorbutton,gpointer user_data,const char * conf_str)593 color_set_helper (GtkColorButton  *colorbutton, gpointer user_data, const char* conf_str)
594 {
595     if (conf_str == NULL) {
596         return;
597     }
598     GdkColor clr;
599     gtk_color_button_get_color (colorbutton, &clr);
600     char str[100];
601     snprintf (str, sizeof (str), "%d %d %d", clr.red, clr.green, clr.blue);
602     deadbeef->conf_set_str (conf_str, str);
603     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
604     gtkui_init_theme_colors ();
605     gtk_widget_queue_draw (mainwin);
606 }
607 void
on_tabstrip_light_color_set(GtkColorButton * colorbutton,gpointer user_data)608 on_tabstrip_light_color_set            (GtkColorButton  *colorbutton,
609                                         gpointer         user_data)
610 {
611     color_set_helper (colorbutton, user_data, "gtkui.color.tabstrip_light");
612 }
613 
614 
615 void
on_tabstrip_mid_color_set(GtkColorButton * colorbutton,gpointer user_data)616 on_tabstrip_mid_color_set              (GtkColorButton  *colorbutton,
617                                         gpointer         user_data)
618 {
619     color_set_helper (colorbutton, user_data, "gtkui.color.tabstrip_mid");
620 }
621 
622 
623 void
on_tabstrip_dark_color_set(GtkColorButton * colorbutton,gpointer user_data)624 on_tabstrip_dark_color_set             (GtkColorButton  *colorbutton,
625                                         gpointer         user_data)
626 {
627     color_set_helper (colorbutton, user_data, "gtkui.color.tabstrip_dark");
628 }
629 
630 void
on_tabstrip_base_color_set(GtkColorButton * colorbutton,gpointer user_data)631 on_tabstrip_base_color_set             (GtkColorButton  *colorbutton,
632                                         gpointer         user_data)
633 {
634     color_set_helper (colorbutton, user_data, "gtkui.color.tabstrip_base");
635 }
636 
637 void
on_tabstrip_text_color_set(GtkColorButton * colorbutton,gpointer user_data)638 on_tabstrip_text_color_set             (GtkColorButton  *colorbutton,
639                                         gpointer         user_data)
640 {
641     color_set_helper (colorbutton, user_data, "gtkui.color.tabstrip_text");
642 }
643 
644 void
on_tabstrip_selected_text_color_set(GtkColorButton * colorbutton,gpointer user_data)645 on_tabstrip_selected_text_color_set    (GtkColorButton  *colorbutton,
646                                         gpointer         user_data)
647 {
648     color_set_helper (colorbutton, user_data, "gtkui.color.tabstrip_selected_text");
649 }
650 
651 void
on_tabstrip_playing_bold_toggled(GtkToggleButton * togglebutton,gpointer user_data)652 on_tabstrip_playing_bold_toggled       (GtkToggleButton *togglebutton,
653                                         gpointer         user_data)
654 {
655     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
656     deadbeef->conf_set_int ("gtkui.tabstrip_embolden_playing", active);
657     gtkui_tabstrip_embolden_playing = active;
658     playlist_refresh ();
659     gtk_widget_queue_draw (mainwin);
660 }
661 
662 void
on_tabstrip_playing_italic_toggled(GtkToggleButton * togglebutton,gpointer user_data)663 on_tabstrip_playing_italic_toggled     (GtkToggleButton *togglebutton,
664                                         gpointer         user_data)
665 {
666     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
667     deadbeef->conf_set_int ("gtkui.tabstrip_italic_playing", active);
668     gtkui_tabstrip_italic_playing = active;
669     playlist_refresh ();
670     gtk_widget_queue_draw (mainwin);
671 }
672 
673 void
on_tabstrip_selected_bold_toggled(GtkToggleButton * togglebutton,gpointer user_data)674 on_tabstrip_selected_bold_toggled      (GtkToggleButton *togglebutton,
675                                         gpointer         user_data)
676 {
677     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
678     deadbeef->conf_set_int ("gtkui.tabstrip_embolden_selected", active);
679     gtkui_tabstrip_embolden_selected = active;
680     playlist_refresh ();
681     gtk_widget_queue_draw (mainwin);
682 }
683 
684 void
on_tabstrip_selected_italic_toggled(GtkToggleButton * togglebutton,gpointer user_data)685 on_tabstrip_selected_italic_toggled    (GtkToggleButton *togglebutton,
686                                         gpointer         user_data)
687 {
688     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
689     deadbeef->conf_set_int ("gtkui.tabstrip_italic_selected", active);
690     gtkui_tabstrip_italic_selected = active;
691     playlist_refresh ();
692     gtk_widget_queue_draw (mainwin);
693 }
694 
695 void
on_tabstrip_text_font_set(GtkFontButton * fontbutton,gpointer user_data)696 on_tabstrip_text_font_set              (GtkFontButton   *fontbutton,
697                                         gpointer         user_data)
698 {
699     deadbeef->conf_set_str ("gtkui.font.tabstrip_text", gtk_font_button_get_font_name (fontbutton));
700     gtkui_init_theme_colors ();
701     playlist_refresh ();
702     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
703     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
704     gtk_widget_queue_draw (mainwin);
705 }
706 
707 void
on_tabstrip_playing_text_color_set(GtkColorButton * colorbutton,gpointer user_data)708 on_tabstrip_playing_text_color_set     (GtkColorButton  *colorbutton,
709                                         gpointer         user_data)
710 {
711     color_set_helper (colorbutton, user_data, "gtkui.color.tabstrip_playing_text");
712 }
713 
714 void
on_bar_foreground_color_set(GtkColorButton * colorbutton,gpointer user_data)715 on_bar_foreground_color_set            (GtkColorButton  *colorbutton,
716                                         gpointer         user_data)
717 {
718     color_set_helper (colorbutton, user_data, "gtkui.color.bar_foreground");
719 }
720 
721 
722 void
on_bar_background_color_set(GtkColorButton * colorbutton,gpointer user_data)723 on_bar_background_color_set            (GtkColorButton  *colorbutton,
724                                         gpointer         user_data)
725 {
726     color_set_helper (colorbutton, user_data, "gtkui.color.bar_background");
727 }
728 
729 void
on_override_listview_colors_toggled(GtkToggleButton * togglebutton,gpointer user_data)730 on_override_listview_colors_toggled    (GtkToggleButton *togglebutton,
731                                         gpointer         user_data)
732 {
733     int active = gtk_toggle_button_get_active (togglebutton);
734     deadbeef->conf_set_int ("gtkui.override_listview_colors", active);
735     gtk_widget_set_sensitive (lookup_widget (prefwin, "listview_colors_group"), active);
736     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
737     gtkui_init_theme_colors ();
738     prefwin_init_theme_colors ();
739     playlist_refresh ();
740     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
741     gtk_widget_queue_draw (mainwin);
742 }
743 
744 
745 void
on_listview_even_row_color_set(GtkColorButton * colorbutton,gpointer user_data)746 on_listview_even_row_color_set         (GtkColorButton  *colorbutton,
747                                         gpointer         user_data)
748 {
749     color_set_helper (colorbutton, user_data, "gtkui.color.listview_even_row");
750     playlist_refresh ();
751     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
752 }
753 
754 void
on_listview_odd_row_color_set(GtkColorButton * colorbutton,gpointer user_data)755 on_listview_odd_row_color_set          (GtkColorButton  *colorbutton,
756                                         gpointer         user_data)
757 {
758     color_set_helper (colorbutton, user_data, "gtkui.color.listview_odd_row");
759     playlist_refresh ();
760     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
761 }
762 
763 void
on_listview_selected_row_color_set(GtkColorButton * colorbutton,gpointer user_data)764 on_listview_selected_row_color_set     (GtkColorButton  *colorbutton,
765                                         gpointer         user_data)
766 {
767     color_set_helper (colorbutton, user_data, "gtkui.color.listview_selection");
768     playlist_refresh ();
769     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
770 }
771 
772 void
on_listview_text_color_set(GtkColorButton * colorbutton,gpointer user_data)773 on_listview_text_color_set             (GtkColorButton  *colorbutton,
774                                         gpointer         user_data)
775 {
776     color_set_helper (colorbutton, user_data, "gtkui.color.listview_text");
777     playlist_refresh ();
778     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
779 }
780 
781 
782 void
on_listview_selected_text_color_set(GtkColorButton * colorbutton,gpointer user_data)783 on_listview_selected_text_color_set    (GtkColorButton  *colorbutton,
784                                         gpointer         user_data)
785 {
786     color_set_helper (colorbutton, user_data, "gtkui.color.listview_selected_text");
787     playlist_refresh ();
788     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
789 }
790 
791 void
on_listview_cursor_color_set(GtkColorButton * colorbutton,gpointer user_data)792 on_listview_cursor_color_set           (GtkColorButton  *colorbutton,
793                                         gpointer         user_data)
794 {
795     color_set_helper (colorbutton, user_data, "gtkui.color.listview_cursor");
796     playlist_refresh ();
797     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
798 }
799 
800 void
on_listview_playing_text_color_set(GtkColorButton * colorbutton,gpointer user_data)801 on_listview_playing_text_color_set     (GtkColorButton  *colorbutton,
802                                         gpointer         user_data)
803 {
804     color_set_helper (colorbutton, user_data, "gtkui.color.listview_playing_text");
805     playlist_refresh ();
806     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
807 }
808 
809 void
on_listview_group_text_color_set(GtkColorButton * colorbutton,gpointer user_data)810 on_listview_group_text_color_set       (GtkColorButton  *colorbutton,
811                                         gpointer         user_data)
812 {
813     color_set_helper (colorbutton, user_data, "gtkui.color.listview_group_text");
814     playlist_refresh ();
815     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
816     gtk_widget_queue_draw (mainwin);
817 }
818 
819 void
on_listview_group_text_font_set(GtkFontButton * fontbutton,gpointer user_data)820 on_listview_group_text_font_set        (GtkFontButton   *fontbutton,
821                                         gpointer         user_data)
822 {
823     deadbeef->conf_set_str ("gtkui.font.listview_group_text", gtk_font_button_get_font_name (fontbutton));
824     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
825     gtkui_init_theme_colors ();
826     playlist_refresh ();
827     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
828     gtk_widget_queue_draw (mainwin);
829 }
830 
831 void
on_listview_text_font_set(GtkFontButton * fontbutton,gpointer user_data)832 on_listview_text_font_set              (GtkFontButton   *fontbutton,
833                                         gpointer         user_data)
834 {
835     deadbeef->conf_set_str ("gtkui.font.listview_text", gtk_font_button_get_font_name (fontbutton));
836     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
837     gtkui_init_theme_colors ();
838     playlist_refresh ();
839     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
840     gtk_widget_queue_draw (mainwin);
841 }
842 
843 void
on_listview_playing_text_bold_toggled(GtkToggleButton * togglebutton,gpointer user_data)844 on_listview_playing_text_bold_toggled  (GtkToggleButton *togglebutton,
845                                         gpointer         user_data)
846 {
847     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
848     deadbeef->conf_set_int ("gtkui.embolden_current_track", active);
849     gtkui_embolden_current_track = active;
850     playlist_refresh ();
851     gtk_widget_queue_draw (mainwin);
852 }
853 
854 void
on_listview_playing_text_italic_toggled(GtkToggleButton * togglebutton,gpointer user_data)855 on_listview_playing_text_italic_toggled (GtkToggleButton *togglebutton,
856                                         gpointer         user_data)
857 {
858     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
859     deadbeef->conf_set_int ("gtkui.italic_current_track", active);
860     gtkui_italic_current_track = active;
861     playlist_refresh ();
862     gtk_widget_queue_draw (mainwin);
863 }
864 
865 void
on_listview_selected_text_bold_toggled(GtkToggleButton * togglebutton,gpointer user_data)866 on_listview_selected_text_bold_toggled (GtkToggleButton *togglebutton,
867                                         gpointer         user_data)
868 {
869     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
870     deadbeef->conf_set_int ("gtkui.embolden_selected_tracks", active);
871     gtkui_embolden_selected_tracks = active;
872     playlist_refresh ();
873     gtk_widget_queue_draw (mainwin);
874 }
875 
876 void
on_listview_selected_text_italic_toggled(GtkToggleButton * togglebutton,gpointer user_data)877 on_listview_selected_text_italic_toggled (GtkToggleButton *togglebutton,
878                                         gpointer         user_data)
879 {
880     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
881     deadbeef->conf_set_int ("gtkui.italic_selected_tracks", active);
882     gtkui_italic_selected_tracks = active;
883     playlist_refresh ();
884     gtk_widget_queue_draw (mainwin);
885 }
886 
887 void
on_listview_column_text_color_set(GtkColorButton * colorbutton,gpointer user_data)888 on_listview_column_text_color_set      (GtkColorButton  *colorbutton,
889                                         gpointer         user_data)
890 {
891     color_set_helper (colorbutton, user_data, "gtkui.color.listview_column_text");
892     playlist_refresh ();
893     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
894 }
895 
896 void
on_listview_column_text_font_set(GtkFontButton * fontbutton,gpointer user_data)897 on_listview_column_text_font_set       (GtkFontButton   *fontbutton,
898                                         gpointer         user_data)
899 {
900     deadbeef->conf_set_str ("gtkui.font.listview_column_text", gtk_font_button_get_font_name (fontbutton));
901     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
902     gtkui_init_theme_colors ();
903     playlist_refresh ();
904     deadbeef->sendmessage (DB_EV_PLAYLISTCHANGED, 0, DDB_PLAYLIST_CHANGE_CONTENT, 0);
905 }
906 
907 void
on_override_bar_colors_toggled(GtkToggleButton * togglebutton,gpointer user_data)908 on_override_bar_colors_toggled         (GtkToggleButton *togglebutton,
909                                         gpointer         user_data)
910 {
911     int active = gtk_toggle_button_get_active (togglebutton);
912     deadbeef->conf_set_int ("gtkui.override_bar_colors", active);
913     gtk_widget_set_sensitive (lookup_widget (prefwin, "bar_colors_group"), active);
914     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
915     gtkui_init_theme_colors ();
916     prefwin_init_theme_colors ();
917     eq_redraw ();
918 }
919 
920 void
on_override_tabstrip_colors_toggled(GtkToggleButton * togglebutton,gpointer user_data)921 on_override_tabstrip_colors_toggled    (GtkToggleButton *togglebutton,
922                                         gpointer         user_data)
923 {
924     int active = gtk_toggle_button_get_active (togglebutton);
925     deadbeef->conf_set_int ("gtkui.override_tabstrip_colors", active);
926     gtk_widget_set_sensitive (lookup_widget (prefwin, "tabstrip_colors_group"), active);
927     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
928     gtkui_init_theme_colors ();
929     prefwin_init_theme_colors ();
930     gtk_widget_queue_draw (mainwin);
931 }
932 
933 void
on_pref_network_proxyaddress_changed(GtkEditable * editable,gpointer user_data)934 on_pref_network_proxyaddress_changed   (GtkEditable     *editable,
935                                         gpointer         user_data)
936 {
937     deadbeef->conf_set_str ("network.proxy.address", gtk_entry_get_text (GTK_ENTRY (editable)));
938 }
939 
940 
941 void
on_pref_network_enableproxy_clicked(GtkButton * button,gpointer user_data)942 on_pref_network_enableproxy_clicked    (GtkButton       *button,
943                                         gpointer         user_data)
944 {
945     deadbeef->conf_set_int ("network.proxy", gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
946 }
947 
948 
949 void
on_pref_network_proxyport_changed(GtkEditable * editable,gpointer user_data)950 on_pref_network_proxyport_changed      (GtkEditable     *editable,
951                                         gpointer         user_data)
952 {
953     deadbeef->conf_set_int ("network.proxy.port", atoi (gtk_entry_get_text (GTK_ENTRY (editable))));
954 }
955 
956 
957 void
on_pref_network_proxytype_changed(GtkComboBox * combobox,gpointer user_data)958 on_pref_network_proxytype_changed      (GtkComboBox     *combobox,
959                                         gpointer         user_data)
960 {
961 
962     int active = gtk_combo_box_get_active (combobox);
963     switch (active) {
964     case 0:
965         deadbeef->conf_set_str ("network.proxy.type", "HTTP");
966         break;
967     case 1:
968         deadbeef->conf_set_str ("network.proxy.type", "HTTP_1_0");
969         break;
970     case 2:
971         deadbeef->conf_set_str ("network.proxy.type", "SOCKS4");
972         break;
973     case 3:
974         deadbeef->conf_set_str ("network.proxy.type", "SOCKS5");
975         break;
976     case 4:
977         deadbeef->conf_set_str ("network.proxy.type", "SOCKS4A");
978         break;
979     case 5:
980         deadbeef->conf_set_str ("network.proxy.type", "SOCKS5_HOSTNAME");
981         break;
982     default:
983         deadbeef->conf_set_str ("network.proxy.type", "HTTP");
984         break;
985     }
986 }
987 
988 void
on_proxyuser_changed(GtkEditable * editable,gpointer user_data)989 on_proxyuser_changed                   (GtkEditable     *editable,
990                                         gpointer         user_data)
991 {
992     deadbeef->conf_set_str ("network.proxy.username", gtk_entry_get_text (GTK_ENTRY (editable)));
993 }
994 
995 
996 void
on_proxypassword_changed(GtkEditable * editable,gpointer user_data)997 on_proxypassword_changed               (GtkEditable     *editable,
998                                         gpointer         user_data)
999 {
1000     deadbeef->conf_set_str ("network.proxy.password", gtk_entry_get_text (GTK_ENTRY (editable)));
1001 }
1002 
1003 void
on_hide_delete_from_disk_toggled(GtkToggleButton * togglebutton,gpointer user_data)1004 on_hide_delete_from_disk_toggled       (GtkToggleButton *togglebutton,
1005                                         gpointer         user_data)
1006 {
1007     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
1008     deadbeef->conf_set_int ("gtkui.hide_remove_from_disk", active);
1009 }
1010 
1011 void
on_titlebar_format_playing_changed(GtkEditable * editable,gpointer user_data)1012 on_titlebar_format_playing_changed     (GtkEditable     *editable,
1013                                         gpointer         user_data)
1014 {
1015     deadbeef->conf_set_str ("gtkui.titlebar_playing_tf", gtk_entry_get_text (GTK_ENTRY (editable)));
1016     gtkui_titlebar_tf_init ();
1017     gtkui_set_titlebar (NULL);
1018 }
1019 
1020 
1021 void
on_titlebar_format_stopped_changed(GtkEditable * editable,gpointer user_data)1022 on_titlebar_format_stopped_changed     (GtkEditable     *editable,
1023                                         gpointer         user_data)
1024 {
1025     deadbeef->conf_set_str ("gtkui.titlebar_stopped_tf", gtk_entry_get_text (GTK_ENTRY (editable)));
1026     gtkui_titlebar_tf_init ();
1027     gtkui_set_titlebar (NULL);
1028 }
1029 
1030 void
on_cli_add_to_playlist_toggled(GtkToggleButton * togglebutton,gpointer user_data)1031 on_cli_add_to_playlist_toggled         (GtkToggleButton *togglebutton,
1032                                         gpointer         user_data)
1033 {
1034     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
1035     deadbeef->conf_set_int ("cli_add_to_specific_playlist", active);
1036     gtk_widget_set_sensitive (lookup_widget (prefwin, "cli_playlist_name"), active);
1037 }
1038 
1039 
1040 void
on_cli_playlist_name_changed(GtkEditable * editable,gpointer user_data)1041 on_cli_playlist_name_changed           (GtkEditable     *editable,
1042                                         gpointer         user_data)
1043 {
1044     deadbeef->conf_set_str ("cli_add_playlist_name", gtk_entry_get_text (GTK_ENTRY (editable)));
1045 }
1046 
1047 void
on_resume_last_session_toggled(GtkToggleButton * togglebutton,gpointer user_data)1048 on_resume_last_session_toggled         (GtkToggleButton *togglebutton,
1049                                         gpointer         user_data)
1050 {
1051     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
1052     deadbeef->conf_set_int ("resume_last_session", active);
1053 }
1054 
1055 void
on_enable_shift_jis_recoding_toggled(GtkToggleButton * togglebutton,gpointer user_data)1056 on_enable_shift_jis_recoding_toggled   (GtkToggleButton *togglebutton,
1057                                         gpointer         user_data)
1058 {
1059     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
1060     deadbeef->conf_set_int ("junk.enable_shift_jis_detection", active);
1061     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
1062 }
1063 
1064 void
on_enable_cp1251_recoding_toggled(GtkToggleButton * togglebutton,gpointer user_data)1065 on_enable_cp1251_recoding_toggled      (GtkToggleButton *togglebutton,
1066                                         gpointer         user_data)
1067 {
1068     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
1069     deadbeef->conf_set_int ("junk.enable_cp1251_detection", active);
1070     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
1071 }
1072 
1073 
1074 void
on_enable_cp936_recoding_toggled(GtkToggleButton * togglebutton,gpointer user_data)1075 on_enable_cp936_recoding_toggled       (GtkToggleButton *togglebutton,
1076                                         gpointer         user_data)
1077 {
1078     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
1079     deadbeef->conf_set_int ("junk.enable_cp936_detection", active);
1080     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
1081 }
1082 
1083 
1084 void
on_auto_name_playlist_from_folder_toggled(GtkToggleButton * togglebutton,gpointer user_data)1085 on_auto_name_playlist_from_folder_toggled
1086                                         (GtkToggleButton *togglebutton,
1087                                         gpointer         user_data)
1088 {
1089     int active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton));
1090     deadbeef->conf_set_int ("gtkui.name_playlist_from_folder", active);
1091 }
1092 
1093 static void
show_copyright_window(const char * text,const char * title,GtkWidget ** pwindow)1094 show_copyright_window (const char *text, const char *title, GtkWidget **pwindow) {
1095     if (*pwindow) {
1096         return;
1097     }
1098     GtkWidget *widget = *pwindow = create_helpwindow ();
1099     g_object_set_data (G_OBJECT (widget), "pointer", pwindow);
1100     g_signal_connect (widget, "delete_event", G_CALLBACK (on_gtkui_info_window_delete), pwindow);
1101     gtk_window_set_title (GTK_WINDOW (widget), title);
1102     gtk_window_set_transient_for (GTK_WINDOW (widget), GTK_WINDOW (prefwin));
1103     GtkWidget *txt = lookup_widget (widget, "helptext");
1104     GtkTextBuffer *buffer = gtk_text_buffer_new (NULL);
1105 
1106     gtk_text_buffer_set_text (buffer, text, strlen(text));
1107     gtk_text_view_set_buffer (GTK_TEXT_VIEW (txt), buffer);
1108     g_object_unref (buffer);
1109     gtk_widget_show (widget);
1110 }
1111 
1112 static GtkWidget *copyright_window;
1113 
1114 void
on_plug_copyright_clicked(GtkButton * button,gpointer user_data)1115 on_plug_copyright_clicked              (GtkButton       *button,
1116                                         gpointer         user_data)
1117 {
1118     GtkTreeView *treeview = GTK_TREE_VIEW(lookup_widget (prefwin, "pref_pluginlist"));
1119     GtkTreePath *path;
1120     GtkTreeViewColumn *col;
1121     gtk_tree_view_get_cursor (treeview, &path, &col);
1122     if (!path || !col) {
1123         // reset
1124         return;
1125     }
1126     int *indices = gtk_tree_path_get_indices (path);
1127     DB_plugin_t **plugins = deadbeef->plug_get_list ();
1128     DB_plugin_t *p = plugins[*indices];
1129     g_free (indices);
1130     assert (p);
1131 
1132     if (p->copyright) {
1133         show_copyright_window (p->copyright, "Copyright", &copyright_window);
1134     }
1135 }
1136 
1137 gboolean
on_prefwin_configure_event(GtkWidget * widget,GdkEventConfigure * event,gpointer user_data)1138 on_prefwin_configure_event             (GtkWidget       *widget,
1139                                         GdkEventConfigure *event,
1140                                         gpointer         user_data)
1141 {
1142     wingeom_save (widget, "prefwin");
1143     return FALSE;
1144 }
1145 
1146 
1147 gboolean
on_prefwin_window_state_event(GtkWidget * widget,GdkEventWindowState * event,gpointer user_data)1148 on_prefwin_window_state_event          (GtkWidget       *widget,
1149                                         GdkEventWindowState *event,
1150                                         gpointer         user_data)
1151 {
1152     wingeom_save_max (event, widget, "prefwin");
1153     return FALSE;
1154 }
1155 
1156 
1157 void
on_prefwin_realize(GtkWidget * widget,gpointer user_data)1158 on_prefwin_realize                     (GtkWidget       *widget,
1159                                         gpointer         user_data)
1160 {
1161     wingeom_restore (widget, "prefwin", -1, -1, -1, -1, 0);
1162 }
1163 
1164 void
on_gui_plugin_changed(GtkComboBox * combobox,gpointer user_data)1165 on_gui_plugin_changed                  (GtkComboBox     *combobox,
1166                                         gpointer         user_data)
1167 {
1168     gchar *txt = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combobox));
1169     if (txt) {
1170         deadbeef->conf_set_str ("gui_plugin", txt);
1171         g_free (txt);
1172     }
1173 }
1174 
1175 void
on_gui_fps_value_changed(GtkRange * range,gpointer user_data)1176 on_gui_fps_value_changed           (GtkRange        *range,
1177                                         gpointer         user_data)
1178 {
1179     int val = gtk_range_get_value (range);
1180     deadbeef->conf_set_int ("gtkui.refresh_rate", val);
1181     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
1182 }
1183 
1184 void
on_ignore_archives_toggled(GtkToggleButton * togglebutton,gpointer user_data)1185 on_ignore_archives_toggled             (GtkToggleButton *togglebutton,
1186                                         gpointer         user_data)
1187 {
1188 
1189     deadbeef->conf_set_int ("ignore_archives", gtk_toggle_button_get_active (togglebutton));
1190 }
1191 
1192 void
on_reset_autostop_toggled(GtkToggleButton * togglebutton,gpointer user_data)1193 on_reset_autostop_toggled              (GtkToggleButton *togglebutton,
1194                                         gpointer         user_data)
1195 {
1196     deadbeef->conf_set_int ("playlist.stop_after_current_reset", gtk_toggle_button_get_active (togglebutton));
1197 }
1198 
1199 void
on_reset_autostopalbum_toggled(GtkToggleButton * togglebutton,gpointer user_data)1200 on_reset_autostopalbum_toggled         (GtkToggleButton *togglebutton,
1201                                         gpointer         user_data)
1202 {
1203     deadbeef->conf_set_int ("playlist.stop_after_album_reset", gtk_toggle_button_get_active (togglebutton));
1204 }
1205 
1206 
1207 
1208 void
on_convert8to16_toggled(GtkToggleButton * togglebutton,gpointer user_data)1209 on_convert8to16_toggled                (GtkToggleButton *togglebutton,
1210                                         gpointer         user_data)
1211 {
1212     deadbeef->conf_set_int ("streamer.8_to_16", gtk_toggle_button_get_active (togglebutton));
1213     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
1214 }
1215 
1216 void
on_convert16to24_toggled(GtkToggleButton * togglebutton,gpointer user_data)1217 on_convert16to24_toggled                (GtkToggleButton *togglebutton,
1218                                         gpointer         user_data)
1219 {
1220     deadbeef->conf_set_int ("streamer.16_to_24", gtk_toggle_button_get_active (togglebutton));
1221     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
1222 }
1223 
1224 void
on_useragent_changed(GtkEditable * editable,gpointer user_data)1225 on_useragent_changed                   (GtkEditable     *editable,
1226                                         gpointer         user_data)
1227 {
1228     deadbeef->conf_set_str ("network.http_user_agent", gtk_entry_get_text (GTK_ENTRY (editable)));
1229     deadbeef->sendmessage (DB_EV_CONFIGCHANGED, 0, 0, 0);
1230 }
1231 
1232 void
on_auto_size_columns_toggled(GtkToggleButton * togglebutton,gpointer user_data)1233 on_auto_size_columns_toggled           (GtkToggleButton *togglebutton,
1234                                         gpointer         user_data)
1235 {
1236     deadbeef->conf_set_int ("gtkui.autoresize_columns", gtk_toggle_button_get_active (togglebutton));
1237 }
1238