2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999-2003 Alexander König
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.
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.
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.
21 Description: This contains the main() function. All the initializing
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.
29 20 Mar 1999: Big endian support.
31 23 Mar 1999: display of new keys (<-, ->)
33 4 October 1999: Rewrite ;) - back to C++
36 #define TX_GTKRC "/usr/share/themes/terminatorX/gtk/gtkrc"
38 #define BENCH_CYCLES 100000
41 #include "tX_mastergui.h"
53 #include "tX_endian.h"
55 #include "tX_global.h"
56 #include "tX_audiodevice.h"
58 #include "tX_dialog.h"
63 #include "tX_ladspa.h"
64 #include "tX_ladspa_class.h"
65 #include "tX_engine.h"
66 #include "tX_capabilities.h"
68 #ifdef CREATE_BENCHMARK
74 #include <sys/types.h>
81 if ((!tX_jack_client::get_instance()) && (globals.audiodevice_type==JACK)) {
82 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);
87 static bool timesup=false;
89 gboolean timeout(void *)
99 usage: terminatorX [options]n\
101 -h, --help Display help info\n\
102 -f, --file Load saved terminatorX set file\n\
103 -r, --rc-file [file] Load alternate rc file\n\
104 -d, --dont-save Do not save settings at exit\n\
105 -s, --std-out Use stdout for sound output\n\
106 --device=[output device] Use alternate device for sound output\n\
110 int parse_args(int *argc, char **argv)
112 // pass over argv once to see if we need to load an alternate_rc file
113 for (int i = 1 ; i != *argc ; ++i ) {
114 if ((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) {
117 fprintf(stderr, "tX: Loading alternate rc file %s\n", argv[i]);
118 globals.alternate_rc = argv[i];
127 // load up the global values
130 // default the flag options, or they'll be set from last execution... (think globals.no_gui ;)
132 globals.alternate_rc = 0;
133 globals.store_globals = 1;
134 globals.startup_set = 0;
136 // then pass over again, this time setting passed values
137 for (int i = 1 ; i < *argc ; ++i ) {
138 if ((strcmp(argv[i], "-f") == 0) || (strcmp(argv[i], "--file") == 0)) {
140 globals.startup_set = argv[i];
141 } else if (((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) && (argv[i+1])) {
143 globals.alternate_rc = argv[i];
144 } else if ((strcmp(argv[i], "-d") == 0) || (strcmp(argv[i], "--dont-save") == 0)) {
145 fprintf(stderr, "tX: Do not save settings on exit\n");
146 globals.store_globals = 0;
148 } else if ((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "--std-out") == 0)) {
149 globals.use_stdout_cmdline = 1;
150 globals.use_stdout = 1;
151 } else if ((strncmp(argv[i], "--device",8) == 0)) {
152 if (strlen(argv[i]+9)<=PATH_MAX)
153 strcpy(globals.oss_device,argv[i]+9);
166 void checkenv(const char *name)
173 length=strlen(value);
175 strnlen requires extra macros...
176 length=strnlen(value, PATH_MAX+1);
179 if (length>=PATH_MAX) {
180 tX_error("Your \"%s\" environment variable seems malicious (%i chars).", name, length);
181 tX_error("Please correct that and restart terminatorX.");
187 int main(int argc, char **argv)
189 fprintf(stderr, "%s - Copyright (C) 1999-2003 by Alexander König\n", VERSIONSTRING);
190 fprintf(stderr, "terminatorX comes with ABSOLUTELY NO WARRANTY - for details read the license.\n");
192 #ifdef USE_CAPABILITIES
194 if (prctl(PR_SET_KEEPCAPS, 1, -1, -1, -1)) {
195 tX_error("failed to keep capabilites.");
197 set_nice_capability(CAP_PERMITTED);
200 if ((!geteuid()) && (getuid() != geteuid())) {
201 tX_debug("main() - capabilites set, dropping root privileges.");
203 int result=setuid(getuid());
206 tX_error("main() Panic: can't drop root privileges.");
211 set_nice_capability(CAP_EFFECTIVE);
215 checkenv("XLOCALEDIR");
217 #ifndef USE_CAPABILITIES
218 /* If we're not using capabilities we're still
219 running suid-root here. So we get rid of root
220 before doing anything esle.
222 tX_engine *engine=tX_engine::get_instance();
225 gtk_init (&argc, &argv);
228 parse_args(&argc, argv); // loads settings
230 if (globals.show_nag) {
232 g_timeout_add(2000, (GSourceFunc) timeout, NULL);
235 #ifdef USE_CAPABILITIES
236 /* If we have capabilities it's save to
237 first read the config and then create
240 tX_engine *engine=tX_engine::get_instance();
243 LADSPA_Class::init();
244 LADSPA_Plugin::init();
246 tX_jack_client::init();
250 tX_debug("main() GUI thread is p:%i, t:%i and has policy %i.", getpid(), (int) pthread_self(), sched_getscheduler(getpid()));
253 create_mastergui(globals.width, globals.height);
255 if (globals.show_nag) {
257 while (gtk_events_pending()) gtk_main_iteration();
269 if (globals.startup_set) {
270 while (gtk_events_pending()) gtk_main_iteration(); gdk_flush();
271 tX_cursor::set_cursor(tX_cursor::WAIT_CURSOR);
272 load_tt_part(globals.startup_set);
273 tX_cursor::reset_cursor();
275 #ifdef USE_ALSA_MIDI_IN
276 if (globals.auto_assign_midi) tX_midiin::auto_assign_midi_mappings(NULL, NULL);
280 #ifndef CREATE_BENCHMARK
287 if (tX_jack_client::get_instance()) {
288 delete tX_jack_client::get_instance();
292 fprintf(stderr, "Have a nice life.\n");
293 #else // CREATE_BENCHMARK
294 gtk_widget_hide(main_window);
295 while (gtk_events_pending()) gtk_main_iteration(); gdk_flush();
298 vtt_class::set_sample_rate(48000);
300 printf("\n* BENCHMARKING *\n");
302 GTimer *bench_time = g_timer_new();
306 list <vtt_class *> :: iterator vtt;
308 for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++) {
309 if ((*vtt)->autotrigger) (*vtt)->trigger();
313 g_timer_start(bench_time);
315 for (int i=0; i<BENCH_CYCLES; i++) {
316 vtt_class::render_all_turntables();
318 g_timer_stop(bench_time);
319 res=g_timer_elapsed(bench_time, µs);
321 ratio=((double) BENCH_CYCLES)/res;
322 printf ("Rendered %i blocks in %f secons,\n=> %f blocks per second.\n\n", (long) BENCH_CYCLES, res, ratio);
323 #endif // CREATE_BENCHMARK