Pretty colors everywhere!
[terminatorX.git] / src / tX_global.c
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_global.c
19  
20     Description:  This file contains the routines for handling the
21                   "globals" block. Intializing, reading setup from
22                   disk and storing it.
23 */    
24
25 #include <config.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include "tX_types.h"
29 #include "tX_global.h"
30 #include "string.h"
31 #include <libxml/xmlmemory.h>
32 #include <libxml/parser.h>
33 #include <libxml/encoding.h>
34
35
36 #define TX_XML_RC_VERSION "1.0"
37
38 tx_global globals;
39 int _store_compress_xml=0;
40
41 #ifdef USE_ALSA_MIDI_IN
42 extern void tX_midiin_store_connections(FILE *rc, char *indent);
43 extern void tX_midiin_restore_connections(xmlNodePtr node);
44 #endif
45
46 void get_rc_name(char *buffer, int length)
47 {
48         strncpy(buffer,"", length);
49         if (globals.alternate_rc) {
50                 strncpy(buffer, globals.alternate_rc, length);
51         } else {
52                 if (getenv("HOME")) {
53                         strncpy(buffer, getenv("HOME"), length-16);
54                         if (buffer[strlen(buffer)-1]!='/')
55                         strcat(buffer, "/");
56                 }
57                 strcat(buffer, ".terminatorXrc");
58         }
59 }
60
61 void set_global_defaults() {
62         globals.startup_set = 0;
63         globals.store_globals = 1;
64         globals.no_gui = 0;
65         globals.alternate_rc = 0;
66         
67         strcpy(globals.xinput_device, "");
68         globals.xinput_enable=0;
69         
70         globals.update_idle=14;
71         globals.update_delay=1;
72         
73         strcpy(globals.oss_device, "/dev/dsp");
74         globals.oss_buff_no=2;
75         globals.oss_buff_size=9;
76         globals.oss_samplerate=44100;
77
78         strcpy(globals.alsa_device_id, "hw:0,0");       
79         globals.alsa_buffer_time=80000;
80         globals.alsa_period_time=20000;
81         globals.alsa_samplerate=44100;
82
83         globals.pulse_buffer_length=320;
84
85         globals.sense_cycles=80;
86         
87         globals.mouse_speed=0.8;
88         
89         globals.width=800;
90         globals.height=440;     
91         
92         globals.tooltips=1;
93         
94         globals.use_stdout=0;
95         globals.use_stdout_from_conf_file=0;
96         
97         globals.show_nag=1;
98         globals.input_fallback_warning=1;
99         globals.prelis=1;
100         
101         strcpy(globals.last_fn,"");
102         
103         globals.pitch=1.0;
104         globals.volume=1.0;
105         globals.gui_wrap=3;
106         
107         globals.flash_response=0.95;
108         globals.knob_size_override=0;
109         
110         globals.button_type=BUTTON_TYPE_BOTH;
111                 
112         globals.true_block_size=0;
113         
114         strcpy(globals.tables_filename, "");
115         strcpy(globals.record_filename, "tX_record.wav");
116         strcpy(globals.file_editor, "");
117
118 #ifdef USE_PULSE
119         globals.audiodevice_type=PULSE;
120 #else   
121 #ifdef USE_ALSA
122         globals.audiodevice_type=ALSA;
123 #else
124 #ifdef USE_OSS
125         globals.audiodevice_type=OSS;
126 #endif  
127 #endif  
128 #endif
129         globals.use_stdout_cmdline=0;
130         strcpy(globals.current_path, "");
131         strcpy(globals.lrdf_path, "/usr/share/ladspa/rdf:/usr/local/share/ladspa/rdf");
132         globals.fullscreen_enabled=0;
133         globals.confirm_events=0;
134         globals.compress_set_files=0;
135         
136         globals.vtt_inertia=10.0;
137         
138         globals.alsa_free_hwstats=0;
139         globals.filename_length=20;
140         globals.restore_midi_connections=1;
141
142         globals.wav_display_history=1;
143
144         strcpy(globals.wav_display_bg_focus, "#00004C");
145         strcpy(globals.wav_display_bg_no_focus, "#000000");
146
147         strcpy(globals.wav_display_fg_focus, "#FFFF00");
148         strcpy(globals.wav_display_fg_no_focus, "#00FF00");
149
150         strcpy(globals.wav_display_cursor, "#FF6666");
151         strcpy(globals.wav_display_cursor_mute, "#FFFFFF");
152
153         globals.wav_use_vtt_color = 1;
154         globals.title_bar_alpha = 0.5;
155         
156         strcpy(globals.vu_meter_bg, "#000000");
157         strcpy(globals.vu_meter_loud, "#FF0000");
158         strcpy(globals.vu_meter_normal, "#00FF00");     
159         globals.vu_meter_border_intensity=0.7;
160         globals.quit_confirm=1;
161         globals.use_realtime=1;
162         globals.auto_assign_midi=0;
163         
164         globals.verbose_plugin_loading=0;
165         globals.force_nonrt_plugins=0;  
166 }
167
168 int load_globals_xml() {
169         char rc_name[PATH_MAX]="";      
170         char device_type[16]="oss";
171         xmlDocPtr doc;
172         xmlNodePtr cur;
173         int elementFound;
174         double dvalue;
175         char tmp_xml_buffer[4096];
176         
177         get_rc_name(rc_name, sizeof(rc_name));
178         
179         doc = xmlParseFile(rc_name);
180         
181         if (doc == NULL ) {
182                 fprintf(stderr, "tX: err: Error parsing terminatorXrc.\n");
183                 return 1;
184         }
185         
186         cur = xmlDocGetRootElement(doc);
187         
188         if (cur == NULL) {
189                 fprintf(stderr,"tX: err: terminatorXrc contains no elements.\n");
190                 xmlFreeDoc(doc);
191                 return 2;
192         }
193         
194         if (xmlStrcmp(cur->name, (const xmlChar *) "terminatorXrc")) {
195                 fprintf(stderr,"tX: err: This terminatorXrc is not a terminatorXrc.");
196                 xmlFreeDoc(doc);
197                 return 3;
198         }
199                 
200         for (cur=cur->xmlChildrenNode; cur != NULL; cur = cur->next) {
201                 if (cur->type == XML_ELEMENT_NODE) {                    
202                         elementFound=0;
203
204                         restore_int("store_globals", globals.store_globals);
205
206                         restore_string("audio_driver", device_type);
207                         
208                         restore_string("oss_device", globals.oss_device);
209                         restore_int("oss_buff_no", globals.oss_buff_no);
210                         restore_int("oss_buff_size", globals.oss_buff_size);
211                         restore_int("oss_samplerate", globals.oss_samplerate);
212
213                         restore_string("alsa_device_id", globals.alsa_device_id);
214                         restore_int("alsa_buffer_time", globals.alsa_buffer_time);
215                         restore_int("alsa_period_time", globals.alsa_period_time);
216                         restore_int("alsa_samplerate", globals.alsa_samplerate);
217                         restore_int("alsa_free_hwstats", globals.alsa_free_hwstats);
218                         
219                         restore_int("pulse_buffer_length", globals.pulse_buffer_length);
220
221                         restore_string("xinput_device", globals.xinput_device);
222                         restore_int("xinput_enable", globals.xinput_enable);
223                         restore_int("update_idle", globals.update_idle);
224                         restore_int("update_delay", globals.update_delay);
225                         restore_int("sense_cycles", globals.sense_cycles);
226                         restore_float("mouse_speed", globals.mouse_speed);
227                         restore_int("width", globals.width);
228                         restore_int("height", globals.height);
229                         restore_int("filename_length", globals.filename_length);
230                         restore_int("tooltips", globals.tooltips);
231                         restore_int("use_stdout", globals.use_stdout);
232                         restore_int("show_nag", globals.show_nag);
233                         restore_int("input_fallback_warning", globals.input_fallback_warning);
234                         restore_int("prelis", globals.prelis);
235                         restore_string("last_fn", globals.last_fn);
236                         restore_float("pitch", globals.pitch);
237                         restore_float("volume", globals.volume);
238                         restore_float("flash_response", globals.flash_response);
239                         restore_int("knob_size_override", globals.knob_size_override);
240                         restore_int("button_type", globals.button_type);
241                         restore_string("tables_filename", globals.tables_filename);
242                         restore_string("record_filename", globals.record_filename);
243                         restore_string("file_editor", globals.file_editor);
244                         restore_string("lrdf_path", globals.lrdf_path);
245                         restore_string("last_path", globals.current_path);
246                         
247                         restore_int("compress_set_files", globals.compress_set_files);
248                         restore_int("fullscreen_enabled", globals.fullscreen_enabled);
249                         restore_int("confirm_events", globals.confirm_events);
250                         restore_float("vtt_inertia", globals.vtt_inertia);
251                         restore_int("restore_midi_connections", globals.restore_midi_connections);
252
253                         restore_int("wav_display_history", globals.wav_display_history);
254                         restore_float("title_bar_alpha", globals.title_bar_alpha);
255                         restore_int("wav_use_vtt_color", globals.wav_use_vtt_color);
256                         restore_string("wav_display_bg_focus", globals.wav_display_bg_focus);
257                         restore_string("wav_display_bg_no_focus", globals.wav_display_bg_no_focus);
258                         restore_string("wav_display_fg_focus", globals.wav_display_fg_focus);
259                         restore_string("wav_display_fg_no_focus", globals.wav_display_fg_no_focus);
260                         restore_string("wav_display_cursor", globals.wav_display_cursor);
261                         restore_string("wav_display_cursor_mute", globals.wav_display_cursor_mute);
262                         
263                         restore_string("vu_meter_bg", globals.vu_meter_bg);
264                         restore_string("vu_meter_normal", globals.vu_meter_normal);
265                         restore_string("vu_meter_loud", globals.vu_meter_loud);
266                         
267                         restore_float("vu_meter_border_intensity", globals.vu_meter_border_intensity);
268
269                         restore_int("quit_confirm", globals.quit_confirm);
270                         restore_int("use_realtime", globals.use_realtime);
271                         restore_int("auto_assign_midi", globals.auto_assign_midi);
272                         restore_int("force_nonrt_plugins", globals.force_nonrt_plugins);
273                         restore_int("verbose_plugin_loading", globals.verbose_plugin_loading);
274
275 #ifdef USE_ALSA_MIDI_IN
276                         if (!elementFound && (xmlStrcmp(cur->name, (xmlChar *) "midi_connections")==0)) {
277                                 if (globals.restore_midi_connections) {
278                                         tX_midiin_restore_connections(cur);
279                                 }
280                                 elementFound=1;
281                         }
282 #endif                  
283
284                         if (!elementFound) {
285                                 fprintf(stderr, "tX: Unhandled XML element: \"%s\"\n", cur->name);
286                         }
287                 }
288         }
289
290         xmlFreeDoc(doc);
291         
292         if (strcmp(device_type, "alsa")==0) { globals.audiodevice_type=ALSA; }
293         else if (strcmp(device_type, "jack")==0) { globals.audiodevice_type=JACK; }
294         else if (strcmp(device_type, "pulse")==0) { globals.audiodevice_type=PULSE; }
295         else globals.audiodevice_type=OSS;
296         
297         return 0;
298 }
299
300 void store_globals() {
301         char rc_name[PATH_MAX+256]="";
302         char device_type[16];
303         char indent[32]="\t";
304         FILE *rc=NULL;
305         gzFile rz=NULL;
306         char tmp_xml_buffer[4096];
307         _store_compress_xml=0;
308         
309         get_rc_name(rc_name, sizeof(rc_name));
310
311         rc=fopen(rc_name, "w");
312         
313         switch (globals.audiodevice_type) {
314                 case PULSE:
315                         strcpy(device_type, "pulse");
316                         break;
317                 case JACK:
318                         strcpy(device_type, "jack");
319                         break;
320                 case ALSA:
321                         strcpy(device_type, "alsa");
322                         break;
323                 case OSS:
324                 default:
325                         strcpy(device_type, "oss");
326         }
327         
328         if (rc) {               
329                 fprintf(rc, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n");
330                 fprintf(rc, "<!-- Warning: this file will be rewritten by terminatorX on exit!\n     Don\'t waste your time adding comments - they will be erased -->\n\n" );
331                 fprintf(rc, "<terminatorXrc version=\"%s\">\n", TX_XML_RC_VERSION);
332
333                 store_int("store_globals", globals.store_globals);
334
335                 store_string("audio_driver", device_type);
336                 
337                 store_string("oss_device", globals.oss_device);
338                 store_int("oss_buff_no", globals.oss_buff_no);
339                 store_int("oss_buff_size", globals.oss_buff_size);
340                 store_int("oss_samplerate", globals.oss_samplerate);
341
342                 store_string("alsa_device_id", globals.alsa_device_id);
343                 store_int("alsa_buffer_time", globals.alsa_buffer_time);
344                 store_int("alsa_period_time", globals.alsa_period_time);
345                 store_int("alsa_samplerate", globals.alsa_samplerate);          
346                 store_int("alsa_free_hwstats", globals.alsa_free_hwstats);
347                 
348                 store_int("pulse_buffer_length", globals.pulse_buffer_length);
349
350                 store_string("xinput_device", globals.xinput_device);
351                 store_int("xinput_enable", globals.xinput_enable);
352                 store_int("update_idle", globals.update_idle);
353                 store_int("update_delay", globals.update_delay);
354                 store_int("sense_cycles", globals.sense_cycles);
355                 store_float("mouse_speed", globals.mouse_speed);
356                 store_int("width", globals.width);
357                 store_int("height", globals.height);
358                 store_int("filename_length", globals.filename_length);
359                 store_int("tooltips", globals.tooltips);
360                 store_int("use_stdout", globals.use_stdout);
361                 // globals.use_stdout_from_conf_file=0; What the heck is this?
362                 store_int("show_nag", globals.show_nag);
363                 store_int("input_fallback_warning", globals.input_fallback_warning);
364                 store_int("prelis", globals.prelis);
365                 store_string("last_fn", globals.last_fn);
366                 store_float("pitch", globals.pitch);
367                 store_float("volume", globals.volume);
368                 store_float("flash_response", globals.flash_response);
369                 store_int("knob_size_override", globals.knob_size_override);
370                 store_int("button_type", globals.button_type);
371                 store_string("tables_filename", globals.tables_filename);
372                 store_string("record_filename", globals.record_filename);
373                 store_string("file_editor", globals.file_editor);
374                 store_string("lrdf_path", globals.lrdf_path);
375                 store_int("compress_set_files", globals.compress_set_files);
376                 store_int("fullscreen_enabled", globals.fullscreen_enabled);
377                 store_int("confirm_events", globals.confirm_events);
378                 store_float("vtt_inertia", globals.vtt_inertia);
379
380                 store_string("last_path", globals.current_path);
381                 store_int("restore_midi_connections", globals.restore_midi_connections);
382
383                 store_int("wav_display_history", globals.wav_display_history);
384                 store_float("title_bar_alpha", globals.title_bar_alpha);
385                 store_int("wav_use_vtt_color", globals.wav_use_vtt_color);
386                 store_string("wav_display_bg_focus", globals.wav_display_bg_focus);
387                 store_string("wav_display_bg_no_focus", globals.wav_display_bg_no_focus);
388                 store_string("wav_display_fg_focus", globals.wav_display_fg_focus);
389                 store_string("wav_display_fg_no_focus", globals.wav_display_fg_no_focus);
390                 store_string("wav_display_cursor", globals.wav_display_cursor);
391                 store_string("wav_display_cursor_mute", globals.wav_display_cursor_mute);
392
393                 store_string("vu_meter_bg", globals.vu_meter_bg);
394                 store_string("vu_meter_normal", globals.vu_meter_normal);
395                 store_string("vu_meter_loud", globals.vu_meter_loud);
396                         
397                 store_float("vu_meter_border_intensity", globals.vu_meter_border_intensity);
398
399                 store_int("quit_confirm", globals.quit_confirm);
400                 store_int("use_realtime", globals.use_realtime);
401                 store_int("auto_assign_midi", globals.auto_assign_midi);
402                 
403                 store_int("verbose_plugin_loading", globals.verbose_plugin_loading);
404                 store_int("force_nonrt_plugins", globals.force_nonrt_plugins);
405
406 #ifdef USE_ALSA_MIDI_IN
407                 tX_midiin_store_connections(rc, indent);
408 #endif          
409
410                 fprintf(rc,"</terminatorXrc>\n");
411         }
412 }
413
414 #ifdef ENABLE_TX_LEGACY
415 extern void load_globals_old();
416 #endif
417
418 void load_globals() {
419         set_global_defaults();
420
421         if (load_globals_xml()!=0) {
422                 fprintf(stderr, "tX: Failed loading terminatorXrc - trying to load old binary rc.\n");
423 #ifdef ENABLE_TX_LEGACY         
424                 load_globals_old();
425 #endif          
426         }
427 }
428
429 char *encode_xml(char *dest, const char *src) {
430         int i, t, max;
431         char tmp[4096];
432         int outlen=4096;
433         int inlen;
434         int res;
435         
436         tmp[0]=0;
437         t=0;
438         max=strlen(src);
439         
440         for (i=0; i<max; i++) {
441                 switch (src[i]) {
442                         case '<': tmp[t]=0; strcat(tmp, "&lt;"); t+=4; break;
443                         case '>': tmp[t]=0; strcat(tmp, "&gt;"); t+=4; break;
444                         case '&': tmp[t]=0; strcat(tmp, "&amp;"); t+=5; break;
445                         case '"': tmp[t]=0; strcat(tmp, "&quot;"); t+=6; break;
446                         case '\'': strcat(tmp, "&apos;"); t+=7; break;
447                         default: tmp[t]=src[i]; t++;
448                 }
449         }
450         tmp[t]=0;
451
452         inlen=t;
453         res=isolat1ToUTF8((unsigned char *) dest, &outlen, (unsigned char *) tmp, &inlen);
454         dest[outlen]=0;
455         if (res<0) {
456                 tX_error("failed to encode string (%s) to UTF-8.", src);
457         }
458         
459         return dest;
460 }
461
462 char *decode_xml(char *dest, const char *src) {
463         int inlen=strlen(src);
464         int outlen=4096;
465         
466         int res=UTF8Toisolat1((unsigned char *) dest, &outlen, (const unsigned char *) src, &inlen);
467         dest[outlen]=0;
468         
469         if (res<0) {
470                 tX_error("failed to decode UTF-8 string (%s).", src);
471         }
472         
473         return dest;
474 }