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 << 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 << 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 << 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_DIALOG);
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.signal_add_events (Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK);
311 win.set_position (GTK_WIN_POS_CENTER);
313 win.get_window().set_decorations (GdkWMDecoration (GDK_DECOR_BORDER|GDK_DECOR_RESIZEH));
315 ok.signal_clicked().connect (sigc::ptr_fun (jack_foobar));
323 main (int argc, char *argv[])
325 ARDOUR::AudioEngine *engine;
326 char *null_file_list[] = { 0 };
330 (void) bindtextdomain (PACKAGE, LOCALEDIR);
331 (void) textdomain (PACKAGE);
333 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
337 text_receiver.listen_to (error);
338 text_receiver.listen_to (info);
339 text_receiver.listen_to (fatal);
340 text_receiver.listen_to (warning);
343 if (parse_opts (argc, argv)) {
347 if (curvetest_file) {
348 return curvetest (curvetest_file);
351 /* desktop standard themes: just say no! */
353 if (getenv("GTK_RC_FILES")) {
354 unsetenv("GTK_RC_FILES");
357 if (getenv("GTK2_RC_FILES")) {
358 unsetenv("GTK_RC_FILES");
361 gtk_rc_set_default_files (null_file_list);
363 cout << _("Ardour/GTK ")
365 << _("\n (built using ")
366 << gtk_ardour_major_version << '.'
367 << gtk_ardour_minor_version << '.'
368 << gtk_ardour_micro_version
369 << _(" with libardour ")
370 << libardour_major_version << '.'
371 << libardour_minor_version << '.'
372 << libardour_micro_version
374 << _(" and GCC version ") << __VERSION__
384 cerr << _("Copyright (C) 1999-2005 Paul Davis") << endl
385 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
387 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
388 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
389 << _("This is free software, and you are welcome to redistribute it ") << endl
390 << _("under certain conditions; see the source for copying conditions.")
395 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
398 catch (failed_constructor& err) {
399 error << _("could not create ARDOUR GUI") << endmsg;
406 if (session_name.length()) {
407 gtk_timeout_add (4000, show_ui_callback, ui);
412 engine = new ARDOUR::AudioEngine (jack_client_name);
413 ARDOUR::init (*engine, use_vst, try_hw_optimization, handler2);
414 ui->set_engine (*engine);
417 catch (AudioEngine::NoBackendAvailable& err) {
419 error << compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
423 catch (failed_constructor& err) {
424 error << _("could not initialize Ardour.") << endmsg;
428 /* load session, if given */
431 if (session_name.length()){
434 if (Session::find_session (session_name, path, name, isnew)) {
435 error << compose(_("could not load command line session \"%1\""), session_name) << endmsg;
440 /* command line required that the session be new */
444 /* popup the new session dialog
445 once everything else is OK.
448 Main::idle.connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
449 ui->set_will_create_new_session_automatically (true);
453 /* it wasn't new, but we require a new session */
455 error << compose (_("\n\nA session named \"%1\" already exists.\n\
456 To avoid this message, start ardour as \"ardour %1"), path)
463 /* command line didn't require a new session */
466 error << compose (_("\n\nNo session named \"%1\" exists.\n\
467 To create it from the command line, start ardour as \"ardour --new %1"), path)
472 ui->load_session (path, name);
483 if (!Config->get_no_new_session_dialog()) {
484 ui->new_session (true);
488 ui->run (text_receiver);