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"
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);
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 signal_thread (void *arg)
113 PBD::ThreadCreated (pthread_self(), X_("Signal"));
115 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
117 /* find out what's blocked right now */
119 //sigprocmask (SIG_SETMASK, 0, &blocked);
120 if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
121 cerr << "getting blocked signals failed\n";
124 /* wait for any of the currently blocked signals.
126 According to the man page found in linux 2.6 and 2.4, sigwait()
127 never returns an error. This is incorrect. Checking the man
128 pages for some other *nix systems makes it clear that
129 sigwait() can return several error codes, one of which
130 is EINTR. This happens if the thread receives a signal
131 which is not in the blocked set.
133 We do not expect that to happen, and if it did we should generally
134 exit as planned. However, under 2.6, the ptrace facility used
135 by gdb seems to also cause sigwait() to return with EINTR
136 but with a signal that sigwait cannot understand. As a result,
137 "sig" is set to zero, an impossible signal number.
139 Handling the EINTR code makes it possible to debug
140 ardour on a 2.6 kernel.
147 if ((swerr = sigwait (&blocked, &sig))) {
148 if (swerr == EINTR) {
151 cerr << "sigwait failed with " << swerr << endl;
155 cerr << "Signal " << sig << " received\n";
157 if (sig != SIGSEGV) {
159 /* unblock signals so we can see them during shutdown.
160 this will help prod developers not to lose sight
161 of bugs that cause segfaults etc. during shutdown.
164 sigprocmask (SIG_UNBLOCK, &blocked, 0);
175 struct sigaction action;
176 pthread_t signal_thread_id;
179 // if (setpgid (0,0)) {
181 warning << string_compose (_("cannot become new process group leader (%1)"),
186 sigemptyset (&signals);
187 sigaddset(&signals, SIGHUP);
188 sigaddset(&signals, SIGINT);
189 sigaddset(&signals, SIGQUIT);
190 sigaddset(&signals, SIGPIPE);
191 sigaddset(&signals, SIGTERM);
192 sigaddset(&signals, SIGUSR1);
193 sigaddset(&signals, SIGUSR2);
196 /* install a handler because otherwise
197 pthreads behaviour is undefined when we enter
201 action.sa_handler = handler;
202 action.sa_mask = signals;
203 action.sa_flags = SA_RESTART|SA_RESETHAND;
205 for (int i = 1; i < 32; i++) {
206 if (sigismember (&signals, i)) {
207 if (sigaction (i, &action, 0)) {
208 cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
214 /* this sets the signal mask for this and all
215 subsequent threads that do not reset it.
218 if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
219 cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
223 /* start a thread to wait for signals */
225 if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
226 cerr << "cannot create signal catching thread" << endl;
230 pthread_detach (signal_thread_id);
240 if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
243 rcfile = "ardour2_ui.rc";
246 rcfile = find_config_file (rcfile);
248 if (rcfile.empty()) {
249 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;
251 cerr << "Loading ui configuration file " << rcfile << endl;
258 show_ui_callback (void *arg)
260 ARDOUR_UI * ui = (ARDOUR_UI *) arg;
270 MessageDialog win (_("Ardour could not connect to JACK."),
273 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
274 win.set_secondary_text(_("There are several possible reasons:\n\
276 1) JACK is not running.\n\
277 2) JACK is running as another user, perhaps root.\n\
278 3) There is already another client called \"ardour\".\n\
280 Please consider the possibilities, and perhaps (re)start JACK."));
282 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
283 win.set_default_response (RESPONSE_CLOSE);
286 win.set_position (Gtk::WIN_POS_CENTER);
292 /* we just don't care about the result, but we want to block */
298 maybe_load_session ()
300 /* If no session name is given: we're not loading a session yet, nor creating a new one */
301 if (!session_name.length()) {
303 if (!Config->get_no_new_session_dialog()) {
304 ui->new_session (true);
310 /* Load session or start the new session dialog */
315 if (Session::find_session (session_name, path, name, isnew)) {
316 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
322 /* Loading a session, but the session doesn't exist */
324 error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
325 To create it from the command line, start ardour as \"ardour --new %1"), path) << endmsg;
329 ui->load_session (path, name);
333 /* TODO: This bit of code doesn't work properly yet
334 Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
335 ui->set_will_create_new_session_automatically (true);
340 if (!Config->get_no_new_session_dialog()) {
341 ui->new_session (true);
349 /* this is called from the entry point of a wine-compiled
350 executable that is linked against gtk2_ardour built
354 int ardour_main (int argc, char *argv[])
356 int main (int argc, char *argv[])
360 ARDOUR::AudioEngine *engine;
361 vector<Glib::ustring> null_file_list;
365 (void) bindtextdomain (PACKAGE, LOCALEDIR);
366 (void) textdomain (PACKAGE);
368 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
372 text_receiver.listen_to (error);
373 text_receiver.listen_to (info);
374 text_receiver.listen_to (fatal);
375 text_receiver.listen_to (warning);
377 if (parse_opts (argc, argv)) {
381 if (curvetest_file) {
382 return curvetest (curvetest_file);
385 cout << _("Ardour/GTK ")
387 << _("\n (built using ")
388 << ardour_svn_revision
390 << _(" and GCC version ") << __VERSION__
400 cerr << _("Copyright (C) 1999-2006 Paul Davis") << endl
401 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
403 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
404 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
405 << _("This is free software, and you are welcome to redistribute it ") << endl
406 << _("under certain conditions; see the source for copying conditions.")
410 // needs a better home.
414 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
415 } catch (failed_constructor& err) {
416 error << _("could not create ARDOUR GUI") << endmsg;
423 if (session_name.length()) {
424 g_timeout_add (4000, show_ui_callback, ui);
430 engine = new ARDOUR::AudioEngine (jack_client_name);
431 } catch (AudioEngine::NoBackendAvailable& err) {
433 error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
439 ARDOUR::init (use_vst, try_hw_optimization);
440 Config->set_current_owner (ConfigVariableBase::Interface);
441 ui->set_engine (*engine);
442 } catch (failed_constructor& err) {
443 error << _("could not initialize Ardour.") << endmsg;
448 if (maybe_load_session ()) {
449 ui->run (text_receiver);
460 } // end of extern C block