2 Copyright (C) 2001-2006 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/failed_constructor.h>
35 #include <pbd/pthread_utils.h>
37 #include <jack/jack.h>
39 #include <ardour/version.h>
40 #include <ardour/ardour.h>
41 #include <ardour/audioengine.h>
43 #include <gtkmm/main.h>
44 #include <gtkmm2ext/popup.h>
45 #include <gtkmm2ext/utils.h>
47 #include "svn_revision.h"
49 #include "ardour_ui.h"
56 using namespace GTK_ARDOUR;
57 using namespace ARDOUR;
61 TextReceiver text_receiver ("ardour");
63 extern int curvetest (string);
65 static ARDOUR_UI *ui = 0;
74 msg = _("ardour is killing itself for a clean exit\n");
75 write (1, msg, strlen (msg));
76 /* drastic, but perhaps necessary */
77 kill (-getpgrp(), SIGKILL);
86 pthread_cancel_all ();
99 /* XXX its doubtful that snprintf() is async-safe */
100 n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig);
107 signal_thread (void *arg)
112 PBD::ThreadCreated (pthread_self(), X_("Signal"));
114 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
116 /* find out what's blocked right now */
118 //sigprocmask (SIG_SETMASK, 0, &blocked);
119 if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
120 cerr << "getting blocked signals failed\n";
123 /* wait for any of the currently blocked signals.
125 According to the man page found in linux 2.6 and 2.4, sigwait()
126 never returns an error. This is incorrect. Checking the man
127 pages for some other *nix systems makes it clear that
128 sigwait() can return several error codes, one of which
129 is EINTR. This happens if the thread receives a signal
130 which is not in the blocked set.
132 We do not expect that to happen, and if it did we should generally
133 exit as planned. However, under 2.6, the ptrace facility used
134 by gdb seems to also cause sigwait() to return with EINTR
135 but with a signal that sigwait cannot understand. As a result,
136 "sig" is set to zero, an impossible signal number.
138 Handling the EINTR code makes it possible to debug
139 ardour on a 2.6 kernel.
146 if ((swerr = sigwait (&blocked, &sig))) {
147 if (swerr == EINTR) {
150 cerr << "sigwait failed with " << swerr << endl;
154 cerr << "Signal " << sig << " received\n";
156 if (sig != SIGSEGV) {
158 /* unblock signals so we can see them during shutdown.
159 this will help prod developers not to lose sight
160 of bugs that cause segfaults etc. during shutdown.
163 sigprocmask (SIG_UNBLOCK, &blocked, 0);
174 struct sigaction action;
175 pthread_t signal_thread_id;
178 // if (setpgid (0,0)) {
180 warning << string_compose (_("cannot become new process group leader (%1)"),
185 sigemptyset (&signals);
186 sigaddset(&signals, SIGHUP);
187 sigaddset(&signals, SIGINT);
188 sigaddset(&signals, SIGQUIT);
189 sigaddset(&signals, SIGPIPE);
190 sigaddset(&signals, SIGTERM);
191 sigaddset(&signals, SIGUSR1);
192 sigaddset(&signals, SIGUSR2);
195 /* install a handler because otherwise
196 pthreads behaviour is undefined when we enter
200 action.sa_handler = handler;
201 action.sa_mask = signals;
202 action.sa_flags = SA_RESTART|SA_RESETHAND;
204 for (int i = 1; i < 32; i++) {
205 if (sigismember (&signals, i)) {
206 if (sigaction (i, &action, 0)) {
207 cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
213 /* this sets the signal mask for this and all
214 subsequent threads that do not reset it.
217 if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
218 cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
222 /* start a thread to wait for signals */
224 if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
225 cerr << "cannot create signal catching thread" << endl;
229 pthread_detach (signal_thread_id);
239 if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
242 rcfile = "ardour2_ui.rc";
245 rcfile = find_config_file (rcfile);
247 if (rcfile.empty()) {
248 warning << _("Without a UI style file, ardour will look strange.\n Please set ARDOUR2_UI_RC to point to a valid UI style file") << endmsg;
250 cerr << "Loading ui configuration file " << rcfile << endl;
257 show_ui_callback (void *arg)
259 ARDOUR_UI * ui = (ARDOUR_UI *) arg;
269 MessageDialog win (_("Ardour could not connect to JACK."),
272 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
273 win.set_secondary_text(_("There are several possible reasons:\n\
275 1) JACK is not running.\n\
276 2) JACK is running as another user, perhaps root.\n\
277 3) There is already another client called \"ardour\".\n\
279 Please consider the possibilities, and perhaps (re)start JACK."));
281 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
282 win.set_default_response (RESPONSE_CLOSE);
285 win.set_position (Gtk::WIN_POS_CENTER);
291 /* we just don't care about the result, but we want to block */
297 maybe_load_session ()
299 /* If no session name is given: we're not loading a session yet, nor creating a new one */
300 if (!session_name.length()) {
302 if (!Config->get_no_new_session_dialog()) {
309 /* Load session or start the new session dialog */
314 if (Session::find_session (session_name, path, name, isnew)) {
315 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
321 /* Loading a session, but the session doesn't exist */
323 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
324 "To create it from the command line, start ardour as \"ardour --new %1"), path)
329 if (ui->load_session (path, name)) {
336 /* TODO: This bit of code doesn't work properly yet
337 Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
338 ui->set_will_create_new_session_automatically (true);
343 if (!Config->get_no_new_session_dialog()) {
352 /* this is called from the entry point of a wine-compiled
353 executable that is linked against gtk2_ardour built
357 int ardour_main (int argc, char *argv[])
359 int main (int argc, char *argv[])
363 ARDOUR::AudioEngine *engine;
364 vector<Glib::ustring> null_file_list;
369 (void) bindtextdomain (PACKAGE, LOCALEDIR);
370 /* our i18n translations are all in UTF-8, so make sure
371 that even if the user locale doesn't specify UTF-8,
372 we use that when handling them.
374 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
375 (void) textdomain (PACKAGE);
377 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
379 // catch error message system signals ();
381 text_receiver.listen_to (error);
382 text_receiver.listen_to (info);
383 text_receiver.listen_to (fatal);
384 text_receiver.listen_to (warning);
386 if (parse_opts (argc, argv)) {
390 if (curvetest_file) {
391 return curvetest (curvetest_file);
394 cout << _("Ardour/GTK ")
396 << _("\n (built using ")
397 << ardour_svn_revision
399 << _(" and GCC version ") << __VERSION__
409 cerr << _("Copyright (C) 1999-2006 Paul Davis") << endl
410 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
412 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
413 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
414 << _("This is free software, and you are welcome to redistribute it ") << endl
415 << _("under certain conditions; see the source for copying conditions.")
420 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
421 } catch (failed_constructor& err) {
422 error << _("could not create ARDOUR GUI") << endmsg;
426 if (!keybindings_path.empty()) {
427 ui->set_keybindings_path (keybindings_path);
432 if (session_name.length()) {
433 g_timeout_add (4000, show_ui_callback, ui);
438 ARDOUR::init (use_vst, try_hw_optimization);
439 setup_gtk_ardour_enums ();
440 Config->set_current_owner (ConfigVariableBase::Interface);
443 engine = new ARDOUR::AudioEngine (jack_client_name);
444 } catch (AudioEngine::NoBackendAvailable& err) {
446 error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
450 ui->set_engine (*engine);
452 } catch (failed_constructor& err) {
453 error << _("could not initialize Ardour.") << endmsg;
459 if (maybe_load_session ()) {
460 ui->run (text_receiver);
471 } // end of extern C block