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>
48 #include "ardour_ui.h"
54 using namespace GTK_ARDOUR;
55 using namespace ARDOUR;
59 TextReceiver text_receiver ("ardour");
61 extern int curvetest (string);
63 static ARDOUR_UI *ui = 0;
72 msg = _("ardour is killing itself for a clean exit\n");
73 write (1, msg, strlen (msg));
74 /* drastic, but perhaps necessary */
75 kill (-getpgrp(), SIGKILL);
81 msg = _("stopping user interface\n");
82 write (1, msg, strlen (msg));
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 handler2 (int sig, siginfo_t* ctxt, void* ignored)
113 signal_thread (void *arg)
118 PBD::ThreadCreated (pthread_self(), X_("Signal"));
120 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
122 /* find out what's blocked right now */
124 //sigprocmask (SIG_SETMASK, 0, &blocked);
125 if (pthread_sigmask (SIG_SETMASK, 0, &blocked)) {
126 cerr << "getting blocked signals failed\n";
129 /* wait for any of the currently blocked signals.
131 According to the man page found in linux 2.6 and 2.4, sigwait()
132 never returns an error. This is incorrect. Checking the man
133 pages for some other *nix systems makes it clear that
134 sigwait() can return several error codes, one of which
135 is EINTR. This happens if the thread receives a signal
136 which is not in the blocked set.
138 We do not expect that to happen, and if it did we should generally
139 exit as planned. However, under 2.6, the ptrace facility used
140 by gdb seems to also cause sigwait() to return with EINTR
141 but with a signal that sigwait cannot understand. As a result,
142 "sig" is set to zero, an impossible signal number.
144 Handling the EINTR code makes it possible to debug
145 ardour on a 2.6 kernel.
152 if ((swerr = sigwait (&blocked, &sig))) {
153 if (swerr == EINTR) {
156 cerr << "sigwait failed with " << swerr << endl;
160 cerr << "Signal " << sig << " received\n";
162 if (sig != SIGSEGV) {
164 /* unblock signals so we can see them during shutdown.
165 this will help prod developers not to lose sight
166 of bugs that cause segfaults etc. during shutdown.
169 sigprocmask (SIG_UNBLOCK, &blocked, 0);
180 struct sigaction action;
181 pthread_t signal_thread_id;
184 // if (setpgid (0,0)) {
186 warning << string_compose (_("cannot become new process group leader (%1)"),
191 sigemptyset (&signals);
192 sigaddset(&signals, SIGHUP);
193 sigaddset(&signals, SIGINT);
194 sigaddset(&signals, SIGQUIT);
195 sigaddset(&signals, SIGPIPE);
196 sigaddset(&signals, SIGTERM);
197 sigaddset(&signals, SIGUSR1);
198 sigaddset(&signals, SIGUSR2);
201 /* install a handler because otherwise
202 pthreads behaviour is undefined when we enter
206 action.sa_handler = handler;
207 action.sa_mask = signals;
208 action.sa_flags = SA_RESTART|SA_RESETHAND;
210 for (int i = 1; i < 32; i++) {
211 if (sigismember (&signals, i)) {
212 if (sigaction (i, &action, 0)) {
213 cerr << string_compose (_("cannot setup signal handling for %1"), i) << endl;
219 /* this sets the signal mask for this and all
220 subsequent threads that do not reset it.
223 if (pthread_sigmask (SIG_SETMASK, &signals, 0)) {
224 cerr << string_compose (_("cannot set default signal mask (%1)"), strerror (errno)) << endl;
228 /* start a thread to wait for signals */
230 if (pthread_create_and_store ("signal", &signal_thread_id, 0, signal_thread, 0)) {
231 cerr << "cannot create signal catching thread" << endl;
235 pthread_detach (signal_thread_id);
245 if ((env = getenv ("ARDOUR2_UI_RC")) != 0 && strlen (env)) {
248 rcfile = "ardour2_ui.rc";
251 rcfile = find_config_file (rcfile);
253 if (rcfile.empty()) {
254 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;
256 cerr << "Loading ui configuration file " << rcfile << endl;
263 show_ui_callback (void *arg)
265 ARDOUR_UI * ui = (ARDOUR_UI *) arg;
276 MessageDialog win (_("Ardour could not connect to JACK."),
279 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
280 win.set_secondary_text(_("There are several possible reasons:\n\
282 1) JACK is not running.\n\
283 2) JACK is running as another user, perhaps root.\n\
284 3) There is already another client called \"ardour\".\n\
286 Please consider the possibilities, and perhaps (re)start JACK."));
288 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
289 win.set_default_response (RESPONSE_CLOSE);
292 win.set_position (Gtk::WIN_POS_CENTER);
294 /* we just don't care about the result */
300 maybe_load_session ()
303 /* load session, if given */
306 if (session_name.length()){
309 if (Session::find_session (session_name, path, name, isnew)) {
310 error << string_compose(_("could not load command line session \"%1\""), session_name) << endmsg;
315 /* command line required that the session be new */
319 /* popup the new session dialog
320 once everything else is OK.
323 Glib::signal_idle().connect (bind (mem_fun (*ui, &ARDOUR_UI::cmdline_new_session), path));
324 ui->set_will_create_new_session_automatically (true);
328 /* it wasn't new, but we require a new session */
330 error << string_compose (_("\n\nA session named \"%1\" already exists.\n\
331 To avoid this message, start ardour as \"ardour %1"), path)
338 /* command line didn't require a new session */
341 error << string_compose (_("\n\nNo session named \"%1\" exists.\n\
342 To create it from the command line, start ardour as \"ardour --new %1"), path)
347 ui->load_session (path, name);
357 if (!Config->get_no_new_session_dialog()) {
358 ui->new_session (true);
366 /* this is called from the entry point of a wine-compiled
367 executable that is linked against gtk2_ardour built
371 int ardour_main (int argc, char *argv[])
373 int main (int argc, char *argv[])
377 ARDOUR::AudioEngine *engine;
378 vector<Glib::ustring> null_file_list;
380 // needs a better home.
385 (void) bindtextdomain (PACKAGE, LOCALEDIR);
386 (void) textdomain (PACKAGE);
388 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
392 text_receiver.listen_to (error);
393 text_receiver.listen_to (info);
394 text_receiver.listen_to (fatal);
395 text_receiver.listen_to (warning);
397 if (parse_opts (argc, argv)) {
401 if (curvetest_file) {
402 return curvetest (curvetest_file);
405 cout << _("Ardour/GTK ")
407 << _("\n (built using ")
408 << gtk_ardour_major_version << '.'
409 << gtk_ardour_minor_version << '.'
410 << gtk_ardour_micro_version
411 << _(" with libardour ")
412 << libardour_major_version << '.'
413 << libardour_minor_version << '.'
414 << libardour_micro_version
416 << _(" and GCC version ") << __VERSION__
426 cerr << _("Copyright (C) 1999-2006 Paul Davis") << endl
427 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
429 << _("Ardour comes with ABSOLUTELY NO WARRANTY") << endl
430 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
431 << _("This is free software, and you are welcome to redistribute it ") << endl
432 << _("under certain conditions; see the source for copying conditions.")
437 ui = new ARDOUR_UI (&argc, &argv, which_ui_rcfile());
440 catch (failed_constructor& err) {
441 error << _("could not create ARDOUR GUI") << endmsg;
448 if (session_name.length()) {
449 gtk_timeout_add (4000, show_ui_callback, ui);
454 engine = new ARDOUR::AudioEngine (jack_client_name);
455 ARDOUR::init (*engine, use_vst, try_hw_optimization, handler2);
456 ui->set_engine (*engine);
457 } catch (AudioEngine::NoBackendAvailable& err) {
459 error << string_compose (_("Could not connect to JACK server as \"%1\""), jack_client_name) << endmsg;
461 } catch (failed_constructor& err) {
462 error << _("could not initialize Ardour.") << endmsg;
466 if (maybe_load_session ()) {
467 ui->run (text_receiver);
478 } // end of extern C block