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