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