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>
30 #include <gtkmm/settings.h>
32 #include <pbd/error.h>
33 #include <pbd/textreceiver.h>
34 #include <pbd/platform.h>
35 #include <pbd/platform_factory.h>
36 #include <pbd/failed_constructor.h>
37 #include <pbd/pthread_utils.h>
39 #include <jack/jack.h>
41 #include <ardour/version.h>
42 #include <ardour/ardour.h>
43 #include <ardour/audioengine.h>
45 #include <gtkmm/main.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/utils.h>
50 #include "ardour_ui.h"
56 using namespace GTK_ARDOUR;
57 using namespace ARDOUR;
60 Transmitter error (Transmitter::Error);
61 Transmitter info (Transmitter::Info);
62 Transmitter fatal (Transmitter::Fatal);
63 Transmitter warning (Transmitter::Warning);
64 TextReceiver text_receiver ("ardour");
66 extern int curvetest (string);
68 static ARDOUR_UI *ui = 0;
77 msg = _("ardour is killing itself for a clean exit\n");
78 write (1, msg, strlen (msg));
79 /* drastic, but perhaps necessary */
80 kill (-getpgrp(), SIGKILL);
86 msg = _("stopping user interface\n");
87 write (1, msg, strlen (msg));
91 pthread_cancel_all ();
104 /* XXX its doubtful that snprintf() is async-safe */
105 n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig);
112 handler2 (int sig, siginfo_t* ctxt, void* ignored)
118 signal_thread (void *arg)
123 PBD::ThreadCreated (pthread_self(), X_("Signal"));
125 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
127 /* find out what's blocked right now */
129 //sigprocmask (SIG_SETMASK, 0, &blocked);
130 if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
131 cerr << "getting blocked signals failed\n";
134 /* wait for any of the currently blocked signals.
136 According to the man page found in linux 2.6 and 2.4, sigwait()
137 never returns an error. This is incorrect. Checking the man
138 pages for some other *nix systems makes it clear that
139 sigwait() can return several error codes, one of which
140 is EINTR. This happens if the thread receives a signal
141 which is not in the blocked set.
143 We do not expect that to happen, and if it did we should generally
144 exit as planned. However, under 2.6, the ptrace facility used
145 by gdb seems to also cause sigwait() to return with EINTR
146 but with a signal that sigwait cannot understand. As a result,
147 "sig" is set to zero, an impossible signal number.
149 Handling the EINTR code makes it possible to debug
150 ardour on a 2.6 kernel.
157 if ((swerr = sigwait (&blocked, &sig))) {
158 if (swerr == EINTR) {
161 cerr << "sigwait failed with " << swerr << endl;
165 cerr << "Signal " << sig << " received\n";
167 if (sig != SIGSEGV) {
169 /* unblock signals so we can see them during shutdown.
170 this will help prod developers not to lose sight
171 of bugs that cause segfaults etc. during shutdown.
174 sigprocmask (SIG_UNBLOCK, &blocked, 0);
185 struct sigaction action;
186 pthread_t signal_thread_id;
189 // if (setpgid (0,0)) {
191 warning << string_compose (_("cannot become new process group leader (%1)"),
196 sigemptyset (&signals);
197 sigaddset(&signals, SIGHUP);
198 sigaddset(&signals, SIGINT);
199 sigaddset(&signals, SIGQUIT);
200 sigaddset(&signals, SIGPIPE);
201 sigaddset(&signals, SIGTERM);
202 sigaddset(&signals, SIGUSR1);
203 sigaddset(&signals, SIGUSR2);
206 /* install a handler because otherwise
207 pthreads behaviour is undefined when we enter
211 action.sa_handler = handler;
212 action.sa_mask = signals;
213 action.sa_flags = SA_RESTART|SA_RESETHAND;
215 for (int i = 1; i < 32; i++) {
216 if (sigismember (&signals, i)) {
217 if (sigaction (i, &action, 0)) {
218 cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
224 /* this sets the signal mask for this and all
225 subsequent threads that do not reset it.
228 if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
229 cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
233 /* start a thread to wait for signals */
235 if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
236 cerr << "cannot create signal catching thread" << endl;
240 pthread_detach (signal_thread_id);
250 if ((envvar = getenv("ARDOUR_UI_RC")) == 0) {
251 rcfile = find_config_file ("ardour_ui.rc");
253 if (rcfile.length() == 0) {
254 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;
264 show_ui_callback (void *arg)
266 ARDOUR_UI * ui = (ARDOUR_UI *) arg;
275 jack_fooey (GdkEventAny* ignored)
290 Window win (Gtk::WINDOW_POPUP);
293 Label label (_("Ardour could not connect to JACK.\n\
294 There are several possible reasons:\n\
296 1) JACK is not running.\n\
297 2) JACK is running as another user, perhaps root.\n\
298 3) There is already another client called \"ardour\".\n\
300 Please consider the possibilities, and perhaps (re)start JACK."));
302 vpacker.set_spacing (12);
303 vpacker.pack_start (label);
304 vpacker.pack_start (ok, false, false);
306 win.set_title (_("ardour: unplugged"));
307 win.set_border_width (7);
310 win.signal_delete_event().connect (sigc::ptr_fun (jack_fooey));
311 win.add_events (Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK);
312 win.set_position (Gtk::WIN_POS_CENTER);
314 ok.signal_clicked().connect (sigc::ptr_fun (jack_foobar));
322 main (int argc, char *argv[])
324 ARDOUR::AudioEngine *engine;
325 char *null_file_list[] = { 0 };
329 (void) bindtextdomain (PACKAGE, LOCALEDIR);
330 (void) textdomain (PACKAGE);
332 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
336 text_receiver.listen_to (error);
337 text_receiver.listen_to (info);
338 text_receiver.listen_to (fatal);
339 text_receiver.listen_to (warning);
342 if (parse_opts (argc, argv)) {
346 if (curvetest_file) {
347 return curvetest (curvetest_file);
350 /* desktop standard themes: just say no! */
352 if (getenv("GTK_RC_FILES")) {
353 unsetenv("GTK_RC_FILES");
356 if (getenv("GTK2_RC_FILES")) {
357 unsetenv("GTK_RC_FILES");
360 gtk_rc_set_default_files (null_file_list);
362 cout << _("Ardour/GTK ")
364 << _("\n (built using ")
365 << gtk_ardour_major_version << '.'
366 << gtk_ardour_minor_version << '.'
367 << gtk_ardour_micro_version
368 << _(" with libardour ")
369 << libardour_major_version << '.'
370 << libardour_minor_version << '.'
371 << libardour_micro_version
373 << _(" and GCC version ") << __VERSION__
383 cerr << _("Copyright (C) 1999-2005 Paul Davis") << endl
384 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
386 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
387 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
388 << _("This is free software, and you are welcome to redistribute it ") << endl
389 << _("under certain conditions; see the source for copying conditions.")
394 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
397 catch (failed_constructor& err) {
398 error << _("could not create ARDOUR GUI") << endmsg;
405 if (session_name.length()) {
406 gtk_timeout_add (4000, show_ui_callback, ui);
411 engine = new ARDOUR::AudioEngine (jack_client_name);
412 ARDOUR::init (*engine, use_vst, try_hw_optimization, handler2);
413 ui->set_engine (*engine);
416 catch (AudioEngine::NoBackendAvailable& err) {
418 error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
422 catch (failed_constructor& err) {
423 error << _("could not initialize Ardour.") << endmsg;
427 /* load session, if given */
430 if (session_name.length()){
433 if (Session::find_session (session_name, path, name, isnew)) {
434 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
439 /* command line required that the session be new */
443 /* popup the new session dialog
444 once everything else is OK.
447 Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
448 ui->set_will_create_new_session_automatically (true);
452 /* it wasn't new, but we require a new session */
454 error << string_compose (_("\n\nA session named \"%1\" already exists.\n\
455 To avoid this message, start ardour as \"ardour %1"), path)
462 /* command line didn't require a new session */
465 error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
466 To create it from the command line, start ardour as \"ardour --new %1"), path)
471 ui->load_session (path, name);
482 if (!Config->get_no_new_session_dialog()) {
483 ui->new_session (true);
487 ui->run (text_receiver);