if STRIP is not set, don't strip included libraries either
[ardour2.git] / gtk2_ardour / main.cc
blob793297837925e1f15144f535d29064fb8b262ade
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"
35 #include <jack/jack.h>
37 #include "ardour/svn_revision.h"
38 #include "ardour/version.h"
39 #include "ardour/ardour.h"
40 #include "ardour/audioengine.h"
41 #include "ardour/session_utils.h"
42 #include "ardour/filesystem_paths.h"
44 #include <gtkmm/main.h>
45 #include <gtkmm2ext/application.h>
46 #include <gtkmm2ext/popup.h>
47 #include <gtkmm2ext/utils.h>
49 #include "version.h"
50 #include "utils.h"
51 #include "ardour_ui.h"
52 #include "opts.h"
53 #include "enums.h"
55 #include "i18n.h"
57 using namespace std;
58 using namespace Gtk;
59 using namespace ARDOUR_COMMAND_LINE;
60 using namespace ARDOUR;
61 using namespace PBD;
63 TextReceiver text_receiver ("ardour");
65 extern int curvetest (string);
67 static ARDOUR_UI *ui = 0;
68 static const char* localedir = LOCALEDIR;
70 void
71 gui_jack_error ()
73 MessageDialog win (string_compose (_("%1 could not connect to JACK."), PROGRAM_NAME),
74 false,
75 Gtk::MESSAGE_INFO,
76 (Gtk::ButtonsType)(Gtk::BUTTONS_NONE));
77 win.set_secondary_text(_("There are several possible reasons:\n\
78 \n\
79 1) JACK is not running.\n\
80 2) JACK is running as another user, perhaps root.\n\
81 3) There is already another client called \"ardour\".\n\
82 \n\
83 Please consider the possibilities, and perhaps (re)start JACK."));
85 win.add_button (Stock::QUIT, RESPONSE_CLOSE);
86 win.set_default_response (RESPONSE_CLOSE);
88 win.show_all ();
89 win.set_position (Gtk::WIN_POS_CENTER);
91 if (!no_splash) {
92 ui->hide_splash ();
95 /* we just don't care about the result, but we want to block */
97 win.run ();
101 #ifdef __APPLE__
103 #include <mach-o/dyld.h>
104 #include <sys/param.h>
106 extern void set_language_preference (); // cocoacarbon.mm
108 void
109 fixup_bundle_environment (int, char* [])
111 if (!getenv ("ARDOUR_BUNDLED")) {
112 return;
115 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
117 set_language_preference ();
119 char execpath[MAXPATHLEN+1];
120 uint32_t pathsz = sizeof (execpath);
122 _NSGetExecutablePath (execpath, &pathsz);
124 std::string exec_path (execpath);
125 std::string dir_path = Glib::path_get_dirname (exec_path);
126 std::string path;
127 const char *cstr = getenv ("PATH");
129 /* ensure that we find any bundled executables (e.g. JACK),
130 and find them before any instances of the same name
131 elsewhere in PATH
134 path = dir_path;
136 /* JACK is often in /usr/local/bin and since Info.plist refuses to
137 set PATH, we have to force this in order to discover a running
138 instance of JACK ...
141 path += ':';
142 path += "/usr/local/bin";
144 if (cstr) {
145 path += ':';
146 path += cstr;
148 setenv ("PATH", path.c_str(), 1);
150 path = dir_path;
151 path += "/../Resources";
152 path += dir_path;
153 path += "/../Resources/Surfaces";
154 path += dir_path;
155 path += "/../Resources/Panners";
157 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
159 path = user_config_directory().to_string();
160 path += ':';
161 path += dir_path;
162 path += "/../Resources/icons:";
163 path += dir_path;
164 path += "/../Resources/pixmaps:";
165 path += dir_path;
166 path += "/../Resources/share:";
167 path += dir_path;
168 path += "/../Resources";
170 setenv ("ARDOUR_PATH", path.c_str(), 1);
171 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
173 path = dir_path;
174 path += "/../Resources";
175 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
177 cstr = getenv ("LADSPA_PATH");
178 if (cstr) {
179 path = cstr;
180 path += ':';
181 } else {
182 path = "";
184 path += dir_path;
185 path += "/../Plugins";
187 setenv ("LADSPA_PATH", path.c_str(), 1);
189 cstr = getenv ("VAMP_PATH");
190 if (cstr) {
191 path = cstr;
192 path += ':';
193 } else {
194 path = "";
196 path += dir_path;
197 path += "/../Frameworks";
199 setenv ("VAMP_PATH", path.c_str(), 1);
201 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
202 if (cstr) {
203 path = cstr;
204 path += ':';
205 } else {
206 path = "";
208 path += dir_path;
209 path += "/../Surfaces";
211 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
213 cstr = getenv ("ARDOUR_PANNER_PATH");
214 if (cstr) {
215 path = cstr;
216 path += ':';
217 } else {
218 path = "";
220 path += dir_path;
221 path += "/lib/panners";
223 setenv ("ARDOUR_PANNER_PATH", path.c_str(), 1);
225 path = dir_path;
226 path += "/../Frameworks/clearlooks";
228 setenv ("GTK_PATH", path.c_str(), 1);
230 /* unset GTK_RC_FILES so that we only load the RC files that we define
233 unsetenv ("GTK_RC_FILES");
235 if (!ARDOUR::translations_are_disabled ()) {
237 path = dir_path;
238 path += "/../Resources/locale";
240 localedir = strdup (path.c_str());
241 setenv ("GTK_LOCALEDIR", localedir, 1);
244 /* write a pango.rc file and tell pango to use it. we'd love
245 to put this into the PROGRAM_NAME.app bundle and leave it there,
246 but the user may not have write permission. so ...
248 we also have to make sure that the user ardour directory
249 actually exists ...
252 try {
253 sys::create_directories (user_config_directory ());
255 catch (const sys::filesystem_error& ex) {
256 error << _("Could not create user configuration directory") << endmsg;
259 sys::path pangopath = user_config_directory();
260 pangopath /= "pango.rc";
261 path = pangopath.to_string();
263 std::ofstream pangorc (path.c_str());
264 if (!pangorc) {
265 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
266 return;
267 } else {
268 pangorc << "[Pango]\nModuleFiles=";
270 pangopath = dir_path;
271 pangopath /= "..";
272 pangopath /= "Resources";
273 pangopath /= "pango.modules";
275 pangorc << pangopath.to_string() << endl;
277 pangorc.close ();
279 setenv ("PANGO_RC_FILE", path.c_str(), 1);
282 // gettext charset aliases
284 setenv ("CHARSETALIASDIR", path.c_str(), 1);
286 // font config
288 path = dir_path;
289 path += "/../Resources/fonts.conf";
291 setenv ("FONTCONFIG_FILE", path.c_str(), 1);
293 // GDK Pixbuf loader module file
295 path = dir_path;
296 path += "/../Resources/gdk-pixbuf.loaders";
298 setenv ("GDK_PIXBUF_MODULE_FILE", path.c_str(), 1);
300 if (getenv ("ARDOUR_WITH_JACK")) {
301 // JACK driver dir
303 path = dir_path;
304 path += "/../Frameworks";
306 setenv ("JACK_DRIVER_DIR", path.c_str(), 1);
310 #else
312 void
313 fixup_bundle_environment (int /*argc*/, char* argv[])
315 if (!getenv ("ARDOUR_BUNDLED")) {
316 return;
319 EnvironmentalProtectionAgency::set_global_epa (new EnvironmentalProtectionAgency (true, "PREBUNDLE_ENV"));
321 Glib::ustring exec_path = argv[0];
322 Glib::ustring dir_path = Glib::path_get_dirname (Glib::path_get_dirname (exec_path));
323 Glib::ustring path;
324 const char *cstr = getenv ("PATH");
325 Glib::ustring userconfigdir = user_config_directory().to_string();
327 /* ensure that we find any bundled executables (e.g. JACK),
328 and find them before any instances of the same name
329 elsewhere in PATH
332 /* note that this function is POSIX/Linux specific, so using / as
333 a dir separator in this context is just fine.
336 path = dir_path;
337 path += "/etc:";
338 path += dir_path;
339 path += "/lib/surfaces:";
340 path += dir_path;
341 path += "/lib/panners:";
343 setenv ("ARDOUR_MODULE_PATH", path.c_str(), 1);
345 path = userconfigdir;
346 path += ':';
347 path += dir_path;
348 path += "/etc/icons:";
349 path += dir_path;
350 path += "/etc/pixmaps:";
351 path += dir_path;
352 path += "/share:";
353 path += dir_path;
354 path += "/etc";
356 setenv ("ARDOUR_PATH", path.c_str(), 1);
357 setenv ("ARDOUR_CONFIG_PATH", path.c_str(), 1);
359 path = dir_path;
360 path += "/etc";
361 setenv ("ARDOUR_INSTANT_XML_PATH", path.c_str(), 1);
363 cstr = getenv ("LADSPA_PATH");
364 if (cstr) {
365 path = cstr;
366 path += ':';
367 } else {
368 path = "";
370 path += dir_path;
371 path += "/lib/plugins";
373 setenv ("LADSPA_PATH", path.c_str(), 1);
375 cstr = getenv ("VAMP_PATH");
376 if (cstr) {
377 path = cstr;
378 path += ':';
379 } else {
380 path = "";
382 path += dir_path;
383 path += "/lib";
385 setenv ("VAMP_PATH", path.c_str(), 1);
387 cstr = getenv ("ARDOUR_CONTROL_SURFACE_PATH");
388 if (cstr) {
389 path = cstr;
390 path += ':';
391 } else {
392 path = "";
394 path += dir_path;
395 path += "/lib/surfaces";
397 setenv ("ARDOUR_CONTROL_SURFACE_PATH", path.c_str(), 1);
399 cstr = getenv ("ARDOUR_PANNER_PATH");
400 if (cstr) {
401 path = cstr;
402 path += ':';
403 } else {
404 path = "";
406 path += dir_path;
407 path += "/lib/panners";
409 setenv ("ARDOUR_PANNER_PATH", path.c_str(), 1);
411 path = dir_path;
412 path += "/lib/clearlooks";
414 setenv ("GTK_PATH", path.c_str(), 1);
416 /* unset GTK_RC_FILES so that we only load the RC files that we define
419 unsetenv ("GTK_RC_FILES");
421 if (!ARDOUR::translations_are_disabled ()) {
422 path = dir_path;
423 path += "/share/locale";
425 localedir = strdup (path.c_str());
426 setenv ("GTK_LOCALEDIR", localedir, 1);
429 /* write a pango.rc file and tell pango to use it. we'd love
430 to put this into the Ardour.app bundle and leave it there,
431 but the user may not have write permission. so ...
433 we also have to make sure that the user ardour directory
434 actually exists ...
437 if (g_mkdir_with_parents (userconfigdir.c_str(), 0755) < 0) {
438 error << string_compose (_("cannot create user ardour folder %1 (%2)"), userconfigdir, strerror (errno))
439 << endmsg;
440 } else {
442 Glib::ustring mpath;
444 path = Glib::build_filename (userconfigdir, "pango.rc");
446 std::ofstream pangorc (path.c_str());
447 if (!pangorc) {
448 error << string_compose (_("cannot open pango.rc file %1") , path) << endmsg;
449 } else {
450 mpath = Glib::build_filename (userconfigdir, "pango.modules");
452 pangorc << "[Pango]\nModuleFiles=";
453 pangorc << mpath << endl;
454 pangorc.close ();
457 setenv ("PANGO_RC_FILE", path.c_str(), 1);
459 /* similar for GDK pixbuf loaders, but there's no RC file required
460 to specify where it lives.
463 mpath = Glib::build_filename (userconfigdir, "gdk-pixbuf.loaders");
464 setenv ("GDK_PIXBUF_MODULE_FILE", mpath.c_str(), 1);
468 #endif
470 static gboolean
471 tell_about_jack_death (void* /* ignored */)
473 if (AudioEngine::instance()->processed_frames() == 0) {
474 /* died during startup */
475 MessageDialog msg (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_OK);
476 msg.set_position (Gtk::WIN_POS_CENTER);
477 msg.set_secondary_text (string_compose (_(
478 "JACK exited unexpectedly, and without notifying %1.\n\
480 This could be due to misconfiguration or to an error inside JACK.\n\
482 Click OK to exit %1."), PROGRAM_NAME));
484 msg.run ();
485 _exit (0);
487 } else {
489 /* engine has already run, so this is a mid-session JACK death */
491 MessageDialog* msg = manage (new MessageDialog (_("JACK exited"), false, Gtk::MESSAGE_INFO, Gtk::BUTTONS_NONE));
492 msg->set_secondary_text (string_compose (_(
493 "JACK exited unexpectedly, and without notifying %1.\n\
495 This is probably due to an error inside JACK. You should restart JACK\n\
496 and reconnect %1 to it, or exit %1 now. You cannot save your\n\
497 session at this time, because we would lose your connection information.\n"), PROGRAM_NAME));
498 msg->present ();
500 return false; /* do not call again */
503 static void
504 sigpipe_handler (int /*signal*/)
506 /* XXX fix this so that we do this again after a reconnect to JACK
509 static bool done_the_jack_thing = false;
511 if (!done_the_jack_thing) {
512 AudioEngine::instance()->died ();
513 g_idle_add (tell_about_jack_death, 0);
514 done_the_jack_thing = true;
518 #ifdef HAVE_LV2
519 void close_external_ui_windows();
520 #endif
522 #ifdef VST_SUPPORT
524 extern int gui_init (int* argc, char** argv[]);
526 /* this is called from the entry point of a wine-compiled
527 executable that is linked against gtk2_ardour built
528 as a shared library.
530 extern "C" {
531 int ardour_main (int argc, char *argv[])
532 #else
533 int main (int argc, char *argv[])
534 #endif
536 fixup_bundle_environment (argc, argv);
538 if (!Glib::thread_supported())
539 Glib::thread_init();
541 gtk_set_locale ();
543 #ifdef VST_SUPPORT
544 /* this does some magic that is needed to make GTK and Wine's own
545 X11 client interact properly.
547 gui_init (&argc, &argv);
548 #endif
550 (void) bindtextdomain (PACKAGE, localedir);
551 /* our i18n translations are all in UTF-8, so make sure
552 that even if the user locale doesn't specify UTF-8,
553 we use that when handling them.
555 (void) bind_textdomain_codeset (PACKAGE,"UTF-8");
556 (void) textdomain (PACKAGE);
558 pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, 0);
560 // catch error message system signals ();
562 text_receiver.listen_to (error);
563 text_receiver.listen_to (info);
564 text_receiver.listen_to (fatal);
565 text_receiver.listen_to (warning);
567 if (parse_opts (argc, argv)) {
568 exit (1);
571 if (curvetest_file) {
572 return curvetest (curvetest_file);
575 cout << PROGRAM_NAME
576 << VERSIONSTRING
577 << _(" (built using ")
578 << svn_revision
579 #ifdef __GNUC__
580 << _(" and GCC version ") << __VERSION__
581 #endif
582 << ')'
583 << endl;
585 if (just_version) {
586 exit (0);
589 if (no_splash) {
590 cerr << _("Copyright (C) 1999-2010 Paul Davis") << endl
591 << _("Some portions Copyright (C) Steve Harris, Ari Johnson, Brett Viren, Joel Baker") << endl
592 << endl
593 << string_compose (_("%1 comes with ABSOLUTELY NO WARRANTY"), PROGRAM_NAME) << endl
594 << _("not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.") << endl
595 << _("This is free software, and you are welcome to redistribute it ") << endl
596 << _("under certain conditions; see the source for copying conditions.")
597 << endl;
600 /* some GUI objects need this */
602 PBD::ID::init ();
604 if (::signal (SIGPIPE, sigpipe_handler)) {
605 cerr << _("Cannot xinstall SIGPIPE error handler") << endl;
608 try {
609 ui = new ARDOUR_UI (&argc, &argv);
610 } catch (failed_constructor& err) {
611 error << _("could not create ARDOUR GUI") << endmsg;
612 exit (1);
615 ui->run (text_receiver);
616 Gtkmm2ext::Application::instance()->cleanup();
617 ui = 0;
619 ARDOUR::cleanup ();
620 pthread_cancel_all ();
622 #ifdef HAVE_LV2
623 close_external_ui_windows();
624 #endif
625 return 0;
627 #ifdef VST_SUPPORT
628 } // end of extern C block
629 #endif