2 Copyright (C) 2001-2004 Paul Davis
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 #include <sys/types.h>
29 #include <sigc++/bind.h>
31 #include <pbd/error.h>
32 #include <pbd/textreceiver.h>
33 #include <pbd/platform.h>
34 #include <pbd/platform_factory.h>
35 #include <pbd/failed_constructor.h>
36 #include <pbd/pthread_utils.h>
38 #include <jack/jack.h>
40 #include <ardour/version.h>
41 #include <ardour/ardour.h>
42 #include <ardour/audioengine.h>
44 #include <gtkmm/main.h>
45 #include <gtkmm2ext/popup.h>
46 #include <gtkmm2ext/utils.h>
49 #include "ardour_ui.h"
55 using namespace GTK_ARDOUR;
56 using namespace ARDOUR;
59 Transmitter error (Transmitter::Error);
60 Transmitter info (Transmitter::Info);
61 Transmitter fatal (Transmitter::Fatal);
62 Transmitter warning (Transmitter::Warning);
63 TextReceiver text_receiver ("ardour");
65 extern int curvetest (string);
67 static ARDOUR_UI *ui = 0;
76 msg = _("ardour is killing itself for a clean exit\n");
77 write (1, msg, strlen (msg));
78 /* drastic, but perhaps necessary */
79 kill (-getpgrp(), SIGKILL);
85 msg = _("stopping user interface\n");
86 write (1, msg, strlen (msg));
90 pthread_cancel_all ();
103 /* XXX its doubtful that snprintf() is async-safe */
104 n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig);
111 handler2 (int sig, siginfo_t* ctxt, void* ignored)
117 signal_thread (void *arg)
122 PBD::ThreadCreated (pthread_self(), X_("Signal"));
124 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
126 /* find out what's blocked right now */
128 //sigprocmask (SIG_SETMASK, 0, &blocked);
129 if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
130 cerr << "getting blocked signals failed\n";
133 /* wait for any of the currently blocked signals.
135 According to the man page found in linux 2.6 and 2.4, sigwait()
136 never returns an error. This is incorrect. Checking the man
137 pages for some other *nix systems makes it clear that
138 sigwait() can return several error codes, one of which
139 is EINTR. This happens if the thread receives a signal
140 which is not in the blocked set.
142 We do not expect that to happen, and if it did we should generally
143 exit as planned. However, under 2.6, the ptrace facility used
144 by gdb seems to also cause sigwait() to return with EINTR
145 but with a signal that sigwait cannot understand. As a result,
146 "sig" is set to zero, an impossible signal number.
148 Handling the EINTR code makes it possible to debug
149 ardour on a 2.6 kernel.
156 if ((swerr = sigwait (&blocked, &sig))) {
157 if (swerr == EINTR) {
160 cerr << "sigwait failed with " << swerr << endl;
164 cerr << "Signal " << sig << " received\n";
166 if (sig != SIGSEGV) {
168 /* unblock signals so we can see them during shutdown.
169 this will help prod developers not to lose sight
170 of bugs that cause segfaults etc. during shutdown.
173 sigprocmask (SIG_UNBLOCK, &blocked, 0);
184 struct sigaction action;
185 pthread_t signal_thread_id;
188 // if (setpgid (0,0)) {
190 warning << string_compose (_("cannot become new process group leader (%1)"),
195 sigemptyset (&signals);
196 sigaddset(&signals, SIGHUP);
197 sigaddset(&signals, SIGINT);
198 sigaddset(&signals, SIGQUIT);
199 sigaddset(&signals, SIGPIPE);
200 sigaddset(&signals, SIGTERM);
201 sigaddset(&signals, SIGUSR1);
202 sigaddset(&signals, SIGUSR2);
205 /* install a handler because otherwise
206 pthreads behaviour is undefined when we enter
210 action.sa_handler = handler;
211 action.sa_mask = signals;
212 action.sa_flags = SA_RESTART|SA_RESETHAND;
214 for (int i = 1; i < 32; i++) {
215 if (sigismember (&signals, i)) {
216 if (sigaction (i, &action, 0)) {
217 cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
223 /* this sets the signal mask for this and all
224 subsequent threads that do not reset it.
227 if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
228 cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
232 /* start a thread to wait for signals */
234 if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
235 cerr << "cannot create signal catching thread" << endl;
239 pthread_detach (signal_thread_id);
249 if ((envvar = getenv("ARDOUR_UI_RC")) == 0) {
250 rcfile = find_config_file ("ardour_ui.rc");
252 if (rcfile.length() == 0) {
253 warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR_UI_RC to point to a valid UI style file") << endmsg;
263 show_ui_callback (void *arg)
265 ARDOUR_UI * ui = (ARDOUR_UI *) arg;
274 jack_fooey (GdkEventAny* ignored)
289 Window win (Gtk::WINDOW_POPUP);
292 Label label (_("Ardour could not connect to JACK.\n\
293 There are several possible reasons:\n\
295 1) JACK is not running.\n\
296 2) JACK is running as another user, perhaps root.\n\
297 3) There is already another client called \"ardour\".\n\
299 Please consider the possibilities, and perhaps (re)start JACK."));
301 vpacker.set_spacing (12);
302 vpacker.pack_start (label);
303 vpacker.pack_start (ok, false, false);
305 win.set_title (_("ardour: unplugged"));
306 win.set_border_width (7);
309 win.signal_delete_event().connect (sigc::ptr_fun (jack_fooey));
310 win.add_events (Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK);
311 win.set_position (Gtk::WIN_POS_CENTER);
313 ok.signal_clicked().connect (sigc::ptr_fun (jack_foobar));
321 main (int argc, char *argv[])
323 ARDOUR::AudioEngine *engine;
324 char *null_file_list[] = { 0 };
328 (void) bindtextdomain (PACKAGE, LOCALEDIR);
329 (void) textdomain (PACKAGE);
331 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
335 text_receiver.listen_to (error);
336 text_receiver.listen_to (info);
337 text_receiver.listen_to (fatal);
338 text_receiver.listen_to (warning);
341 if (parse_opts (argc, argv)) {
345 if (curvetest_file) {
346 return curvetest (curvetest_file);
349 /* desktop standard themes: just say no! */
351 if (getenv("GTK_RC_FILES")) {
352 unsetenv("GTK_RC_FILES");
355 if (getenv("GTK2_RC_FILES")) {
356 unsetenv("GTK_RC_FILES");
359 gtk_rc_set_default_files (null_file_list);
361 cout << _("Ardour/GTK ")
363 << _("\n (built using ")
364 << gtk_ardour_major_version << '.'
365 << gtk_ardour_minor_version << '.'
366 << gtk_ardour_micro_version
367 << _(" with libardour ")
368 << libardour_major_version << '.'
369 << libardour_minor_version << '.'
370 << libardour_micro_version
372 << _(" and GCC version ") << __VERSION__
382 cerr << _("Copyright (C) 1999-2005 Paul Davis") << endl
383 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
385 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
386 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
387 << _("This is free software, and you are welcome to redistribute it ") << endl
388 << _("under certain conditions; see the source for copying conditions.")
393 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
396 catch (failed_constructor& err) {
397 error << _("could not create ARDOUR GUI") << endmsg;
404 if (session_name.length()) {
405 gtk_timeout_add (4000, show_ui_callback, ui);
410 engine = new ARDOUR::AudioEngine (jack_client_name);
411 ARDOUR::init (*engine, use_vst, try_hw_optimization, handler2);
412 ui->set_engine (*engine);
415 catch (AudioEngine::NoBackendAvailable& err) {
417 error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
421 catch (failed_constructor& err) {
422 error << _("could not initialize Ardour.") << endmsg;
426 /* load session, if given */
429 if (session_name.length()){
432 if (Session::find_session (session_name, path, name, isnew)) {
433 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
438 /* command line required that the session be new */
442 /* popup the new session dialog
443 once everything else is OK.
446 Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
447 ui->set_will_create_new_session_automatically (true);
451 /* it wasn't new, but we require a new session */
453 error << string_compose (_("\n\nA session named \"%1\" already exists.\n\
454 To avoid this message, start ardour as \"ardour %1"), path)
461 /* command line didn't require a new session */
464 error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
465 To create it from the command line, start ardour as \"ardour --new %1"), path)
470 ui->load_session (path, name);
481 if (!Config->get_no_new_session_dialog()) {
482 ui->new_session (true);
486 ui->run (text_receiver);