039fb6fffefc887fe591d0a3886cde1663392158
[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
62 #include "tX_ladspa.h"
63 #include "tX_ladspa_class.h"
64 #include "tX_engine.h"
65
66 #ifdef CREATE_BENCHMARK 
67 #include "tX_vtt.h"
68 #endif
69
70 GTimer *my_time;
71 gint idle_tag;
72 #ifdef USE_JACK 
73 void jack_check()
74 {
75         if ((!tX_jack_client::get_instance()) && (globals.audiodevice_type==JACK)) {
76                 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);
77         }
78 }
79 #endif                  
80
81 int idle()
82 {
83         gdouble time;
84         gulong ms;
85         
86         time=g_timer_elapsed(my_time, &ms);
87         if (time > 1.5)
88         {
89                 gtk_idle_remove(idle_tag);
90                 g_timer_destroy(my_time);
91                 destroy_about();                
92                 display_mastergui();            
93 #ifdef USE_JACK 
94                 jack_check();
95 #endif                  
96         }
97         
98         return TRUE;
99 }
100
101 void show_help()
102 {
103                         
104         fprintf(stderr, "\
105 usage: terminatorX [options]n\
106 \n\
107   -h, --help                    Display help info\n\
108   -f, --file                    Load saved terminatorX set file\n\
109   -r, --rc-file [file]          Load alternate rc file\n\
110   -d, --dont-save               Do not save settings at exit\n\
111   -s, --std-out                 Use stdout for sound output\n\
112   --device=[output device]      Use alternate device for sound output\n\
113 \n");
114 /*
115   -n, --no-gui                  Run terminatorX with no GUI\n\
116   -m, --midi-in [file]          Use [file] for midi input\n\
117   -o, --midi-out [file]         Use [file] for midi input\n\
118   -s, --std-out                 Use stdout for sound output\n\
119 \n");
120 */
121 }
122
123
124 int parse_args(int *argc, char **argv)
125 {
126         // pass over argv once to see if we need to load an alternate_rc file
127         for (int i = 1 ; i != *argc ; ++i )
128         {
129                 if ((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) 
130                 {
131                         if (argv[i+1] )
132                         {       
133                                 ++i;
134                                 fprintf(stderr, "tX: Loading alternate rc file %s\n", argv[i]);
135                                 globals.alternate_rc = argv[i];
136                         }
137                         else
138                         {
139                                 show_help();    
140                                 exit(1);
141                         }
142                         break;
143                 }
144         }
145         
146         // load up the global values
147         load_globals();
148
149         // default the flag options, or they'll be set from last execution... (think globals.no_gui ;)
150         globals.no_gui = 0;
151         globals.alternate_rc = 0;
152         globals.store_globals = 1;
153         globals.startup_set = 0;
154                 
155         // then pass over again, this time setting passed values
156         for (int i = 1 ; i < *argc ; ++i )
157         {
158                 if ((strcmp(argv[i], "-f") == 0) || (strcmp(argv[i], "--file") == 0))
159                 {
160                         ++i;
161                         globals.startup_set = argv[i];
162                 }       
163                 else if (((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) && (argv[i+1]))
164                 {
165                         ++i;
166                         globals.alternate_rc = argv[i];
167                 }
168                 else if ((strcmp(argv[i], "-d") == 0) || (strcmp(argv[i], "--dont-save") == 0))
169                 {
170                         fprintf(stderr, "tX: Do not save settings on exit\n");
171                         globals.store_globals = 0;
172
173                 }
174                 else if ((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "--std-out") == 0))
175                 {
176                         globals.use_stdout_cmdline = 1;
177                         globals.use_stdout = 1;
178                 }
179                 else if ((strncmp(argv[i], "--device",8) == 0))
180                 {
181                         if (strlen(argv[i]+9)<=PATH_MAX)
182                                 strcpy(globals.oss_device,argv[i]+9);
183                         else
184                         {
185                                 show_help();
186                                 exit(1);
187                         }
188                 }
189                 else
190                 {
191                         show_help();
192                         exit(1);
193                 }
194         }
195         return 1;
196 }
197
198 void checkenv(const char *name) {
199         char *value;
200         int length;
201         
202         value=getenv(name);
203         if (value) {
204                 length=strlen(value);
205                 
206                 if (length>=PATH_MAX) {
207                         tX_error("Your \"%s\" environment variable seems malicious (%i chars).", name, length);
208                         tX_error("Please correct that and restart terminatorX.");
209                         exit(-1);
210                 }
211         }
212 }
213
214 int main(int argc, char **argv)
215 {
216         fprintf(stderr, "%s - Copyright (C) 1999-2003 by Alexander König\n", VERSIONSTRING);
217         fprintf(stderr, "terminatorX comes with ABSOLUTELY NO WARRANTY - for details read the license.\n");
218
219         checkenv("HOME");
220         checkenv("XLOCALEDIR"); 
221         
222         tX_engine *engine=tX_engine::get_instance();
223         
224         gtk_init (&argc, &argv);
225         gtk_set_locale();
226         
227         parse_args(&argc, argv); 
228
229         if (globals.show_nag) { 
230                 show_about(1);
231
232                 my_time=g_timer_new();
233                 g_timer_start(my_time);         
234         
235                 idle_tag=gtk_idle_add((GtkFunction)idle, NULL);
236         }
237         
238         LADSPA_Class :: init();
239         LADSPA_Plugin :: init();
240 #ifdef USE_JACK 
241         tX_jack_client :: init();
242 #endif  
243         
244         create_mastergui(globals.width, globals.height);
245                 
246         if (!globals.show_nag) {
247                 display_mastergui();
248         }
249                 
250         if (globals.startup_set) {
251                 while (gtk_events_pending()) gtk_main_iteration(); gdk_flush(); 
252                 tX_cursor::set_cursor(tX_cursor::WAIT_CURSOR);
253                 load_tt_part(globals.startup_set);
254                 tX_cursor::reset_cursor();
255         }
256
257 #ifndef CREATE_BENCHMARK
258         gtk_main();
259
260         store_globals();
261
262         delete engine;
263 #ifdef USE_JACK 
264         if (tX_jack_client::get_instance()) {
265                 delete tX_jack_client::get_instance();
266         }
267 #endif  
268         
269         fprintf(stderr, "Have a nice life.\n");
270 #else
271         gtk_widget_hide(main_window);
272         while (gtk_events_pending()) gtk_main_iteration(); gdk_flush(); 
273         gdk_flush();
274         
275         vtt_class::set_sample_rate(48000);
276         
277         printf("\n* BENCHMARKING *\n");
278         
279         GTimer *bench_time = g_timer_new();
280         gulong micros;
281         double ratio;
282         double res;
283         list <vtt_class *> :: iterator vtt;
284         
285         for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++)
286         {
287                 if ((*vtt)->autotrigger) (*vtt)->trigger();
288         }
289         sleep(3);
290         
291         g_timer_start(bench_time);
292         for (int i=0; i<BENCH_CYCLES; i++)
293         {
294                 vtt_class::render_all_turntables();
295         }
296         g_timer_stop(bench_time);
297         res=g_timer_elapsed(bench_time, &micros);
298         
299         ratio=((double) BENCH_CYCLES)/res;
300         printf ("Rendered %i blocks in %f secons,\n=> %f blocks per second.\n\n", (long) BENCH_CYCLES, res, ratio);
301 #endif
302         return (0);
303 }