comparison Plugins/Output/crossfade/configure.c @ 261:5fd398406cf7 trunk

[svn] Still need to pry internal OSS from clenched fingers. In need of anti-warning love too, but it compiles.
author chainsaw
date Tue, 06 Dec 2005 16:09:32 -0800
parents
children 5410de731c3c
comparison
equal deleted inserted replaced
260:4b1c9d1a469b 261:5fd398406cf7
1
2 /*
3 * XMMS Crossfade Plugin
4 * Copyright (C) 2000-2004 Peter Eisenlohr <peter@eisenlohr.org>
5 *
6 * based on the original OSS Output Plugin
7 * Copyright (C) 1998-2000 Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
22 * USA.
23 */
24
25 #ifdef HAVE_CONFIG_H
26 # include "config.h"
27 #endif
28
29 #undef PRESET_SUPPORT
30
31 #include "crossfade.h"
32 #include "configure.h"
33 #include "interface.h"
34 #include "monitor.h"
35 #include "support.h"
36 #ifdef HAVE_OSS
37 # include "oss.h"
38 #endif
39
40 #include <stdio.h>
41 #include <string.h>
42 #include <stdlib.h>
43 #include <ctype.h>
44
45 #include <fcntl.h>
46 #include <unistd.h>
47 #include <sys/ioctl.h>
48 #include <sys/stat.h>
49
50 #ifdef HAVE_OSS
51 # ifdef HAVE_SYS_SOUNDCARD_H
52 # include <sys/soundcard.h>
53 # elif defined(HAVE_MACHINE_SOUNDCARD_H)
54 # include <machine/soundcard.h>
55 # endif
56 #endif
57
58 #ifdef HAVE_LIBSAMPLERATE
59 # include <samplerate.h>
60 #endif
61
62
63 #define HIDE(name) \
64 { if((set_wgt = lookup_widget(config_win, name))) \
65 gtk_widget_hide(set_wgt); }
66
67 #define SHOW(name) \
68 { if((set_wgt = lookup_widget(config_win, name))) \
69 gtk_widget_show(set_wgt); }
70
71
72 #define SETW_SENSITIVE(wgt, sensitive) \
73 gtk_widget_set_sensitive(wgt, sensitive)
74
75 #define SETW_TOGGLE(wgt, active) \
76 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(wgt), active)
77
78 #define SETW_SPIN(wgt, value) \
79 gtk_spin_button_set_value(GTK_SPIN_BUTTON(wgt), value)
80
81
82 #define SET_SENSITIVE(name, sensitive) \
83 { if((set_wgt = lookup_widget(config_win, name))) \
84 gtk_widget_set_sensitive(set_wgt, sensitive); }
85
86 #define SET_TOGGLE(name, active) \
87 { if((set_wgt = lookup_widget(config_win, name))) \
88 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(set_wgt), active); }
89
90 #define SET_SPIN(name, value) \
91 { if((set_wgt = lookup_widget(config_win, name))) \
92 gtk_spin_button_set_value(GTK_SPIN_BUTTON(set_wgt), value); }
93
94 #define SET_PAGE(name, index) \
95 { if((set_wgt = lookup_widget(config_win, name))) \
96 gtk_notebook_set_page(GTK_NOTEBOOK(set_wgt), index); }
97
98 #define SET_HISTORY(name, index) \
99 { if((set_wgt = lookup_widget(config_win, name))) \
100 gtk_option_menu_set_history(GTK_OPTION_MENU(set_wgt), index); }
101
102
103 #define GET_SENSITIVE(name) \
104 ((get_wgt = lookup_widget(config_win, name)) \
105 && GTK_WIDGET_SENSITIVE(get_wgt)) \
106
107 #define GET_TOGGLE(name) \
108 ((get_wgt = lookup_widget(config_win, name)) \
109 && gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(get_wgt)))
110
111 #define GET_SPIN(name) \
112 ((get_wgt = lookup_widget(config_win, name)) \
113 ? gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(get_wgt)) : 0)
114
115
116 static GtkWidget *config_win = NULL;
117 static GtkWidget *about_win = NULL;
118 static GtkWidget *set_wgt;
119 static GtkWidget *get_wgt;
120
121 /* init with DEFAULT_CFG to make sure all string pointers are set to NULL */
122 static config_t _cfg = CONFIG_DEFAULT;
123 static config_t *cfg = &_cfg;
124
125 /* some helpers to keep track of the GUI's state */
126 static gboolean checking = FALSE;
127 static gint op_index;
128 static plugin_config_t op_config;
129 static gint ep_index;
130
131
132 static void update_plugin_config(gchar **config_string, gchar *name,
133 plugin_config_t *pc, gboolean save);
134
135 /*****************************************************************************/
136
137 void g_free_f(gpointer data, gpointer user_data)
138 {
139 g_free(data);
140 }
141
142 /*****************************************************************************/
143
144 #ifdef PRESET_SUPPORT
145 static void
146 scan_presets(gchar *filename)
147 {
148 struct stat stats;
149 FILE *fh;
150 gchar *data, **lines, *tmp, *name;
151 int i;
152
153 if(lstat(filename, &stats)) {
154 DEBUG(("[crossfade] scan_presets: \"%s\":\n", filename));
155 PERROR("[crossfade] scan_presets: lstat");
156 return;
157 }
158 if(stats.st_size <= 0) return;
159
160 if(!(data = g_malloc(stats.st_size + 1))) {
161 DEBUG(("[crossfade] scan_presets: g_malloc(%ld) failed!\n", stats.st_size));
162 return;
163 }
164
165 if(!(fh = fopen(filename, "r"))) {
166 PERROR("[crossfade] scan_presets: fopen");
167 g_free(data);
168 return;
169 }
170
171 if(fread(data, stats.st_size, 1, fh) != 1) {
172 DEBUG(("[crossfade] scan_presets: fread() failed!\n"));
173 g_free(data);
174 fclose(fh);
175 return;
176 }
177 fclose(fh);
178 data[stats.st_size] = 0;
179
180 lines = g_strsplit(data, "\n", 0);
181 g_free(data);
182
183 if(!lines) {
184 DEBUG(("[crossfade] scan_presets: g_strsplit() failed!\n"));
185 return;
186 }
187
188 g_list_foreach(config->presets, g_free_f, NULL);
189 g_list_free(config->presets);
190 config->presets = NULL;
191
192 for(i=0; lines[i]; i++) {
193 if(lines[i][0] == '[') {
194 if((tmp = strchr(lines[i], ']'))) {
195 *tmp = 0;
196 if((name = g_strdup(lines[i]+1)))
197 config->presets = g_list_append(config->presets, name);
198 }
199 }
200 }
201
202 g_strfreev(lines);
203 }
204 #endif
205
206 static void
207 read_fade_config(ConfigFile *cfgfile, gchar *section, gchar *key, fade_config_t *fc)
208 {
209 gchar *s = NULL;
210 gint n;
211
212 if(!cfgfile || !section || !key || !fc) return;
213
214 xmms_cfg_read_string(cfgfile, section, key, &s);
215 if(!s) return;
216
217 n = sscanf(s,
218 "%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
219 &fc->type,
220 &fc->pause_len_ms,
221 &fc->simple_len_ms,
222 &fc->out_enable,
223 &fc->out_len_ms,
224 &fc->out_volume,
225 &fc->ofs_type,
226 &fc->ofs_type_wanted,
227 &fc->ofs_custom_ms,
228 &fc->in_locked,
229 &fc->in_enable,
230 &fc->in_len_ms,
231 &fc->in_volume,
232 &fc->flush_pause_enable,
233 &fc->flush_pause_len_ms,
234 &fc->flush_in_enable,
235 &fc->flush_in_len_ms,
236 &fc->flush_in_volume);
237
238 g_free(s);
239 }
240
241 static void
242 write_fade_config(ConfigFile *cfgfile, gchar *section, gchar *key, fade_config_t *fc)
243 {
244 gchar *s;
245
246 if(!cfgfile || !section || !key || !fc) return;
247
248 s = g_strdup_printf("%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d",
249 fc->type,
250 fc->pause_len_ms,
251 fc->simple_len_ms,
252 fc->out_enable,
253 fc->out_len_ms,
254 fc->out_volume,
255 fc->ofs_type,
256 fc->ofs_type_wanted,
257 fc->ofs_custom_ms,
258 fc->in_locked,
259 fc->in_enable,
260 fc->in_len_ms,
261 fc->in_volume,
262 fc->flush_pause_enable,
263 fc->flush_pause_len_ms,
264 fc->flush_in_enable,
265 fc->flush_in_len_ms,
266 fc->flush_in_volume);
267
268 if(!s) return;
269
270 xmms_cfg_write_string(cfgfile, section, key, s);
271 g_free(s);
272 }
273
274 void
275 xfade_load_config()
276 {
277 #ifdef PRESET_SUPPORT
278 gchar *filename;
279 #endif
280 gchar *section = "Crossfade";
281 ConfigFile *cfgfile;
282
283 if((cfgfile = xmms_cfg_open_default_file())) {
284 /* config items used in v0.1 */
285 xmms_cfg_read_int (cfgfile, section, "output_method", &config->output_method);
286 xmms_cfg_read_int (cfgfile, section, "audio_device", &config->oss_audio_device);
287 xmms_cfg_read_boolean(cfgfile, section, "use_alt_audio_device", &config->oss_use_alt_audio_device);
288 xmms_cfg_read_string (cfgfile, section, "alt_audio_device", &config->oss_alt_audio_device);
289 xmms_cfg_read_int (cfgfile, section, "mixer_device", &config->oss_mixer_device);
290 xmms_cfg_read_string (cfgfile, section, "output_plugin", &config->op_name);
291 xmms_cfg_read_string (cfgfile, section, "op_config_string", &config->op_config_string);
292 xmms_cfg_read_int (cfgfile, section, "buffer_size", &config->mix_size_ms);
293 xmms_cfg_read_int (cfgfile, section, "sync_size", &config->sync_size_ms);
294 xmms_cfg_read_int (cfgfile, section, "preload_size", &config->preload_size_ms);
295 xmms_cfg_read_int (cfgfile, section, "songchange_timeout", &config->songchange_timeout);
296 xmms_cfg_read_boolean(cfgfile, section, "enable_mixer", &config->enable_mixer);
297 xmms_cfg_read_boolean(cfgfile, section, "mixer_reverse", &config->mixer_reverse);
298 xmms_cfg_read_boolean(cfgfile, section, "enable_debug", &config->enable_debug);
299 xmms_cfg_read_boolean(cfgfile, section, "enable_monitor", &config->enable_monitor);
300
301 /* config items introduced by v0.2 */
302 xmms_cfg_read_int (cfgfile, section, "oss_buffer_size", &config->oss_buffer_size_ms);
303 xmms_cfg_read_int (cfgfile, section, "oss_preload_size", &config->oss_preload_size_ms);
304 xmms_cfg_read_boolean(cfgfile, section, "oss_mixer_use_master", &config->oss_mixer_use_master);
305 xmms_cfg_read_boolean(cfgfile, section, "gap_lead_enable", &config->gap_lead_enable);
306 xmms_cfg_read_int (cfgfile, section, "gap_lead_len_ms", &config->gap_lead_len_ms);
307 xmms_cfg_read_int (cfgfile, section, "gap_lead_level", &config->gap_lead_level);
308 xmms_cfg_read_boolean(cfgfile, section, "gap_trail_enable", &config->gap_trail_enable);
309 xmms_cfg_read_int (cfgfile, section, "gap_trail_len_ms", &config->gap_trail_len_ms);
310 xmms_cfg_read_int (cfgfile, section, "gap_trail_level", &config->gap_trail_level);
311 xmms_cfg_read_int (cfgfile, section, "gap_trail_locked", &config->gap_trail_locked);
312
313 /* config items introduced by v0.2.1 */
314 xmms_cfg_read_boolean(cfgfile, section, "buffer_size_auto", &config->mix_size_auto);
315
316 /* config items introduced by v0.2.3 */
317 xmms_cfg_read_boolean(cfgfile, section, "album_detection", &config->album_detection);
318
319 /* config items introduced by v0.2.4 */
320 xmms_cfg_read_boolean(cfgfile, section, "http_workaround", &config->enable_http_workaround);
321 xmms_cfg_read_boolean(cfgfile, section, "enable_op_max_used", &config->enable_op_max_used);
322 xmms_cfg_read_int (cfgfile, section, "op_max_used_ms", &config->op_max_used_ms);
323
324 /* config items introduced by v0.2.6 */
325 xmms_cfg_read_string (cfgfile, section, "effect_plugin", &config->ep_name);
326 xmms_cfg_read_boolean(cfgfile, section, "effect_enable", &config->ep_enable);
327 xmms_cfg_read_int (cfgfile, section, "output_rate", &config->output_rate);
328
329 /* config items introduced by v0.2.7 */
330 xmms_cfg_read_boolean(cfgfile, section, "oss_maxbuf_enable", &config->oss_maxbuf_enable);
331
332 /* config items introduced by v0.3.0 */
333 xmms_cfg_read_boolean(cfgfile, section, "use_alt_mixer_device", &config->oss_use_alt_mixer_device);
334 xmms_cfg_read_int (cfgfile, section, "oss_fragments", &config->oss_fragments);
335 xmms_cfg_read_int (cfgfile, section, "oss_fragment_size", &config->oss_fragment_size);
336 xmms_cfg_read_boolean(cfgfile, section, "volnorm_enable", &config->volnorm_enable);
337 xmms_cfg_read_boolean(cfgfile, section, "volnorm_use_qa", &config->volnorm_use_qa);
338 xmms_cfg_read_int (cfgfile, section, "volnorm_target", &config->volnorm_target);
339 xmms_cfg_read_boolean(cfgfile, section, "output_keep_opened", &config->output_keep_opened);
340 xmms_cfg_read_boolean(cfgfile, section, "mixer_software", &config->mixer_software);
341 xmms_cfg_read_int (cfgfile, section, "mixer_vol_left", &config->mixer_vol_left);
342 xmms_cfg_read_int (cfgfile, section, "mixer_vol_right", &config->mixer_vol_right);
343
344 /* config items introduced by v0.3.2 */
345 xmms_cfg_read_boolean(cfgfile, section, "no_xfade_if_same_file",&config->no_xfade_if_same_file);
346
347 /* config items introduced by v0.3.3 */
348 xmms_cfg_read_string (cfgfile, section, "alt_mixer_device", &config->oss_alt_mixer_device);
349 xmms_cfg_read_boolean(cfgfile, section, "gap_crossing", &config->gap_crossing);
350
351 /* config items introduced by v0.3.6 */
352 xmms_cfg_read_int (cfgfile, section, "output_quality", &config->output_quality);
353
354 /* fade configs */
355 read_fade_config(cfgfile, section, "fc_xfade", &config->fc[FADE_CONFIG_XFADE]);
356 read_fade_config(cfgfile, section, "fc_manual", &config->fc[FADE_CONFIG_MANUAL]);
357 read_fade_config(cfgfile, section, "fc_album", &config->fc[FADE_CONFIG_ALBUM]);
358 read_fade_config(cfgfile, section, "fc_start", &config->fc[FADE_CONFIG_START]);
359 read_fade_config(cfgfile, section, "fc_stop", &config->fc[FADE_CONFIG_STOP]);
360 read_fade_config(cfgfile, section, "fc_eop", &config->fc[FADE_CONFIG_EOP]);
361 read_fade_config(cfgfile, section, "fc_seek", &config->fc[FADE_CONFIG_SEEK]);
362 read_fade_config(cfgfile, section, "fc_pause", &config->fc[FADE_CONFIG_PAUSE]);
363
364 xmms_cfg_free(cfgfile);
365 DEBUG(("[crossfade] load_config: configuration loaded\n"));
366 }
367 else
368 DEBUG(("[crossfade] load_config: error loading config, using defaults\n"));
369
370 #ifdef PRESET_SUPPORT
371 filename = g_strconcat(g_get_home_dir(), "/.xmms/xmms-crossfade-presets", NULL);
372 scan_presets(filename);
373 g_free(filename);
374 #endif
375 }
376
377 void
378 xfade_save_config()
379 {
380 gchar *section = "Crossfade";
381 ConfigFile *cfgfile;
382
383 if((cfgfile = xmms_cfg_open_default_file())) {
384 /* obsolete config items */
385 xmms_cfg_remove_key(cfgfile, section, "underrun_pct");
386 xmms_cfg_remove_key(cfgfile, section, "enable_crossfade");
387 xmms_cfg_remove_key(cfgfile, section, "enable_gapkiller");
388 xmms_cfg_remove_key(cfgfile, section, "mixer_use_master");
389 xmms_cfg_remove_key(cfgfile, section, "late_effect");
390 xmms_cfg_remove_key(cfgfile, section, "gap_lead_length");
391
392 /* config items used in v0.1 */
393 xmms_cfg_write_int (cfgfile, section, "output_method", config->output_method);
394 xmms_cfg_write_int (cfgfile, section, "audio_device", config->oss_audio_device);
395 xmms_cfg_write_boolean(cfgfile, section, "use_alt_audio_device", config->oss_use_alt_audio_device);
396 xmms_cfg_write_string (cfgfile, section, "alt_audio_device", config->oss_alt_audio_device ? config->oss_alt_audio_device : DEFAULT_OSS_ALT_AUDIO_DEVICE);
397 xmms_cfg_write_int (cfgfile, section, "mixer_device", config->oss_mixer_device);
398 xmms_cfg_write_string (cfgfile, section, "output_plugin", config->op_name ? config->op_name : DEFAULT_OP_NAME);
399 xmms_cfg_write_string (cfgfile, section, "op_config_string", config->op_config_string ? config->op_config_string : DEFAULT_OP_CONFIG_STRING);
400 xmms_cfg_write_int (cfgfile, section, "buffer_size", config->mix_size_ms);
401 xmms_cfg_write_int (cfgfile, section, "sync_size", config->sync_size_ms);
402 xmms_cfg_write_int (cfgfile, section, "preload_size", config->preload_size_ms);
403 xmms_cfg_write_int (cfgfile, section, "songchange_timeout", config->songchange_timeout);
404 xmms_cfg_write_boolean(cfgfile, section, "enable_mixer", config->enable_mixer);
405 xmms_cfg_write_boolean(cfgfile, section, "mixer_reverse", config->mixer_reverse);
406 xmms_cfg_write_boolean(cfgfile, section, "enable_debug", config->enable_debug);
407 xmms_cfg_write_boolean(cfgfile, section, "enable_monitor", config->enable_monitor);
408
409 /* config items introduced by v0.2 */
410 xmms_cfg_write_int (cfgfile, section, "oss_buffer_size", config->oss_buffer_size_ms);
411 xmms_cfg_write_int (cfgfile, section, "oss_preload_size", config->oss_preload_size_ms);
412 xmms_cfg_write_boolean(cfgfile, section, "oss_mixer_use_master", config->oss_mixer_use_master);
413 xmms_cfg_write_boolean(cfgfile, section, "gap_lead_enable", config->gap_lead_enable);
414 xmms_cfg_write_int (cfgfile, section, "gap_lead_len_ms", config->gap_lead_len_ms);
415 xmms_cfg_write_int (cfgfile, section, "gap_lead_level", config->gap_lead_level);
416 xmms_cfg_write_boolean(cfgfile, section, "gap_trail_enable", config->gap_trail_enable);
417 xmms_cfg_write_int (cfgfile, section, "gap_trail_len_ms", config->gap_trail_len_ms);
418 xmms_cfg_write_int (cfgfile, section, "gap_trail_level", config->gap_trail_level);
419 xmms_cfg_write_int (cfgfile, section, "gap_trail_locked", config->gap_trail_locked);
420
421 /* config items introduced by v0.2.1 */
422 xmms_cfg_write_boolean(cfgfile, section, "buffer_size_auto", config->mix_size_auto);
423
424 /* config items introduced by v0.2.3 */
425 xmms_cfg_write_boolean(cfgfile, section, "album_detection", config->album_detection);
426
427 /* config items introduced by v0.2.4 */
428 xmms_cfg_write_boolean(cfgfile, section, "http_workaround", config->enable_http_workaround);
429 xmms_cfg_write_boolean(cfgfile, section, "enable_op_max_used", config->enable_op_max_used);
430 xmms_cfg_write_int (cfgfile, section, "op_max_used_ms", config->op_max_used_ms);
431
432 /* config items introduced by v0.2.6 */
433 xmms_cfg_write_string (cfgfile, section, "effect_plugin", config->ep_name ? config->ep_name : DEFAULT_EP_NAME);
434 xmms_cfg_write_boolean(cfgfile, section, "effect_enable", config->ep_enable);
435 xmms_cfg_write_int (cfgfile, section, "output_rate", config->output_rate);
436
437 /* config items introduced by v0.2.7 */
438 xmms_cfg_write_boolean(cfgfile, section, "oss_maxbuf_enable", config->oss_maxbuf_enable);
439
440 /* config items introduced by v0.3.0 */
441 xmms_cfg_write_boolean(cfgfile, section, "use_alt_mixer_device", config->oss_use_alt_mixer_device);
442 xmms_cfg_write_int (cfgfile, section, "oss_fragments", config->oss_fragments);
443 xmms_cfg_write_int (cfgfile, section, "oss_fragment_size", config->oss_fragment_size);
444 #ifdef VOLUME_NORMALIZER
445 xmms_cfg_write_boolean(cfgfile, section, "volnorm_enable", config->volnorm_enable);
446 xmms_cfg_write_boolean(cfgfile, section, "volnorm_use_qa", config->volnorm_use_qa);
447 xmms_cfg_write_int (cfgfile, section, "volnorm_target", config->volnorm_target);
448 #endif
449 xmms_cfg_write_boolean(cfgfile, section, "output_keep_opened", config->output_keep_opened);
450 xmms_cfg_write_boolean(cfgfile, section, "mixer_software", config->mixer_software);
451 xmms_cfg_write_int (cfgfile, section, "mixer_vol_left", config->mixer_vol_left);
452 xmms_cfg_write_int (cfgfile, section, "mixer_vol_right", config->mixer_vol_right);
453
454 /* config items introduced by v0.3.2 */
455 xmms_cfg_write_boolean(cfgfile, section, "no_xfade_if_same_file",config->no_xfade_if_same_file);
456
457 /* config items introduced by v0.3.2 */
458 xmms_cfg_write_string (cfgfile, section, "alt_mixer_device", config->oss_alt_mixer_device ? config->oss_alt_mixer_device : DEFAULT_OSS_ALT_MIXER_DEVICE);
459 xmms_cfg_write_boolean(cfgfile, section, "gap_crossing", config->gap_crossing);
460
461 /* config items introduced by v0.3.6 */
462 xmms_cfg_write_int (cfgfile, section, "output_quality", config->output_quality);
463
464 /* fade configs */
465 write_fade_config(cfgfile, section, "fc_xfade", &config->fc[FADE_CONFIG_XFADE]);
466 write_fade_config(cfgfile, section, "fc_manual", &config->fc[FADE_CONFIG_MANUAL]);
467 write_fade_config(cfgfile, section, "fc_album", &config->fc[FADE_CONFIG_ALBUM]);
468 write_fade_config(cfgfile, section, "fc_start", &config->fc[FADE_CONFIG_START]);
469 write_fade_config(cfgfile, section, "fc_stop", &config->fc[FADE_CONFIG_STOP]);
470 write_fade_config(cfgfile, section, "fc_eop", &config->fc[FADE_CONFIG_EOP]);
471 write_fade_config(cfgfile, section, "fc_seek", &config->fc[FADE_CONFIG_SEEK]);
472 write_fade_config(cfgfile, section, "fc_pause", &config->fc[FADE_CONFIG_PAUSE]);
473
474 xmms_cfg_write_default_file(cfgfile);
475 xmms_cfg_free (cfgfile);
476 DEBUG(("[crossfade] save_config: configuration saved\n"));
477 }
478 else
479 DEBUG(("[crossfade] save_config: error saving configuration!\n"));
480 }
481
482 #define SAFE_FREE(x) if(x) { g_free(x); x = NULL; }
483 void
484 xfade_free_config()
485 {
486 SAFE_FREE(cfg->oss_alt_audio_device);
487 SAFE_FREE(cfg->oss_alt_mixer_device);
488 SAFE_FREE(cfg->op_config_string);
489 SAFE_FREE(cfg->op_name);
490
491 g_list_foreach(config->presets, g_free_f, NULL);
492 g_list_free(config->presets);
493 config->presets = NULL;
494 }
495
496 void
497 xfade_load_plugin_config(gchar *config_string,
498 gchar *plugin_name,
499 plugin_config_t *plugin_config)
500 {
501 update_plugin_config(&config_string, plugin_name, plugin_config, FALSE);
502 }
503
504 void
505 xfade_save_plugin_config(gchar **config_string,
506 gchar *plugin_name,
507 plugin_config_t *plugin_config)
508 {
509 update_plugin_config(config_string, plugin_name, plugin_config, TRUE);
510 }
511
512 /*** helpers *****************************************************************/
513
514 gint
515 xfade_cfg_fadeout_len(fade_config_t *fc)
516 {
517 if(!fc) return 0;
518 switch(fc->type) {
519 case FADE_TYPE_SIMPLE_XF:
520 return fc->simple_len_ms;
521 case FADE_TYPE_ADVANCED_XF:
522 return fc->out_enable ? fc->out_len_ms : 0;
523 case FADE_TYPE_FADEOUT:
524 case FADE_TYPE_PAUSE_ADV:
525 return fc->out_len_ms;
526 }
527 return 0;
528 }
529
530 gint
531 xfade_cfg_fadeout_volume(fade_config_t *fc)
532 {
533 gint volume;
534 if(!fc) return 0;
535 switch(fc->type) {
536 case FADE_TYPE_ADVANCED_XF:
537 case FADE_TYPE_FADEOUT:
538 volume = fc->out_volume;
539 if(volume < 0) volume = 0;
540 if(volume > 100) volume = 100;
541 return volume;
542 }
543 return 0;
544 }
545
546 gint
547 xfade_cfg_offset(fade_config_t *fc)
548 {
549 if(!fc) return 0;
550 switch(fc->type) {
551 case FADE_TYPE_FLUSH:
552 return fc->flush_pause_enable ? fc->flush_pause_len_ms : 0;
553 case FADE_TYPE_PAUSE:
554 return fc->pause_len_ms;
555 case FADE_TYPE_SIMPLE_XF:
556 return -fc->simple_len_ms;
557 case FADE_TYPE_ADVANCED_XF:
558 switch(fc->ofs_type) {
559 case FC_OFFSET_LOCK_OUT:
560 return -fc->out_len_ms;
561 case FC_OFFSET_LOCK_IN:
562 return -fc->in_len_ms;
563 case FC_OFFSET_CUSTOM:
564 return fc->ofs_custom_ms;
565 }
566 return 0;
567 case FADE_TYPE_FADEOUT:
568 case FADE_TYPE_PAUSE_ADV:
569 return fc->ofs_custom_ms;
570 }
571 return 0;
572 }
573
574 gint
575 xfade_cfg_fadein_len(fade_config_t *fc)
576 {
577 if(!fc) return 0;
578 switch(fc->type) {
579 case FADE_TYPE_FLUSH:
580 return fc->flush_in_enable ? fc->flush_in_len_ms : 0;
581 case FADE_TYPE_SIMPLE_XF:
582 return fc->simple_len_ms;
583 case FADE_TYPE_ADVANCED_XF:
584 return
585 fc->in_locked
586 ? (fc->out_enable ? fc->out_len_ms : 0)
587 : (fc->in_enable ? fc->in_len_ms : 0);
588 case FADE_TYPE_FADEIN:
589 case FADE_TYPE_PAUSE_ADV:
590 return fc->in_len_ms;
591 }
592 return 0;
593 }
594
595 gint
596 xfade_cfg_fadein_volume(fade_config_t *fc)
597 {
598 gint volume;
599 if(!fc) return 0;
600 switch(fc->type) {
601 case FADE_TYPE_FLUSH:
602 volume = fc->flush_in_volume;
603 break;
604 case FADE_TYPE_ADVANCED_XF:
605 volume = fc->in_locked ? fc->out_volume : fc->in_volume;
606 break;
607 case FADE_TYPE_FADEIN:
608 volume = fc->in_volume;
609 break;
610 default:
611 volume = 0;
612 }
613 if(volume < 0) volume = 0;
614 if(volume > 100) volume = 100;
615 return volume;
616 }
617
618 gboolean
619 xfade_cfg_gap_trail_enable(config_t *cfg)
620 {
621 return cfg->gap_trail_locked
622 ? cfg->gap_lead_enable
623 : cfg->gap_trail_enable;
624 }
625
626 gint
627 xfade_cfg_gap_trail_len(config_t *cfg)
628 {
629 if(!xfade_cfg_gap_trail_enable(cfg)) return 0;
630 return cfg->gap_trail_locked
631 ? cfg->gap_lead_len_ms
632 : cfg->gap_trail_len_ms;
633 }
634
635 gint
636 xfade_cfg_gap_trail_level(config_t *cfg)
637 {
638 return cfg->gap_trail_locked
639 ? cfg->gap_lead_level
640 : cfg->gap_trail_level;
641 }
642
643 gint
644 xfade_mix_size_ms(config_t *cfg)
645 {
646 if(cfg->mix_size_auto) {
647 gint i, min_size = 0;
648
649 for(i=0; i<MAX_FADE_CONFIGS; i++) {
650 gint size = xfade_cfg_fadeout_len(&cfg->fc[i]);
651 gint offset = xfade_cfg_offset(&cfg->fc[i]);
652
653 if(cfg->fc[i].type == FADE_TYPE_PAUSE_ADV)
654 size += xfade_cfg_fadein_len(&cfg->fc[i]);
655
656 if(size < -offset)
657 size = -offset;
658
659 if(size > min_size)
660 min_size = size;
661 }
662 return min_size += xfade_cfg_gap_trail_len(cfg)
663 + cfg->songchange_timeout;
664 }
665 else
666 return cfg->mix_size_ms;
667 }
668
669 /*** internal helpers ********************************************************/
670
671 static void
672 add_menu_item(GtkWidget *menu, gchar *title, GtkSignalFunc func, gint index, gint **imap)
673 {
674 GtkWidget *item;
675 if(!menu || !title || !func) return;
676 item = gtk_menu_item_new_with_label(title);
677 gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(func), (gpointer)index);
678 gtk_widget_show(item);
679 gtk_menu_append(GTK_MENU(menu), item);
680
681 if(imap) *((*imap)++) = index;
682 }
683
684 /*** output method ***********************************************************/
685
686 /*-- callbacks --------------------------------------------------------------*/
687
688 void on_output_oss_radio_toggled(GtkToggleButton *togglebutton, gpointer user_data)
689 {
690 SET_PAGE("output_notebook", 0);
691 cfg->output_method = OUTPUT_METHOD_BUILTIN_OSS;
692 }
693
694 void on_output_plugin_radio_toggled(GtkToggleButton *togglebutton, gpointer user_data)
695 {
696 SET_PAGE("output_notebook", 1);
697 cfg->output_method = OUTPUT_METHOD_PLUGIN;
698 }
699
700 void on_output_none_radio_toggled(GtkToggleButton *togglebutton, gpointer user_data)
701 {
702 SET_PAGE("output_notebook", 2);
703 cfg->output_method = OUTPUT_METHOD_BUILTIN_NULL;
704 }
705
706 static void resampling_rate_cb(GtkWidget *widget, gint index)
707 {
708 cfg->output_rate = index;
709 }
710
711 #ifdef HAVE_LIBSAMPLERATE
712 static void resampling_quality_cb(GtkWidget *widget, gint index)
713 {
714 cfg->output_quality = index;
715 }
716 #endif
717
718 /*** oss output **************************************************************/
719
720 static void
721 scan_devices(gchar *type, GtkWidget *option_menu, GtkSignalFunc signal_f)
722 {
723 #ifdef HAVE_OSS
724 gchar buffer[256];
725 FILE *file;
726
727 GtkWidget *item;
728 gboolean found = FALSE;
729 gint type_len = strlen(type);
730 #endif
731
732 GtkWidget *menu;
733 gint index = 0;
734 gint mixer = 0;
735
736 menu = gtk_menu_new();
737
738 #ifdef HAVE_OSS
739 /* look for devices in /dev/sndstat or /proc/asound/sndstat (OSS style) */
740 if((file = fopen("/dev/sndstat", "r")) ||
741 (file = fopen("/proc/asound/sndstat", "r")) ||
742 (file = fopen("/proc/asound/oss/sndstat", "r"))) {
743 while(fgets(buffer, sizeof(buffer), file)) {
744 gint i = strlen(buffer)-1;
745 while((i >= 0) && isspace(buffer[i])) buffer[i--] = 0;
746 if(found) {
747 if(!buffer[0] || !isdigit(buffer[0])) break;
748 if(index == 0) {
749 gchar *label, *p = strchr(buffer, ':');
750 if(p) do p++; while(*p == ' ');
751 else p = buffer;
752 label = g_strdup_printf("Default (%s)", p);
753 item = gtk_menu_item_new_with_label(label);
754 g_free(label);
755 }
756 else item = gtk_menu_item_new_with_label(buffer);
757
758 gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(signal_f),
759 (gpointer)index);
760 gtk_widget_show(item);
761 gtk_menu_append(GTK_MENU(menu), item);
762 index++;
763 }
764 else if(!strcmp(buffer, type))
765 found = TRUE;
766 else if(!strncmp(buffer, type, type_len))
767 DEBUG(("[crossfade] scan_devices: %s\n", buffer));
768 }
769 fclose(file);
770
771 if(!found)
772 DEBUG(("[crossfade] scan_devices: section \"%s\" not found!\n", type));
773 }
774 else {
775 DEBUG(("[crossfade] scan_devices: no sndstat found!\n"));
776 #ifdef SOUND_MIXER_INFO
777 /* from xmms-3dse7 by Frank Cornelis */
778 DEBUG(("[crossfade] scan_devices: using alternate method...\n"));
779 for(;;) {
780 gchar dev_name[32];
781 int fd;
782 mixer_info info;
783 gchar *label;
784
785 if(mixer != 0)
786 sprintf(dev_name, "/dev/mixer%d", mixer);
787 else
788 strcpy(dev_name, "/dev/mixer");
789
790 if((fd = open(dev_name, O_RDONLY)) != -1) {
791 if(ioctl(fd, SOUND_MIXER_INFO, &info) != -1) {
792 label = g_strdup_printf(index ? "%s" : "Default (%s)", info.name);
793 add_menu_item(menu, label, signal_f, index, NULL);
794 g_free(label);
795 index++;
796 }
797 close(fd);
798 }
799 else break;
800 mixer++;
801 }
802 #endif
803 }
804 #endif /* HAVE_OSS */
805
806 /* create default entry if no device(s) could be found */
807 if(index == 0) add_menu_item(menu, "Default", signal_f, 0, NULL);
808
809 /* attach menu */
810 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
811 }
812
813 /*-- oss output callbacks ---------------------------------------------------*/
814
815 void check_oss_dependencies()
816 {
817 if(checking) return;
818 checking = TRUE;
819
820 SET_SENSITIVE("oss_adevice_optionmenu", !cfg->oss_use_alt_audio_device);
821 SET_SENSITIVE("oss_adevice_alt_entry", cfg->oss_use_alt_audio_device);
822
823 SET_SENSITIVE("oss_mdevice_optionmenu", !cfg->oss_use_alt_mixer_device);
824 SET_SENSITIVE("oss_mdevice_alt_entry", cfg->oss_use_alt_mixer_device);
825
826 SET_SENSITIVE("osshwb_fragments_label", !cfg->oss_maxbuf_enable);
827 SET_SENSITIVE("osshwb_fragments_spin", !cfg->oss_maxbuf_enable);
828 SET_SENSITIVE("osshwb_fragsize_label", !cfg->oss_maxbuf_enable);
829 SET_SENSITIVE("osshwb_fragsize_spin", !cfg->oss_maxbuf_enable);
830
831 checking = FALSE;
832 }
833
834 void config_adevice_cb(GtkWidget *widget, gint device)
835 {
836 cfg->oss_audio_device = device;
837 }
838
839 void config_mdevice_cb(GtkWidget *widget, gint device)
840 {
841 cfg->oss_mixer_device = device;
842 }
843
844 void on_config_adevice_alt_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
845 {
846 if(checking) return;
847 cfg->oss_use_alt_audio_device = gtk_toggle_button_get_active(togglebutton);
848 check_oss_dependencies();
849 }
850
851 void on_config_mdevice_alt_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
852 {
853 if(checking) return;
854 cfg->oss_use_alt_mixer_device = gtk_toggle_button_get_active(togglebutton);
855 check_oss_dependencies();
856 }
857
858 void on_osshwb_maxbuf_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
859 {
860 if(checking) return;
861 cfg->oss_maxbuf_enable = gtk_toggle_button_get_active(togglebutton);
862 check_oss_dependencies();
863 }
864
865 /*** plugin output ***********************************************************/
866
867 static gchar *
868 strip(gchar *s)
869 {
870 gchar *p;
871 if(!s) return NULL;
872 for(; *s == ' '; s++);
873 if(!*s) return s;
874 for(p = s+strlen(s)-1; *p == ' '; p--);
875 *++p = 0;
876 return s;
877 }
878
879 static void
880 update_plugin_config(gchar **config_string, gchar *name,
881 plugin_config_t *pc, gboolean save)
882 {
883 plugin_config_t default_pc = DEFAULT_OP_CONFIG;
884
885 gchar *buffer = NULL;
886 gchar out[1024];
887
888 gboolean plugin_found = FALSE;
889 gchar *plugin, *next_plugin;
890 gchar *args;
891
892 if(pc && !save) *pc = default_pc;
893 if(!config_string || !*config_string || !name || !pc) {
894 DEBUG(("[crossfade] update_plugin_config: missing arg!\n"));
895 return;
896 }
897
898 buffer = g_strdup(*config_string);
899 out[0] = 0;
900
901 for(plugin = buffer; plugin; plugin = next_plugin) {
902 if((next_plugin = strchr(plugin, ';'))) *next_plugin++ = 0;
903 if((args = strchr(plugin, '='))) *args++ = 0;
904 plugin = strip(plugin);
905 if(!*plugin || !args || !*args) continue;
906
907 if(save) {
908 if(0 == strcmp(plugin, name)) continue;
909 if(*out) strcat(out, "; ");
910 strcat(out, plugin);
911 strcat(out, "=");
912 strcat(out, args);
913 continue;
914 }
915 else if(strcmp(plugin, name)) continue;
916
917 args = strip(args);
918 sscanf(args, "%d,%d,%d,%d",
919 &pc->throttle_enable,
920 &pc->max_write_enable,
921 &pc->max_write_len,
922 &pc->force_reopen);
923 pc->max_write_len &= -4;
924 plugin_found = TRUE;
925 }
926
927 if(save) {
928 /* only save if settings differ from defaults */
929 if(( pc->throttle_enable != default_pc.throttle_enable)
930 ||(pc->max_write_enable != default_pc.max_write_enable)
931 ||(pc->max_write_len != default_pc.max_write_len)
932 ||(pc->force_reopen != default_pc.force_reopen)) {
933 if(*out) strcat(out, "; ");
934 sprintf(out + strlen(out), "%s=%d,%d,%d,%d", name,
935 pc->throttle_enable ? 1 : 0,
936 pc->max_write_enable ? 1 : 0,
937 pc->max_write_len,
938 pc->force_reopen);
939 }
940 if(*config_string) g_free(*config_string);
941 *config_string = g_strdup(out);
942 }
943
944 g_free(buffer);
945 }
946
947 static void
948 config_plugin_cb(GtkWidget *widget, gint index);
949
950 static gint
951 scan_plugins(GtkWidget *option_menu, gchar *selected)
952 {
953 GtkWidget *menu = gtk_menu_new();
954 GList *list = g_list_first(get_output_list()); /* XMMS */
955 gint index = 0;
956 gint sel_index = -1;
957 gint def_index = -1;
958
959 /* sanity check */
960 if(selected == NULL) selected = "";
961
962 /* parse module list */
963 while(list) {
964 OutputPlugin *op = (OutputPlugin *)list->data;
965 GtkWidget *item = gtk_menu_item_new_with_label(op->description);
966
967 if(op == get_crossfade_oplugin_info()) /* disable selecting ourselves */
968 gtk_widget_set_sensitive(item, FALSE);
969 else {
970 if(def_index == -1) def_index = index;
971 if(selected && !strcmp(g_basename(op->filename), selected))
972 sel_index = index;
973 }
974
975 /* create menu item */
976 gtk_signal_connect(GTK_OBJECT(item), "activate",
977 GTK_SIGNAL_FUNC(config_plugin_cb), (gpointer)index++);
978 gtk_widget_show(item);
979 gtk_menu_append(GTK_MENU(menu), item);
980
981 /* advance to next module */
982 list = g_list_next(list);
983 }
984
985 /* attach menu */
986 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
987
988 if(sel_index == -1) {
989 DEBUG(("[crossfade] scan_plugins: plugin not found (\"%s\")\n", selected));
990 return def_index; /* use default (first entry) */
991 }
992 return sel_index;
993 }
994
995 /*-- plugin output callbacks ------------------------------------------------*/
996
997 static void
998 config_plugin_cb(GtkWidget *widget, gint index)
999 {
1000 OutputPlugin *op = g_list_nth_data(get_output_list(), index); /* XMMS */
1001
1002 /* get plugin options from gui */
1003 op_config.throttle_enable = GET_TOGGLE("op_throttle_check");
1004 op_config.max_write_enable = GET_TOGGLE("op_maxblock_check");
1005 op_config.max_write_len = GET_SPIN ("op_maxblock_spin");
1006 op_config.force_reopen = GET_TOGGLE("op_forcereopen_check");
1007
1008 /* config -> string */
1009 xfade_save_plugin_config(&cfg->op_config_string, cfg->op_name, &op_config);
1010
1011 /* select new plugin */
1012 op_index = index;
1013
1014 /* get new plugin's name */
1015 if(cfg->op_name) g_free(cfg->op_name);
1016 cfg->op_name = (op && op->filename)
1017 ? g_strdup(g_basename(op->filename)) : NULL;
1018
1019 /* string -> config */
1020 xfade_load_plugin_config(cfg->op_config_string, cfg->op_name, &op_config);
1021
1022 /* update gui */
1023 SET_SENSITIVE("op_configure_button", op && (op->configure != NULL));
1024 SET_SENSITIVE("op_about_button", op && (op->about != NULL));
1025 SET_TOGGLE ("op_throttle_check", op_config.throttle_enable);
1026 SET_TOGGLE ("op_maxblock_check", op_config.max_write_enable);
1027 SET_SPIN ("op_maxblock_spin", op_config.max_write_len);
1028 SET_SENSITIVE("op_maxblock_spin", op_config.max_write_enable);
1029 SET_TOGGLE ("op_forcereopen_check", op_config.force_reopen);
1030 }
1031
1032 void on_output_plugin_configure_button_clicked (GtkButton *button, gpointer user_data)
1033 {
1034 OutputPlugin *op = g_list_nth_data(get_output_list(), op_index); /* XMMS */
1035 if((op == NULL) || (op->configure == NULL)) return;
1036 op->configure();
1037 }
1038
1039 void on_output_plugin_about_button_clicked(GtkButton *button, gpointer user_data)
1040 {
1041 OutputPlugin *op = g_list_nth_data(get_output_list(), op_index); /* XMMS */
1042 if((op == NULL) || (op->about == NULL)) return;
1043 op->about();
1044 }
1045
1046 void on_op_throttle_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1047 {
1048 op_config.throttle_enable = gtk_toggle_button_get_active(togglebutton);
1049 }
1050
1051 void on_op_maxblock_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1052 {
1053 op_config.max_write_enable = gtk_toggle_button_get_active(togglebutton);
1054 SET_SENSITIVE("op_maxblock_spin", op_config.max_write_enable);
1055 }
1056
1057 void on_op_maxblock_spin_changed(GtkEditable *editable, gpointer user_data)
1058 {
1059 op_config.max_write_len = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1060 }
1061
1062 void on_op_forcereopen_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1063 {
1064 op_config.max_write_enable = gtk_toggle_button_get_active(togglebutton);
1065 }
1066
1067 /*** effects *****************************************************************/
1068
1069 static void
1070 config_effect_plugin_cb(GtkWidget *widget, gint index);
1071
1072 static gint
1073 scan_effect_plugins(GtkWidget *option_menu, gchar *selected)
1074 {
1075 GtkWidget *menu = gtk_menu_new();
1076 GList *list = g_list_first(get_effect_list()); /* XMMS */
1077 gint index = 0;
1078 gint sel_index = -1;
1079 gint def_index = -1;
1080
1081 /* sanity check */
1082 if(selected == NULL) selected = "";
1083
1084 /* parse module list */
1085 while(list) {
1086 EffectPlugin *ep = (EffectPlugin *)list->data;
1087 GtkWidget *item = gtk_menu_item_new_with_label(ep->description);
1088
1089 if(def_index == -1) def_index = index;
1090 if(selected && !strcmp(g_basename(ep->filename), selected))
1091 sel_index = index;
1092
1093 /* create menu item */
1094 gtk_signal_connect(GTK_OBJECT(item), "activate",
1095 GTK_SIGNAL_FUNC(config_effect_plugin_cb), (gpointer)index++);
1096 gtk_widget_show(item);
1097 gtk_menu_append(GTK_MENU(menu), item);
1098
1099 /* advance to next module */
1100 list = g_list_next(list);
1101 }
1102
1103 /* attach menu */
1104 gtk_option_menu_set_menu(GTK_OPTION_MENU(option_menu), menu);
1105
1106 if(sel_index == -1) {
1107 DEBUG(("[crossfade] scan_effect_plugins: plugin not found (\"%s\")\n", selected));
1108 return def_index; /* use default (first entry) */
1109 }
1110 return sel_index;
1111 }
1112
1113 /*-- plugin output callbacks ------------------------------------------------*/
1114
1115 static void
1116 config_effect_plugin_cb(GtkWidget *widget, gint index)
1117 {
1118 EffectPlugin *ep = g_list_nth_data(get_effect_list(), index); /* XMMS */
1119
1120 /* select new plugin */
1121 ep_index = index;
1122
1123 /* get new plugin's name */
1124 if(cfg->ep_name) g_free(cfg->ep_name);
1125 cfg->ep_name = (ep && ep->filename)
1126 ? g_strdup(g_basename(ep->filename)) : NULL;
1127
1128 /* update gui */
1129 SET_SENSITIVE("ep_configure_button", ep && (ep->configure != NULL));
1130 SET_SENSITIVE("ep_about_button", ep && (ep->about != NULL));
1131
1132 /* 0.3.5: apply effect config immediatelly */
1133 if(config->ep_name) g_free(config->ep_name);
1134 config->ep_name = g_strdup(cfg->ep_name);
1135 xfade_realize_ep_config();
1136 }
1137
1138 void on_ep_configure_button_clicked(GtkButton *button, gpointer user_data)
1139 {
1140 EffectPlugin *ep = g_list_nth_data(get_effect_list(), ep_index); /* XMMS */
1141 if((ep == NULL) || (ep->configure == NULL)) return;
1142 ep->configure();
1143 }
1144
1145 void on_ep_about_button_clicked(GtkButton *button, gpointer user_data)
1146 {
1147 EffectPlugin *ep = g_list_nth_data(get_effect_list(), ep_index); /* XMMS */
1148 if((ep == NULL) || (ep->about == NULL)) return;
1149 ep->about();
1150 }
1151
1152 void on_ep_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1153 {
1154 /* 0.3.5: apply effect config immediatelly */
1155 config->ep_enable = cfg->ep_enable = GET_TOGGLE("ep_enable_check");
1156 xfade_realize_ep_config();
1157 }
1158
1159 /*-- volume normalizer ------------------------------------------------------*/
1160
1161 void check_effects_dependencies()
1162 {
1163 if(checking) return;
1164 checking = TRUE;
1165
1166 SET_SENSITIVE("volnorm_target_spin", cfg->volnorm_enable);
1167 SET_SENSITIVE("volnorm_target_label", cfg->volnorm_enable);
1168 SET_SENSITIVE("volnorm_quantaudio_check", cfg->volnorm_enable);
1169 SET_SENSITIVE("volnorm_target_spin", cfg->volnorm_enable);
1170
1171 checking = FALSE;
1172 }
1173
1174 void on_volnorm_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1175 {
1176 if(checking) return;
1177 cfg->volnorm_enable = gtk_toggle_button_get_active(togglebutton);
1178 check_effects_dependencies();
1179 }
1180
1181 /*** crossfader **************************************************************/
1182
1183 static void xf_config_cb(GtkWidget *widget, gint index);
1184 static void xf_type_cb (GtkWidget *widget, gint index);
1185
1186 /* crude hack to keep track of menu items */
1187 static gint xf_config_index_map[MAX_FADE_CONFIGS];
1188 static gint xf_type_index_map [MAX_FADE_TYPES];
1189
1190 static void
1191 create_crossfader_config_menu()
1192 {
1193 GtkWidget *optionmenu, *menu;
1194 gint i, *imap;
1195
1196 if((optionmenu = lookup_widget(config_win, "xf_config_optionmenu"))) {
1197 for(i=0; i<MAX_FADE_CONFIGS; i++) xf_config_index_map[i] = -1;
1198 imap = xf_config_index_map;
1199 menu = gtk_menu_new();
1200 add_menu_item(menu, "Start of playback", xf_config_cb, FADE_CONFIG_START, &imap);
1201 add_menu_item(menu, "Automatic songchange", xf_config_cb, FADE_CONFIG_XFADE, &imap);
1202 #if 0
1203 /* this should be FADE_TYPE_NONE all the time, anyway,
1204 so no need to make it configureable by the user */
1205 add_menu_item(menu, "Automatic (gapless)", xf_config_cb, FADE_CONFIG_ALBUM, &imap);
1206 #endif
1207 add_menu_item(menu, "Manual songchange", xf_config_cb, FADE_CONFIG_MANUAL, &imap);
1208 add_menu_item(menu, "Manual stop", xf_config_cb, FADE_CONFIG_STOP, &imap);
1209 add_menu_item(menu, "End of playlist", xf_config_cb, FADE_CONFIG_EOP, &imap);
1210 add_menu_item(menu, "Seeking", xf_config_cb, FADE_CONFIG_SEEK, &imap);
1211 add_menu_item(menu, "Pause", xf_config_cb, FADE_CONFIG_PAUSE, &imap);
1212 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu), menu);
1213 }
1214
1215 }
1216
1217 static void
1218 create_crossfader_type_menu()
1219 {
1220 GtkWidget *optionmenu, *menu;
1221 gint i, *imap;
1222 guint32 mask;
1223
1224 if((optionmenu = lookup_widget(config_win, "xf_type_optionmenu"))) {
1225 for(i=0; i<MAX_FADE_TYPES; i++) xf_type_index_map[i] = -1;
1226 imap = xf_type_index_map;
1227 menu = gtk_menu_new();
1228 mask = cfg->fc[cfg->xf_index].type_mask;
1229 if(mask & (1 << FADE_TYPE_REOPEN)) add_menu_item(menu, "Reopen output device", xf_type_cb, FADE_TYPE_REOPEN, &imap);
1230 if(mask & (1 << FADE_TYPE_FLUSH)) add_menu_item(menu, "Flush output device", xf_type_cb, FADE_TYPE_FLUSH, &imap);
1231 if(mask & (1 << FADE_TYPE_NONE)) add_menu_item(menu, "None (gapless/off)", xf_type_cb, FADE_TYPE_NONE, &imap);
1232 if(mask & (1 << FADE_TYPE_PAUSE)) add_menu_item(menu, "Pause", xf_type_cb, FADE_TYPE_PAUSE, &imap);
1233 if(mask & (1 << FADE_TYPE_SIMPLE_XF)) add_menu_item(menu, "Simple crossfade", xf_type_cb, FADE_TYPE_SIMPLE_XF, &imap);
1234 if(mask & (1 << FADE_TYPE_ADVANCED_XF)) add_menu_item(menu, "Advanced crossfade", xf_type_cb, FADE_TYPE_ADVANCED_XF, &imap);
1235 if(mask & (1 << FADE_TYPE_FADEIN)) add_menu_item(menu, "Fadein", xf_type_cb, FADE_TYPE_FADEIN, &imap);
1236 if(mask & (1 << FADE_TYPE_FADEOUT)) add_menu_item(menu, "Fadeout", xf_type_cb, FADE_TYPE_FADEOUT, &imap);
1237 if(mask & (1 << FADE_TYPE_PAUSE_NONE)) add_menu_item(menu, "None", xf_type_cb, FADE_TYPE_PAUSE_NONE, &imap);
1238 if(mask & (1 << FADE_TYPE_PAUSE_ADV)) add_menu_item(menu, "Fadeout/Fadein", xf_type_cb, FADE_TYPE_PAUSE_ADV, &imap);
1239 gtk_option_menu_set_menu(GTK_OPTION_MENU(optionmenu), menu);
1240 }
1241 }
1242
1243 #define NONE 0x00000000L
1244 #define XF_CONFIG 0x00000001L
1245 #define XF_TYPE 0x00000002L
1246 #define XF_MIX_SIZE 0x00000004L
1247 #define XF_FADEOUT 0x00000008L
1248 #define XF_OFFSET 0x00000010L
1249 #define XF_FADEIN 0x00000020L
1250 #define XF_PAGE 0x00000040L
1251 #define XF_FLUSH 0x00000080L
1252 #define ANY 0xffffffffL
1253
1254 static void
1255 check_crossfader_dependencies(guint32 mask)
1256 {
1257 fade_config_t *fc = &cfg->fc[cfg->xf_index];
1258 gint i;
1259
1260 /* HACK: avoid endless recursion */
1261 if(checking) return;
1262 checking = TRUE;
1263
1264 if(mask & XF_FLUSH) {
1265 SET_TOGGLE ("xftfp_enable_check", fc->flush_pause_enable);
1266 SET_SENSITIVE("xftfp_length_label", fc->flush_pause_enable);
1267 SET_SENSITIVE("xftfp_length_spin", fc->flush_pause_enable);
1268 SET_TOGGLE ("xftffi_enable_check", fc->flush_in_enable);
1269 SET_SENSITIVE("xftffi_length_label", fc->flush_in_enable);
1270 SET_SENSITIVE("xftffi_length_spin", fc->flush_in_enable);
1271 SET_SENSITIVE("xftffi_volume_label", fc->flush_in_enable);
1272 SET_SENSITIVE("xftffi_volume_spin", fc->flush_in_enable);
1273 }
1274
1275 if(mask & XF_MIX_SIZE) {
1276 SET_TOGGLE ("xf_autobuf_check", cfg->mix_size_auto);
1277 SET_SENSITIVE("xf_buffer_spin", !cfg->mix_size_auto);
1278 SET_SPIN ("xf_buffer_spin", xfade_mix_size_ms(cfg));
1279 }
1280
1281 if(mask & XF_CONFIG) {
1282 for(i=0; i<MAX_FADE_CONFIGS && (xf_config_index_map[i] != cfg->xf_index); i++);
1283 if(i == MAX_FADE_CONFIGS) i=0;
1284 SET_HISTORY("xf_config_optionmenu", i);
1285 }
1286
1287 if(mask & XF_TYPE) {
1288 create_crossfader_type_menu();
1289 for(i=0; i<MAX_FADE_TYPES && (xf_type_index_map[i] != fc->type); i++);
1290 if(i == MAX_FADE_TYPES) {
1291 fc->type = FADE_TYPE_NONE;
1292 for(i=0; i<MAX_FADE_TYPES && (xf_type_index_map[i] != fc->type); i++);
1293 if(i == MAX_FADE_CONFIGS) i=0;
1294 }
1295 SET_HISTORY("xf_type_optionmenu", i);
1296 }
1297
1298 if(mask & XF_PAGE) {
1299 SET_PAGE("xf_type_notebook", fc->type);
1300 SET_SPIN("pause_length_spin", fc->pause_len_ms);
1301 SET_SPIN("simple_length_spin", fc->simple_len_ms);
1302 if(fc->config == FADE_CONFIG_SEEK) {
1303 HIDE("xftf_pause_frame");
1304 HIDE("xftf_fadein_frame");
1305 }
1306 else {
1307 SHOW("xftf_pause_frame");
1308 SHOW("xftf_fadein_frame");
1309 }
1310 }
1311
1312 if(mask & XF_FADEOUT) {
1313 SET_TOGGLE ("fadeout_enable_check", fc->out_enable);
1314 SET_SENSITIVE("fadeout_length_label", fc->out_enable);
1315 SET_SENSITIVE("fadeout_length_spin", fc->out_enable);
1316 SET_SPIN ("fadeout_length_spin", fc->out_len_ms);
1317 SET_SENSITIVE("fadeout_volume_label", fc->out_enable);
1318 SET_SENSITIVE("fadeout_volume_spin", fc->out_enable);
1319 SET_SPIN ("fadeout_volume_spin", fc->out_volume);
1320 SET_SPIN ("xftfo_length_spin", fc->out_len_ms);
1321 SET_SPIN ("xftfo_volume_spin", fc->out_volume);
1322 SET_SPIN ("xftfoi_fadeout_spin", fc->out_len_ms);
1323 }
1324
1325 if(mask & XF_FADEIN) {
1326 SET_TOGGLE ("fadein_lock_check", fc->in_locked);
1327 SET_SENSITIVE("fadein_enable_check", !fc->in_locked);
1328 SET_TOGGLE ("fadein_enable_check", fc->in_locked ? fc->out_enable : fc->in_enable);
1329 SET_SENSITIVE("fadein_length_label", !fc->in_locked && fc->in_enable);
1330 SET_SENSITIVE("fadein_length_spin", !fc->in_locked && fc->in_enable);
1331 SET_SPIN ("fadein_length_spin", fc->in_locked ? fc->out_len_ms : fc->in_len_ms);
1332 SET_SENSITIVE("fadein_volume_label", !fc->in_locked && fc->in_enable);
1333 SET_SENSITIVE("fadein_volume_spin", !fc->in_locked && fc->in_enable);
1334 SET_SPIN ("fadein_volume_spin", fc->in_locked ? fc->out_volume : fc->in_volume);
1335 SET_SPIN ("xftfi_length_spin", fc->in_len_ms);
1336 SET_SPIN ("xftfi_volume_spin", fc->in_volume);
1337 SET_SPIN ("xftfoi_fadein_spin", fc->in_len_ms);
1338 }
1339
1340 if(mask & XF_OFFSET) {
1341 if(fc->out_enable)
1342 SET_SENSITIVE("xfofs_lockout_radiobutton", TRUE);
1343 if(!fc->in_locked && fc->in_enable)
1344 SET_SENSITIVE("xfofs_lockin_radiobutton", TRUE);
1345
1346 switch(fc->ofs_type) {
1347 case FC_OFFSET_LOCK_OUT:
1348 if(!fc->out_enable) {
1349 SET_TOGGLE("xfofs_none_radiobutton", TRUE);
1350 fc->ofs_type = FC_OFFSET_NONE;
1351 }
1352 break;
1353 case FC_OFFSET_LOCK_IN:
1354 if(!(!fc->in_locked && fc->in_enable)) {
1355 if((fc->in_locked && fc->out_enable)) {
1356 SET_TOGGLE("xfofs_lockout_radiobutton", TRUE);
1357 fc->ofs_type = FC_OFFSET_LOCK_OUT;
1358 } else {
1359 SET_TOGGLE("xfofs_none_radiobutton", TRUE);
1360 fc->ofs_type = FC_OFFSET_NONE;
1361 }
1362 }
1363 break;
1364 }
1365
1366 switch(fc->ofs_type_wanted) {
1367 case FC_OFFSET_NONE:
1368 SET_TOGGLE("xfofs_none_radiobutton", TRUE);
1369 fc->ofs_type = FC_OFFSET_NONE;
1370 break;
1371 case FC_OFFSET_LOCK_OUT:
1372 if(fc->out_enable) {
1373 SET_TOGGLE("xfofs_lockout_radiobutton", TRUE);
1374 fc->ofs_type = FC_OFFSET_LOCK_OUT;
1375 }
1376 break;
1377 case FC_OFFSET_LOCK_IN:
1378 if(!fc->in_locked && fc->in_enable) {
1379 SET_TOGGLE("xfofs_lockin_radiobutton", TRUE);
1380 fc->ofs_type = FC_OFFSET_LOCK_IN;
1381 }
1382 else if(fc->out_enable) {
1383 SET_TOGGLE("xfofs_lockout_radiobutton", TRUE);
1384 fc->ofs_type = FC_OFFSET_LOCK_OUT;
1385 }
1386 break;
1387 case FC_OFFSET_CUSTOM:
1388 SET_TOGGLE("xfofs_custom_radiobutton", TRUE);
1389 fc->ofs_type = FC_OFFSET_CUSTOM;
1390 break;
1391 }
1392
1393 if(!fc->out_enable)
1394 SET_SENSITIVE("xfofs_lockout_radiobutton", FALSE);
1395 if(!(!fc->in_locked && fc->in_enable))
1396 SET_SENSITIVE("xfofs_lockin_radiobutton", FALSE);
1397
1398 SET_SENSITIVE("xfofs_custom_spin", fc->ofs_type == FC_OFFSET_CUSTOM);
1399 SET_SPIN ("xfofs_custom_spin", xfade_cfg_offset(fc));
1400 SET_SPIN ("xftfo_silence_spin", xfade_cfg_offset(fc));
1401 SET_SPIN ("xftfoi_silence_spin", xfade_cfg_offset(fc));
1402 }
1403
1404 checking = FALSE;
1405 }
1406
1407 /*-- crossfader callbacks ---------------------------------------------------*/
1408
1409 void on_xf_buffer_spin_changed(GtkEditable *editable, gpointer user_data)
1410 {
1411 if(checking) return;
1412 cfg->mix_size_ms = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1413 check_crossfader_dependencies(NONE);
1414 }
1415
1416 void on_xf_autobuf_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1417 {
1418 cfg->mix_size_auto = gtk_toggle_button_get_active(togglebutton);
1419 check_crossfader_dependencies(XF_MIX_SIZE);
1420 }
1421
1422 /* - config/type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1423
1424 void xf_config_cb(GtkWidget *widget, gint index)
1425 {
1426 if(checking) return;
1427 cfg->xf_index = index;
1428 check_crossfader_dependencies(ANY & ~XF_CONFIG);
1429 }
1430
1431 void xf_type_cb(GtkWidget *widget, gint index)
1432 {
1433 if(checking) return;
1434 cfg->fc[cfg->xf_index].type = index;
1435 check_crossfader_dependencies(ANY & ~XF_CONFIG);
1436 }
1437
1438 /* - flush - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1439
1440 void on_xftfp_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1441 {
1442 if(checking) return;
1443 cfg->fc[cfg->xf_index].flush_pause_enable
1444 = gtk_toggle_button_get_active(togglebutton);
1445 check_crossfader_dependencies(XF_FLUSH|XF_MIX_SIZE);
1446 }
1447
1448 void on_xftfp_length_spin_changed(GtkEditable *editable, gpointer user_data)
1449 {
1450 if(checking) return;
1451 cfg->fc[cfg->xf_index].flush_pause_len_ms
1452 = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1453 check_crossfader_dependencies(XF_FLUSH);
1454 }
1455
1456 void on_xftffi_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1457 {
1458 if(checking) return;
1459 cfg->fc[cfg->xf_index].flush_in_enable
1460 = gtk_toggle_button_get_active(togglebutton);
1461 check_crossfader_dependencies(XF_FLUSH|XF_OFFSET|XF_FADEOUT|XF_FADEIN);
1462 }
1463
1464 void on_xftffi_length_spin_changed(GtkEditable *editable, gpointer user_data)
1465 {
1466 if(checking) return;
1467 cfg->fc[cfg->xf_index].flush_in_len_ms
1468 = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1469 check_crossfader_dependencies(XF_FLUSH);
1470 }
1471
1472 void on_xftffi_volume_spin_changed(GtkEditable *editable, gpointer user_data)
1473 {
1474 if(checking) return;
1475 cfg->fc[cfg->xf_index].flush_in_volume
1476 = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1477 check_crossfader_dependencies(XF_FLUSH);
1478 }
1479
1480 /* - pause - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1481
1482 void on_pause_length_spin_changed(GtkEditable *editable, gpointer user_data)
1483 {
1484 if(checking) return;
1485 cfg->fc[cfg->xf_index].pause_len_ms
1486 = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1487 check_crossfader_dependencies(XF_MIX_SIZE);
1488 }
1489
1490 /* - simple - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1491
1492 void on_simple_length_spin_changed(GtkEditable *editable, gpointer user_data)
1493 {
1494 if(checking) return;
1495 cfg->fc[cfg->xf_index].simple_len_ms
1496 = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1497 check_crossfader_dependencies(XF_MIX_SIZE);
1498 }
1499
1500 /* - crossfade-fadeout - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1501
1502 void on_fadeout_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1503 {
1504 if(checking) return;
1505 cfg->fc[cfg->xf_index].out_enable
1506 = gtk_toggle_button_get_active(togglebutton);
1507 check_crossfader_dependencies(XF_MIX_SIZE|XF_OFFSET|XF_FADEOUT|XF_FADEIN);
1508 }
1509
1510 void on_fadeout_length_spin_changed(GtkEditable *editable, gpointer user_data)
1511 {
1512 if(checking) return;
1513 cfg->fc[cfg->xf_index].out_len_ms
1514 = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1515 check_crossfader_dependencies(XF_MIX_SIZE|XF_OFFSET|XF_FADEIN);
1516 }
1517
1518 void on_fadeout_volume_spin_changed(GtkEditable *editable, gpointer user_data)
1519 {
1520 cfg->fc[cfg->xf_index].out_volume
1521 = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1522 check_crossfader_dependencies(XF_OFFSET|XF_FADEIN);
1523 }
1524
1525 /* - crossfade-offset - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1526
1527 void on_xfofs_none_radiobutton_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1528 {
1529 if(checking || !gtk_toggle_button_get_active(togglebutton)) return;
1530 cfg->fc[cfg->xf_index].ofs_type = FC_OFFSET_NONE;
1531 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_NONE;
1532 check_crossfader_dependencies(XF_MIX_SIZE|XF_OFFSET);
1533 }
1534
1535 void on_xfofs_none_radiobutton_clicked(GtkButton *button, gpointer user_data)
1536 {
1537 if(checking) return;
1538 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_NONE;
1539 }
1540
1541 void on_xfofs_lockout_radiobutton_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1542 {
1543 if(checking || !gtk_toggle_button_get_active(togglebutton)) return;
1544 cfg->fc[cfg->xf_index].ofs_type = FC_OFFSET_LOCK_OUT;
1545 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_LOCK_OUT;
1546 check_crossfader_dependencies(XF_MIX_SIZE|XF_OFFSET);
1547 }
1548
1549 void on_xfofs_lockout_radiobutton_clicked(GtkButton *button, gpointer user_data)
1550 {
1551 if(checking) return;
1552 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_LOCK_OUT;
1553 }
1554
1555 void on_xfofs_lockin_radiobutton_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1556 {
1557 if(checking || !gtk_toggle_button_get_active(togglebutton)) return;
1558 cfg->fc[cfg->xf_index].ofs_type = FC_OFFSET_LOCK_IN;
1559 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_LOCK_IN;
1560 check_crossfader_dependencies(XF_MIX_SIZE|XF_OFFSET);
1561 }
1562
1563 void on_xfofs_lockin_radiobutton_clicked(GtkButton *button, gpointer user_data)
1564 {
1565 if(checking) return;
1566 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_LOCK_IN;
1567 }
1568
1569 void on_xfofs_custom_radiobutton_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1570 {
1571 if(checking || !gtk_toggle_button_get_active(togglebutton)) return;
1572 cfg->fc[cfg->xf_index].ofs_type = FC_OFFSET_CUSTOM;
1573 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_CUSTOM;
1574 check_crossfader_dependencies(XF_MIX_SIZE|XF_OFFSET);
1575 }
1576
1577 void on_xfofs_custom_radiobutton_clicked(GtkButton *button, gpointer user_data)
1578 {
1579 if(checking) return;
1580 cfg->fc[cfg->xf_index].ofs_type_wanted = FC_OFFSET_CUSTOM;
1581 }
1582
1583 void on_xfofs_custom_spin_changed(GtkEditable *editable, gpointer user_data)
1584 {
1585 if(checking) return;
1586 cfg->fc[cfg->xf_index].ofs_custom_ms = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1587 check_crossfader_dependencies(XF_MIX_SIZE);
1588 }
1589
1590 /* - crossfade-fadein - - - - - - - - - - - - - - - - - - - - - - - - - - - -*/
1591
1592 void on_fadein_lock_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1593 {
1594 if(checking) return;
1595 cfg->fc[cfg->xf_index].in_locked = gtk_toggle_button_get_active(togglebutton);
1596 check_crossfader_dependencies(XF_OFFSET|XF_FADEIN);
1597 }
1598
1599 void on_fadein_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1600 {
1601 if(checking) return;
1602 cfg->fc[cfg->xf_index].in_enable = gtk_toggle_button_get_active(togglebutton);
1603 check_crossfader_dependencies(XF_OFFSET|XF_FADEIN);
1604 }
1605
1606 void on_fadein_length_spin_changed(GtkEditable *editable, gpointer user_data)
1607 {
1608 if(checking) return;
1609 cfg->fc[cfg->xf_index].in_len_ms = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1610 check_crossfader_dependencies(XF_MIX_SIZE|XF_OFFSET);
1611 }
1612
1613 void on_fadein_volume_spin_changed(GtkEditable *editable, gpointer user_data)
1614 {
1615 if(checking) return;
1616 cfg->fc[cfg->xf_index].in_volume = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1617 check_crossfader_dependencies(NONE);
1618 }
1619
1620 /*-- fadein -----------------------------------------------------------------*/
1621
1622 /* signal set to on_fadein_length_spin_changed */
1623 /* signal set to on_fadein_volume_spin_changed */
1624
1625 /*-- fadeout ----------------------------------------------------------------*/
1626
1627 /* signal set to on_fadeout_length_spin_changed */
1628 /* signal set to on_fadeout_volume_spin_changed */
1629
1630 /*-- fadeout/fadein ---------------------------------------------------------*/
1631
1632 /* signal set to on_fadeout_length_spin_changed */
1633 /* signal set to on_xfofs_custom_spin_changed */
1634 /* signal set to on_fadeout_volume_spin_changed */
1635
1636 /*** gap killer **************************************************************/
1637
1638 void check_gapkiller_dependencies()
1639 {
1640 if(checking) return;
1641 checking = TRUE;
1642
1643 SET_SENSITIVE("lgap_length_spin", cfg->gap_lead_enable);
1644 SET_SENSITIVE("lgap_level_spin", cfg->gap_lead_enable);
1645 SET_SENSITIVE("tgap_enable_check", !cfg->gap_trail_locked);
1646 SET_SENSITIVE("tgap_length_spin", !cfg->gap_trail_locked && cfg->gap_trail_enable);
1647 SET_SENSITIVE("tgap_level_spin", !cfg->gap_trail_locked && cfg->gap_trail_enable);
1648
1649 if(cfg->gap_trail_locked) {
1650 SET_TOGGLE("tgap_enable_check", cfg->gap_lead_enable);
1651 SET_SPIN ("tgap_length_spin", cfg->gap_lead_len_ms);
1652 SET_SPIN ("tgap_level_spin", cfg->gap_lead_level);
1653 }
1654 else {
1655 SET_TOGGLE("tgap_enable_check", cfg->gap_trail_enable);
1656 SET_SPIN ("tgap_length_spin", cfg->gap_trail_len_ms);
1657 SET_SPIN ("tgap_level_spin", cfg->gap_trail_level);
1658 }
1659
1660 if(cfg->mix_size_auto)
1661 SET_SPIN("xf_buffer_spin", xfade_mix_size_ms(cfg));
1662
1663 checking = FALSE;
1664 }
1665
1666 /*-- gapkiller callbacks ----------------------------------------------------*/
1667
1668 void on_lgap_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1669 {
1670 if(checking) return;
1671 cfg->gap_lead_enable = gtk_toggle_button_get_active(togglebutton);
1672 check_gapkiller_dependencies();
1673 }
1674
1675 void on_lgap_length_spin_changed(GtkEditable *editable, gpointer user_data)
1676 {
1677 if(checking) return;
1678 cfg->gap_lead_len_ms = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1679 check_gapkiller_dependencies();
1680 }
1681
1682 void on_lgap_level_spin_changed(GtkEditable *editable, gpointer user_data)
1683 {
1684 if(checking) return;
1685 cfg->gap_lead_level = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1686 check_gapkiller_dependencies();
1687 }
1688
1689 void on_tgap_lock_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1690 {
1691 if(checking) return;
1692 cfg->gap_trail_locked = gtk_toggle_button_get_active(togglebutton);
1693 check_gapkiller_dependencies();
1694 }
1695
1696 void on_tgap_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1697 {
1698 if(checking) return;
1699 cfg->gap_trail_enable = gtk_toggle_button_get_active(togglebutton);
1700 check_gapkiller_dependencies();
1701 }
1702
1703 void on_tgap_length_spin_changed(GtkEditable *editable, gpointer user_data)
1704 {
1705 if(checking) return;
1706 cfg->gap_trail_len_ms = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1707 }
1708
1709 void on_tgap_level_spin_changed(GtkEditable *editable, gpointer user_data)
1710 {
1711 if(checking) return;
1712 cfg->gap_trail_level = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1713 }
1714
1715 /*** misc ********************************************************************/
1716
1717 void check_misc_dependencies()
1718 {
1719 if(checking) return;
1720 checking = TRUE;
1721
1722 if(cfg->mix_size_auto)
1723 SET_SPIN("xf_buffer_spin", xfade_mix_size_ms(cfg));
1724
1725 SET_SENSITIVE("moth_opmaxused_spin", cfg->enable_op_max_used);
1726
1727 checking = FALSE;
1728 }
1729
1730 /*-- misc callbacks ---------------------------------------------------------*/
1731
1732 void on_config_mixopt_enable_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1733 {
1734 SET_SENSITIVE("mixopt_reverse_check", gtk_toggle_button_get_active(togglebutton));
1735 SET_SENSITIVE("mixopt_software_check", gtk_toggle_button_get_active(togglebutton));
1736 }
1737
1738 void on_moth_songchange_spin_changed(GtkEditable *editable, gpointer user_data)
1739 {
1740 if(checking) return;
1741 cfg->songchange_timeout = gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(editable));
1742 check_misc_dependencies();
1743 }
1744
1745 void on_moth_opmaxused_check_toggled(GtkToggleButton *togglebutton, gpointer user_data)
1746 {
1747 if(checking) return;
1748 cfg->enable_op_max_used = gtk_toggle_button_get_active(togglebutton);
1749 check_misc_dependencies();
1750 }
1751
1752 /*** presets *****************************************************************/
1753
1754 void on_presets_list_click_column(GtkCList *clist, gint column, gpointer user_data)
1755 {
1756 DEBUG(("*** column=%d\n", column));
1757 }
1758
1759 /*** main config *************************************************************/
1760
1761 void on_config_apply_clicked(GtkButton *button, gpointer user_data)
1762 {
1763 GtkWidget *widget;
1764
1765 /* get current notebook page */
1766 if((widget = lookup_widget(config_win, "config_notebook")))
1767 cfg->page = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget));
1768
1769 /* output method */
1770
1771 /* sample rate */
1772
1773 /* output method: builtin OSS */
1774 if((widget = lookup_widget(config_win, "output_oss_notebook")))
1775 cfg->oss_page = gtk_notebook_get_current_page(GTK_NOTEBOOK(widget));
1776
1777 if((widget = lookup_widget(config_win, "oss_adevice_alt_entry"))) {
1778 if(cfg->oss_alt_audio_device) g_free(cfg->oss_alt_audio_device);
1779 cfg->oss_alt_audio_device = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1);
1780 g_strstrip(cfg->oss_alt_audio_device);
1781 }
1782
1783 if((widget = lookup_widget(config_win, "oss_mdevice_alt_entry"))) {
1784 if(cfg->oss_alt_mixer_device) g_free(cfg->oss_alt_mixer_device);
1785 cfg->oss_alt_mixer_device = gtk_editable_get_chars(GTK_EDITABLE(widget), 0, -1);
1786 g_strstrip(cfg->oss_alt_mixer_device);
1787 }
1788
1789 cfg->oss_buffer_size_ms = GET_SPIN ("ossbuf_buffer_spin");
1790 cfg->oss_preload_size_ms = GET_SPIN ("ossbuf_preload_spin");
1791
1792 cfg->oss_fragments = GET_SPIN ("osshwb_fragments_spin");
1793 cfg->oss_fragment_size = GET_SPIN ("osshwb_fragsize_spin");
1794 cfg->oss_maxbuf_enable = GET_TOGGLE("osshwb_maxbuf_check");
1795
1796 cfg->oss_mixer_use_master = GET_TOGGLE("ossmixer_pcm_check");
1797
1798 /* output method: plugin */
1799 op_config.throttle_enable = GET_TOGGLE("op_throttle_check");
1800 op_config.max_write_enable = GET_TOGGLE("op_maxblock_check");
1801 op_config.max_write_len = GET_SPIN ("op_maxblock_spin");
1802 op_config.force_reopen = GET_TOGGLE("op_forcereopen_check");
1803
1804 xfade_save_plugin_config(&cfg->op_config_string, cfg->op_name, &op_config);
1805
1806 /* output method: none: */
1807
1808 /* effects: pre-mixing effect plugin */
1809
1810 /* effects: volume normalizer */
1811 cfg->volnorm_target = GET_SPIN ("volnorm_target_spin");
1812 cfg->volnorm_use_qa = GET_TOGGLE("volnorm_quantaudio_check");
1813
1814 /* crossfader */
1815 cfg->mix_size_auto = GET_TOGGLE("xf_autobuf_check");
1816
1817 /* gap killer */
1818 cfg->gap_lead_enable = GET_TOGGLE("lgap_enable_check");
1819 cfg->gap_lead_len_ms = GET_SPIN ("lgap_length_spin");
1820 cfg->gap_lead_level = GET_SPIN ("lgap_level_spin");
1821
1822 cfg->gap_trail_locked = GET_TOGGLE("tgap_lock_check");
1823
1824 cfg->gap_crossing = GET_TOGGLE("gadv_crossing_check");
1825
1826 /* misc */
1827 cfg->enable_debug = GET_TOGGLE("debug_stderr_check");
1828 cfg->enable_monitor = GET_TOGGLE("debug_monitor_check");
1829 cfg->enable_mixer = GET_TOGGLE("mixopt_enable_check");
1830 cfg->mixer_reverse = GET_TOGGLE("mixopt_reverse_check");
1831 cfg->mixer_software = GET_TOGGLE("mixopt_software_check");
1832 cfg->preload_size_ms = GET_SPIN ("moth_preload_spin");
1833 cfg->album_detection = GET_TOGGLE("noxf_album_check");
1834 cfg->no_xfade_if_same_file = GET_TOGGLE("noxf_samefile_check");
1835 cfg->enable_http_workaround = GET_TOGGLE("moth_httpworkaround_check");
1836 cfg->op_max_used_ms = GET_SPIN ("moth_opmaxused_spin");
1837 cfg->output_keep_opened = GET_TOGGLE("moth_outputkeepopened_check");
1838
1839 /* presets */
1840
1841 /* lock buffer */
1842 g_static_mutex_lock(&buffer_mutex);
1843
1844 /* free existing strings */
1845 if(config->oss_alt_audio_device) g_free(config->oss_alt_audio_device);
1846 if(config->oss_alt_mixer_device) g_free(config->oss_alt_mixer_device);
1847 if(config->op_config_string) g_free(config->op_config_string);
1848 if(config->op_name) g_free(config->op_name);
1849 if(config->ep_name) g_free(config->ep_name);
1850
1851 /* copy current settings (dupping the strings) */
1852 *config = *cfg;
1853 config->oss_alt_audio_device = g_strdup(cfg->oss_alt_audio_device);
1854 config->oss_alt_mixer_device = g_strdup(cfg->oss_alt_mixer_device);
1855 config->op_config_string = g_strdup(cfg->op_config_string);
1856 config->op_name = g_strdup(cfg->op_name);
1857 config->ep_name = g_strdup(cfg->ep_name);
1858
1859 /* tell the engine that the config has changed */
1860 xfade_realize_config();
1861
1862 /* unlock buffer */
1863 g_static_mutex_unlock(&buffer_mutex);
1864
1865 /* save configuration */
1866 xfade_save_config();
1867
1868 /* show/hide monitor win depending on config->enable_monitor */
1869 xfade_check_monitor_win();
1870 }
1871
1872 void on_config_ok_clicked(GtkButton *button, gpointer user_data)
1873 {
1874 /* apply and save config */
1875 on_config_apply_clicked(button, user_data);
1876
1877 /* close and destroy window */
1878 gtk_widget_destroy(config_win);
1879 }
1880
1881 void xfade_configure()
1882 {
1883 GtkWidget *widget;
1884
1885 if(!config_win) {
1886 /* create */
1887 if(!(config_win = create_config_win())) {
1888 DEBUG(("[crossfade] plugin_configure: error creating window!\n"));
1889 return;
1890 }
1891
1892 /* update config_win when window is destroyed */
1893 gtk_signal_connect(GTK_OBJECT(config_win), "destroy",
1894 GTK_SIGNAL_FUNC(gtk_widget_destroyed), &config_win);
1895
1896 /* free any strings that might be left in our local copy of the config */
1897 if(cfg->oss_alt_audio_device) g_free(cfg->oss_alt_audio_device);
1898 if(cfg->oss_alt_mixer_device) g_free(cfg->oss_alt_mixer_device);
1899 if(cfg->op_config_string) g_free(cfg->op_config_string);
1900 if(cfg->op_name) g_free(cfg->op_name);
1901 if(cfg->ep_name) g_free(cfg->ep_name);
1902
1903 /* copy current settings (dupping the strings) */
1904 *cfg = *config;
1905 cfg->oss_alt_audio_device = g_strdup(config->oss_alt_audio_device);
1906 cfg->oss_alt_mixer_device = g_strdup(config->oss_alt_mixer_device);
1907 cfg->op_config_string = g_strdup(config->op_config_string);
1908 cfg->op_name = g_strdup(config->op_name);
1909 cfg->ep_name = g_strdup(config->ep_name);
1910
1911 /* go to remembered notebook page */
1912 if((widget = lookup_widget(config_win, "config_notebook")))
1913 gtk_notebook_set_page(GTK_NOTEBOOK(widget), config->page);
1914
1915 /* output: method */
1916 #ifdef HAVE_OSS
1917 SET_SENSITIVE("output_oss_radio", TRUE);
1918 #else
1919 SET_SENSITIVE("output_oss_radio", FALSE);
1920 #endif
1921
1922 switch(cfg->output_method) {
1923 case OUTPUT_METHOD_BUILTIN_OSS:
1924 widget = lookup_widget(config_win, "output_oss_radio");
1925 break;
1926 case OUTPUT_METHOD_PLUGIN:
1927 widget = lookup_widget(config_win, "output_plugin_radio");
1928 break;
1929 case OUTPUT_METHOD_BUILTIN_NULL:
1930 widget = lookup_widget(config_win, "output_none_radio");
1931 break;
1932 default:
1933 widget = NULL;
1934 }
1935 if(widget) gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(widget), TRUE);
1936
1937 if((widget = lookup_widget(config_win, "output_notebook")))
1938 gtk_notebook_set_page(GTK_NOTEBOOK(widget), cfg->output_method);
1939
1940 /* output: resampling rate */
1941 if((widget = lookup_widget(config_win, "resampling_rate_optionmenu"))) {
1942 GtkWidget *menu = gtk_menu_new();
1943 GtkWidget *item;
1944
1945 item = gtk_menu_item_new_with_label("44100 Hz");
1946 gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(resampling_rate_cb), (gpointer)44100);
1947 gtk_widget_show(item);
1948 gtk_menu_append(GTK_MENU(menu), item);
1949
1950 item = gtk_menu_item_new_with_label("48000 Hz");
1951 gtk_signal_connect(GTK_OBJECT(item), "activate", GTK_SIGNAL_FUNC(resampling_rate_cb), (gpointer)48000);
1952 gtk_widget_show(item);
1953 gtk_menu_append(GTK_MENU(menu), item);
1954
1955 gtk_option_menu_set_menu(GTK_OPTION_MENU(widget), menu);
1956
1957 switch(cfg->output_rate) {
1958 default:
1959 DEBUG(("[crossfade] plugin_configure: WARNING: invalid output sample rate (%d)!\n", cfg->output_rate));
1960 DEBUG(("[crossfade] plugin_configure: ... using default of 44100\n"));
1961 cfg->output_rate = 44100;
1962 case 44100: gtk_option_menu_set_history(GTK_OPTION_MENU(widget), 0); break;
1963 case 48000: gtk_option_menu_set_history(GTK_OPTION_MENU(widget), 1); break;
1964 }
1965 }
1966
1967 /* output: resampling quality (libsamplerate setting) */
1968 #ifdef HAVE_LIBSAMPLERATE
1969 if((widget = lookup_widget(config_win, "resampling_quality_optionmenu"))) {
1970 GtkWidget *menu = gtk_menu_new();
1971 GtkWidget *item;
1972
1973 GtkTooltips *tooltips = (GtkTooltips *)gtk_object_get_data(GTK_OBJECT(config_win), "tooltips");
1974
1975 int converter_type;
1976 const char *name, *description;
1977 for(converter_type = 0; (name = src_get_name(converter_type));
1978 converter_type++) {
1979 description = src_get_description(converter_type);
1980
1981 item = gtk_menu_item_new_with_label(name);
1982 gtk_tooltips_set_tip(tooltips, item, description, NULL);
1983
1984 gtk_signal_connect(GTK_OBJECT(item), "activate",
1985 GTK_SIGNAL_FUNC(resampling_quality_cb), (gpointer)converter_type);
1986 gtk_widget_show(item);
1987 gtk_menu_append(GTK_MENU(menu), item);
1988 }
1989
1990 gtk_option_menu_set_menu (GTK_OPTION_MENU(widget), menu);
1991 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), cfg->output_quality);
1992 }
1993 #else
1994 HIDE("resampling_quality_hbox");
1995 HIDE("resampling_quality_optionmenu");
1996 #endif
1997
1998 /* output method: builtin OSS */
1999 if((widget = lookup_widget(config_win, "output_oss_notebook")))
2000 gtk_notebook_set_page(GTK_NOTEBOOK(widget), cfg->oss_page);
2001
2002 if((widget = lookup_widget(config_win, "oss_adevice_optionmenu"))) {
2003 scan_devices("Audio devices:", widget, config_adevice_cb);
2004 gtk_option_menu_set_history(GTK_OPTION_MENU(widget),
2005 cfg->oss_audio_device);
2006 gtk_widget_set_sensitive(widget, !cfg->oss_use_alt_audio_device);
2007 }
2008 SET_TOGGLE("oss_adevice_alt_check", cfg->oss_use_alt_audio_device);
2009 if((widget = lookup_widget(config_win, "oss_adevice_alt_entry"))) {
2010 gtk_entry_set_text(GTK_ENTRY(widget), cfg->oss_alt_audio_device
2011 ? cfg->oss_alt_audio_device
2012 : DEFAULT_OSS_ALT_AUDIO_DEVICE);
2013 gtk_widget_set_sensitive(widget, cfg->oss_use_alt_audio_device);
2014 }
2015
2016 if((widget = lookup_widget(config_win, "oss_mdevice_optionmenu"))) {
2017 scan_devices("Mixers:", widget, config_mdevice_cb);
2018 gtk_option_menu_set_history(GTK_OPTION_MENU(widget),
2019 cfg->oss_mixer_device);
2020 gtk_widget_set_sensitive(widget, !cfg->oss_use_alt_mixer_device);
2021 }
2022 SET_TOGGLE("oss_mdevice_alt_check", cfg->oss_use_alt_mixer_device);
2023 if((widget = lookup_widget(config_win, "oss_mdevice_alt_entry"))) {
2024 gtk_entry_set_text(GTK_ENTRY(widget), cfg->oss_alt_mixer_device
2025 ? cfg->oss_alt_mixer_device
2026 : DEFAULT_OSS_ALT_MIXER_DEVICE);
2027 gtk_widget_set_sensitive(widget, cfg->oss_use_alt_mixer_device);
2028 }
2029
2030 SET_SPIN ("ossbuf_buffer_spin", cfg->oss_buffer_size_ms);
2031 SET_SPIN ("ossbuf_preload_spin", cfg->oss_preload_size_ms);
2032
2033 SET_SPIN ("osshwb_fragments_spin", cfg->oss_fragments);
2034 SET_SPIN ("osshwb_fragsize_spin", cfg->oss_fragment_size);
2035 SET_TOGGLE("osshwb_maxbuf_check", cfg->oss_maxbuf_enable);
2036
2037 SET_TOGGLE("ossmixer_pcm_check", cfg->oss_mixer_use_master);
2038
2039 check_oss_dependencies();
2040
2041 /* output method: plugin */
2042 xfade_load_plugin_config(cfg->op_config_string, cfg->op_name, &op_config);
2043 SET_TOGGLE ("op_throttle_check", op_config.throttle_enable);
2044 SET_TOGGLE ("op_maxblock_check", op_config.max_write_enable);
2045 SET_SPIN ("op_maxblock_spin", op_config.max_write_len);
2046 SET_SENSITIVE("op_maxblock_spin", op_config.max_write_enable);
2047 SET_TOGGLE ("op_forcereopen_check", op_config.force_reopen);
2048
2049 if((widget = lookup_widget(config_win, "op_plugin_optionmenu"))) {
2050 OutputPlugin *op = NULL;
2051 if((op_index = scan_plugins(widget, cfg->op_name)) >= 0) {
2052 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), op_index);
2053 op = g_list_nth_data(get_output_list(), op_index); /* XMMS */
2054 }
2055 SET_SENSITIVE("op_configure_button", op && (op->configure != NULL));
2056 SET_SENSITIVE("op_about_button", op && (op->about != NULL));
2057 }
2058
2059 /* output method: none */
2060
2061 /* effects: pre-mixing effect plugin */
2062 if((widget = lookup_widget(config_win, "ep_plugin_optionmenu"))) {
2063 EffectPlugin *ep = NULL;
2064 if((ep_index = scan_effect_plugins(widget, cfg->ep_name)) >= 0) {
2065 gtk_option_menu_set_history(GTK_OPTION_MENU(widget), ep_index);
2066 ep = g_list_nth_data(get_effect_list(), ep_index); /* XMMS */
2067 }
2068 SET_SENSITIVE("ep_configure_button", ep && (ep->configure != NULL));
2069 SET_SENSITIVE("ep_about_button", ep && (ep->about != NULL));
2070 SET_TOGGLE ("ep_enable_check", cfg->ep_enable);
2071 }
2072
2073 /* effects: volume normalizer */
2074 SET_TOGGLE("volnorm_enable_check", cfg->volnorm_enable);
2075 SET_TOGGLE("volnorm_quantaudio_check", cfg->volnorm_use_qa);
2076 SET_SPIN ("volnorm_target_spin", cfg->volnorm_target);
2077
2078 check_effects_dependencies();
2079
2080 /* crossfader */
2081 create_crossfader_config_menu();
2082
2083 if((cfg->xf_index < 0) || (cfg->xf_index >= MAX_FADE_CONFIGS)) {
2084 DEBUG(("[crossfade] plugin_configure: crossfade index out of range (%d)!\n", cfg->xf_index));
2085 cfg->xf_index = CLAMP(cfg->xf_index, 0, MAX_FADE_CONFIGS);
2086 }
2087
2088 check_crossfader_dependencies(ANY);
2089
2090 /* gap killer */
2091 SET_TOGGLE ("lgap_enable_check", cfg->gap_lead_enable);
2092 SET_SPIN ("lgap_length_spin", cfg->gap_lead_len_ms);
2093 SET_SPIN ("lgap_level_spin", cfg->gap_lead_level);
2094 SET_TOGGLE ("tgap_lock_check", cfg->gap_trail_locked);
2095 SET_TOGGLE ("tgap_enable_check", cfg->gap_trail_enable);
2096 SET_SPIN ("tgap_length_spin", cfg->gap_trail_len_ms);
2097 SET_SPIN ("tgap_level_spin", cfg->gap_trail_level);
2098 SET_TOGGLE ("gadv_crossing_check", cfg->gap_crossing);
2099
2100 check_gapkiller_dependencies();
2101
2102 /* misc */
2103 SET_TOGGLE("debug_stderr_check", cfg->enable_debug);
2104 SET_TOGGLE("debug_monitor_check", cfg->enable_monitor);
2105 SET_TOGGLE("mixopt_enable_check", cfg->enable_mixer);
2106 SET_TOGGLE("mixopt_reverse_check", cfg->mixer_reverse);
2107 SET_TOGGLE("mixopt_software_check", cfg->mixer_software);
2108 SET_SPIN ("moth_songchange_spin", cfg->songchange_timeout);
2109 SET_SPIN ("moth_preload_spin", cfg->preload_size_ms);
2110 SET_TOGGLE("noxf_album_check", cfg->album_detection);
2111 SET_TOGGLE("noxf_samefile_check", cfg->album_detection);
2112 SET_TOGGLE("moth_httpworkaround_check", cfg->enable_http_workaround);
2113 SET_TOGGLE("moth_opmaxused_check", cfg->enable_op_max_used);
2114 SET_SPIN ("moth_opmaxused_spin", cfg->op_max_used_ms);
2115 SET_TOGGLE("moth_outputkeepopened_check", cfg->output_keep_opened);
2116
2117 check_misc_dependencies();
2118
2119 /* presets */
2120 if((set_wgt = lookup_widget(config_win, "presets_list_list"))) {
2121 GList *item;
2122
2123 for(item = config->presets; item; item = g_list_next(item)) {
2124 gchar *name = (gchar *)item->data;
2125 gchar *text[] = {name, "Default", "No"};
2126 gtk_clist_append(GTK_CLIST(set_wgt), text);
2127 }
2128 }
2129
2130 /* show window near mouse pointer */
2131 gtk_window_set_position(GTK_WINDOW(config_win), GTK_WIN_POS_MOUSE);
2132 gtk_widget_show(config_win);
2133 }
2134 else
2135 /* bring window to front */
2136 gdk_window_raise(config_win->window);
2137 }
2138
2139 void xfade_about()
2140 {
2141 if(!about_win) {
2142 gchar *about_text =
2143 "XMMS Crossfade Plugin "VERSION"\n"
2144 "Copyright (C) 2000-2004 Peter Eisenlohr <peter@eisenlohr.org>\n"
2145 "\n"
2146 "based on the original OSS Output Plugin Copyright (C) 1998-2000\n"
2147 "Peter Alm, Mikael Alm, Olle Hallnas, Thomas Nilsson and 4Front Technologies\n"
2148 "\n"
2149 "This program is free software; you can redistribute it and/or modify\n"
2150 "it under the terms of the GNU General Public License as published by\n"
2151 "the Free Software Foundation; either version 2 of the License, or\n"
2152 "(at your option) any later version.\n"
2153 "\n"
2154 "This program is distributed in the hope that it will be useful,\n"
2155 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2156 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2157 "GNU General Public License for more details.\n"
2158 "\n"
2159 "You should have received a copy of the GNU General Public License\n"
2160 "along with this program; if not, write to the Free Software\n"
2161 "Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,\n"
2162 "USA.";
2163
2164 about_win = create_about_win();
2165
2166 /* update about_win when window is destroyed */
2167 gtk_signal_connect(GTK_OBJECT(about_win), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &about_win);
2168
2169 /* set about box text (this is done here and not in interface.c because
2170 of the VERSION #define -- there is no way to do this with GLADE */
2171 if((set_wgt = lookup_widget(about_win, "about_label")))
2172 gtk_label_set_text(GTK_LABEL(set_wgt), about_text);
2173
2174 /* show near mouse pointer */
2175 gtk_window_set_position(GTK_WINDOW(about_win), GTK_WIN_POS_MOUSE);
2176 gtk_widget_show(about_win);
2177 }
2178 else
2179 gdk_window_raise(about_win->window);
2180 }