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 TextReceiver text_receiver ("ardour");
62 extern int curvetest (string);
64 static ARDOUR_UI *ui = 0;
73 msg = _("ardour is killing itself for a clean exit\n");
74 write (1, msg, strlen (msg));
75 /* drastic, but perhaps necessary */
76 kill (-getpgrp(), SIGKILL);
82 msg = _("stopping user interface\n");
83 write (1, msg, strlen (msg));
87 pthread_cancel_all ();
100 /* XXX its doubtful that snprintf() is async-safe */
101 n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig);
108 handler2 (int sig, siginfo_t* ctxt, void* ignored)
114 signal_thread (void *arg)
119 PBD::ThreadCreated (pthread_self(), X_("Signal"));
121 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
123 /* find out what's blocked right now */
125 //sigprocmask (SIG_SETMASK, 0, &blocked);
126 if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
127 cerr << "getting blocked signals failed\n";
130 /* wait for any of the currently blocked signals.
132 According to the man page found in linux 2.6 and 2.4, sigwait()
133 never returns an error. This is incorrect. Checking the man
134 pages for some other *nix systems makes it clear that
135 sigwait() can return several error codes, one of which
136 is EINTR. This happens if the thread receives a signal
137 which is not in the blocked set.
139 We do not expect that to happen, and if it did we should generally
140 exit as planned. However, under 2.6, the ptrace facility used
141 by gdb seems to also cause sigwait() to return with EINTR
142 but with a signal that sigwait cannot understand. As a result,
143 "sig" is set to zero, an impossible signal number.
145 Handling the EINTR code makes it possible to debug
146 ardour on a 2.6 kernel.
153 if ((swerr = sigwait (&blocked, &sig))) {
154 if (swerr == EINTR) {
157 cerr << "sigwait failed with " << swerr << endl;
161 cerr << "Signal " << sig << " received\n";
163 if (sig != SIGSEGV) {
165 /* unblock signals so we can see them during shutdown.
166 this will help prod developers not to lose sight
167 of bugs that cause segfaults etc. during shutdown.
170 sigprocmask (SIG_UNBLOCK, &blocked, 0);
181 struct sigaction action;
182 pthread_t signal_thread_id;
185 // if (setpgid (0,0)) {
187 warning << string_compose (_("cannot become new process group leader (%1)"),
192 sigemptyset (&signals);
193 sigaddset(&signals, SIGHUP);
194 sigaddset(&signals, SIGINT);
195 sigaddset(&signals, SIGQUIT);
196 sigaddset(&signals, SIGPIPE);
197 sigaddset(&signals, SIGTERM);
198 sigaddset(&signals, SIGUSR1);
199 sigaddset(&signals, SIGUSR2);
202 /* install a handler because otherwise
203 pthreads behaviour is undefined when we enter
207 action.sa_handler = handler;
208 action.sa_mask = signals;
209 action.sa_flags = SA_RESTART|SA_RESETHAND;
211 for (int i = 1; i < 32; i++) {
212 if (sigismember (&signals, i)) {
213 if (sigaction (i, &action, 0)) {
214 cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
220 /* this sets the signal mask for this and all
221 subsequent threads that do not reset it.
224 if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
225 cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
229 /* start a thread to wait for signals */
231 if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
232 cerr << "cannot create signal catching thread" << endl;
236 pthread_detach (signal_thread_id);
246 if ((envvar = getenv("ARDOUR_UI_RC")) == 0) {
247 rcfile = find_config_file ("ardour_ui.rc");
249 if (rcfile.length() == 0) {
250 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;
260 show_ui_callback (void *arg)
262 ARDOUR_UI * ui = (ARDOUR_UI *) arg;
271 jack_fooey (GdkEventAny* ignored)
286 Window win (Gtk::WINDOW_POPUP);
289 Label label (_("Ardour could not connect to JACK.\n\
290 There are several possible reasons:\n\
292 1) JACK is not running.\n\
293 2) JACK is running as another user, perhaps root.\n\
294 3) There is already another client called \"ardour\".\n\
296 Please consider the possibilities, and perhaps (re)start JACK."));
298 vpacker.set_spacing (12);
299 vpacker.pack_start (label);
300 vpacker.pack_start (ok, false, false);
302 win.set_title (_("ardour: unplugged"));
303 win.set_border_width (7);
306 win.signal_delete_event().connect (sigc::ptr_fun (jack_fooey));
307 win.add_events (Gdk::BUTTON_RELEASE_MASK|Gdk::BUTTON_PRESS_MASK);
308 win.set_position (Gtk::WIN_POS_CENTER);
310 ok.signal_clicked().connect (sigc::ptr_fun (jack_foobar));
318 main (int argc, char *argv[])
320 ARDOUR::AudioEngine *engine;
321 vector<Glib::ustring> null_file_list;
325 (void) bindtextdomain (PACKAGE, LOCALEDIR);
326 (void) textdomain (PACKAGE);
328 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
332 text_receiver.listen_to (error);
333 text_receiver.listen_to (info);
334 text_receiver.listen_to (fatal);
335 text_receiver.listen_to (warning);
337 if (parse_opts (argc, argv)) {
341 if (curvetest_file) {
342 return curvetest (curvetest_file);
345 /* desktop standard themes: just say no! */
347 if (getenv("GTK_RC_FILES")) {
348 unsetenv("GTK_RC_FILES");
351 if (getenv("GTK2_RC_FILES")) {
352 unsetenv("GTK_RC_FILES");
355 RC::set_default_files (null_file_list);
357 cout << _("Ardour/GTK ")
359 << _("\n (built using ")
360 << gtk_ardour_major_version << '.'
361 << gtk_ardour_minor_version << '.'
362 << gtk_ardour_micro_version
363 << _(" with libardour ")
364 << libardour_major_version << '.'
365 << libardour_minor_version << '.'
366 << libardour_micro_version
368 << _(" and GCC version ") << __VERSION__
378 cerr << _("Copyright (C) 1999-2005 Paul Davis") << endl
379 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
381 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
382 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
383 << _("This is free software, and you are welcome to redistribute it ") << endl
384 << _("under certain conditions; see the source for copying conditions.")
389 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
392 catch (failed_constructor& err) {
393 error << _("could not create ARDOUR GUI") << endmsg;
400 if (session_name.length()) {
401 gtk_timeout_add (4000, show_ui_callback, ui);
406 engine = new ARDOUR::AudioEngine (jack_client_name);
407 ARDOUR::init (*engine, use_vst, try_hw_optimization, handler2);
408 ui->set_engine (*engine);
409 } catch (AudioEngine::NoBackendAvailable& err) {
411 error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
413 } catch (failed_constructor& err) {
414 error << _("could not initialize Ardour.") << endmsg;
418 /* load session, if given */
421 if (session_name.length()){
424 if (Session::find_session (session_name, path, name, isnew)) {
425 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
430 /* command line required that the session be new */
434 /* popup the new session dialog
435 once everything else is OK.
438 Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
439 ui->set_will_create_new_session_automatically (true);
443 /* it wasn't new, but we require a new session */
445 error << string_compose (_("\n\nA session named \"%1\" already exists.\n\
446 To avoid this message, start ardour as \"ardour %1"), path)
453 /* command line didn't require a new session */
456 error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
457 To create it from the command line, start ardour as \"ardour --new %1"), path)
462 ui->load_session (path, name);
473 if (!Config->get_no_new_session_dialog()) {
474 ui->new_session (true);
478 if (!ui->set_quit_context ()) {
479 ui->run (text_receiver);