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.
20 #include <sys/types.h>
28 #include <sigc++/bind.h>
29 #include <gtkmm/settings.h>
31 #include <pbd/error.h>
32 #include <pbd/textreceiver.h>
33 #include <pbd/failed_constructor.h>
34 #include <pbd/pthread_utils.h>
36 #include <jack/jack.h>
38 #include <ardour/version.h>
39 #include <ardour/ardour.h>
40 #include <ardour/audioengine.h>
42 #include <gtkmm/main.h>
43 #include <gtkmm2ext/popup.h>
44 #include <gtkmm2ext/utils.h>
46 #include "svn_revision.h"
48 #include "ardour_ui.h"
55 using namespace GTK_ARDOUR;
56 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);
85 pthread_cancel_all ();
98 /* XXX its doubtful that snprintf() is async-safe */
99 n = snprintf (buf, sizeof(buf), _("%d(%d): received signal %d\n"), getpid(), (int) pthread_self(), sig);
106 signal_thread (void *arg)
111 PBD::ThreadCreated (pthread_self(), X_("Signal"));
113 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
115 /* find out what's blocked right now */
117 //sigprocmask (SIG_SETMASK, 0, &blocked);
118 if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
119 cerr << "getting blocked signals failed\n";
122 /* wait for any of the currently blocked signals.
124 According to the man page found in linux 2.6 and 2.4, sigwait()
125 never returns an error. This is incorrect. Checking the man
126 pages for some other *nix systems makes it clear that
127 sigwait() can return several error codes, one of which
128 is EINTR. This happens if the thread receives a signal
129 which is not in the blocked set.
131 We do not expect that to happen, and if it did we should generally
132 exit as planned. However, under 2.6, the ptrace facility used
133 by gdb seems to also cause sigwait() to return with EINTR
134 but with a signal that sigwait cannot understand. As a result,
135 "sig" is set to zero, an impossible signal number.
137 Handling the EINTR code makes it possible to debug
138 ardour on a 2.6 kernel.
145 if ((swerr = sigwait (&blocked, &sig))) {
146 if (swerr == EINTR) {
149 cerr << "sigwait failed with " << swerr << endl;
153 cerr << "Signal " << sig << " received\n";
155 if (sig != SIGSEGV) {
157 /* unblock signals so we can see them during shutdown.
158 this will help prod developers not to lose sight
159 of bugs that cause segfaults etc. during shutdown.
162 sigprocmask (SIG_UNBLOCK, &blocked, 0);
173 struct sigaction action;
174 pthread_t signal_thread_id;
177 // if (setpgid (0,0)) {
179 warning << string_compose (_("cannot become new process group leader (%1)"),
184 sigemptyset (&signals);
185 sigaddset(&signals, SIGHUP);
186 sigaddset(&signals, SIGINT);
187 sigaddset(&signals, SIGQUIT);
188 sigaddset(&signals, SIGPIPE);
189 sigaddset(&signals, SIGTERM);
190 sigaddset(&signals, SIGUSR1);
191 sigaddset(&signals, SIGUSR2);
194 /* install a handler because otherwise
195 pthreads behaviour is undefined when we enter
199 action.sa_handler = handler;
200 action.sa_mask = signals;
201 action.sa_flags = SA_RESTART|SA_RESETHAND;
203 for (int i = 1; i < 32; i++) {
204 if (sigismember (&signals, i)) {
205 if (sigaction (i, &action, 0)) {
206 cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
212 /* this sets the signal mask for this and all
213 subsequent threads that do not reset it.
216 if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
217 cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
221 /* start a thread to wait for signals */
223 if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
224 cerr << "cannot create signal catching thread" << endl;
228 pthread_detach (signal_thread_id);
238 if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
241 rcfile = "ardour2_ui.rc";
244 rcfile = find_config_file (rcfile);
246 if (rcfile.empty()) {
247 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;
249 cerr << "Loading ui configuration file " << rcfile << endl;
256 show_ui_callback (void *arg)
258 ARDOUR_UI * ui = (ARDOUR_UI *) arg;
268 MessageDialog win (_("Ardour could not connect to JACK."),
271 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
272 win.set_secondary_text(_("There are several possible reasons:\n\
274 1) JACK is not running.\n\
275 2) JACK is running as another user, perhaps root.\n\
276 3) There is already another client called \"ardour\".\n\
278 Please consider the possibilities, and perhaps (re)start JACK."));
280 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
281 win.set_default_response (RESPONSE_CLOSE);
284 win.set_position (Gtk::WIN_POS_CENTER);
290 /* we just don't care about the result, but we want to block */
296 maybe_load_session ()
298 /* If no session name is given: we're not loading a session yet, nor creating a new one */
299 if (!session_name.length()) {
301 if (!Config->get_no_new_session_dialog()) {
308 /* Load session or start the new session dialog */
313 if (Session::find_session (session_name, path, name, isnew)) {
314 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
320 /* Loading a session, but the session doesn't exist */
322 error << string_compose (_("\n\nNo session named \"%1\" exists.\n"
323 "To create it from the command line, start ardour as \"ardour --new %1"), path)
328 if (ui->load_session (path, name)) {
335 /* TODO: This bit of code doesn't work properly yet
336 Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
337 ui->set_will_create_new_session_automatically (true);
342 if (!Config->get_no_new_session_dialog()) {
351 /* this is called from the entry point of a wine-compiled
352 executable that is linked against gtk2_ardour built
356 int ardour_main (int argc, char *argv[])
358 int main (int argc, char *argv[])
362 ARDOUR::AudioEngine *engine;
363 vector<Glib::ustring> null_file_list;
368 (void) bindtextdomain (PACKAGE, LOCALEDIR);
369 /* our i18n translations are all in UTF-8, so make sure
370 that even if the user locale doesn't specify UTF-8,
371 we use that when handling them.
373 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
374 (void) textdomain (PACKAGE);
376 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
378 // catch error message system signals ();
380 text_receiver.listen_to (error);
381 text_receiver.listen_to (info);
382 text_receiver.listen_to (fatal);
383 text_receiver.listen_to (warning);
385 if (parse_opts (argc, argv)) {
389 if (curvetest_file) {
390 return curvetest (curvetest_file);
393 cout << _("Ardour/GTK ")
395 << _("\n (built using ")
396 << ardour_svn_revision
398 << _(" and GCC version ") << __VERSION__
408 cerr << _("Copyright (C) 1999-2006 Paul Davis") << endl
409 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
411 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
412 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
413 << _("This is free software, and you are welcome to redistribute it ") << endl
414 << _("under certain conditions; see the source for copying conditions.")
418 /* some GUI objects need this */
423 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
424 } catch (failed_constructor& err) {
425 error << _("could not create ARDOUR GUI") << endmsg;
429 if (!keybindings_path.empty()) {
430 ui->set_keybindings_path (keybindings_path);
435 if (session_name.length()) {
436 g_timeout_add (4000, show_ui_callback, ui);
441 ARDOUR::init (use_vst, try_hw_optimization);
442 setup_gtk_ardour_enums ();
443 Config->set_current_owner (ConfigVariableBase::Interface);
446 engine = new ARDOUR::AudioEngine (jack_client_name);
447 } catch (AudioEngine::NoBackendAvailable& err) {
449 error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
453 ui->set_engine (*engine);
455 } catch (failed_constructor& err) {
456 error << _("could not initialize Ardour.") << endmsg;
462 if (maybe_load_session ()) {
463 ui->run (text_receiver);
474 } // end of extern C block