comment fix
[ardour2.git] / gtk2_ardour / main.cc
bloba35cd1f3e7735a00ed3c10338319e14761b2a047
1 /*
2 Copyright (C) 2001-2007 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 <cstdlib>
21 #include <signal.h>
22 #include <cerrno>
23 #include <fstream>
25 #include <sigc++/bind.h>
26 #include <gtkmm/settings.h>
28 #include "pbd/error.h"
29 #include "pbd/epa.h"
30 #include "pbd/file_utils.h"
31 #include "pbd/textreceiver.h"
32 #include "pbd/failed_constructor.h"
33 #include "pbd/pthread_utils.h"
34 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
35 #include "pbd/boost_debug.h"
36 #endif
38 #include <jack/jack.h>
40 #include "ardour/svn_revision.h"
41 #include "ardour/version.h"
42 #include "ardour/ardour.h"
43 #include "ardour/audioengine.h"
44 #include "ardour/session_utils.h"
45 #include "ardour/filesystem_paths.h"
47 #include <gtkmm/main.h>
48 #include <gtkmm2ext/application.h>
49 #include <gtkmm2ext/popup.h>
50 #include <gtkmm2ext/utils.h>
52 #include "version.h"
53 #include "utils.h"
54 #include "ardour_ui.h"
55 #include "opts.h"
56 #include "enums.h"
58 #include "i18n.h"
60 using namespace std;
61 using namespace Gtk;
62 using namespace ARDOUR_COMMAND_LINE;
63 using namespace ARDOUR;
64 using namespace PBD;
66 TextReceiver text_receiver ("ardour");
68 extern int curvetest (string);
70 static ARDOUR_UI *ui = 0;
71 static const char* localedir = LOCALEDIR;
73 void
74 gui_jack_error ()
76 MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
77 false,
78 Gtk::MESSAGE_INFO,
79 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
80 win.set_secondary_text(_("There are several possible reasons:\n\
81 \n\
82 1) JACK is not running.\n\
83 2) JACK is running as another user, perhaps root.\n\
84 3) There is already another client called \"ardour\".\n\
85 \n\
86 Please consider the possibilities, and perhaps (re)start JACK."));
88 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
89 win.set_default_response (RESPONSE_CLOSE);
91 win.show_all ();
92 win.set_position (Gtk::WIN_POS_CENTER);
94 if (!no_splash) {
95 ui->hide_splash ();
98 /* we just don't care about the result, but we want to block */
100 win.run ();
104 #ifdef __APPLE__
106 #include <mach-o/dyld.h>
107 #include <sys/param.h>
109 extern void set_language_preference (); // cocoacarbon.mm
111 void
112 fixup_bundle_environment (int, char* [])
114 if (!getenv ("ARDOUR_BUNDLED")) {
115 return;
118 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
120 set_language_preference ();
122 char execpath[MAXPATHLEN+1];
123 uint32_t pathsz = sizeof (execpath);
125 _NSGetExecutablePath (execpath, &pathsz);
127 std::string exec_path (execpath);
128 std::string dir_path = Glib::path_get_dirname (exec_path);
129 std::string path;
130 const char *cstr = getenv ("PATH");
132 /* ensure that we find any bundled executables (e.g. JACK),
133 and find them before any instances of the same name
134 elsewhere in PATH
137 path = dir_path;
139 /* JACK is often in /usr/local/bin and since Info.plist refuses to
140 set PATH, we have to force this in order to discover a running
141 instance of JACK ...
144 path += ':';
145 path += "/usr/local/bin";
147 if (cstr) {
148 path += ':';
149 path += cstr;
151 setenv ("PATH", path.c_str(), 1);
153 path = dir_path;
154 path += "/../Resources";
155 path += dir_path;
156 path += "/../Resources/Surfaces";
157 path += dir_path;
158 path += "/../Resources/Panners";
160 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
162 path = user_config_directory().to_string();
163 path += ':';
164 path += dir_path;
165 path += "/../Resources/icons:";
166 path += dir_path;
167 path += "/../Resources/pixmaps:";
168 path += dir_path;
169 path += "/../Resources/share:";
170 path += dir_path;
171 path += "/../Resources";
173 setenv ("ARDOUR_PATH", path.c_str(), 1);
174 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
176 path = dir_path;
177 path += "/../Resources";
178 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
180 cstr = getenv ("LADSPA_PATH");
181 if (cstr) {
182 path = cstr;
183 path += ':';
184 } else {
185 path = "";
187 path += dir_path;
188 path += "/../Plugins";
190 setenv ("LADSPA_PATH", path.c_str(), 1);
192 cstr = getenv ("VAMP_PATH");
193 if (cstr) {
194 path = cstr;
195 path += ':';
196 } else {
197 path = "";
199 path += dir_path;
200 path += "/../Frameworks";
202 setenv ("VAMP_PATH", path.c_str(), 1);
204 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
205 if (cstr) {
206 path = cstr;
207 path += ':';
208 } else {
209 path = "";
211 path += dir_path;
212 path += "/../Surfaces";
214 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
216 cstr = getenv ("ARDOUR_PANNER_PATH");
217 if (cstr) {
218 path = cstr;
219 path += ':';
220 } else {
221 path = "";
223 path += dir_path;
224 path += "/lib/panners";
226 setenv ("ARDOUR_PANNER_PATH", path.c_str(), 1);
228 path = dir_path;
229 path += "/../Frameworks/clearlooks";
231 setenv ("GTK_PATH", path.c_str(), 1);
233 /* unset GTK_RC_FILES so that we only load the RC files that we define
236 unsetenv ("GTK_RC_FILES");
238 if (!ARDOUR::translations_are_disabled ()) {
240 path = dir_path;
241 path += "/../Resources/locale";
243 localedir = strdup (path.c_str());
244 setenv ("GTK_LOCALEDIR", localedir, 1);
247 /* write a pango.rc file and tell pango to use it. we'd love
248 to put this into the PROGRAM_NAME.app bundle and leave it there,
249 but the user may not have write permission. so ...
251 we also have to make sure that the user ardour directory
252 actually exists ...
255 try {
256 sys::create_directories (user_config_directory ());
258 catch (const sys::filesystem_error& ex) {
259 error << _("Could not create user configuration directory") << endmsg;
262 sys::path pangopath = user_config_directory();
263 pangopath /= "pango.rc";
264 path = pangopath.to_string();
266 std::ofstream pangorc (path.c_str());
267 if (!pangorc) {
268 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
269 return;
270 } else {
271 pangorc << "[Pango]\nModuleFiles=";
273 pangopath = dir_path;
274 pangopath /= "..";
275 pangopath /= "Resources";
276 pangopath /= "pango.modules";
278 pangorc << pangopath.to_string() << endl;
280 pangorc.close ();
282 setenv ("PANGO_RC_FILE", path.c_str(), 1);
285 // gettext charset aliases
287 setenv ("CHARSETALIASDIR", path.c_str(), 1);
289 // font config
291 path = dir_path;
292 path += "/../Resources/fonts.conf";
294 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
296 // GDK Pixbuf loader module file
298 path = dir_path;
299 path += "/../Resources/gdk-pixbuf.loaders";
301 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
303 if (getenv ("ARDOUR_WITH_JACK")) {
304 // JACK driver dir
306 path = dir_path;
307 path += "/../Frameworks";
309 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
313 #else
315 void
316 fixup_bundle_environment (int /*argc*/, char* argv[])
318 if (!getenv ("ARDOUR_BUNDLED")) {
319 return;
322 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
324 Glib::ustring exec_path = argv[0];
325 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
326 Glib::ustring path;
327 const char *cstr = getenv ("PATH");
328 Glib::ustring userconfigdir = user_config_directory().to_string();
330 /* ensure that we find any bundled executables (e.g. JACK),
331 and find them before any instances of the same name
332 elsewhere in PATH
335 /* note that this function is POSIX/Linux specific, so using / as
336 a dir separator in this context is just fine.
339 path = dir_path;
340 path += "/etc:";
341 path += dir_path;
342 path += "/lib/surfaces:";
343 path += dir_path;
344 path += "/lib/panners:";
346 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
348 path = userconfigdir;
349 path += ':';
350 path += dir_path;
351 path += "/etc/icons:";
352 path += dir_path;
353 path += "/etc/pixmaps:";
354 path += dir_path;
355 path += "/share:";
356 path += dir_path;
357 path += "/etc";
359 setenv ("ARDOUR_PATH", path.c_str(), 1);
360 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
362 path = dir_path;
363 path += "/etc";
364 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
366 cstr = getenv ("LADSPA_PATH");
367 if (cstr) {
368 path = cstr;
369 path += ':';
370 } else {
371 path = "";
373 path += dir_path;
374 path += "/lib/plugins";
376 setenv ("LADSPA_PATH", path.c_str(), 1);
378 cstr = getenv ("VAMP_PATH");
379 if (cstr) {
380 path = cstr;
381 path += ':';
382 } else {
383 path = "";
385 path += dir_path;
386 path += "/lib";
388 setenv ("VAMP_PATH", path.c_str(), 1);
390 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
391 if (cstr) {
392 path = cstr;
393 path += ':';
394 } else {
395 path = "";
397 path += dir_path;
398 path += "/lib/surfaces";
400 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
402 cstr = getenv ("ARDOUR_PANNER_PATH");
403 if (cstr) {
404 path = cstr;
405 path += ':';
406 } else {
407 path = "";
409 path += dir_path;
410 path += "/lib/panners";
412 setenv ("ARDOUR_PANNER_PATH", path.c_str(), 1);
414 path = dir_path;
415 path += "/lib/clearlooks";
417 setenv ("GTK_PATH", path.c_str(), 1);
419 /* unset GTK_RC_FILES so that we only load the RC files that we define
422 unsetenv ("GTK_RC_FILES");
424 if (!ARDOUR::translations_are_disabled ()) {
425 path = dir_path;
426 path += "/share/locale";
428 localedir = strdup (path.c_str());
429 setenv ("GTK_LOCALEDIR", localedir, 1);
432 /* write a pango.rc file and tell pango to use it. we'd love
433 to put this into the Ardour.app bundle and leave it there,
434 but the user may not have write permission. so ...
436 we also have to make sure that the user ardour directory
437 actually exists ...
440 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
441 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
442 << endmsg;
443 } else {
445 Glib::ustring mpath;
447 path = Glib::build_filename (userconfigdir, "pango.rc");
449 std::ofstream pangorc (path.c_str());
450 if (!pangorc) {
451 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
452 } else {
453 mpath = Glib::build_filename (userconfigdir, "pango.modules");
455 pangorc << "[Pango]\nModuleFiles=";
456 pangorc << mpath << endl;
457 pangorc.close ();
460 setenv ("PANGO_RC_FILE", path.c_str(), 1);
462 /* similar for GDK pixbuf loaders, but there's no RC file required
463 to specify where it lives.
466 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
467 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
471 #endif
473 static gboolean
474 tell_about_jack_death (void* /* ignored */)
476 if (AudioEngine::instance()->processed_frames() == 0) {
477 /* died during startup */
478 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
479 msg.set_position (Gtk::WIN_POS_CENTER);
480 msg.set_secondary_text (string_compose (_(
481 "JACK exited unexpectedly, and without notifying %1.\n\
483 This could be due to misconfiguration or to an error inside JACK.\n\
485 Click OK to exit %1."), PROGRAM_NAME));
487 msg.run ();
488 _exit (0);
490 } else {
492 /* engine has already run, so this is a mid-session JACK death */
494 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
495 msg->set_secondary_text (string_compose (_(
496 "JACK exited unexpectedly, and without notifying %1.\n\
498 This is probably due to an error inside JACK. You should restart JACK\n\
499 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
500 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
501 msg->present ();
503 return false; /* do not call again */
506 static void
507 sigpipe_handler (int /*signal*/)
509 /* XXX fix this so that we do this again after a reconnect to JACK
512 static bool done_the_jack_thing = false;
514 if (!done_the_jack_thing) {
515 AudioEngine::instance()->died ();
516 g_idle_add (tell_about_jack_death, 0);
517 done_the_jack_thing = true;
521 #ifdef HAVE_LV2
522 void close_external_ui_windows();
523 #endif
525 #ifdef VST_SUPPORT
527 extern int gui_init (int* argc, char** argv[]);
529 /* this is called from the entry point of a wine-compiled
530 executable that is linked against gtk2_ardour built
531 as a shared library.
533 extern "C" {
534 int ardour_main (int argc, char *argv[])
535 #else
536 int main (int argc, char *argv[])
537 #endif
539 fixup_bundle_environment (argc, argv);
541 if (!Glib::thread_supported()) {
542 Glib::thread_init();
545 gtk_set_locale ();
547 #ifdef VST_SUPPORT
548 /* this does some magic that is needed to make GTK and Wine's own
549 X11 client interact properly.
551 gui_init (&argc, &argv);
552 #endif
554 (void) bindtextdomain (PACKAGE, localedir);
555 /* our i18n translations are all in UTF-8, so make sure
556 that even if the user locale doesn't specify UTF-8,
557 we use that when handling them.
559 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
560 (void) textdomain (PACKAGE);
562 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
564 // catch error message system signals ();
566 text_receiver.listen_to (error);
567 text_receiver.listen_to (info);
568 text_receiver.listen_to (fatal);
569 text_receiver.listen_to (warning);
571 #ifdef BOOST_SP_ENABLE_DEBUG_HOOKS
572 if (getenv ("BOOST_DEBUG")) {
573 boost_debug_shared_ptr_show_live_debugging (true);
575 #endif
577 if (parse_opts (argc, argv)) {
578 exit (1);
581 if (curvetest_file) {
582 return curvetest (curvetest_file);
585 cout << PROGRAM_NAME
586 << VERSIONSTRING
587 << _(" (built using ")
588 << svn_revision
589 #ifdef __GNUC__
590 << _(" and GCC version ") << __VERSION__
591 #endif
592 << ')'
593 << endl;
595 if (just_version) {
596 exit (0);
599 if (no_splash) {
600 cerr << _("Copyright (C) 1999-2011 Paul Davis") << endl
601 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
602 << endl
603 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
604 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
605 << _("This is free software, and you are welcome to redistribute it ") << endl
606 << _("under certain conditions; see the source for copying conditions.")
607 << endl;
610 /* some GUI objects need this */
612 PBD::ID::init ();
614 if (::signal (SIGPIPE, sigpipe_handler)) {
615 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
618 try {
619 ui = new ARDOUR_UI (&argc, &argv);
620 } catch (failed_constructor& err) {
621 error << _("could not create ARDOUR GUI") << endmsg;
622 exit (1);
625 ui->run (text_receiver);
626 Gtkmm2ext::Application::instance()->cleanup();
627 ui = 0;
629 ARDOUR::cleanup ();
630 pthread_cancel_all ();
632 #ifdef HAVE_LV2
633 close_external_ui_windows();
634 #endif
635 return 0;
637 #ifdef VST_SUPPORT
638 } // end of extern C block
639 #endif