2 terminatorX - realtime audio scratching software
3 Copyright (C) 1999-2016 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, see <http://www.gnu.org/licenses/>.
20 Description: This contains the main() function. All the initializing
24 #define TX_GTKRC "/usr/share/themes/terminatorX/gtk/gtkrc"
26 #define BENCH_CYCLES 100000
29 #include "tX_mastergui.h"
41 #include "tX_endian.h"
43 #include "tX_global.h"
44 #include "tX_audiodevice.h"
46 #include "tX_dialog.h"
51 #include "tX_ladspa.h"
52 #include "tX_ladspa_class.h"
53 #include "tX_engine.h"
54 #include "tX_capabilities.h"
55 #include "tX_pbutton.h"
57 #ifdef CREATE_BENCHMARK
63 #include <sys/types.h>
70 if ((!tX_jack_client::get_instance()) && (globals.audiodevice_type==JACK)) {
71 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);
76 static bool timesup=false;
78 gboolean timeout(void *)
88 usage: terminatorX [options]n\
90 -h, --help Display help info\n\
91 -f, --file Load saved terminatorX set file\n\
92 -r, --rc-file [file] Load alternate rc file\n\
93 -d, --dont-save Do not save settings at exit\n\
94 -s, --std-out Use stdout for sound output\n\
95 --device=[output device] Use alternate device for sound output\n\
99 int parse_args(int *argc, char **argv)
101 // pass over argv once to see if we need to load an alternate_rc file
102 for (int i = 1 ; i != *argc ; ++i ) {
103 if ((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) {
106 fprintf(stderr, "tX: Loading alternate rc file %s\n", argv[i]);
107 globals.alternate_rc = argv[i];
116 // load up the global values
119 // default the flag options, or they'll be set from last execution... (think globals.no_gui ;)
121 globals.alternate_rc = 0;
122 globals.store_globals = 1;
123 globals.startup_set = 0;
125 // then pass over again, this time setting passed values
126 for (int i = 1 ; i < *argc ; ++i ) {
127 if ((strcmp(argv[i], "-f") == 0) || (strcmp(argv[i], "--file") == 0)) {
129 globals.startup_set = argv[i];
130 } else if (((strcmp(argv[i], "-r") == 0) || (strcmp(argv[i], "--rc-file") == 0)) && (argv[i+1])) {
132 globals.alternate_rc = argv[i];
133 } else if ((strcmp(argv[i], "-d") == 0) || (strcmp(argv[i], "--dont-save") == 0)) {
134 fprintf(stderr, "tX: Do not save settings on exit\n");
135 globals.store_globals = 0;
137 } else if ((strcmp(argv[i], "-s") == 0) || (strcmp(argv[i], "--std-out") == 0)) {
138 globals.use_stdout_cmdline = 1;
139 globals.use_stdout = 1;
140 } else if ((strncmp(argv[i], "--device",8) == 0)) {
141 if (strlen(argv[i]+9)<=PATH_MAX)
142 strcpy(globals.oss_device,argv[i]+9);
155 void checkenv(const char *name)
162 length=strlen(value);
164 strnlen requires extra macros...
165 length=strnlen(value, PATH_MAX+1);
168 if (length>=PATH_MAX) {
169 tX_error("Your \"%s\" environment variable seems malicious (%i chars).", name, length);
170 tX_error("Please correct that and restart terminatorX.");
176 int main(int argc, char **argv)
178 bool keep_caps_failed = false;
179 bool root_dropped = false;
181 #ifdef USE_CAPABILITIES
183 if (prctl(PR_SET_KEEPCAPS, 1, -1, -1, -1)) {
184 keep_caps_failed = true;
186 set_nice_capability(CAP_PERMITTED);
190 GError *mouse_error = mouse.open_channel();
192 if ((!geteuid()) && (getuid() != geteuid())) {
193 int result=setuid(getuid());
197 tX_error("main() panic: can't drop root privileges.");
202 /* No suidroot below this comment. */
204 fprintf(stderr, "%s - Copyright (C) 1999-2016 by Alexander König\n", VERSIONSTRING);
205 fprintf(stderr, "terminatorX comes with ABSOLUTELY NO WARRANTY - for details read the license.\n");
207 if (keep_caps_failed) {
208 tX_error("failed to keep capabilities.");
212 tX_msg("started suid-root - root privileges dropped.");
216 #ifdef USE_CAPABILITIES
217 set_nice_capability(CAP_EFFECTIVE);
220 /* Theses checks are now sort of unecessary... Anyway... */
222 checkenv("XLOCALEDIR");
224 gtk_init (&argc, &argv);
226 #ifdef USE_STARTUP_NOTIFICATION
227 // startup isn't really finished with the nagbox alone...
228 gtk_window_set_auto_startup_notification(FALSE);
231 parse_args(&argc, argv); // loads settings
233 if (globals.show_nag) {
235 g_timeout_add(2000, (GSourceFunc) timeout, NULL);
238 tX_engine *engine=tX_engine::get_instance();
239 LADSPA_Class::init();
240 LADSPA_Plugin::init();
243 if (globals.audiodevice_type == JACK) {
244 // only init jack interface when chosen via configuration
245 // to allow wiring of jack in-/outputs
246 tX_jack_client::get_instance()->init();
251 tX_debug("main() GUI thread is p:%i, t:%i and has policy %i.", getpid(), (int) pthread_self(), sched_getscheduler(getpid()));
254 create_mastergui(globals.width, globals.height);
256 if (globals.show_nag) {
258 while (gtk_events_pending()) { gtk_main_iteration(); }
270 if (globals.startup_set) {
271 while (gtk_events_pending()) { gtk_main_iteration(); }
273 tX_cursor::set_cursor(tX_cursor::WAIT_CURSOR);
274 load_tt_part(globals.startup_set);
275 tX_cursor::reset_cursor();
277 #ifdef USE_ALSA_MIDI_IN
278 if (globals.auto_assign_midi) tX_midiin::auto_assign_midi_mappings(NULL, NULL);
284 const char *errorFmt = "<span size=\"larger\" weight=\"bold\">Failed to access input hardware</span>\n\n"
285 "terminatorX failed to get direct access to the Linux input interface and "
286 "will now fallback to the standard \"pointer warp\" mode, which will result in "
287 "<span weight=\"bold\">significantly reduced scratching precision</span>.\n\nTo achieve "
288 "high precision scratching either\n - <span style=\"italic\">install terminatorX suid-root</span>, or\n"
289 " - <span style=\"italic\">add the users running terminatorX to a group that can access the special "
290 "file \"/dev/input/mice\"</span>\nand restart terminatorX.\n\n"
291 "The reported error was: <span weight=\"bold\">%s</span>";
293 snprintf(buffer, 4096, errorFmt, mouse_error->message);
294 tx_note(buffer, true, NULL);
295 g_error_free(mouse_error);
298 #ifdef USE_STARTUP_NOTIFICATION
299 gdk_notify_startup_complete();
302 #ifndef CREATE_BENCHMARK
307 mouse.close_channel();
311 fprintf(stderr, "Have a nice life.\n");
312 #else // CREATE_BENCHMARK
313 gtk_widget_hide(main_window);
314 while (gtk_events_pending()) gtk_main_iteration(); gdk_flush();
317 vtt_class::set_sample_rate(48000);
319 printf("\n* BENCHMARKING *\n");
321 GTimer *bench_time = g_timer_new();
325 list <vtt_class *> :: iterator vtt;
327 for (vtt=vtt_class::main_list.begin(); vtt!=vtt_class::main_list.end(); vtt++) {
328 if ((*vtt)->autotrigger) (*vtt)->trigger();
332 g_timer_start(bench_time);
334 for (int i=0; i<BENCH_CYCLES; i++) {
335 vtt_class::render_all_turntables();
337 g_timer_stop(bench_time);
338 res=g_timer_elapsed(bench_time, µs);
340 ratio=((double) BENCH_CYCLES)/res;
341 printf ("Rendered %i blocks in %f secons,\n=> %f blocks per second.\n\n", (long) BENCH_CYCLES, res, ratio);
342 #endif // CREATE_BENCHMARK