MIDI set_sync_client fix, cleanups, compilation fixes for gcc 2.95 - Alex
[terminatorX.git] / src / main.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: main.c
20     
21     Description: This contains the main() function. All the initializing
22                  happens here.
23     
24     Changes:
25     
26     19 Mar 1999: Applied a patch by Andrew C. Bul+hac?k (eMail: acb@zikzak.net)
27                  that fixes wavfile reading routine for the overreading bug.
28                  
29     20 Mar 1999: Big endian support.
30     
31     23 Mar 1999: display of new keys (<-, ->)
32     
33     4 October 1999: Rewrite ;) - back to C++
34 */
35
36 #define TX_GTKRC "/usr/share/themes/terminatorX/gtk/gtkrc"
37
38 #define BENCH_CYCLES 100000
39
40 #include <stdio.h>
41 #include "tX_mastergui.h"
42 #include <malloc.h>
43 #include <math.h>
44 #include <stdio.h>
45 #ifndef WIN32
46 #include <unistd.h>
47 #endif
48
49 #ifdef HAVE_CONFIG_H
50 #include <config.h>
51 #endif
52
53 #include "tX_endian.h"
54 #include "tX_types.h"
55 #include "tX_global.h"
56 #include "tX_audiodevice.h"
57 #include "version.h"
58 #include "tX_dialog.h"
59 #include <gtk/gtk.h>
60 #include <glib.h>
61 #include <string.h>
62
63 #include "tX_ladspa.h"
64 #include "tX_ladspa_class.h"
65 #include "tX_engine.h"
66 #include "tX_capabilities.h"
67
68 #ifdef CREATE_BENCHMARK 
69 #include "tX_vtt.h"
70 #endif
71
72 GTimer *my_time;
73 gint idle_tag;
74 #ifdef USE_JACK 
75 void jack_check()
76 {
77         if ((!tX_jack_client::get_instance()) && (globals.audiodevice_type==JACK)) {
78                 tx_note("Couldn't connect to JACK server - JACK output not available.\n\nIf you want to use JACK, ensure the JACK daemon is running before you start terminatorX.", true);
79         }
80 }
81 #endif // USE_JACK
82
83 int idle()
84 {
85         gdouble time;
86         gulong ms;
87         
88         time=g_timer_elapsed(my_time, &ms);
89         if (time > 1.5)
90         {
91                 gtk_idle_remove(idle_tag);
92                 g_timer_destroy(my_time);
93                 destroy_about();                
94                 display_mastergui();            
95 #ifdef USE_JACK 
96                 jack_check();
97 #endif                  
98         }
99         
100         return TRUE;
101 }
102
103 void show_help()
104 {
105                         
106         fprintf(stderr, "\
107 usage: terminatorX [options]n\
108 \n\
109   -h, --help                    Display help info\n\
110   -f, --file                    Load saved terminatorX set file\n\
111   -r, --rc-file [file]          Load alternate rc file\n\
112   -d, --dont-save               Do not save settings at exit\n\
113   -s, --std-out                 Use stdout for sound output\n\
114   --device=[output device]      Use alternate device for sound output\n\
115 \n");
116 }
117
118 int parse_args(int *argc, char **argv)
119 {
120         // pass over argv once to see if we need to load an alternate_rc file
121         for (int i = 1 ; i != *argc ; ++i ) {
122                 if ((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) {
123                         if (argv[i+1] ) {       
124                                 ++i;
125                                 fprintf(stderr, "tX: Loading alternate rc file %s\n", argv[i]);
126                                 globals.alternate_rc = argv[i];
127                         } else {
128                                 show_help();    
129                                 exit(1);
130                         }
131                         break;
132                 }
133         }
134         
135         // load up the global values
136         load_globals();
137
138         // default the flag options, or they'll be set from last execution... (think globals.no_gui ;)
139         globals.no_gui = 0;
140         globals.alternate_rc = 0;
141         globals.store_globals = 1;
142         globals.startup_set = 0;
143                 
144         // then pass over again, this time setting passed values
145         for (int i = 1 ; i < *argc ; ++i ) {
146                 if ((strcmp(argv[i], "-f") == 0) || (strcmp(argv[i], "--file") == 0)) {
147                         ++i;
148                         globals.startup_set = argv[i];
149                 } else if (((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) && (argv[i+1])) {
150                         ++i;
151                         globals.alternate_rc = argv[i];
152                 } else if ((strcmp(argv[i], "-d") == 0) || (strcmp(argv[i], "--dont-save") == 0)) {
153                         fprintf(stderr, "tX: Do not save settings on exit\n");
154                         globals.store_globals = 0;
155
156                 } else if ((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "--std-out") == 0)) {
157                         globals.use_stdout_cmdline = 1;
158                         globals.use_stdout = 1;
159                 } else if ((strncmp(argv[i], "--device",8) == 0)) {
160                         if (strlen(argv[i]+9)<=PATH_MAX)
161                                 strcpy(globals.oss_device,argv[i]+9);
162                         else {
163                                 show_help();
164                                 exit(1);
165                         }
166                 } else {
167                         show_help();
168                         exit(1);
169                 }
170         }
171         return 1;
172 }
173
174 void checkenv(const char *name) {
175         char *value;
176         int length;
177         
178         value=getenv(name);
179         if (value) {
180                 length=strlen(value);
181                 /*
182                  strnlen requires extra macros...
183                  length=strnlen(value, PATH_MAX+1);
184                 */
185                 
186                 if (length>=PATH_MAX) {
187                         tX_error("Your \"%s\" environment variable seems malicious (%i chars).", name, length);
188                         tX_error("Please correct that and restart terminatorX.");
189                         exit(-1);
190                 }
191         }
192 }
193
194 int main(int argc, char **argv)
195 {
196         fprintf(stderr, "%s - Copyright (C) 1999-2003 by Alexander König\n", VERSIONSTRING);
197         fprintf(stderr, "terminatorX comes with ABSOLUTELY NO WARRANTY - for details read the license.\n");
198
199 #ifdef USE_CAPABILITIES 
200         if (!geteuid()) {
201                 if (prctl(PR_SET_KEEPCAPS, 1, -1, -1, -1)) {
202                         tX_error("failed to keep capabilites.");
203                 }
204                 set_nice_capability(CAP_PERMITTED);
205         }
206         
207         if ((!geteuid()) && (getuid() != geteuid())) {
208                 tX_debug("main() - capabilites set, dropping root privileges.");
209                 
210                 int result=setuid(getuid());
211                 
212                 if (result) {
213                         tX_error("main() Panic: can't drop root privileges.");
214                         exit(2);
215                 }
216         }
217         
218         set_nice_capability(CAP_EFFECTIVE);     
219 #endif
220         
221         checkenv("HOME");
222         checkenv("XLOCALEDIR"); 
223         
224         tX_engine *engine=tX_engine::get_instance();
225         
226         gtk_init (&argc, &argv);
227         gtk_set_locale();
228         
229         parse_args(&argc, argv); 
230
231         if (globals.show_nag) { 
232                 show_about(1);
233
234                 my_time=g_timer_new();
235                 g_timer_start(my_time);         
236         
237                 idle_tag=gtk_idle_add((GtkFunction)idle, NULL);
238         }
239         
240         LADSPA_Class::init();
241         LADSPA_Plugin::init();
242 #ifdef USE_JACK 
243         tX_jack_client::init();
244 #endif  
245         
246         create_mastergui(globals.width, globals.height);
247                 
248         if (!globals.show_nag) {
249 #ifdef USE_JACK
250                 jack_check();
251 #endif
252                 display_mastergui();
253         }
254                 
255         if (globals.startup_set) {
256                 while (gtk_events_pending()) gtk_main_iteration(); gdk_flush(); 
257                 tX_cursor::set_cursor(tX_cursor::WAIT_CURSOR);
258                 load_tt_part(globals.startup_set);
259                 tX_cursor::reset_cursor();
260         }
261
262 #ifndef CREATE_BENCHMARK
263         gtk_main();
264
265         store_globals();
266
267         delete engine;
268 #ifdef USE_JACK 
269         if (tX_jack_client::get_instance()) {
270                 delete tX_jack_client::get_instance();
271         }
272 #endif // USE_JACK
273         
274         fprintf(stderr, "Have a nice life.\n");
275 #else // CREATE_BENCHMARK
276         gtk_widget_hide(main_window);
277         while (gtk_events_pending()) gtk_main_iteration(); gdk_flush(); 
278         gdk_flush();
279         
280         vtt_class::set_sample_rate(48000);
281         
282         printf("\n* BENCHMARKING *\n");
283         
284         GTimer *bench_time = g_timer_new();
285         gulong micros;
286         double ratio;
287         double res;
288         list <vtt_class *> :: iterator vtt;
289         
290         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
291         {
292                 if ((*vtt)->autotrigger) (*vtt)->trigger();
293         }
294         sleep(3);
295         
296         g_timer_start(bench_time);
297         for (int i=0; i<BENCH_CYCLES; i++)
298         {
299                 vtt_class::render_all_turntables();
300         }
301         g_timer_stop(bench_time);
302         res=g_timer_elapsed(bench_time, &micros);
303         
304         ratio=((double) BENCH_CYCLES)/res;
305         printf ("Rendered %i blocks in %f secons,\n=> %f blocks per second.\n\n", (long) BENCH_CYCLES, res, ratio);
306 #endif // CREATE_BENCHMARK
307         return (0);
308 }