Adding support for Linux' POSIX capabilities - Alex
[terminatorX.git] / src / tX_dialog.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2003  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_dialog.cc
20  
21     Description: Contains the implementation of the Options and About
22                  Dialogs. (And some really ugly "WE WANT TO 
23                  TYPE LESS" macros)
24                  
25     Changes:
26     
27     28 Jul 1999: Now display compiletime settings in the about dialog.
28 */    
29
30 #include "config.h"
31 #include "tX_types.h"
32 #include "tX_global.h"
33 #include "tX_dialog.h"
34 #include <gtk/gtk.h>
35 #include <string.h>
36 #include <gdk/gdk.h>
37 #include "tX_icon.h"
38 #include "tX_glade_interface.h"
39 #include "tX_glade_support.h"
40
41 #include "tX_widget.h"
42 #include "tX_flash.h"
43
44 #ifndef WIN32
45 #include <X11/extensions/XInput.h>
46 #include <X11/X.h>
47 #endif
48
49 #include "license.c"
50 #include "tX_mastergui.h"
51 #include "version.h"
52 #include "tX_vtt.h"
53 #include <dirent.h>
54 #include "tX_engine.h"
55
56 #ifdef USE_SCHEDULER
57 #include <sched.h>
58 #endif
59
60 #ifdef USE_JACK
61 extern void jack_check();
62 #endif
63
64 extern char *logo_xpm[];
65 GtkWidget *opt_dialog;
66 int opt_hidden=0;
67
68 static GtkWidget *last_alsa_device_widget=NULL;
69 static GtkWidget *alsa_device_entry=NULL;
70
71 void apply_options(GtkWidget *dialog) {
72         /* Audio */
73         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_driver")))) {
74                 globals.audiodevice_type=ALSA;
75         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "oss_driver")))) {
76                 globals.audiodevice_type=OSS;
77         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "jack_driver")))) {
78                 globals.audiodevice_type=JACK;
79         }
80         globals.use_realtime=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "use_realtime")));
81         
82         /* Audio: OSS */
83         strcpy(globals.oss_device, gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "oss_audio_device"))->entry)));
84         globals.oss_buff_no=(int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(dialog, "oss_buffers")));
85         globals.oss_buff_size=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "oss_buffersize")));
86         globals.oss_samplerate=atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "oss_samplerate"))->entry)));
87         
88         /* Audio: ALSA */
89         strcpy(globals.alsa_device_id, gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "alsa_audio_device"))->entry)));
90         globals.alsa_buffer_time=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "alsa_buffer_time")));
91         globals.alsa_buffer_time*=1000;
92         globals.alsa_period_time=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "alsa_period_time")));
93         globals.alsa_period_time*=1000;
94         globals.alsa_samplerate=atoi(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "alsa_samplerate"))->entry)));        
95         globals.alsa_free_hwstats=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_free_hwstats")));
96         
97         /* TODO: JACK
98         */
99         
100         /* Input */
101         globals.xinput_enable=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "xinput_enable")))==TRUE);
102         strcpy(globals.xinput_device, gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "xinput_device"))->entry)));
103         globals.mouse_speed=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "mouse_speed")));
104         globals.sense_cycles=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "stop_sense_cycles")));
105         globals.vtt_inertia=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "vtt_inertia")));
106         
107         /* User Interface */ 
108         globals.show_nag=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "startup_nagbox")))==TRUE);
109         globals.tooltips=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "mainwin_tooltips")))==TRUE);
110         globals.filename_length=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(dialog, "filename_length")));
111         if (globals.tooltips) gtk_tooltips_enable(gui_tooltips);
112         else gtk_tooltips_disable(gui_tooltips);
113
114         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_only")))) {
115                 globals.button_type=BUTTON_TYPE_TEXT;
116         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_icon_only")))) {
117                 globals.button_type=BUTTON_TYPE_ICON;
118         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_and_icon")))) {
119                 globals.button_type=BUTTON_TYPE_BOTH;
120         }
121         
122         globals.update_delay=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "update_delay")));
123         globals.update_idle=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "update_idle")));
124         globals.flash_response=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "vumeter_decay")));
125         
126         /* Audio Colors */
127         
128         strcpy(globals.wav_display_bg_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_bg_focus")), "Color"));
129         strcpy(globals.wav_display_bg_no_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_bg_no_focus")), "Color"));
130         strcpy(globals.wav_display_fg_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_fg_focus")), "Color"));
131         strcpy(globals.wav_display_fg_no_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_fg_no_focus")), "Color"));
132         strcpy(globals.wav_display_cursor, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_cursor")), "Color"));
133         strcpy(globals.wav_display_cursor_mute, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_cursor_mute")), "Color"));
134
135         /* VU Colors */ 
136         strcpy(globals.vu_meter_bg, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "vu_meter_bg")), "Color"));
137         strcpy(globals.vu_meter_loud, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "vu_meter_loud")), "Color"));
138         strcpy(globals.vu_meter_normal, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "vu_meter_normal")), "Color"));
139
140         globals.vu_meter_border_intensity=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "vu_meter_border_intensity")));
141         
142         /* Misc */
143         strcpy(globals.file_editor, gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog, "soundfile_editor"))));
144         strcpy(globals.lrdf_path, gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path"))));
145         globals.compress_set_files=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "compress_set_files")))==TRUE);        
146         globals.prelis=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")))==TRUE);
147         globals.restore_midi_connections=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "reconnect_enabled")))==TRUE);
148         globals.quit_confirm=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "quit_confirm")))==TRUE);
149         
150         /* update colors */
151         std::list<vtt_class *>::iterator vtt;
152         
153         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++) {
154                 gtk_tx_update_colors(GTK_TX((*vtt)->gui.display));
155                 gtk_widget_queue_draw((*vtt)->gui.display);
156                 gtk_tx_flash_update_colors(GTK_TX_FLASH((*vtt)->gui.flash));
157                 gtk_widget_queue_draw((*vtt)->gui.flash);
158         }
159         
160         gtk_tx_flash_update_colors(GTK_TX_FLASH(main_flash_l));
161         gtk_widget_queue_draw(main_flash_l);
162         gtk_tx_flash_update_colors(GTK_TX_FLASH(main_flash_r));
163         gtk_widget_queue_draw(main_flash_r);
164         
165 #ifdef USE_JACK
166         jack_check();
167 #endif  
168 }
169
170
171 #define WID_DYN TRUE, TRUE, 0
172 #define WID_FIX FALSE, FALSE, 0
173
174 #define my_new_subsec(s); \
175         separator=gtk_hseparator_new(); \
176         gtk_box_pack_start(GTK_BOX(vbox), separator, WID_DYN);\
177         gtk_widget_show(separator); \
178         label=gtk_label_new(s); \
179         gtk_misc_set_alignment (GTK_MISC(label), 0 ,0.5); \
180         gtk_box_pack_start(GTK_BOX(vbox), label, WID_DYN); \
181         gtk_widget_show(label); 
182
183 #define my_new_button(btn, s); \
184         btn=gtk_button_new_with_label(s); \
185         gtk_box_pack_start(GTK_BOX(aa), btn, WID_DYN); \
186         gtk_widget_show(btn);
187         
188
189 #define begin_box(); box=gtk_hbox_new(FALSE, 5);
190
191 #define begin_hom_box(); box=gtk_hbox_new(TRUE, 5);
192
193 #define end_box(); gtk_box_pack_start(GTK_BOX(vbox), box, WID_DYN); \
194         gtk_widget_show(box);
195
196 #define add_widget_dyn(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN);\
197         gtk_widget_show(wid);
198         
199 #define add_widget_fix(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_FIX);\
200         gtk_widget_show(wid);
201
202 #define add_expl(s); label=gtk_label_new(s); \
203         gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);\
204         add_widget_fix(label);
205
206 #define add_expl_dyn(s); label=gtk_label_new(s); \
207         gtk_misc_set_alignment(GTK_MISC(label), 0.5, 0.5);\
208         add_widget_dyn(label);
209
210 #ifdef USE_ALSA
211 static GList *alsa_devices=NULL;
212
213 GList *get_alsa_device_list() {
214         if (alsa_devices) {
215                 return alsa_devices;
216         }
217         
218         FILE *file;
219         char buffer[PATH_MAX+1];
220         alsa_devices=NULL;
221         
222         if ((file = fopen("/proc/asound/pcm", "r"))) {
223                 while(fgets(buffer, PATH_MAX, file)) {
224                         buffer[PATH_MAX]=0;
225                         if (strlen(buffer)) buffer[strlen(buffer)-1]=0;
226                         if(strstr(buffer, "playback")) {
227                                 char foo[PATH_MAX];
228                                 char tmp[PATH_MAX];
229                                 memset(foo, 0, PATH_MAX);
230                                 int card;
231                                 int device;
232  
233                                 sscanf(buffer, "%i-%i: %1024c", &card, &device, foo);
234                                 sprintf(tmp, "hw:%i,%i# %s", card, device, foo);
235                                 
236                                 alsa_devices=g_list_append (alsa_devices, strdup(tmp));
237                         }
238                 }
239                 fclose(file);
240         }
241         
242         return alsa_devices;
243 }
244 #else
245 GList *get_alsa_device_list() {
246         return NULL;
247 }
248 #endif
249
250
251 #ifdef USE_OSS
252 static GList *oss_devices=NULL;
253
254 int oss_select_dsp_only(const struct dirent *entry){
255         return (strstr(entry->d_name, "dsp")!=0);
256 }
257
258 GList *get_oss_device_list() {
259         if (oss_devices) {
260                 return oss_devices;
261         }
262                 
263     struct dirent **namelist;
264     int n,i;
265     n = scandir("/dev", &namelist, oss_select_dsp_only, alphasort);
266     
267         oss_devices=NULL;
268         
269     if (n>0) {
270         for (i=0; i<n; i++) {
271                         char buffer[256];
272             sprintf(buffer, "/dev/%s", namelist[i]->d_name);
273             free(namelist[i]);
274                         oss_devices=g_list_append (oss_devices, strdup(buffer));
275                 }
276         }
277         
278         return oss_devices;
279 }
280 #endif
281
282 static GList *sampling_rates=NULL;
283
284 GList *get_sampling_rates_list() {
285         if (sampling_rates) {
286                 return sampling_rates;
287         }
288
289         sampling_rates=g_list_append(sampling_rates, (void *) "22000");
290         sampling_rates=g_list_append(sampling_rates, (void *) "32000");
291         sampling_rates=g_list_append(sampling_rates, (void *) "44100");
292         sampling_rates=g_list_append(sampling_rates, (void *) "48000");
293
294         return sampling_rates;  
295 }
296
297 static GList *xinput_devices=NULL;
298
299 GList *get_xinput_devices_list() {
300         if (xinput_devices) {
301                 return xinput_devices;
302         }
303         
304         int devmax;
305         Display *dpy=XOpenDisplay(NULL);
306         XDeviceInfo *xdev=XListInputDevices(dpy, &devmax);
307         XCloseDisplay(dpy);
308
309         for (int i=0; i<devmax; i++) {
310                 xinput_devices=g_list_append(xinput_devices, strdup(xdev[i].name));
311         }
312         
313         XFreeDeviceList(xdev);
314         
315         return xinput_devices;
316 }
317
318 #define MAX_COLORS 10
319 char *colors[MAX_COLORS]={ NULL };
320
321 #define set_color_button(s,g); \
322         sprintf(tmp, "<span foreground=\"%s\"><b>%s</b></span>", s, s);\
323         gtk_label_set_markup(GTK_LABEL(gtk_container_get_children(GTK_CONTAINER(lookup_widget(dialog, g)))->data), tmp);\
324         strcpy(colors[ctr], s);\
325         g_object_set_data(G_OBJECT(lookup_widget(dialog, g)), "Color", colors[ctr]);\
326         ctr++;
327
328
329 void init_tx_options(GtkWidget *dialog) {
330         GtkTooltips *tooltips=GTK_TOOLTIPS(lookup_widget(dialog, "tooltips"));
331         
332         if (colors[0]==NULL) {
333                 for (int i=0; i<MAX_COLORS; i++) {
334                         colors[i]=new char[8];
335                         colors[i][0]=0;
336                 }
337         }
338         
339         /* Audio */
340         switch (globals.audiodevice_type) {             
341                 case ALSA: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_driver")), 1);
342                         break;
343                 
344                 case JACK: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "jack_driver")), 1);
345                         break;
346
347                 case OSS: 
348                 default:
349                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "oss_driver")), 1);
350                         break;
351         }
352
353         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "use_realtime")), globals.use_realtime);
354         
355 #ifndef USE_OSS
356         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_driver"), 0);
357         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_audio_device"), 0);
358         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_buffers"), 0);
359         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_buffersize"), 0);
360 #endif
361         
362 #ifndef USE_ALSA
363         gtk_widget_set_sensitive(lookup_widget(dialog, "alsa_driver"), 0);      
364         // TODO: Rest!  
365 #endif
366         
367 #ifndef USE_JACK
368         gtk_widget_set_sensitive(lookup_widget(dialog, "jack_driver"), 0);
369 #endif  
370         
371         /* Audio: OSS */
372         GList *oss_list=get_oss_device_list();
373         if (oss_list) {
374                 gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(dialog, "oss_audio_device")), oss_list);
375         }
376         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "oss_audio_device"))->entry), globals.oss_device);
377
378         gtk_spin_button_set_value(GTK_SPIN_BUTTON(lookup_widget(dialog, "oss_buffers")), globals.oss_buff_no);
379         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "oss_buffersize")), globals.oss_buff_size);
380         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "oss_buffersize"), "Set the size of the kernel level audio buffers. On slower systems you might have to increase this value (if you hear \"clicks\" or drop-outs). Lower values mean lower latency though.", NULL);        
381         gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(dialog, "oss_samplerate")), get_sampling_rates_list());
382         char tmp[64];
383         sprintf(tmp, "%i", globals.oss_samplerate);
384         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "oss_samplerate"))->entry), tmp);
385         
386         
387         /* Audio: ALSA */
388         GtkCombo *combo=GTK_COMBO(lookup_widget(dialog, "alsa_audio_device"));
389         GList *alsa_list=get_alsa_device_list();
390         last_alsa_device_widget=NULL;
391         alsa_device_entry=combo->entry;
392         
393         if (alsa_list) {
394                 gtk_combo_set_popdown_strings(combo, get_alsa_device_list());
395         }
396         gtk_entry_set_text(GTK_ENTRY(combo->entry), globals.alsa_device_id);
397
398         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "alsa_buffer_time")), globals.alsa_buffer_time/1000);
399         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "alsa_buffer_time"), "Sets the size of the ALSA ring buffer. On slower systems you might have to increase this value (if you hear \"clicks\" or drop-outs). Lower values mean lower latency though.", NULL);       
400         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "alsa_period_time")), globals.alsa_period_time/1000);
401         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "alsa_period_time"), "The ALSA period time determines how much audio data will be written to the device at once. It is recommended to set this value to a half or a third of the ALSA buffer time.", NULL);        
402
403         gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(dialog, "alsa_samplerate")), get_sampling_rates_list());
404         sprintf(tmp, "%i", globals.alsa_samplerate);
405         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "alsa_samplerate"))->entry), tmp);
406         
407         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_free_hwstats")), globals.alsa_free_hwstats);
408         
409         /* Input */
410         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "xinput_enable")), globals.xinput_enable);
411         
412         gtk_combo_set_popdown_strings(GTK_COMBO(lookup_widget(dialog, "xinput_device")), get_xinput_devices_list());
413         gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(lookup_widget(dialog, "xinput_device"))->entry), globals.xinput_device);
414
415         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "mouse_speed")), globals.mouse_speed);
416         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "mouse_speed"), "The speed of your mouse in scratch mode. Use negative values to invert motion.", NULL);
417         
418         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "stop_sense_cycles")), globals.sense_cycles);
419         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "stop_sense_cycles"),"If there is no \"motion-event\" for x cycles, where x is the number of cycles you select here, terminatorX assumes mouse motion has stopped. For smaller buffer sizes (=> shorter cycle times) you might have to increase this value", NULL);        
420
421         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "vtt_inertia")), globals.vtt_inertia);
422         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "vtt_inertia"),"This value defines how fast the turntables will adapt to the speed input - the higher this value, the longer it will take the turntable to actually reach the target speed.", NULL);       
423
424         gtk_spin_button_set_value(GTK_SPIN_BUTTON(lookup_widget(dialog, "filename_length")), globals.filename_length);
425
426         /* User Interface */ 
427         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "startup_nagbox")), globals.show_nag);
428         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "mainwin_tooltips")), globals.tooltips);
429         
430         switch (globals.button_type) {
431                 case BUTTON_TYPE_TEXT:
432                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_only")), 1);
433                         break;
434                 
435                 case BUTTON_TYPE_ICON:
436                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_icon_only")), 1);
437                         break;
438                 
439                 case BUTTON_TYPE_BOTH:
440                 default:
441                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_and_icon")), 1);
442         }
443         
444         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "update_delay")), globals.update_delay);
445         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "update_delay"), "How often to update the slow widgets.", NULL);   
446         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "update_idle")), globals.update_idle);
447         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "update_idle"), "The update thread will idle for the selcted amount of milliseconds. If you want to have a more responsive display update increase this value - if you have performance problems reduce this value.", NULL);       
448         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "vumeter_decay")), globals.flash_response);
449         gtk_tooltips_set_tip(tooltips, lookup_widget(dialog, "vumeter_decay"), "Defines how fast the maximum values of the VU meters should be decayed.", NULL);        
450
451         /* Audio Colors */
452         int ctr=0;
453         
454         set_color_button(globals.wav_display_bg_focus, "wav_display_bg_focus");
455         set_color_button(globals.wav_display_bg_no_focus, "wav_display_bg_no_focus");
456         set_color_button(globals.wav_display_fg_focus, "wav_display_fg_focus");
457         set_color_button(globals.wav_display_fg_no_focus, "wav_display_fg_no_focus");
458         set_color_button(globals.wav_display_cursor, "wav_display_cursor");
459         set_color_button(globals.wav_display_cursor_mute, "wav_display_cursor_mute");
460         
461         /* VU Colors */
462         set_color_button(globals.vu_meter_bg, "vu_meter_bg");
463         set_color_button(globals.vu_meter_loud, "vu_meter_loud");
464         set_color_button(globals.vu_meter_normal, "vu_meter_normal");
465         
466         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "vu_meter_border_intensity")), globals.vu_meter_border_intensity);
467         
468         /* Misc */
469         gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog, "soundfile_editor")), globals.file_editor);
470         gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path")), globals.lrdf_path);
471         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "compress_set_files")), globals.compress_set_files);
472         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")), globals.prelis);
473         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "reconnect_enabled")), globals.restore_midi_connections);
474         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "quit_confirm")), globals.quit_confirm);
475 }
476
477 void create_options()
478 {
479         opt_dialog=create_tx_options();
480         tX_set_icon(opt_dialog);
481         init_tx_options(opt_dialog);
482         gtk_widget_show(opt_dialog);
483 }
484
485 void display_options()
486 {
487         if (opt_dialog) {
488                 gdk_window_raise(opt_dialog->window);   
489         } else {
490                 create_options();
491         }
492 }
493
494 GtkWidget *about=NULL;
495
496 void raise_about()
497 {
498         if (about) gdk_window_raise(about->window);
499 }
500
501
502 void destroy_about()
503 {
504         if (about) {    
505                 gtk_widget_destroy(about);
506                 about=NULL;
507         }
508 }
509
510 #define add_about_wid(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN); \
511         gtk_widget_show(wid);
512
513 #define add_about_wid_fix(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_FIX); \
514         gtk_widget_show(wid);
515
516 GdkFont *GPL_font=NULL;
517
518 void show_about(int nag)
519 {
520         GtkWidget *window;
521         GtkWidget *btn;
522         GtkWidget *box;
523         GtkWidget *hbox;
524         GtkWidget *label;
525         GtkWidget *sep;
526         GtkWidget *text;
527         GtkWidget *scroll;
528         GtkWidget *iwid;
529         
530         /* Only raise the window if it's already open... */
531         if (about)  {
532                 gdk_window_raise(about->window);
533                 return;
534         }
535         
536         /* Create the window... */
537         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
538         gtk_container_set_border_width(GTK_CONTAINER(window), 5);
539         gtk_window_set_title(GTK_WINDOW(window), "terminatorX - About");
540         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
541         gtk_window_set_modal(GTK_WINDOW(window), TRUE);
542         gtk_window_set_resizable(GTK_WINDOW(window), nag ? TRUE: FALSE);
543
544         GdkPixbuf *image=gdk_pixbuf_new_from_xpm_data((const char **)logo_xpm);
545         iwid = gtk_image_new_from_pixbuf(image);
546         
547         if (nag) {
548                 GtkWidget *box=gtk_vbox_new(FALSE, 2);
549                 GtkWidget *box2=gtk_hbox_new(FALSE, 2);
550                 GtkWidget *label;
551                 
552                 gtk_container_add(GTK_CONTAINER(window), box);
553                 gtk_box_pack_start(GTK_BOX(box), iwid, WID_FIX);
554                 gtk_box_pack_start(GTK_BOX(box), box2, WID_FIX);
555                 
556                 label=gtk_label_new(PACKAGE" release "VERSION);
557                 gtk_box_pack_start(GTK_BOX(box2), label, WID_DYN);
558                 gtk_misc_set_alignment(GTK_MISC(label), 0.1, 0.5);
559                 gtk_widget_show(label);
560
561                 label=gtk_label_new("Copyright (C) 1999-2003 by Alexander K\xC3\xB6nig");
562                 gtk_box_pack_start(GTK_BOX(box2), label, WID_DYN);
563                 gtk_misc_set_alignment(GTK_MISC(label), 0.9, 0.5);
564                 gtk_widget_show(label);
565                 
566                 gtk_widget_show(box2);
567                 gtk_widget_show(box);
568                 gtk_widget_show(iwid);
569
570                 gtk_window_set_decorated(GTK_WINDOW(window), FALSE);            
571                 gtk_widget_show(window);
572         } else {
573                 box=gtk_vbox_new(FALSE, 5);
574                 add_about_wid_fix(iwid);
575                 
576                 sep=gtk_hseparator_new();
577                 add_about_wid_fix(sep);
578                 char about_prefix_umlaut[]="\nThis is "PACKAGE" Release "VERSION" - Copyright (C) 1999-2003 by Alexander K\xC3\xB6nig";
579                 char about_rest[]="\n\nSend comments, patches and scratches to: alex@lisas.de\n"
580                 "terminatorX-homepage: http://www.terminatorX.cx\n\nThis binary has been compiled with the following flags: "
581                 "Sox support: "
582 #ifdef USE_SOX_INPUT
583                 "ON"
584 #else
585                 "OFF"
586 #endif          
587                 " - mpg123 support: "
588 #ifdef USE_MPG123_INPUT
589                 "ON"
590 #else
591                 "OFF"
592 #endif
593                 " - \nogg123 support: "
594 #ifdef USE_OGG123_INPUT
595                 "ON"
596 #else
597                 "OFF"
598 #endif
599
600                 " - enhanced scheduling: "
601 #ifdef USE_SCHEDULER
602                 "ON"
603 #else
604                 "OFF"
605 #endif
606                 " - for a "
607 #ifdef WORDS_BIGENDIAN
608                 "big"
609                 
610 #else
611                 "little"
612 #endif
613                 " endian machine.\n";
614                 
615                 char buffer[4096];
616                 
617                 strcpy(buffer, about_prefix_umlaut);
618                 strcat(buffer, about_rest);
619                 
620                 label=gtk_label_new(buffer);
621
622                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
623                 add_about_wid_fix(label);
624                 
625 #ifdef  USE_SCHEDULER
626                 int prio=sched_getscheduler(tX_engine::get_instance()->get_pid());
627                 char prio_str[32]="";
628                 
629                 switch (prio) {
630                         case SCHED_OTHER:
631                                 strcpy(prio_str, "SCHED_OTHER");
632                                 break;
633                         
634                         case SCHED_RR:
635                                 strcpy(prio_str, "SCHED_RR");
636                                 break;
637                         
638                         case SCHED_FIFO:
639                                 strcpy(prio_str, "SCHED_FIFO");
640                                 break;
641                         
642                         default:
643                                 sprintf(prio_str, "UNKOWN (%i)", prio);
644                 }
645                 
646                 sprintf(buffer, "Audio engine scheduling policy: %s.\n(Note: SCHED_FIFO equals realtime scheduling.)", prio_str);
647
648                 label=gtk_label_new(buffer);
649
650                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
651                 add_about_wid_fix(label);
652 #endif
653
654                 sep=gtk_hseparator_new();
655                 add_about_wid_fix(sep);
656
657                 label=gtk_label_new("License (GPL V2):");
658                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
659                 add_about_wid_fix(label);
660
661                 hbox=gtk_hbox_new(FALSE, 5);            
662
663                 GtkTextIter iter;
664                 GtkTextBuffer *tbuffer;
665
666                 text=gtk_text_view_new();
667                 tbuffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
668                 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_NONE);
669                 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), false);
670                 gtk_text_buffer_get_iter_at_offset (tbuffer, &iter, 0);
671                 
672                 scroll=gtk_scrolled_window_new (NULL, NULL);
673         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
674                 gtk_container_add (GTK_CONTAINER (scroll), text);
675                 gtk_text_buffer_create_tag (tbuffer, "courier", "family", "courier", NULL);
676                 
677                 gtk_text_buffer_insert_with_tags_by_name(tbuffer, &iter, license, -1, "courier", NULL);
678                 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);
679                 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 5);
680                 gtk_widget_set_size_request(GTK_WIDGET(text), 640, 200);
681                 gtk_widget_show(text);          
682                 
683                 gtk_box_pack_start(GTK_BOX(hbox), scroll, WID_DYN);
684                 gtk_widget_show(scroll);                
685                 
686                 add_about_wid(hbox);
687
688                 sep=gtk_hseparator_new();
689                 add_about_wid_fix(sep);
690
691                 btn=gtk_button_new_with_label("Close");
692                 add_about_wid_fix(btn);
693
694                 gtk_container_add(GTK_CONTAINER(window), box);
695                 gtk_widget_show(box);
696                 
697                 g_signal_connect(G_OBJECT(btn), "clicked", (GtkSignalFunc) destroy_about, NULL);                
698                 g_signal_connect(G_OBJECT(window), "delete-event", (GtkSignalFunc) destroy_about, NULL);                
699         }
700         gtk_widget_show(window);        
701         tX_set_icon(window);
702         
703         while (gtk_events_pending()) gtk_main_iteration();
704                 
705         about=window;
706 }
707
708 static GdkPixbuf *tX_window_icon=NULL;
709
710 void tX_set_icon(GtkWidget *widget)
711 {       
712         if (!tX_window_icon) {
713                 tX_window_icon=gdk_pixbuf_new_from_inline(-1, tX_icon, FALSE, NULL);
714         }
715
716         gtk_window_set_icon(GTK_WINDOW(widget), tX_window_icon);
717 }