fe4e00f471ba5952c9f1fb6e88e3fd2d35c2a3e3
[terminatorX.git] / src / tX_dialog.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999-2020  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, see <http://www.gnu.org/licenses/>.
17  
18     File: tX_dialog.cc
19  
20     Description: Contains the implementation of the Options and About
21                  Dialogs. (And some really ugly "WE WANT TO 
22                  TYPE LESS" macros)
23 */    
24
25 #include "config.h"
26 #include "tX_types.h"
27 #include "tX_global.h"
28 #include "tX_dialog.h"
29 #include <gtk/gtk.h>
30 #include <string.h>
31 #include <gdk/gdk.h>
32 #include "tX_ui_interface.h"
33 #include "tX_ui_support.h"
34
35 #include "tX_widget.h"
36 #include "tX_flash.h"
37
38 #include "license.c"
39 #include "tX_mastergui.h"
40 #include "version.h"
41 #include "tX_vtt.h"
42 #include <dirent.h>
43 #include "tX_engine.h"
44
45 #include "icons/tX_dialog_resources.c"
46
47 #ifdef USE_SCHEDULER
48 #include <sched.h>
49 #include <pthread.h>
50 #endif
51
52 #ifdef USE_JACK
53 extern void jack_check();
54 #endif
55
56 extern char *logo_xpm[];
57 GtkWidget *opt_dialog;
58 int opt_hidden=0;
59
60 static GtkWidget *last_alsa_device_widget=NULL;
61
62 void apply_options(GtkWidget *dialog) {
63         /* Audio */
64         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_driver")))) {
65                 globals.audiodevice_type=ALSA;
66         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "oss_driver")))) {
67                 globals.audiodevice_type=OSS;
68         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "jack_driver")))) {
69                 globals.audiodevice_type=JACK;
70         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "pulse_driver")))) {
71                 globals.audiodevice_type=PULSE;
72         }
73         globals.use_realtime=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "use_realtime")));
74         
75         /* Audio: OSS */
76         char *oss_device = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "oss_audio_device")));
77         if (oss_device) {
78                 strcpy(globals.oss_device, oss_device);
79         }
80         globals.oss_buff_no=(int) gtk_spin_button_get_value(GTK_SPIN_BUTTON(lookup_widget(dialog, "oss_buffers")));
81         globals.oss_buff_size=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "oss_buffersize")));
82         globals.oss_samplerate=atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "oss_samplerate"))));
83         
84         /* Audio: ALSA */
85         char *alsa_device = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "alsa_audio_device")));
86         if (alsa_device) {
87                 strcpy(globals.alsa_device_id, alsa_device);
88         }
89         globals.alsa_buffer_time=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "alsa_buffer_time")));
90         globals.alsa_buffer_time*=1000;
91         globals.alsa_period_time=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "alsa_period_time")));
92         globals.alsa_period_time*=1000;
93         globals.alsa_samplerate=atoi(gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "alsa_samplerate")))); 
94         globals.alsa_free_hwstats=gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_free_hwstats")));
95         globals.pulse_buffer_length=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "pulse_buffer_size")));
96
97         /* TODO: JACK
98         */
99         
100         globals.mouse_speed=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "mouse_speed")));
101         globals.sense_cycles=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "stop_sense_cycles")));
102         globals.vtt_inertia=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "vtt_inertia")));
103         
104         /* User Interface */ 
105         globals.show_nag=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "startup_nagbox")))==TRUE);
106         globals.tooltips=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "mainwin_tooltips")))==TRUE);
107         globals.filename_length=gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(lookup_widget(dialog, "filename_length")));
108 //      if (globals.tooltips) gtk_tooltips_enable(gui_tooltips);
109 //      else gtk_tooltips_disable(gui_tooltips);
110 //      TODO: Disable Tooltips no longer possible?
111
112         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_only")))) {
113                 globals.button_type=BUTTON_TYPE_TEXT;
114         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_icon_only")))) {
115                 globals.button_type=BUTTON_TYPE_ICON;
116         } else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_and_icon")))) {
117                 globals.button_type=BUTTON_TYPE_BOTH;
118         }
119         
120         globals.update_delay=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "update_delay")));
121         globals.update_idle=(int) gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "update_idle")));
122         globals.flash_response=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "vumeter_decay")));
123
124         if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "override_knob_size")))) {
125                 globals.knob_size_override=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "knob_size")));
126         } else {
127                 globals.knob_size_override = 0;
128         }
129
130         globals.wav_display_history=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "wav_display_history")))==TRUE);
131         globals.title_bar_alpha=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "title_bar_alpha")));
132
133         /* Audio Colors */
134         
135         strcpy(globals.wav_display_bg_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_bg_focus")), "Color"));
136         strcpy(globals.wav_display_bg_no_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_bg_no_focus")), "Color"));
137         strcpy(globals.wav_display_fg_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_fg_focus")), "Color"));
138         strcpy(globals.wav_display_fg_no_focus, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_fg_no_focus")), "Color"));
139         strcpy(globals.wav_display_cursor, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_cursor")), "Color"));
140         strcpy(globals.wav_display_cursor_mute, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "wav_display_cursor_mute")), "Color"));
141         globals.wav_use_vtt_color=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "wav_use_vtt_color")))==TRUE);
142
143         /* VU Colors */ 
144         strcpy(globals.vu_meter_bg, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "vu_meter_bg")), "Color"));
145         strcpy(globals.vu_meter_loud, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "vu_meter_loud")), "Color"));
146         strcpy(globals.vu_meter_normal, (char *) g_object_get_data(G_OBJECT(lookup_widget(dialog, "vu_meter_normal")), "Color"));
147
148         globals.vu_meter_border_intensity=gtk_range_get_value(GTK_RANGE(lookup_widget(dialog, "vu_meter_border_intensity")));
149         
150         /* Misc */
151         strcpy(globals.file_editor, gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog, "soundfile_editor"))));
152         strcpy(globals.lrdf_path, gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path"))));
153         globals.compress_set_files=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "compress_set_files")))==TRUE);        
154         globals.prelis=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")))==TRUE);
155         globals.restore_midi_connections=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "reconnect_enabled")))==TRUE);
156         globals.quit_confirm=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "quit_confirm")))==TRUE);
157         globals.verbose_plugin_loading=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "verbose_plugin_loading")))==TRUE);
158         globals.force_nonrt_plugins=(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "force_nonrt_plugins")))==TRUE);
159         
160         /* update colors */
161         std::list<vtt_class *>::iterator vtt;
162         
163         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++) {
164                 gtk_tx_update_colors(GTK_TX((*vtt)->gui.display), (*vtt)->get_color());
165                 gtk_widget_queue_draw((*vtt)->gui.display);
166                 gtk_tx_flash_update_colors(GTK_TX_FLASH((*vtt)->gui.flash));
167                 gtk_widget_queue_draw((*vtt)->gui.flash);
168                 update_vtt_css((*vtt), (*vtt)->get_color());
169         }
170         
171         gtk_tx_flash_update_colors(GTK_TX_FLASH(main_flash));
172         gtk_widget_queue_draw(main_flash);
173         
174 #ifdef USE_JACK
175         jack_check();
176 #endif  
177 }
178
179
180 #define WID_DYN TRUE, TRUE, 0
181 #define WID_FIX FALSE, FALSE, 0
182
183 #define my_new_subsec(s); \
184         separator=gtk_separator_new(GTK_ORIENTATION_HORIZONTAL); \
185         gtk_box_pack_start(GTK_BOX(vbox), separator, WID_DYN);\
186         gtk_widget_show(separator); \
187         label=gtk_label_new(s); \
188         gtk_widget_set_halign(label, GTK_ALIGN_START); \
189         gtk_box_pack_start(GTK_BOX(vbox), label, WID_DYN); \
190         gtk_widget_show(label); 
191
192 #define my_new_button(btn, s); \
193         btn=gtk_button_new_with_label(s); \
194         gtk_box_pack_start(GTK_BOX(aa), btn, WID_DYN); \
195         gtk_widget_show(btn);
196         
197
198 #define begin_box(); box=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5);
199
200 #define begin_hom_box(); box=gtk_hbox_new(TRUE, 5);
201
202 #define end_box(); gtk_box_pack_start(GTK_BOX(vbox), box, WID_DYN); \
203         gtk_widget_show(box);
204
205 #define add_widget_dyn(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN);\
206         gtk_widget_show(wid);
207         
208 #define add_widget_fix(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_FIX);\
209         gtk_widget_show(wid);
210
211 #define add_expl(s); label=gtk_label_new(s); \
212         add_widget_fix(label);
213
214 #define add_expl_dyn(s); label=gtk_label_new(s); \
215         add_widget_dyn(label);
216
217 #ifdef USE_ALSA
218 void append_alsa_device_list(GtkComboBoxText *combo, char *current) {
219         FILE *file;
220         char buffer[PATH_MAX+1];
221         int ctr = 0;
222         
223         if ((file = fopen("/proc/asound/pcm", "r"))) {
224                 while(fgets(buffer, PATH_MAX, file)) {
225                         buffer[PATH_MAX]=0;
226                         if (strlen(buffer)) buffer[strlen(buffer)-1]=0;
227                         if(strstr(buffer, "playback")) {
228                                 char foo[PATH_MAX];
229                                 char tmp[PATH_MAX];
230                                 memset(foo, 0, PATH_MAX);
231                                 int card;
232                                 int device;
233  
234                                 sscanf(buffer, "%i-%i: %1024c", &card, &device, foo);
235                                 sprintf(tmp, "hw:%i,%i# %s", card, device, foo);
236                                 
237                                 gtk_combo_box_text_append_text(combo, strdup(tmp));
238                                 
239                                 if (strcmp(tmp, current) == 0) {
240                                         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), ctr);
241                                 }
242                                 ctr++;
243                                         
244                         }
245                 }
246                 fclose(file);
247         }
248 }
249 #else
250 void append_alsa_device_list(GtkComboBoxText *combo, char* current) {
251 }
252 #endif
253
254
255 int oss_select_dsp_only(const struct dirent *entry){
256         return (strstr(entry->d_name, "dsp")!=0);
257 }
258
259 void append_oss_device_list(GtkComboBoxText *combo, char *current) {
260     struct dirent **namelist;
261     int n,i;
262     n = scandir("/dev", &namelist, oss_select_dsp_only, alphasort);
263
264     if (n>0) {
265     for (i=0; i<n; i++) {
266         char buffer[PATH_MAX];
267         snprintf(buffer, sizeof(buffer), "/dev/%s", namelist[i]->d_name);
268         free(namelist[i]);
269
270         gtk_combo_box_text_append_text(combo, strdup(buffer));
271         if (strcmp(buffer, current)==0) {
272             gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i);
273         }
274         }
275     }
276 }
277
278
279 void append_sampling_rates_list(GtkComboBoxText *combo, int current) {
280
281         gtk_combo_box_text_append_text(combo,  "22000");
282         gtk_combo_box_text_append_text(combo,  "32000");
283         gtk_combo_box_text_append_text(combo,  "44100");
284         gtk_combo_box_text_append_text(combo,  "48000");
285         switch (current) {
286                 case 22000:
287                         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 0);
288                         break;
289                 case 32000:
290                         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);
291                         break;
292                 case 44100:
293                         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 2);
294                         break;
295                 case 48000:
296                 default:
297                         gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 3);
298         }
299 }
300
301 #define MAX_COLORS 10
302 char *colors[MAX_COLORS]={ NULL };
303
304 #define set_color_button(s,g); \
305         sprintf(tmp, "<span foreground=\"%s\"><b>%s</b></span>", s, s);\
306         gtk_label_set_markup(GTK_LABEL(gtk_container_get_children(GTK_CONTAINER(lookup_widget(dialog, g)))->data), tmp);\
307         strcpy(colors[ctr], s);\
308         g_object_set_data(G_OBJECT(lookup_widget(dialog, g)), "Color", colors[ctr]);\
309         ctr++;
310
311
312 void init_tx_options(GtkWidget *dialog) {
313         char tmp[256];
314         
315         if (colors[0]==NULL) {
316                 for (int i=0; i<MAX_COLORS; i++) {
317                         colors[i]=new char[8];
318                         colors[i][0]=0;
319                 }
320         }
321         
322         /* Audio */
323         switch (globals.audiodevice_type) {             
324                 case ALSA: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_driver")), 1);
325                         break;
326                 
327                 case JACK: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "jack_driver")), 1);
328                         break;
329
330                 case PULSE: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "pulse_driver")), 1);
331                         break;
332
333                 case OSS: 
334                 default:
335                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "oss_driver")), 1);
336                         break;
337         }
338
339         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "use_realtime")), globals.use_realtime);
340
341 #ifndef USE_CAPABILITIES
342         /* rt's not configurable without capabilities. */
343         gtk_widget_hide(lookup_widget(dialog, "use_realtime"));
344         gtk_widget_hide(lookup_widget(dialog, "use_realtime_label"));   
345 #endif
346         
347 #ifndef USE_OSS
348         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_driver"), 0);
349         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_audio_device"), 0);
350         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_buffers"), 0);
351         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_buffersize"), 0);
352         gtk_widget_set_sensitive(lookup_widget(dialog, "oss_samplerate"), 0);
353 #endif
354         
355 #ifndef USE_ALSA
356         gtk_widget_set_sensitive(lookup_widget(dialog, "alsa_driver"), 0);      
357         gtk_widget_set_sensitive(lookup_widget(dialog, "alsa_audio_device"), 0);
358         gtk_widget_set_sensitive(lookup_widget(dialog, "alsa_samplerate"), 0);
359         gtk_widget_set_sensitive(lookup_widget(dialog, "alsa_period_time"), 0);
360         gtk_widget_set_sensitive(lookup_widget(dialog, "alsa_buffer_time"), 0);
361         gtk_widget_set_sensitive(lookup_widget(dialog, "alsa_free_hwstats"), 0);
362 #endif
363         
364 #ifndef USE_JACK
365         gtk_widget_set_sensitive(lookup_widget(dialog, "jack_driver"), 0);
366 #endif  
367
368 #ifndef USE_PULSE
369         gtk_widget_set_sensitive(lookup_widget(dialog, "pulse_driver"), 0);
370         gtk_widget_set_sensitive(lookup_widget(dialog, "pulse_buffer_size"), 0);
371 #endif
372         
373         /* Audio: OSS */
374         append_oss_device_list(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "oss_audio_device")), globals.oss_device);
375
376         gtk_spin_button_set_value(GTK_SPIN_BUTTON(lookup_widget(dialog, "oss_buffers")), globals.oss_buff_no);
377         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "oss_buffersize")), globals.oss_buff_size);
378         gtk_widget_set_tooltip_text(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."); 
379         append_sampling_rates_list(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "oss_samplerate")), globals.oss_samplerate);
380         
381         /* Audio: ALSA */
382         GtkComboBoxText *combo=GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "alsa_audio_device"));
383         last_alsa_device_widget=NULL;
384         
385         append_alsa_device_list(GTK_COMBO_BOX_TEXT(combo), globals.alsa_device_id);
386
387         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "alsa_buffer_time")), globals.alsa_buffer_time/1000);
388         gtk_widget_set_tooltip_text(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.");        
389         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "alsa_period_time")), globals.alsa_period_time/1000);
390         gtk_widget_set_tooltip_text(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."); 
391
392         append_sampling_rates_list(GTK_COMBO_BOX_TEXT(lookup_widget(dialog, "alsa_samplerate")), globals.alsa_samplerate);
393         
394         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "alsa_free_hwstats")), globals.alsa_free_hwstats);
395         
396         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "pulse_buffer_size")), globals.pulse_buffer_length);
397         gtk_widget_set_tooltip_text(lookup_widget(dialog, "pulse_buffer_size"), "Sets the requested buffer size for PulseAudio in samples (per channel). Lower values should result in lower latency, however PulseAudio may override this setting.");  
398
399         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "mouse_speed")), globals.mouse_speed);
400         gtk_widget_set_tooltip_text(lookup_widget(dialog, "mouse_speed"), "The speed of your mouse in scratch mode. Use negative values to invert motion.");
401         
402         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "stop_sense_cycles")), globals.sense_cycles);
403         gtk_widget_set_tooltip_text(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"); 
404
405         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "vtt_inertia")), globals.vtt_inertia);
406         gtk_widget_set_tooltip_text(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.");        
407
408         gtk_spin_button_set_value(GTK_SPIN_BUTTON(lookup_widget(dialog, "filename_length")), globals.filename_length);
409
410         /* User Interface */ 
411         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "startup_nagbox")), globals.show_nag);
412         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "mainwin_tooltips")), globals.tooltips);
413         
414         switch (globals.button_type) {
415                 case BUTTON_TYPE_TEXT:
416                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_only")), 1);
417                         break;
418                 
419                 case BUTTON_TYPE_ICON:
420                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_icon_only")), 1);
421                         break;
422                 
423                 case BUTTON_TYPE_BOTH:
424                 default:
425                         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "buttons_text_and_icon")), 1);
426         }
427         
428         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "update_delay")), globals.update_delay);
429         gtk_widget_set_tooltip_text(lookup_widget(dialog, "update_delay"), "How often to update the slow widgets.");    
430         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "update_idle")), globals.update_idle);
431         gtk_widget_set_tooltip_text(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 reduce this value - if you have performance problems increase this value.");        
432         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "vumeter_decay")), globals.flash_response);
433         gtk_widget_set_tooltip_text(lookup_widget(dialog, "vumeter_decay"), "Defines how fast the maximum values of the VU meters should be decayed."); 
434
435
436         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "override_knob_size")), globals.knob_size_override > 0);
437         if (globals.knob_size_override) {
438                 gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "knob_size")), globals.knob_size_override);
439         } else {
440                 gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "knob_size")), 48);
441         }
442         
443         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "wav_display_history")), globals.wav_display_history);
444         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "title_bar_alpha")), globals.title_bar_alpha);
445
446         /* Audio Colors */
447         int ctr=0;
448         
449         set_color_button(globals.wav_display_bg_focus, "wav_display_bg_focus");
450         set_color_button(globals.wav_display_bg_no_focus, "wav_display_bg_no_focus");
451         set_color_button(globals.wav_display_fg_focus, "wav_display_fg_focus");
452         set_color_button(globals.wav_display_fg_no_focus, "wav_display_fg_no_focus");
453         set_color_button(globals.wav_display_cursor, "wav_display_cursor");
454         set_color_button(globals.wav_display_cursor_mute, "wav_display_cursor_mute");
455         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "wav_use_vtt_color")), globals.wav_use_vtt_color);
456         
457         /* VU Colors */
458         set_color_button(globals.vu_meter_bg, "vu_meter_bg");
459         set_color_button(globals.vu_meter_loud, "vu_meter_loud");
460         set_color_button(globals.vu_meter_normal, "vu_meter_normal");
461         
462         gtk_range_set_value(GTK_RANGE(lookup_widget(dialog, "vu_meter_border_intensity")), globals.vu_meter_border_intensity);
463         
464         /* Misc */
465         gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog, "soundfile_editor")), globals.file_editor);
466         gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog, "ladspa_rdf_path")), globals.lrdf_path);
467         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "compress_set_files")), globals.compress_set_files);
468         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "prelisten_enabled")), globals.prelis);
469         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "reconnect_enabled")), globals.restore_midi_connections);
470         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "quit_confirm")), globals.quit_confirm);
471         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "force_nonrt_plugins")), globals.force_nonrt_plugins);     
472         gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog, "verbose_plugin_loading")), globals.verbose_plugin_loading);       
473 }
474
475 void create_options()
476 {
477         opt_dialog=create_tx_options(GTK_WINDOW(main_window));
478         tX_set_icon(opt_dialog);
479         init_tx_options(opt_dialog);
480         gtk_widget_show(opt_dialog);
481 }
482
483 void display_options()
484 {
485         if (opt_dialog) {
486                 gdk_window_raise(gtk_widget_get_window(opt_dialog));    
487         } else {
488                 create_options();
489         }
490 }
491
492 GtkWidget *about=NULL;
493
494 void raise_about()
495 {
496         if (about) gdk_window_raise(gtk_widget_get_window(about));
497 }
498
499
500 void destroy_about()
501 {
502         if (about) {    
503                 gtk_widget_destroy(about);
504                 about=NULL;
505         }
506 }
507
508 #define add_about_wid(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_DYN); \
509         gtk_widget_show(wid);
510
511 #define add_about_wid_fix(wid); gtk_box_pack_start(GTK_BOX(box), wid, WID_FIX); \
512         gtk_widget_show(wid);
513
514 void show_about(int nag)
515 {
516         GtkWidget *window;
517         GtkWidget *btn;
518         GtkWidget *box;
519         GtkWidget *label;
520         GtkWidget *sep;
521         GtkWidget *text;
522         GtkWidget *scroll;
523         GtkWidget *iwid;
524         GtkWidget *expander;
525         
526         /* Only raise the window if it's already open... */
527         if (about)  {
528                 gdk_window_raise(gtk_widget_get_window(about));
529                 return;
530         }
531         
532         /* Create the window... */
533         window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
534         gtk_container_set_border_width(GTK_CONTAINER(window), 5);
535         gtk_window_set_title(GTK_WINDOW(window), "terminatorX - About");
536         gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
537         gtk_window_set_modal(GTK_WINDOW(window), TRUE);
538         gtk_window_set_resizable(GTK_WINDOW(window), nag ? TRUE: FALSE);
539
540         GdkPixbuf *image=gdk_pixbuf_new_from_xpm_data((const char **)logo_xpm);
541         iwid = gtk_image_new_from_pixbuf(image);
542         
543         if (nag) {
544                 GtkWidget *box=gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
545                 GtkWidget *box2=gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
546                 GtkWidget *label;
547                 
548                 gtk_container_add(GTK_CONTAINER(window), box);
549                 gtk_box_pack_start(GTK_BOX(box), iwid, WID_FIX);
550                 gtk_box_pack_start(GTK_BOX(box), box2, WID_FIX);
551                 
552                 label=gtk_label_new(PACKAGE " release " VERSION);
553                 gtk_box_pack_start(GTK_BOX(box2), label, WID_DYN);
554                 gtk_widget_set_halign(label, GTK_ALIGN_START);
555                 gtk_widget_show(label);
556
557                 label=gtk_label_new("Copyright (C) 1999-2020 by Alexander König");
558                 gtk_box_pack_start(GTK_BOX(box2), label, WID_DYN);
559                 gtk_widget_set_halign(label, GTK_ALIGN_END);
560                 gtk_widget_show(label);
561                 
562                 gtk_widget_show(box2);
563                 gtk_widget_show(box);
564                 gtk_widget_show(iwid);
565
566                 gtk_window_set_decorated(GTK_WINDOW(window), FALSE);            
567                 gtk_widget_show(window);
568         } else {
569                 box=gtk_box_new(GTK_ORIENTATION_VERTICAL, 5);
570                 add_about_wid_fix(iwid);
571                 
572                 sep=gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
573                 add_about_wid_fix(sep);
574                 
575                 label=gtk_label_new("This is " PACKAGE " release " VERSION ".\nCopyright (C) 1999-2020 by Alexander König <alex@lisas.de>");
576
577                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
578                 add_about_wid_fix(label);
579
580                 sep=gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
581                 add_about_wid_fix(sep);
582
583                 expander = gtk_expander_new("Build info");
584                 GtkWidget *exbox=gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
585                 gtk_container_add(GTK_CONTAINER(expander), exbox);
586                 gtk_widget_show(exbox);
587
588                 label=gtk_label_new("Compilation flags: "
589 #ifdef USE_SOX_INPUT
590                 " [sox]"
591 #endif
592 #ifdef USE_MPG123_INPUT
593                 " [mpg123]"
594 #endif
595 #ifdef USE_OGG123_INPUT
596                 " [ogg123]"
597 #endif
598 #ifdef USE_MAD_INPUT
599                 " [mad]"
600 #endif
601 #ifdef USE_VORBIS_INPUT
602                 " [vorbis]"
603 #endif
604 #ifdef USE_AUDIOFILE_INPUT
605                 " [audiofile]"
606 #endif
607                 "\n"
608 #ifdef USE_ALSA_MIDI_IN
609                 " [midi]"
610 #endif
611 #ifdef USE_OSS
612                 " [oss]"
613 #endif
614 #ifdef USE_ALSA
615                 " [alsa]"
616 #endif
617 #ifdef USE_JACK
618                 " [jack]"
619 #endif
620 #ifdef USE_PULSE
621                 " [pulse]"
622 #endif
623 #ifdef USE_LRDF
624                 " [lrdf]"
625 #endif
626 #ifdef USE_SCHEDULER
627                 " [rt]"
628 #endif
629 #ifdef USE_CAPABILITIES
630                 " [cap]"
631 #endif
632                 "");
633         
634                 gtk_label_set_line_wrap(GTK_LABEL(label), TRUE);
635                 gtk_widget_set_size_request(label, 640, -1);
636                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
637                 gtk_container_add(GTK_CONTAINER(exbox), label);
638                 gtk_widget_show(label);
639                 add_about_wid_fix(expander);
640
641 #ifdef  USE_SCHEDULER
642                 sep=gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
643                 gtk_widget_show(sep);
644                 gtk_container_add(GTK_CONTAINER(exbox), sep);
645
646                 char buffer[4096];
647                 
648                 int policy=-1;
649                 struct sched_param parm;
650                 
651                 pthread_getschedparam(tX_engine::get_instance()->get_thread_id(), &policy, &parm);
652                 char prio_str[32]="";
653                 bool s_enabled = false;
654                 
655                 switch (policy) {
656                         case SCHED_OTHER:
657                                 strcpy(prio_str, "SCHED_OTHER");
658                                 break;
659                         
660                         case SCHED_RR:
661                                 strcpy(prio_str, "SCHED_RR");
662                                 break;
663                         
664                         case SCHED_FIFO:
665                                 strcpy(prio_str, "SCHED_FIFO");
666                                 s_enabled = true;
667                                 break;
668                         
669                         default:
670                                 sprintf(prio_str, "UNKNOWN (%i)", policy);
671                 }
672                 
673                 sprintf(buffer, "Audio engine scheduling policy: %s.\nScheduling with realtime priority is %s.", prio_str, s_enabled ? "enabled" : "disabled");
674
675                 label=gtk_label_new(buffer);
676
677                 gtk_label_set_justify(GTK_LABEL(label), GTK_JUSTIFY_CENTER);
678                 gtk_widget_show(label);
679                 gtk_container_add(GTK_CONTAINER(exbox), label);
680 #endif
681
682                 sep=gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
683                 add_about_wid_fix(sep);
684
685                 expander = gtk_expander_new("License (GPL V2):");
686
687                 add_about_wid_fix(expander);
688
689                 GtkTextIter iter;
690                 GtkTextBuffer *tbuffer;
691
692                 text=gtk_text_view_new();
693                 tbuffer=gtk_text_view_get_buffer(GTK_TEXT_VIEW(text));
694                 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_NONE);
695                 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), false);
696                 gtk_text_buffer_get_iter_at_offset (tbuffer, &iter, 0);
697                 
698                 scroll=gtk_scrolled_window_new (NULL, NULL);
699         gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
700                 gtk_container_add (GTK_CONTAINER (scroll), text);
701                 gtk_text_buffer_create_tag (tbuffer, "courier", "family", "courier", NULL);
702                 
703                 gtk_text_buffer_insert_with_tags_by_name(tbuffer, &iter, license, -1, "courier", NULL);
704                 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);
705                 gtk_text_view_set_right_margin(GTK_TEXT_VIEW(text), 5);
706                 gtk_widget_set_size_request(GTK_WIDGET(scroll), 640, 200);
707                 gtk_widget_show(text);          
708                 
709                 gtk_container_add(GTK_CONTAINER(expander), scroll);
710                 gtk_widget_show(scroll);                
711                 
712                 sep=gtk_separator_new(GTK_ORIENTATION_HORIZONTAL);
713                 add_about_wid_fix(sep);
714
715                 btn=gtk_button_new_with_label("Close");
716                 add_about_wid_fix(btn);
717
718                 gtk_container_add(GTK_CONTAINER(window), box);
719                 gtk_widget_show(box);
720                 
721                 g_signal_connect(G_OBJECT(btn), "clicked", (GCallback) destroy_about, NULL);            
722                 g_signal_connect(G_OBJECT(window), "delete-event", (GCallback) destroy_about, NULL);            
723         }
724         gtk_widget_show(window);        
725         tX_set_icon(window);
726         
727         while (gtk_events_pending()) gtk_main_iteration();
728                 
729         about=window;
730 }
731
732 static GdkPixbuf *tX_window_icon=NULL;
733
734 void tX_set_icon(GtkWidget *widget)
735 {       
736         if (!tX_window_icon) {
737                 GError *error = NULL;
738                 g_resource_new_from_data(g_bytes_new_static(tX_dialog_resource_data.data, sizeof(tX_dialog_resource_data.data)), &error);
739                 if (error) {
740                     tX_error("Error accesing tX_dialog resources: %s", error->message);
741                 }
742                 tX_window_icon=gdk_pixbuf_new_from_resource("/org/terminatorX/tX_dialog/../../icons/terminatorX.png", &error);
743                 if (error) {
744                     tX_error("Error rendering tX icon: %s", error->message);
745                 }
746         }
747
748         gtk_window_set_icon(GTK_WINDOW(widget), tX_window_icon);
749 }